前言
看到最近智能家居的讨论挺火,我也来分享下在智能家居这块的体会。我主要改造了我租的房子的室灯。主要实现功能有:监控室内环境,改装了室灯,光线暗的时候有人时自动开灯,光线亮自动灭灯,可红外用遥控器、手机客户端改变阈值。
材料
主控板:Arduino UNO/Mega2560(IO口多)
传感器:光敏电阻、DHT11温湿度传感器、串口WIFI模块、红外遥控探头、红外人体探测器、5V继电器(220V)
布线
室灯控制还是很简单的,控制电源即可。
- 首先使用继电器接管室灯的电线。
- 然后放置红外人体探测器,我把它朝向房间门口。
- 温湿度传感器、光敏电阻、wifi模块、红外遥控探头就比较随意了,合理放置就行。
程序开发
Arduino开发工具官方有提供,代码类似c语言,有很多第三方库,开发非常容易。最让我感到幸福的是VS也有相应的开发环境,有个插件叫做Visual Micro。
- 控制电路无非就是置数字IO口高电平或低电平。
- 光敏电阻测光很简单,使用模拟口测电阻值,如果需要精度更高更专业的可以买专门的测光模块。
- 通信方式多种多样,红外遥控、射频、蓝牙、wifi,坑爹的wp不支持蓝牙串口,所以我选用的是串口wifi,使用简单,模块有自己的配置页面,我配置成接入屋里的wifi网络+模块自建AP,并使用UDP模式发送广播。
- 具体代码附在下面。
原型
可以使用220v~5v变压器,这样就可以把主体放到灯罩里了,而且可以使用小点的板子。
扩展
Arduino这种类似积木的搭建方法非常适合咱们程序员自己DIY,不需要自己制作电路板。在这个室灯控制的基础上咱们在扩展一下思维:
- 加上红外发射头就可以控制相应的红外遥控设备,一个接收一个发射组合就是万能遥控器,多个发射器可以防死角
- 加上常用的2.4G或者低频段的无线模块,就可以实现无线设备间通讯(模块很便宜,有兴趣可以尝试鼠标、键盘、遥控车、航模通讯)
- 加个舵机,拉窗帘不在话下。
- 再大胆点,拆开电器找到电路板,接上线,使用Arduino的数字IO直接监控/控制电器电路板。
- 加上语音识别模块(目前的貌似都不太理想,相对Arduino有些重,这活交给家庭网关或者手机比较好)语音控制电器。
Arduino可以方便的实现控制电源、控制/监控带电路控制的电器的电路板。
憧憬一下当WP的Cortana成熟的时候,这些设备控制,Cortana都能根据我的习惯自动搞定,并支持语音控制,全时待命,未来生活啊~
最后附上我的Arduino代码:
#include <EEPROM.h> #include <IRremote.h> #include <dht11.h> //UNO //#define GM_dpin A5 //光敏电阻 //#define dht_dpin 2 //温湿度传感器 //#define wifiRx_dpin 5 //WIFI接收Rx //#define wifiTx_dpin 6 //WIFI发送Tx //#define HW_dpin 8 //红外遥控探头 //#define RSensor_dpin 10 //红外探测器人 //#define jdq_dpin 11 //继电器 //#define light_dpin 13 //指示灯 //2560 #define GM_dpin A15 //光敏电阻 //#define wifiTx_dpin 10 //WIFI发送Rx //#define wifiRx_dpin 11 //WIFI接收Tx #define dht_dpin 21 //温湿度传感器 #define HW_dpin 22 //红外遥控探头 #define RSensor_dpin 23 //红外探测器人 #define jdq_dpin 29 //继电器 #define light_dpin 13 //指示灯 int ADZ = 45; //暗度阀值 int LDZ = 175; //亮度阀值 bool IsJDQOpend = false; bool IsAutoOpen = false; bool IsPause = false; IRrecv irrecv(HW_dpin); decode_results results; dht11 DHT; //SoftwareSerial WiFiPort(wifiRx_dpin, wifiTx_dpin); void InitController(){ pinMode(jdq_dpin, OUTPUT); digitalWrite(jdq_dpin, LOW); pinMode(light_dpin, OUTPUT); digitalWrite(light_dpin, LOW); pinMode(RSensor_dpin, INPUT); pinMode(GM_dpin, INPUT); } void closeLight(){ digitalWrite(light_dpin, LOW); digitalWrite(jdq_dpin, LOW); IsJDQOpend = false; IsAutoOpen = false; delay(2000); } void openLight(){ digitalWrite(light_dpin, HIGH); digitalWrite(jdq_dpin, HIGH); IsJDQOpend = true; delay(2000); } void makePause(){ IsPause = !IsPause; if (IsPause){ for (int i = 0; i < 5; i++) { digitalWrite(light_dpin, HIGH); delay(100); digitalWrite(light_dpin, LOW); delay(100); } } else{ digitalWrite(light_dpin, HIGH); delay(1000); digitalWrite(light_dpin, LOW); } } //室灯控制器 void LightController(){ //接收红外遥控器信号 if (irrecv.decode(&results)) { Serial.println(results.value, HEX); if (results.value == 0xFFA25D){ //关灯 closeLight(); } if (results.value == 0xFFE21D){ //开灯 openLight(); } if (results.value == 0xFFC23D){ //暂停 makePause(); } irrecv.resume(); } if (IsPause)return; //光敏电阻判断室内亮度 int valx = analogRead(GM_dpin); //Serial.println(valx); if (valx < ADZ){ //继电器如果是关的 if (!IsJDQOpend){ //红外人体检测 int val = digitalRead(RSensor_dpin); if (val == 1) { //开灯 openLight(); IsAutoOpen = true; } else { return; } } } else{ if (valx > LDZ && IsJDQOpend && IsAutoOpen){ valx = analogRead(GM_dpin); if (valx <= LDZ)return; //环境亮,关灯 closeLight(); } } } void setup(){ byte value = EEPROM.read(1); if (value != 255)ADZ = value; value = EEPROM.read(2); if (value != 255)LDZ = value; Serial.begin(115200); Serial3.begin(115200); InitController(); irrecv.enableIRIn(); delay(500); Serial.println(); Serial.println("[---ZZY Hareware Startup---]"); } void loop(){ LightController(); InfoQuery(); GetCommand(); } long timespan; void InfoQuery(){ unsigned long t = (micros() - timespan) / 1000000; if (t < 1)return; timespan = micros(); //信息查询 //光控信息 int valx = analogRead(GM_dpin); //温湿度传感器 DHT.read(dht_dpin); String msg = "VMZClub_Home HTP H"; msg += DHT.humidity; msg += "T"; msg += DHT.temperature; msg += "L"; msg += valx; msg += "S"; msg += IsJDQOpend; msg += "P"; msg += IsPause; msg += "F"; msg += ADZ; msg += "/"; msg += LDZ; Serial3.print(msg); Serial.println(msg); } void GetCommand(){ int cmd[10] = { -1 }; for (int i = 0; i < 10; i++) { cmd[i] = Serial3.read(); if (cmd[i] == -1)break; Serial.println((char) cmd[i]); } if (cmd[0] == -1)return; switch ((char) cmd[0]) { case 'L': switch (cmd[1]) { case '0': closeLight(); break; case '1': openLight(); break; } break; case 'P': switch (cmd[1]) { case '0': IsPause = false; break; case '1': IsPause = true; break; } break; case 'F': switch (cmd[1]) { case'A': if (cmd[2] != -1) { ADZ = cmd[2]; EEPROM.write(1, ADZ); } break; case'L': if (cmd[2] != -1){ LDZ = cmd[2]; EEPROM.write(2, LDZ); } break; } break; } }