空間活動偵測 -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 + 乙太網路擴充板 + 自己做的電路板
連接的感測器:
  • 人體紅外線感測器
  • 門窗的磁簧開關



  1. #include <Dhcp.h>
  2. #include <Dns.h>
  3. #include <Ethernet.h>
  4. #include <EthernetClient.h>
  5. #include <EthernetServer.h>
  6. #include <EthernetUdp.h>
  7. //#include "net_function.cpp"
  8. #include "set_ID.h"
  9. #define PushingBox
  10.  
  11. unsigned char hour = 0, minute = 0;
  12. boolean push_man_check;
  13. String URL_data;
  14. #define ReedS0_pin 2
  15. #define ReedS1_pin 3
  16. #define ReedS2_pin 4
  17. #define ReedS3_pin 5
  18. #define ReedS4_pin 6
  19. #define ReedS5_pin 7
  20. #define man0_pin 8
  21. #define man1_pin 9
  22. #define man2_pin A5
  23. #define man3_pin A4
  24. #define man4_pin A3
  25. #define man5_pin A2
  26. #define ReedS_number 5 //6個(0~5)
  27. #define man_number 5 //6個(0~1)
  28.  
  29. #if defined( PushingBox )
  30. //byte mac[] = { 0x00, 0xAB, 0xBC, 0xCD, 0xDE, 0x00 };
  31. char server[] = "api.pushingbox.com";
  32. String strGet = "GET /pushingbox?devid=";
  33. String strHttp = " HTTP/1.1";
  34. String strHost = "Host: api.pushingbox.com"; //OK
  35. int serverPort = 80;
  36.  
  37. char ReedS[] = { 0, 0, 0, 0, 0, 0};//ReedS = Reed Switch 磁簧開關
  38. char oReedS[] = { 0, 0, 0, 0, 0, 0};//oReedS 過去的狀態, ReedS 現在的狀態
  39. int man[] = { 0, 0, 0, 0, 0, 0};
  40.  
  41. #endif
  42.  
  43. EthernetClient client;
  44. boolean conn; // Connected
  45. //DeviceAddress insideThermometer;
  46. unsigned long startime = 0;
  47. //------------------------------------------------------------------------------------------
  48. //串接URL
  49. void getdata(String *data, String ID, String kind) {
  50. *data = strGet;
  51. *data += ID;
  52. *data += "&board=";
  53. *data += board;
  54.  
  55. if (kind == gettime_ID) {
  56. *data += "&information=";
  57. *data += "時間";
  58.  
  59. }
  60. if (kind == push_RS_ID || kind == push_human_ID || kind == pushnotif_ID) {
  61. *data += "&time=";
  62. *data += (int)hour;
  63. *data += ':';
  64. if(minute<=9){
  65. *data += "0";
  66. }
  67. *data += (int)minute;
  68. }
  69.  
  70. if (kind == push_RS_ID) {
  71. *data += "&RS0=";
  72. *data += (int)ReedS[0];
  73. *data += "&RS1=";
  74. *data += (int)ReedS[1];
  75. *data += "&RS2=";
  76. *data += (int)ReedS[2];
  77. *data += "&RS3=";
  78. *data += (int)ReedS[3];
  79. *data += "&RS4=";
  80. *data += (int)ReedS[4];
  81. *data += "&RS5=";
  82. *data += (int)ReedS[5];
  83. }
  84. if (kind == push_human_ID) {
  85. *data += "&man0=";
  86. *data += man[0];
  87. *data += "&man1=";
  88. *data += man[1];
  89. *data += "&man2=";
  90. *data += man[2];
  91. *data += "&man3=";
  92. *data += man[3];
  93. *data += "&man4=";
  94. *data += man[4];
  95. *data += "&man5=";
  96. *data += man[5];
  97. }
  98. if (kind == pushnotif_ID) {
  99. *data += "&title=";
  100. *data += "活動情況";
  101. *data += "&message=";
  102. if (ReedS[0] == 1) {
  103. *data += "門_開啟";
  104. }
  105. else {
  106. *data += "門_關閉";
  107. }
  108. }
  109.  
  110. *data += strHttp;
  111. Serial.print("URL: ");
  112. Serial.println(*data);
  113. }
  114. //push URL data to 網路
  115. bool connect_pushdata(String *push_URL, String *host) {
  116. Serial.println("connect server --->");
  117. if (client.connect(server, serverPort)) {
  118. Serial.println("Make a HTTP request ... ");
  119. conn = true;
  120. client.println(*push_URL);
  121. client.println(*host);
  122. client.println( "Connection: close" );
  123. client.println();
  124. return true;
  125. }
  126. else {
  127. Serial.println("Can not connect server ---X---");
  128. return false;
  129. }
  130. }
  131.  
  132.  
  133. //網路回復
  134. void netword_request() {
  135. int ln = 0;
  136. int count = 0;
  137. char date_str[40]=" ";
  138. while (conn) {
  139. if (client.available()) {
  140. char c = client.read(); // Save http header to c
  141. Serial.print(c); // Print http header to serial monitor
  142. if (c == '\n') {
  143. ln++;
  144. // Serial.print("ln count: ");
  145. // Serial.println(ln);
  146. }
  147. if (ln == 2) {
  148. date_str[count++] = c;
  149. }
  150. }
  151. if (!client.connected()) {
  152. Serial.println("disconnecting...");
  153. client.stop();
  154. URL_data = "";
  155. conn = false;
  156. ln = 0;
  157. count = 0;
  158. Serial.print("seriver date: ");
  159. for (char i = 1; i < 40; i++) {
  160. Serial.print(date_str[i]);
  161. }
  162. Serial.print("\n");
  163. if(((date_str[24] - '0') * 10 + (date_str[25] - '0')) >= 0 && ((date_str[24] - '0') * 10 + (date_str[25] - '0')) <= 23 &&
  164. ((date_str[27] - '0') * 10 + (date_str[28] - '0')) >= 0 && ((date_str[27] - '0') * 10 + (date_str[28] - '0')) <= 59)
  165. {
  166. hour = (date_str[24] - '0') * 10 + (date_str[25] - '0') + 8;
  167. if (hour >= 24) {
  168. hour -= 24;
  169. }
  170. minute = (date_str[27] - '0') * 10 + (date_str[28] - '0');
  171. }
  172. Serial.print("time ");
  173. Serial.print((int)hour);
  174. Serial.print(":");
  175. Serial.println((int)minute);
  176. }
  177. }
  178. }
  179. //網路設定
  180. void net_init() {
  181. char in = "";
  182. byte mac[] = { 0x00, 0xAB, 0xBC, 0xCD, 0xDE, 0x00 };
  183. //Init Net
  184. Serial.print("DHCP: ");
  185. //Ethernet.begin(mac, ip, mydns);
  186. if (Ethernet.begin(mac) == 0) {
  187. Serial.println("FAIL");
  188. while (Ethernet.begin(mac) == 0){
  189. if (Serial.available() > 0) {
  190. in=Serial.read();
  191. if(in == 's'){
  192. Serial.println("skip DHCP");
  193. break;
  194. }
  195. }
  196. }
  197. Serial.print("DHCP: ");
  198. }
  199. if(in != 's'){
  200. Serial.println("OK");
  201. Serial.print("Local IP : ");
  202. Serial.println(Ethernet.localIP());
  203. }
  204. }
  205. void dotime() {
  206. //add one minute 60000=60*1000ms=1m
  207. if ((millis() - startime) >= (60000) || (millis() - startime) < 0) {
  208. startime = millis();
  209. minute++;
  210. if (minute >= 60) {
  211. minute -= 60;
  212. hour++;
  213. if (hour >= 24) {
  214. hour -= 24;
  215. }
  216. }
  217. }
  218. }
  219. //需要先跑第一次的程式
  220. void first_run() {
  221. getdata(&URL_data, gettime_ID, gettime_ID);
  222. while(!connect_pushdata(&URL_data, &strHost));
  223. netword_request();//網路回復
  224. for (char i = 0; i <= ReedS_number; i++) {
  225. ReedS[i] = digitalRead(ReedS0_pin + i);
  226. oReedS[i] = ReedS[i];
  227. }
  228. }
  229. //===========================================================================================
  230. void setup(void)
  231. {
  232. // start serial port
  233. Serial.begin(9600);
  234. while (!Serial) {
  235. ; // wait for serial port to connect. Needed for Leonardo only
  236. }
  237. Serial.println(star_information);
  238. Serial.println("wait DHCP:FAIL input s to skip DHCP");
  239. Serial.println("test send to input r send Reed Switch, m send human, n send notification");
  240. pinMode(4, OUTPUT);
  241. digitalWrite(4,HIGH);
  242. pinMode(ReedS0_pin, INPUT);
  243. pinMode(ReedS1_pin, INPUT);
  244. //pinMode(ReedS2_pin, INPUT);
  245. pinMode(ReedS3_pin, INPUT);
  246. pinMode(ReedS4_pin, INPUT);
  247. pinMode(ReedS5_pin, INPUT);
  248. pinMode(man0_pin, INPUT);
  249. pinMode(man1_pin, INPUT);
  250.  
  251. net_init();
  252. //delay(3000);
  253. /* dht.begin();
  254. Serial.println("DHTxx OK!");*/
  255. startime = millis();
  256. first_run();
  257. }
  258.  
  259. void loop(void)
  260. {
  261. dotime();
  262. //讀ReedS
  263. for (char i = 0; i <= ReedS_number; i++) {
  264. ReedS[i] = digitalRead(ReedS0_pin + i);
  265. }
  266. //讀man
  267. //man[0]=digitalRead(man0_pin);
  268. if (digitalRead(man0_pin) == 1) {
  269. man[0] += 1;
  270. }
  271. if (digitalRead(man1_pin) == 1) {
  272. man[1] += 1;
  273. }
  274. if (digitalRead(man2_pin) == 1) {
  275. man[2] += 1;
  276. }
  277. if (digitalRead(man3_pin) == 1) {
  278. man[3] += 1;
  279. }
  280. if (digitalRead(man4_pin) == 1) {
  281. man[4] += 1;
  282. }
  283. if (digitalRead(man5_pin) == 1) {
  284. man[5] += 1;
  285. }
  286.  
  287. Serial.print("ReedS: ");
  288. for (char i = 0; i <= ReedS_number; i++) {
  289. Serial.print((int)ReedS[i]);
  290. Serial.print(" ");
  291. }
  292. Serial.print("man: ");
  293. for (char i = 0; i <= man_number; i++) {
  294. Serial.print(man[i]);
  295. Serial.print(" ");
  296. }
  297. Serial.println();
  298.  
  299. //手動push
  300. if (Serial.available() > 0) {
  301. char in=Serial.read();
  302. if(in=='r'){
  303. getdata(&URL_data, push_RS_ID, push_RS_ID);
  304. connect_pushdata(&URL_data, &strHost);
  305. netword_request();//網路回復
  306. }else if(in=='m'){
  307. getdata(&URL_data, push_human_ID, push_human_ID);
  308. connect_pushdata(&URL_data, &strHost);
  309. netword_request();//網路回復
  310. }else if(in=='n'){
  311. getdata(&URL_data, pushnotif_ID, pushnotif_ID);
  312. connect_pushdata(&URL_data, &strHost);
  313. netword_request();//網路回復
  314. }else{
  315. //in=Serial.read();
  316. }
  317. }
  318. //如果ReedS通知
  319. if (ReedS[0] != oReedS[0]) {
  320. getdata(&URL_data, pushnotif_ID, pushnotif_ID);
  321. if(!connect_pushdata(&URL_data, &strHost)){
  322. connect_pushdata(&URL_data, &strHost);
  323. }
  324. netword_request();//網路回復
  325. }
  326. //如果ReedS有變化 push data
  327. 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])) {
  328. getdata(&URL_data, push_RS_ID, push_RS_ID);
  329. connect_pushdata(&URL_data, &strHost);
  330. netword_request();//網路回復
  331. for (char i = 0; i <= ReedS_number; i++) {
  332. oReedS[i] = ReedS[i];
  333. }
  334. }
  335. //每15分鐘push man
  336. if (minute == 0 || minute == 15 || minute == 30 || minute == 45) {
  337. if (!push_man_check) {
  338. getdata(&URL_data, push_human_ID, push_human_ID);
  339. connect_pushdata(&URL_data, &strHost);
  340. netword_request();//網路回復
  341. for (char i = 0; i <= man_number; i++) {
  342. man[i] = 0;
  343. }
  344. push_man_check = true;
  345. }
  346. }
  347. //清除每15分鐘已通知標籤
  348. if ((minute > 1 && minute < 14) || (minute > 16 && minute < 29) || (minute > 31 && minute < 44) || (minute > 46 && minute < 59)) {
  349. push_man_check = false;
  350. }
  351.  
  352. //netword_request();//網路回復
  353. delay(2000);
  354. }
跟pushingbox連線的ID分別有這些
  1. #define star_information "test Model"
  2. #define push_RS_ID "vxxxxxxxxxxxxxxx"
  3. #define push_human_ID "vyyyyyyyyyyyyyyy"
  4. #define pushnotif_ID "vzzzzzzzzzzzzzzz"
  5. #define gettime_ID "vaaaaaaaaaaaaaaa" //m
  6. //#define gettime_ID "vbbbbbbbbbbbbbbb"
  7. #define board "1"






留言

這個網誌中的熱門文章

python nn 聲音辨識 -1 傅立葉轉換

android 定時通知(永久長期的) 本篇只講AlarmManager使用

C# 模擬鍵盤滑鼠控制電腦

raspberrypi 開機自動執行程式 與 在terminal開啟第二個terminal執行python

python pyautogui 簡介