空間活動偵測 -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"






留言

這個網誌中的熱門文章

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

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

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

python pyautogui 簡介

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