空間活動偵測 -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"
留言
張貼留言