空間活動偵測 -1 arduino
我想做一個能夠及時通知家中發生異狀的系統
研究結果
用Arduino接收感測器資料,定時傳送資料人體紅外線資料,及即時傳送開關門資料,再用google apps script 做資料交換與分析,將arduino傳送過來的資料存入google試算表,由試算表做圖表繪製,再由apps script 定時推播圖表訊息,以及分析內容推播異常或警告訊息。研究過程
一開始想用自己架設的伺服器存資料,用raspberry pi安裝apache + mysql + phpMyAdmin,但因為網路IP位置是浮動的關係,資料無法從外部傳回進伺服器,只能做本地端的資料傳輸,如果單使用arduino上傳資料到google試算表,又因為arduino uno3無網路連線加密的問題無法傳輸資料。之後找到國外的伺服器能做資料交換,加上用google的試算表做簡單的資料庫儲存,所以最後是用arduino接收感測器資訊,傳輸到資料交換伺服器再到google,由apps script 接收資料及填入試算表,完成了資料接收的問題。
硬體:使用arduino uno3 + 乙太網路擴充板 + 自己做的電路板
連接的感測器:
- 人體紅外線感測器
- 門窗的磁簧開關


#include <Dhcp.h>
#include <Dns.h>
#include <Ethernet.h>
#include <EthernetClient.h>
#include <EthernetServer.h>
#include <EthernetUdp.h>
//#include "net_function.cpp"
#include "set_ID.h"
#define PushingBox
unsigned char hour = 0, minute = 0;
boolean push_man_check;
String URL_data;
#define ReedS0_pin 2
#define ReedS1_pin 3
#define ReedS2_pin 4
#define ReedS3_pin 5
#define ReedS4_pin 6
#define ReedS5_pin 7
#define man0_pin 8
#define man1_pin 9
#define man2_pin A5
#define man3_pin A4
#define man4_pin A3
#define man5_pin A2
#define ReedS_number 5 //6個(0~5)
#define man_number 5 //6個(0~1)
#if defined( PushingBox )
//byte mac[] = { 0x00, 0xAB, 0xBC, 0xCD, 0xDE, 0x00 };
char server[] = "api.pushingbox.com";
String strGet = "GET /pushingbox?devid=";
String strHttp = " HTTP/1.1";
String strHost = "Host: api.pushingbox.com"; //OK
int serverPort = 80;
char ReedS[] = { 0, 0, 0, 0, 0, 0};//ReedS = Reed Switch 磁簧開關
char oReedS[] = { 0, 0, 0, 0, 0, 0};//oReedS 過去的狀態, ReedS 現在的狀態
int man[] = { 0, 0, 0, 0, 0, 0};
#endif
EthernetClient client;
boolean conn; // Connected
//DeviceAddress insideThermometer;
unsigned long startime = 0;
//------------------------------------------------------------------------------------------
//串接URL
void getdata(String *data, String ID, String kind) {
*data = strGet;
*data += ID;
*data += "&board=";
*data += board;
if (kind == gettime_ID) {
*data += "&information=";
*data += "時間";
}
if (kind == push_RS_ID || kind == push_human_ID || kind == pushnotif_ID) {
*data += "&time=";
*data += (int)hour;
*data += ':';
if(minute<=9){
*data += "0";
}
*data += (int)minute;
}
if (kind == push_RS_ID) {
*data += "&RS0=";
*data += (int)ReedS[0];
*data += "&RS1=";
*data += (int)ReedS[1];
*data += "&RS2=";
*data += (int)ReedS[2];
*data += "&RS3=";
*data += (int)ReedS[3];
*data += "&RS4=";
*data += (int)ReedS[4];
*data += "&RS5=";
*data += (int)ReedS[5];
}
if (kind == push_human_ID) {
*data += "&man0=";
*data += man[0];
*data += "&man1=";
*data += man[1];
*data += "&man2=";
*data += man[2];
*data += "&man3=";
*data += man[3];
*data += "&man4=";
*data += man[4];
*data += "&man5=";
*data += man[5];
}
if (kind == pushnotif_ID) {
*data += "&title=";
*data += "活動情況";
*data += "&message=";
if (ReedS[0] == 1) {
*data += "門_開啟";
}
else {
*data += "門_關閉";
}
}
*data += strHttp;
Serial.print("URL: ");
Serial.println(*data);
}
//push URL data to 網路
bool connect_pushdata(String *push_URL, String *host) {
Serial.println("connect server --->");
if (client.connect(server, serverPort)) {
Serial.println("Make a HTTP request ... ");
conn = true;
client.println(*push_URL);
client.println(*host);
client.println( "Connection: close" );
client.println();
return true;
}
else {
Serial.println("Can not connect server ---X---");
return false;
}
}
//網路回復
void netword_request() {
int ln = 0;
int count = 0;
char date_str[40]=" ";
while (conn) {
if (client.available()) {
char c = client.read(); // Save http header to c
Serial.print(c); // Print http header to serial monitor
if (c == '\n') {
ln++;
// Serial.print("ln count: ");
// Serial.println(ln);
}
if (ln == 2) {
date_str[count++] = c;
}
}
if (!client.connected()) {
Serial.println("disconnecting...");
client.stop();
URL_data = "";
conn = false;
ln = 0;
count = 0;
Serial.print("seriver date: ");
for (char i = 1; i < 40; i++) {
Serial.print(date_str[i]);
}
Serial.print("\n");
if(((date_str[24] - '0') * 10 + (date_str[25] - '0')) >= 0 && ((date_str[24] - '0') * 10 + (date_str[25] - '0')) <= 23 &&
((date_str[27] - '0') * 10 + (date_str[28] - '0')) >= 0 && ((date_str[27] - '0') * 10 + (date_str[28] - '0')) <= 59)
{
hour = (date_str[24] - '0') * 10 + (date_str[25] - '0') + 8;
if (hour >= 24) {
hour -= 24;
}
minute = (date_str[27] - '0') * 10 + (date_str[28] - '0');
}
Serial.print("time ");
Serial.print((int)hour);
Serial.print(":");
Serial.println((int)minute);
}
}
}
//網路設定
void net_init() {
char in = "";
byte mac[] = { 0x00, 0xAB, 0xBC, 0xCD, 0xDE, 0x00 };
//Init Net
Serial.print("DHCP: ");
//Ethernet.begin(mac, ip, mydns);
if (Ethernet.begin(mac) == 0) {
Serial.println("FAIL");
while (Ethernet.begin(mac) == 0){
if (Serial.available() > 0) {
in=Serial.read();
if(in == 's'){
Serial.println("skip DHCP");
break;
}
}
}
Serial.print("DHCP: ");
}
if(in != 's'){
Serial.println("OK");
Serial.print("Local IP : ");
Serial.println(Ethernet.localIP());
}
}
void dotime() {
//add one minute 60000=60*1000ms=1m
if ((millis() - startime) >= (60000) || (millis() - startime) < 0) {
startime = millis();
minute++;
if (minute >= 60) {
minute -= 60;
hour++;
if (hour >= 24) {
hour -= 24;
}
}
}
}
//需要先跑第一次的程式
void first_run() {
getdata(&URL_data, gettime_ID, gettime_ID);
while(!connect_pushdata(&URL_data, &strHost));
netword_request();//網路回復
for (char i = 0; i <= ReedS_number; i++) {
ReedS[i] = digitalRead(ReedS0_pin + i);
oReedS[i] = ReedS[i];
}
}
//===========================================================================================
void setup(void)
{
// start serial port
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
Serial.println(star_information);
Serial.println("wait DHCP:FAIL input s to skip DHCP");
Serial.println("test send to input r send Reed Switch, m send human, n send notification");
pinMode(4, OUTPUT);
digitalWrite(4,HIGH);
pinMode(ReedS0_pin, INPUT);
pinMode(ReedS1_pin, INPUT);
//pinMode(ReedS2_pin, INPUT);
pinMode(ReedS3_pin, INPUT);
pinMode(ReedS4_pin, INPUT);
pinMode(ReedS5_pin, INPUT);
pinMode(man0_pin, INPUT);
pinMode(man1_pin, INPUT);
net_init();
//delay(3000);
/* dht.begin();
Serial.println("DHTxx OK!");*/
startime = millis();
first_run();
}
void loop(void)
{
dotime();
//讀ReedS
for (char i = 0; i <= ReedS_number; i++) {
ReedS[i] = digitalRead(ReedS0_pin + i);
}
//讀man
//man[0]=digitalRead(man0_pin);
if (digitalRead(man0_pin) == 1) {
man[0] += 1;
}
if (digitalRead(man1_pin) == 1) {
man[1] += 1;
}
if (digitalRead(man2_pin) == 1) {
man[2] += 1;
}
if (digitalRead(man3_pin) == 1) {
man[3] += 1;
}
if (digitalRead(man4_pin) == 1) {
man[4] += 1;
}
if (digitalRead(man5_pin) == 1) {
man[5] += 1;
}
Serial.print("ReedS: ");
for (char i = 0; i <= ReedS_number; i++) {
Serial.print((int)ReedS[i]);
Serial.print(" ");
}
Serial.print("man: ");
for (char i = 0; i <= man_number; i++) {
Serial.print(man[i]);
Serial.print(" ");
}
Serial.println();
//手動push
if (Serial.available() > 0) {
char in=Serial.read();
if(in=='r'){
getdata(&URL_data, push_RS_ID, push_RS_ID);
connect_pushdata(&URL_data, &strHost);
netword_request();//網路回復
}else if(in=='m'){
getdata(&URL_data, push_human_ID, push_human_ID);
connect_pushdata(&URL_data, &strHost);
netword_request();//網路回復
}else if(in=='n'){
getdata(&URL_data, pushnotif_ID, pushnotif_ID);
connect_pushdata(&URL_data, &strHost);
netword_request();//網路回復
}else{
//in=Serial.read();
}
}
//如果ReedS通知
if (ReedS[0] != oReedS[0]) {
getdata(&URL_data, pushnotif_ID, pushnotif_ID);
if(!connect_pushdata(&URL_data, &strHost)){
connect_pushdata(&URL_data, &strHost);
}
netword_request();//網路回復
}
//如果ReedS有變化 push data
if ((ReedS[0] != oReedS[0]) || (ReedS[1] != oReedS[1]) || (ReedS[2] != oReedS[2]) || (ReedS[3] != oReedS[3]) || (ReedS[4] != oReedS[4]) || (ReedS[5] != oReedS[5])) {
getdata(&URL_data, push_RS_ID, push_RS_ID);
connect_pushdata(&URL_data, &strHost);
netword_request();//網路回復
for (char i = 0; i <= ReedS_number; i++) {
oReedS[i] = ReedS[i];
}
}
//每15分鐘push man
if (minute == 0 || minute == 15 || minute == 30 || minute == 45) {
if (!push_man_check) {
getdata(&URL_data, push_human_ID, push_human_ID);
connect_pushdata(&URL_data, &strHost);
netword_request();//網路回復
for (char i = 0; i <= man_number; i++) {
man[i] = 0;
}
push_man_check = true;
}
}
//清除每15分鐘已通知標籤
if ((minute > 1 && minute < 14) || (minute > 16 && minute < 29) || (minute > 31 && minute < 44) || (minute > 46 && minute < 59)) {
push_man_check = false;
}
//netword_request();//網路回復
delay(2000);
}
跟pushingbox連線的ID分別有這些#define star_information "test Model" #define push_RS_ID "vxxxxxxxxxxxxxxx" #define push_human_ID "vyyyyyyyyyyyyyyy" #define pushnotif_ID "vzzzzzzzzzzzzzzz" #define gettime_ID "vaaaaaaaaaaaaaaa" //m //#define gettime_ID "vbbbbbbbbbbbbbbb" #define board "1"

留言
張貼留言