极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 62219|回复: 21

廉价的无线智能家居

[复制链接]
发表于 2015-10-17 13:33:00 | 显示全部楼层 |阅读模式
      这是一个十分廉价的无线智能家居实例,笔者采用从淘宝上采购的WeMos D1 WiFi Arduino UNO 开发板(35元),采用Arduino编程,十分便捷的实现了无线网关,采用TTL转RS-485模块(2元)连接4路485接口的继电器模块(35元),成功组成了一套简易的智能家居控制系统:

      WeMos D1 WiFi开发板具有11 个 I/O 引脚及1个x ADC 引脚,而且具有4MB Flash 32KB SRAM 80KB DRAM,可扩充的潜力非常大。
      本实例将WeMos D1 WiFi开发板设计成WebServer 模式,让其充当无线网关的角色,控制模块采用了成品485接口的继电器,确保了其安全性及可靠性。控制界面是直接在安卓、PC、苹果等手机、平板或智能终端的浏览器上输入该开发板的IP地址,经测试,各终端的显示效果具有高度的一致性:

源代码:
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
#include <Ticker.h>

Ticker tickerflash;

#define EEPROM_write(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i<sizeof(p); i++) EEPROM.write(address+i,pp);}
#define EEPROM_read(address, p)  {int i = 0; byte *pp = (byte*)&(p);for(; i<sizeof(p); i++) pp=EEPROM.read(address+i);}

/* Set these to your desired credentials. */
static char Apid[9] = "NETGEAR";//根据你的路由器设置
static char softAPID[] = "KYSMART";
static char ApPass[10] = "zjky61448";//根据你的路由器设置
byte  APip[] = { 192, 168, 20, 221 };//根据你的路由器设置
byte  APGateWay[] = { 192, 168, 20, 254 };//根据你的路由器设置
byte  APSubNet[] = { 255, 255, 255, 0 };

unsigned char openc[5][8] = {
  { 0x01, 0x06, 0x00, 0x01, 0x01, 0x01, 0x18, 0x5a},//1号继电器开启
  { 0x01, 0x06, 0x00, 0x01, 0x02, 0x01, 0x18, 0xaa},//2号继电器开启
  { 0x01, 0x06, 0x00, 0x01, 0x03, 0x01, 0x19, 0x3a},//3号继电器开启
  { 0x01, 0x06, 0x00, 0x01, 0x04, 0x01, 0x1b, 0x0a},//4号继电器开启
  { 0x01, 0x06, 0x00, 0x01, 0xff, 0xff, 0xd9, 0xba}//全亮
};
unsigned char closec[5][8] = {
  { 0x01, 0x06, 0x00, 0x01, 0x01, 0x00, 0xd9, 0x9a},//1号继电器关闭
  { 0x01, 0x06, 0x00, 0x01, 0x02, 0x00, 0xd9, 0x6a},//2号继电器关闭
  { 0x01, 0x06, 0x00, 0x01, 0x03, 0x00, 0xd8, 0xfa},//3号继电器关闭
  { 0x01, 0x06, 0x00, 0x01, 0x04, 0x00, 0xda, 0xca},//4号继电器关闭
  { 0x01, 0x06, 0x00, 0x01, 0x00, 0x00, 0xd8, 0x0a}//全灭
};

byte TSwitch[] = {
  0, 0, 0, 0
};
byte StatSave[] = {
  0xff, 0xff, 0xff, 0xff
};//掉电保护
byte Switchnum = 10;//13
const byte SwitchIO[] = {
  D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D14, D15
};//开关列表
byte flashLed = D13; // 呼吸灯
int ledState = LOW;
char funcstr[800];
byte aptype = 0;// 模式:1 AP 0 CLIENT

const char pageS[] PROGMEM = "<meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\">\r\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">\r\n"
                             "<style type=\"text/css\">"
                             "* {margin:3;padding:3;}"
                             "input{width:90%;height:40px;font-size:20px;background:#999;}"
                             "</style>"
                             "<center><h2>欢迎使用科友智能家居<br></h2><h3>"
                             "%s"
                             "<br><a href=\"http://www.it15168.com\">ZJKEYOU SMART HOME</a></center></h3>";
const char LineS[] PROGMEM = "%s<br><br><a href=\"/\">返回</a><br>";
// Create an instance of the server
ESP8266WebServer server(80);

int RevB(int v, byte b) //设置第B位的值取反
{
  return (v ^= 1 << b); //把Number的POS位取反
}

void SaveSta()
{
  EEPROM.begin(512);
  EEPROM_write(30, StatSave);
  EEPROM.commit();
  EEPROM.end();
}

void setSta(byte Aswitch, byte Sta )
{
  byte i = Aswitch / 8;
  byte j = Aswitch % 8;
  bitWrite(TSwitch[3 - i], j, Sta);
}

void flash() {
  digitalWrite(flashLed, ledState);
  ledState = !ledState ;
}

void handleRoot() {
  sprintf_P(funcstr, pageS, "<form action=/op1><input type=submit value=k1开></form>"
            "<form action=/op2><input type=submit value=k1关></form>"
            "<form action=/op3><input type=submit value=k2开></form>"
            "<form action=/op4><input type=submit value=k2关></form>"
            "<form action=/op5><input type=submit value=k3开></form>"
            "<form action=/op6><input type=submit value=k3关></form>"
            "<form action=/op7><input type=submit value=k4开></form>"
            "<form action=/op8><input type=submit value=k4关></form>"
            "<form action=/op9><input type=submit value=全开></form>"
            "<form action=/op10><input type=submit value=全关></form>");
  server.send(200, "text/html", funcstr);
}

void op1() {
  opoper(0, 1, "k1已开");
}

void op2() {
  opoper(0, 0, "k1已关");
}

void op3() {
  opoper(1, 1, "k2已开");
}

void op4() {
  opoper(1, 0, "k2已关");
}

void op5() {
  opoper(2, 1, "k3已开");
}

void op6() {
  opoper(2, 0, "k3已关");
}

void op7() {
  opoper(3, 1, "k4已开");
}

void op8() {
  opoper(3, 0, "k4已关");
}

void op9() {
  opoper(4, 1, "全已开");
}

void op10() {
  opoper(4, 0, "全已关");
}

void opoper(byte port, byte oper, char *str)
{
  char funcstr1[100];
  if (oper == 1) {
    Serial.write(openc[port], 8);
  }
  else
  {
    Serial.write(closec[port], 8);
  }
  if (port < 4) {
    digitalWrite(SwitchIO[port], oper);
    setSta(port, oper);
  }
  funcstr[0] = 0;
  sprintf_P(funcstr1, LineS, str);
  sprintf_P(funcstr, pageS, funcstr1);
  server.send(200, "text/html", funcstr);
}

void handleNotFound() {
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i = 0; i < server.args(); i++) {
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
}

void setup(void) {
  Serial.begin(9600);
  pinMode(flashLed, OUTPUT);
  for (int i = 0; i < Switchnum / 8; i++)
    for (int j = 0; j < 8; j++) {
      pinMode(SwitchIO[i * 8 + j], OUTPUT);
      digitalWrite(SwitchIO[i * 8 + j], (bitRead(TSwitch[3 - i], j) > 0) && (bitRead(StatSave[3 - i], j) > 0));
    }

  Serial.print("Conn to:");
  Serial.println(Apid);
  if (aptype == 1) {
    WiFi.softAP(softAPID, ApPass);
    IPAddress myIP = WiFi.softAPIP();
    Serial.print("AP IP address:");
    Serial.println(myIP);
  }
  else
  {
    WiFi.config(APip, APGateWay, APSubNet);
    WiFi.begin(Apid, ApPass);
    while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
    }
    Serial.println("server started:");
    Serial.println(WiFi.localIP());
  }
  server.on("/", handleRoot);
  server.on("/op1", op1);
  server.on("/op2", op2);
  server.on("/op3", op3);
  server.on("/op4", op4);
  server.on("/op5", op5);
  server.on("/op6", op6);
  server.on("/op7", op7);
  server.on("/op8", op8);
  server.on("/op9", op9);
  server.on("/op10", op10);
  server.onNotFound(handleNotFound);
  server.begin();
  tickerflash.attach_ms(800, flash);
}

void loop(void) {
  server.handleClient();
  WiFiClient client = server.client();
  client.flush();
}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2015-10-17 15:10:37 | 显示全部楼层
我有一个你上面图片中一样的esp8266模块,不过就只是一个单独的模块,买回来不知道怎么用,官网上说的太复杂了,不懂
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-10-17 15:50:58 | 显示全部楼层
本论坛上 讨论esp8266模块的有很多,你搜一下就可以查到大把的资料。
回复 支持 反对

使用道具 举报

发表于 2015-10-17 18:18:35 | 显示全部楼层
dcopyboy 发表于 2015-10-17 15:50
本论坛上 讨论esp8266模块的有很多,你搜一下就可以查到大把的资料。

这个板子是谁家出的?
回复 支持 反对

使用道具 举报

发表于 2015-10-17 18:48:35 | 显示全部楼层
ranqingfa 发表于 2015-10-17 18:18
这个板子是谁家出的?

这里产的:http://www.ai-thinker.com/
回复 支持 反对

使用道具 举报

发表于 2015-10-17 20:00:40 | 显示全部楼层
msold5 发表于 2015-10-17 18:48
这里产的:http://www.ai-thinker.com/

谢谢,不过我是说整块板子,8266知道是安信可搞得
回复 支持 反对

使用道具 举报

发表于 2015-10-18 10:06:17 | 显示全部楼层
界面可以继续优化一下。如果能做出各种平台的APP会好一些。
想法还是很不错的~~~
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-10-18 19:01:11 | 显示全部楼层
开发板厂商http://www.wemos.cc/
回复 支持 反对

使用道具 举报

发表于 2015-12-17 01:50:30 | 显示全部楼层
你好,请问这一款WeMos D1 WiFi Arduino UNO是不是编程好的还是没有编程??
回复 支持 反对

使用道具 举报

发表于 2016-1-19 12:15:33 | 显示全部楼层
想问一下D1开发板和TTLRS485模块怎么接线的? 我只看到你模块R0接RX, DI接TX. DE和RE不用接吗?这个控制RS485方向的应该接哪里呢?
回复 支持 反对

使用道具 举报

发表于 2016-1-19 12:18:54 来自手机 | 显示全部楼层
有些很时髦的概念其实很廉价,只是被包装成了昂贵的东西。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-1-19 13:30:09 | 显示全部楼层
philip80 发表于 2016-1-19 12:15
想问一下D1开发板和TTLRS485模块怎么接线的? 我只看到你模块R0接RX, DI接TX. DE和RE不用接吗?这个控制RS4 ...

这个控制中是单向的,即D1开发板只发送数据。我采用的485模块太廉价了,目前我也无法实现双向通讯。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-1-19 13:37:51 | 显示全部楼层
008 发表于 2015-12-17 01:50
你好,请问这一款WeMos D1 WiFi Arduino UNO是不是编程好的还是没有编程??

WeMos D1 内部已经有最基本的烧写、引导程序,就像Arduino的各种模块类似,具体的应用需呀编写代码并进行编译及烧写,WeMos D1 已经功能做成 Arduino的插件,即在 Arduino 1.5以上的开发环境中就可以编写WeMos D1的具体应用。
回复 支持 反对

使用道具 举报

发表于 2016-1-19 15:43:28 | 显示全部楼层
dcopyboy 发表于 2016-1-19 13:30
这个控制中是单向的,即D1开发板只发送数据。我采用的485模块太廉价了,目前我也无法实现双向通讯。

这种RS485的RE和DE应该就是控制方向的,我在别的地方找到点资料,RE和DE相连接至一个IO口,IO=0:只接收,IO=1:只发射。 D1开发板上应该有这种IO口吧?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-1-20 10:30:03 | 显示全部楼层
philip80 发表于 2016-1-19 15:43
这种RS485的RE和DE应该就是控制方向的,我在别的地方找到点资料,RE和DE相连接至一个IO口,IO=0:只接收, ...

开发板上有11个IO口,我用多种方式 去控制 该485模块的收发,均未成功,你可以试下,成功的话与大家分享经验。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-3-28 23:28 , Processed in 0.052545 second(s), 26 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表