前言
看到最近智能家居的討論挺火,我也來分享下在智能家居這塊的體會。我主要改造了我租的房子的室燈。主要實現功能有:監控室內環境,改裝了室燈,光線暗的時候有人時自動開燈,光線亮自動滅燈,可紅外用遙控器、手機客戶端改變閾值。
材料
主控板: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;
}
}

