这篇文章来源于DevicePlus.com英语网站的翻译稿。点击这里阅读本文的第1部分 >
在DIY智能家居安防系统第1部分中,我们将各种组件(例如PIR传感器、温度传感器和压力传感器)组合在一起,以创建家庭安防系统/探测器。在第2部分中,将对前面所创建系统的离线程序进行测试,并连接到Internet,以便使用Cayenne API进行无线控制。使用myDevices Cayenne,只要您通过网站和/或智能手机中的Cayenne App连接到WiFi,您就能够无线控制安防系统。
硬件
- 笔记本电脑/PC或智能手机
参考第1部分:
- Arduino Mega 2560
- Arduino WiFi Shield(Arduino WiFi扩展板)
- 用于Arduino的Grove Base Shield(Grove基础扩展板)
- 3 只 LED (红色、绿色和蓝色)
- Grove PIR 移动侦测传感器
- 蜂鸣器
- Arduino ROHM 传感器扩展板
- ROHM 温度传感器 (BD1020HFV)
- ROHM 气压传感器 (BM1383GLV)
- Grove 通用4芯电线
- 亚克力: 195 x 195 x 3mm
- 电阻 (10 Kω and 100 KΩ)
- 面包板
- 无线遥控器,带2个发射器和1个接收器
- 电源:12 VDC
软件
- Arduino IDE
- Seeed Studio (https://github.com/Seeed-Studio/PIR_Motion_Sensor, https://www.seeed.cc/project_detail.html?id=284)
- Cayenne API (https://mydevices.com/cayenne/docs/#using-cayenne-library)
使用离线程序测试硬件
完成硬件安装后,现在可以运行离线程序进行测试。这是“离线”模式,系统尚未连接到Internet。我们马上就进行测试。离线程序将执行下列功能:
- 遥控发射器(在示例中使用通道D)打开/关闭警报。如果遥控发射器打开,绿色 LED将亮起,蜂鸣器将发出一次哔哔声。
- PIR传感器将检测移动情况。如果检测到移动,蓝色 LED将亮起。
- 当警报声响起并检测到移动时,红色 LED将亮起,蜂鸣器将熄灭。
- 同样,当警报声响起(即绿色 LED亮起)且热量高于设定目标时,红色 LED将亮起,蜂鸣器将熄灭。
注:
若想关闭警报声,用户只需再次按遥控发射器上的通道D。绿色 LED将熄灭,蜂鸣器将发出两次哔哔声。
若需查看温度和气压的值,请将USB电线从Arduino连接到PC。然后,进入Arduino IDE并单击工具 → 串行监视器。
现在可以上传程序。进行编译以前,请确保已安装所有必需的库。
//**************** Home security Program - offline ******************************
#define PIR_MOTION_SENSOR 2 // Use pin 2 to receive the signal from the module
#define LED1 4 // Blue Led for motion detected
#define LED2 6 // Green Led for triggered alarm
#define LED3 8 // Red Led if motion and trigger switch are on
#define buzzer 5 // Buzzer
#define remote 41 // Remote Control
#include <Wire.h>
#include <BM1383GLV.h>
#include <BD1020.h>
int alarm = 0;
int trigger = 0;
int remote_sw = 0;
int online_sw = 0;
int previousState = -1;
int currentState = -1;
int prev_remote_stat = 0;
int curr_remote_stat = 0;
int currentValue = 0;
int prev_online_stat = 0;
int curr_online_stat = 0;
int tempout_pin = A2;
BM1383GLV bm1383;
BD1020 bd1020;
unsigned long previousMillis = 0;
void setup()
{
Serial.begin(9600);
while (!Serial);
bd1020.init(tempout_pin);
byte rc;
while (!Serial);
Wire.begin();
rc = bm1383.init();
pinMode(LED1,OUTPUT);
pinMode(LED2,OUTPUT);
pinMode(LED3,OUTPUT);
pinMode(buzzer, OUTPUT);
pinMode(remote, INPUT);
pinMode(PIR_MOTION_SENSOR, INPUT);
}
// ********************* Start Loop *****************************************
void loop()
{
checkSensor();
remote_sw = digitalRead(remote);
Serial.print("Remote Status : ");
Serial.println(remote_sw);
Serial.println();
//*********************** read barometric pressure ************************
byte rc;
float press;
rc = bm1383.get_val(&press);
if (rc == 0)
{
Serial.write("BM1383GLV (PRESS) = ");
Serial.print(press);
Serial.println(" [hPa]");
Serial.println();
}
//********************** read Temperature ********************************
float temp;
bd1020.get_val(&temp);
temp = temp - 5; // Temperature adjustment due to heat from circuit board
Serial.print("BD1020HFV Temp=");
Serial.print(temp);
Serial.print(" [degrees Celsius], ADC=");
Serial.println(bd1020.temp_adc);
Serial.println();
// ********** Check if Remote switch or online/App switch is on **********
if(remote_sw == 1 | currentValue == 1)
{
digitalWrite(LED2,HIGH);
alarm = 1;
curr_remote_stat = 1;
if(curr_remote_stat != prev_remote_stat)
{
triggerBuzzer(2,70,30);
prev_remote_stat = curr_remote_stat;
}
}
else
{
curr_remote_stat = 0;
if(curr_remote_stat != prev_remote_stat)
{
triggerBuzzer(3,70,30);
prev_remote_stat = curr_remote_stat;
}
digitalWrite(LED2,LOW);
alarm = 0;
}
// ********************** If motion detected ***********************
if(isPeopleDetected()) //if it detects the moving people?
{
digitalWrite(LED1, HIGH); // Turn on Blue Led
trigger = 1;
delay(10);
}
else
{ digitalWrite(LED1, LOW);
trigger = 0;
delay(2000);
}
// ***************If Alarm is triggerred **************************
if (alarm == 1 && trigger == 1 )
{
digitalWrite(LED3,HIGH);
delay(500);
triggerBuzzer(6,100,100);
Serial.println("Alarm triggered");
}
else
{
alarm = 0;
trigger = 0;
digitalWrite(LED3,LOW);
}
// *********************** If temperature is triggerred **********
if (temp > 45.00)
{
digitalWrite(LED3,HIGH);
delay(500);
triggerBuzzer(10,100,10);
Serial.println("Alarm triggered");
}
delay(10);
}
// ************************** End Loop *****************************
// Function: Write to PIR sensor indicator in Web/App ***************
void checkSensor()
{
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= 250)
{
currentState = digitalRead(PIR_MOTION_SENSOR);
if (currentState != previousState)
{
previousState = currentState;
}
previousMillis = currentMillis;
}
}
//***************************************************************
// Function: Detect whether anyone moves in it's detecting range
boolean isPeopleDetected()
{
int sensorValue = digitalRead(PIR_MOTION_SENSOR);
if(sensorValue == HIGH) //if the sensor value is HIGH?
{
Serial.println("PIR detect motion");
return true; //yes,return true
}
else
{
Serial.println("no motion");
return false; //no,return false
}
}
//***************************************************************
// Function : activate buzzer based on parameters received
void triggerBuzzer(int iteration,int delay1,int delay2)
{
for (int i = 1; i < iteration; i++)
{
digitalWrite(buzzer, HIGH);
delay(delay1);
digitalWrite(buzzer, LOW);
delay(delay2);
}
}
//*****************************************************************
准备在线连接
创建一个myDevices帐户!您可以通过以下链接注册并创建一个新帐户:https://mydevices.com/cayenne/signup/
如果您已经拥有帐户,请随意使用自己的帐户。
然后选择Arduino作为本项目的设备。
阅读文档并通过以下网站安装Cayenne库:
https://mydevices.com/cayenne/docs/#using-cayenne-library
然后继续下一步,在新网页中连接到Arduino。选择Arduino Mega和WiFi Shield。选定这两项后,您将收到设备的“身份验证口令”。务必复制此口令并将其保存于某处。在下一个程序中需要用到此口令。
char token[] = “zzzzzzz”; // Cayenne authentication token
创建微件
我们可以为PIR传感器、触发状态和警报开/关状态创建微件。
为此,必须单击 “添加新…” ,然后单击 “设备/微件”。然后转到 “传感器” 类别并单击 “通用”。在“通用”下,有2个输入选项:模拟输入和数字输入。选择 “数字输入”。进入“数字输入”设置页面后,将连接设置为“虚拟”和“V1”(在下方)。请勿忘记单击步骤1 和 步骤2。
V2和V4微件也按相同步骤操作。请使用下表作为参考:
虚拟通道号 | 微件名称 | 选择微件 | 选择图标/显示 | 连接至 |
V1 | PIR 传感器 | 0/1 2 状态 | 显示值 | PIR 传感器 – 蓝色 Led |
V2 | 触发状态 | 0/1 2 状态 | 显示值 | 触发开关 – 红色 Led |
V4 | 警报状态开/关 | 0/1 2 状态 | 图标指示灯 | 远程开关 |
代码中使用的虚拟引脚分配如下:
#define VIRTUAL_PIN1 V1 // PIR传感器的虚拟引脚 – 蓝色 Led
#define VIRTUAL_PIN2 V2 // 触发开关的虚拟引脚 – 红色 Led
#define VIRTUAL_PIN4 V4 // 远程开关的状态
- 当PIR传感器检测到发生移动时,V1将开启(颜色变为绿色);蓝色LED也将亮起。
- 当触发状态开启时,V2将开启(颜色变为绿色);当警报开启且PIR传感器检测到发生移动时,红色LED也将亮起。
- 通过遥控发射器或在线/应用程序开启警报状态时,V4将开启(颜色变为绿色)
接下来为在线/应用程序切换功能创建一个微件。
转至 “添加新…” ,然后单击 “设备/微件”。这次选择 “执行器” ,然后选择 “通用”。选择 “数字输出” ,然后在“连接”下选择“虚拟”。在“Pin”下,选择“V3”。
使用下表作为参考:
虚拟通道号 | 微件名称 | 选择微件 | 选择图标/显示 | 连接到 |
V3 | 在线/应用程序切换 | 按钮 | 图标锁定 | 在线/应用程序 切换 — 绿色LED |
单击微件(在网站/应用程序上)时,V3将开启(颜色变为紫色)。当V3开启时,绿色LED也会亮起。因此,该虚拟开关与遥控发射器功能相同。但是,通过此虚拟交换机激活时会有一段延时。在下一程序中以下代码将会引用引脚V3。
#define VIRTUAL_PIN3 V3 // 在线切换 – 绿色 led
然后需要创建温度和压力传感器的微件。和前面一样,点击 “添加新…” 和 “设备/微件”。然后选择 “传感器” 和 “通用” ,然后选择 “模拟输入”。连接后,选择“虚拟”和“V5”进行引脚选择。
对V6执行相同操作并使用下表作为参考:
虚拟通道号 | 微件名称 | 选择微件 | 选择单位 | 连接到 |
V5 | 温度(℃) | 测量精度 | 有效位数 — 小数点后2位 | 温度传感器 |
V6 | 气压(hPa) | 测量精度 | 有效位数 — 小数点后2位 | 大气压力传感器 |
在下一程序中以下代码将会引用引脚V5和V6。
#define VIRTUAL_PIN5 V5 // 温度传感器
#define VIRTUAL_PIN6 V6 // 气压传感器
如果上述所有步骤都正确完成,您将看到如图7所示的页面。
最后一步是启用电子邮件通知功能(触发警报时)。为此,请单击“触发器状态”微件上的设置符号,然后选择“触发器”。
然后,您将进入以下页面(图9)。在“添加自定义收件人”中键入您的电子邮件地址,然后单击“发送电子邮件”。
myDevices设置到此结束!
测试在线程序
以上已经完成了与家庭安防系统的在线连接设置。运行最终程序前可以先测试在线程序。
上传以下程序。确保已安装适用于Arduino的Cayenne库。该程序用于执行简单的功能(即显示温度和气压值)。正确运行时,温度和气压微件将改变颜色(绿色和橙色),相应数值显示于微件的底部。
//**************** Home security Program - online test*********************** *
#define CAYENNE_DEBUG // Uncomment to show debug messages
#define CAYENNE_PRINT Serial // Comment this out to disable prints and save space
#define VIRTUAL_PIN5 V5 // Temperature sensor
#define VIRTUAL_PIN6 V6 // Barometric Pressure Sensor
#include <CayenneWiFi.h> // Cayenne wifi library
#include <Wire.h>
#include <BM1383GLV.h>
#include <BD1020.h>
char token[] = "zzzzzzz"; // Cayenne authentication token.
char ssid[] = "xxxxxxxxx"; // Your Wifi network name
char password[] = "yyyy"; // Your Wifi password
int tempout_pin = A2;
BM1383GLV bm1383;
BD1020 bd1020;
unsigned long previousMillis = 0;
void setup()
{
Serial.begin(9600);
while (!Serial);
bd1020.init(tempout_pin);
byte rc;
while (!Serial);
Wire.begin();
rc = bm1383.init();
Cayenne.begin(token, ssid, password);
}
// ********************* Start Loop *****************************************
void loop()
{
Cayenne.run();
//*********************** read barometric pressure ************************
byte rc;
float press;
rc = bm1383.get_val(&press);
if (rc == 0)
{
Cayenne.virtualWrite(VIRTUAL_PIN6, press); // Write Barometric Pressure to Cayenne
Serial.write("BM1383GLV (PRESS) = ");
Serial.print(press);
Serial.println(" [hPa]");
Serial.println();
}
//********************** read Temperature ********************************
float temp;
bd1020.get_val(&temp);
temp = temp - 5; // Temperature adjustment due to heat from circuit board
Cayenne.virtualWrite(VIRTUAL_PIN5, temp); // Write Temperature to Cayenne
Serial.print("BD1020HFV Temp=");
Serial.print(temp);
Serial.print(" [degrees Celsius], ADC=");
Serial.println(bd1020.temp_adc);
Serial.println();
// ********** Check if Remote switch or online/App switch is on **********
delay(5000);
}
// ************************** End Loop *****************************
至此差不多完成了所有步骤!
最终方案
如果以上所有程序都能流畅运行,则可上传最终程序,该程序中嵌入了离线程序以及与Cayenne API的连接功能。
//**************** Home security Program - Final ******************************
#define CAYENNE_DEBUG // Uncomment to show debug messages
#define CAYENNE_PRINT Serial // Comment this out to disable prints and save space
#define VIRTUAL_PIN1 V1 // Virtual Pin for PIR sensor - Blue Led
#define VIRTUAL_PIN2 V2 // Virtual Pin for Trigger Switch - Red Led
#define VIRTUAL_PIN3 V3 // Online Switch - Green led
#define VIRTUAL_PIN4 V4 // Status of Remote Switch
#define VIRTUAL_PIN5 V5 // Temperature sensor
#define VIRTUAL_PIN6 V6 // Barometric Pressure Sensor
#define PIR_MOTION_SENSOR 2 // Use pin 2 to receive the signal from the module
#define LED1 4 // Blue Led for motion detected
#define LED2 6 // Green Led for triggered alarm
#define LED3 8 // Red Led if motion and triger switch are on
#define buzzer 5 // Buzzer
#define remote 41 // Remote Control
#include <CayenneWiFi.h> // Cayenne wifi library
#include <Wire.h>
#include <BM1383GLV.h>
#include <BD1020.h>
char token[] = "zzzzzzz"; // Cayenne authentication token.
char ssid[] = "xxxxxxxxx"; // Your Wifi network name
char password[] = "yyyy"; // Your Wifi password
int alarm = 0;
int trigger = 0;
int remote_sw = 0;
int online_sw = 0;
int previousState = -1;
int currentState = -1;
int prev_remote_stat = 0;
int curr_remote_stat = 0;
int currentValue = 0;
int prev_online_stat = 0;
int curr_online_stat = 0;
int tempout_pin = A2;
BM1383GLV bm1383;
BD1020 bd1020;
unsigned long previousMillis = 0;
void setup()
{
Serial.begin(9600);
while (!Serial);
bd1020.init(tempout_pin);
byte rc;
while (!Serial);
Wire.begin();
rc = bm1383.init();
Cayenne.begin(token, ssid, password);
pinMode(LED1,OUTPUT);
pinMode(LED2,OUTPUT);
pinMode(LED3,OUTPUT);
pinMode(buzzer, OUTPUT);
pinMode(remote, INPUT);
pinMode(PIR_MOTION_SENSOR, INPUT);
}
// ************ Check if Online/App Switch is on *****************************
CAYENNE_IN(VIRTUAL_PIN3)
{currentValue = getValue.asInt();}
// ********************* Start Loop *****************************************
void loop()
{
Cayenne.run();
Serial.print("currentValue: ");
Serial.println(currentValue);
checkSensor();
remote_sw = digitalRead(remote);
Serial.print("Remote Status : ");
Serial.println(remote_sw);
Serial.println();
//*********************** read barometric pressure ************************
byte rc;
float press;
rc = bm1383.get_val(&press);
if (rc == 0)
{
Cayenne.virtualWrite(VIRTUAL_PIN6, press);
Serial.write("BM1383GLV (PRESS) = ");
Serial.print(press);
Serial.println(" [hPa]");
Serial.println();
}
//********************** read Temperature ********************************
float temp;
bd1020.get_val(&temp);
temp = temp - 5; // Temperature adjustment due to heat from circuit board
Cayenne.virtualWrite(VIRTUAL_PIN5, temp);
Serial.print("BD1020HFV Temp=");
Serial.print(temp);
Serial.print(" [degrees Celsius], ADC=");
Serial.println(bd1020.temp_adc);
Serial.println();
// ********** Check if Remote switch or online/App switch is on **********
if(remote_sw == 1 | currentValue == 1)
{
digitalWrite(LED2,HIGH);
Cayenne.virtualWrite(VIRTUAL_PIN4, HIGH);
alarm = 1;
curr_remote_stat = 1;
if(curr_remote_stat != prev_remote_stat)
{
triggerBuzzer(2,70,30);
prev_remote_stat = curr_remote_stat;
}
}
else
{
curr_remote_stat = 0;
if(curr_remote_stat != prev_remote_stat)
{
triggerBuzzer(3,70,30);
prev_remote_stat = curr_remote_stat;
}
digitalWrite(LED2,LOW);
Cayenne.virtualWrite(VIRTUAL_PIN4, LOW);
alarm = 0;
}
// ********************** If motion detected ***********************
if(isPeopleDetected()) //if it detects the moving people?
{
digitalWrite(LED1, HIGH); // Turn on Blue Led
trigger = 1;
delay(10);
}
else
{ digitalWrite(LED1, LOW);
trigger = 0;
delay(2000);
}
// ***************If Alarm is triggerred **************************
if (alarm == 1 && trigger == 1 )
{
digitalWrite(LED3,HIGH);
Cayenne.virtualWrite(VIRTUAL_PIN2, HIGH);
delay(500);
triggerBuzzer(6,100,100);
Serial.println("Alarm triggered");
}
else
{
alarm = 0;
trigger = 0;
digitalWrite(LED3,LOW);
Cayenne.virtualWrite(VIRTUAL_PIN2, LOW);
}
// *********************** If temperature is triggerred **********
if (temp > 45.00)
{
digitalWrite(LED3,HIGH);
Cayenne.virtualWrite(VIRTUAL_PIN2, HIGH);
delay(500);
triggerBuzzer(10,100,10);
Serial.println("Alarm triggered");
}
delay(10);
}
// ************************** End Loop *****************************
// Function: Write to PIR sensor indicator in Web/App ***************
void checkSensor()
{
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= 250)
{
currentState = digitalRead(PIR_MOTION_SENSOR);
if (currentState != previousState)
{
Cayenne.virtualWrite(VIRTUAL_PIN1, currentState);
previousState = currentState;
}
previousMillis = currentMillis;
}
}
//***************************************************************
// Function: Detect whether anyone moves in it's detecting range
boolean isPeopleDetected()
{
int sensorValue = digitalRead(PIR_MOTION_SENSOR);
if(sensorValue == HIGH) //if the sensor value is HIGH?
{
Serial.println("PIR detect motion");
return true; //yes,return true
}
else
{
Serial.println("no motion");
return false; //no,return false
}
}
//***************************************************************
// Function : activate buzzer based on parameters received
void triggerBuzzer(int iteration,int delay1,int delay2)
{
for (int i = 1; i < iteration; i++)
{
digitalWrite(buzzer, HIGH);
delay(delay1);
digitalWrite(buzzer, LOW);
delay(delay2);
}
}
// *****************************************************************
以下几种方法可以测试程序是否正常运行。
检查触发警报时是否发送电子邮件。您应收到如图10所示的电子邮件。
检查您是否可以看到温度和气压图。如需显示图形,请单击窗口微件右上角的图形符号。
然后还会显示图表:
下载智能手机应用程序
如前所述,无论何时何地只要您能连接WiFi,您就可以24/7全天候对安防系统进行监控。您可以在网站上或通过Cayenne手机应用程序进行监控。您可以在智能手机上直接下载Cayenne应用程序。进入App Store(应用商店,适用于iPhone)或Google Play商店(适用于Android)并搜索Cayenne然后就能下载。
成功安装应用程序后,应用程序图标会显示在主屏幕上。
单击应用程序图标并登录myDevices帐户(电子邮件ID和密码应与上一次设置帐户时相同)。登录后,您将看到您创建的微件。现在单击在线/应用程序切换微件就可以打开/关闭警报;警报开/关状态颜色变为绿色,如下图所示:
恭喜您!完整的系统已经建立!每当触发警报时,您将收到电子邮件通知。
这是一个包含多个模块的有趣项目。将来还可以添加更多传感器并增加其他功能和多个蜂鸣器,以使哔哔声更大。我们还可以考虑通过更换一些组件来缩小系统规模。在此之前,尽情享受吧!