編集履歴一覧に戻る
syouwa-taroのアイコン画像

syouwa-taro が 2022年10月10日22時24分34秒 に編集

初版

タイトルの変更

+

レーダーによる園児置き去り防止実験2 写真を撮りLINEで通報

タグの変更

+

置き去り防止

+

レーダー

+

LINENotify

+

ESP32Cam

記事種類の変更

+

製作品

ライセンスの変更

+

(Apache-2.0) Apache License 2.0

本文の変更

+

### 概要 前回ドップラーレーダーで人の動きを計測し、ネットでAmbientにデータを送り時系列で車内温度、動きが見える実験を行ったが緊急時関係者に通報する方法として「データー確認通報サービス」があったが有料で馴染みづらかった。 今回LINENotifyにより、動き検出すると写真を撮りLINE通報する仕組みを作った。写真により車内状況がより正確に伝わり、レーダーにより万一シートで隠れていても電波がシートを通し動きを検出しカメラや感熱センサだけよりも見逃しが防げる。 ### 動作 RCWL_0516レーダー基板により動きがあるとドップラー信号波形が変化し、この波形をPro_Micro のAD入力で読み込み変化量を計算し一定の変化量を検出するとMOVEOUTに出力(動きあり:1 動きなし:0) ESP32Camはこの出力を読み、動きがあると、写真を撮りLINE NotifyによりLINE通報する。着信音でLINEを受け取るとメッセージと写真が表示され緊急通報が行われる。 本実験ソフトでは電源を入れると一度確認用の試し撮り+LINE通報を行う。それ以降は動きがあるとLINE通報する。ただし一度写真を送ると次の写真は75秒以降になる:LINENotify仕様。 ### 主な部品 | 部品 | 備考 | |:---|:- | | ESP32Cam | ESP32にカメラが付いた(¥800~ ) LINE Notifyにより写真を撮りWifiでLINE通報。Wifi起動するとアナログが読めずADマイコン追加して対応 | |Pro_Micro| 3.3V/8M レーダーのドップラー波形を読み変化量を計算し動き判定。5V/16M品もある。**SparkFunでなくArduinoLeonard環境でもコンパイルできるが、転送ソフトが書き替えられ使えなくなることがあるようです。** |RCWL_0516| ドップラーレーダー 4V~28V 3.2G 到達距離5~7m  @¥100~安価であるが、**バラツキでかなり感度の悪い物もあった。**ドップラー信号波形は改造して**IC12pin(2out)から取り出す** |Buzzer|車内から外部へのAlarmを発信する。実験ではうるさいのでLEDなどが良いです。 ### 回路図 ![キャプションを入力できます](https://camo.elchika.com/21bfce01a42180e513acf0f84142c1f7d396c897/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38376461636366622d643365352d343236642d386436312d3538383537333535363238662f37396533646230322d306536382d346563332d626362392d366530386431343039656330/) @[youtube](https://www.youtube.com/watch?v=qU2a4FG-T0E) ### 考察 LINE通報するとき写真があることにより状況把握が確実にでき、有効な機能となることがわかります。 ドップラーレーダーによる検出は指向性が広く、シートも通過して動き検出し有効な方法と考えられます。 また車内温度情報は今回なかったが、より危険状況が把握でき有効な機能と考えられる(40℃車内で動きがあればかなり危険) ESP32はWifi使用時消費i電力が多く通報以外ではdeep sleep mode にし、動きのtriggerでwakeupさせるなどがよさそうです。 ### 参考にさせて頂いた記事 [ESP32-CAMでWebカメラの設定をしてみた](https://shigeru-orikura.com/2020/05/09/esp32-cam_setting/) [ESP32-CAM_Linenotify.ino](uhttps://github.com/fustyles/Arduino/blob/master/ESP32-CAM_Linenotify/ESP32-CAM_Linenotify.inorl) [LINEに写真を送る防犯カメラ](http://www.asahi-net.or.jp/~rn8t-nkmr/family/pic/sc/index.html) [RCWL-0516マイクロ波レーダーセンサーを使ってみる](http://7ujm.net/micro/rcwl.html) [(Arduino) Pro Micro に関する記事です](https://ht-deko.com/arduino/promicro.html) [ESP32のGPIO入力について](https://lang-ship.com/blog/work/esp32-gpio-input/) ```arduino:Pro_Micro const int PIN_RADAR = 20; //A2:20pin A3:21pin const int PIN_MOVOUT = 9; //A9:9pin int r = 0; int rr = 0 ; int rs = 0; int rrs = 0; //radar 差分積算計算 void setup() { //pinMode pinMode(PIN_RADAR,INPUT); //Radar analog 入力 pinMode(PIN_MOVOUT,OUTPUT); //MOVOUT 出力 Serial.begin(115200); } void loop() { int i; int s; int rrs=rs; int RSDS=0; //init for(i=0; i<100; i++ ) { //5sec動き積算 RSDS 45ms X 100 =4.5sec //********radar値積算 = ∑r/10 (300回)/45ms合計******** rs = 0; //rs init for ( s = 0; s < 300; s++) //rsum init { r = analogRead(PIN_RADAR); rs = r/10 + rs; } // Serial.println(rs); //****rs差分積算 = RSDS **** if (abs(rs-rrs) > 1000) //1000以下はノイズ 關地設定 { RSDS = abs(rs-rrs)-1000 + RSDS; //Serial.println(r-rr); if (RSDS > 10000) RSDS=10000; //30000以上計算不可 } rrs = rs; //**************radar Alarm 積算値R閾値設定 if (RSDS > 100 ) digitalWrite(PIN_MOVOUT,HIGH); else digitalWrite(PIN_MOVOUT,LOW); Serial.println(RSDS); } } ``` ```arduino:ESP32Cam /* ESP32-CAM (Save a captured photo to Line Notify) Author : ChungYi Fu (Kaohsiung, Taiwan) 2021-7-4 13:30 https://www.facebook.com/francefu You could only send up to 50 images to Line Notify in one hour. The maximum size of post-upload image is XGA(1024*768). MOVIN IO12= HIGH になると写真を撮りLINEに送信 次の写真は72秒以上必要 */ // Enter your WiFi ssid and password const char* ssid = "-------------"; //***********your network SSID************** const char* password = "-------------"; //***********your network password********** const int PIN_RADAR = 12; //MOVE IN String lineNotifyToken = "----------------"; //********your Line Notify Token************ #include <WiFi.h> #include <WiFiClientSecure.h> #include "soc/soc.h" //用於電源不穩不重開機 #include "soc/rtc_cntl_reg.h" //用於電源不穩不重開機 #include "esp_camera.h" //視訊函式 //ESP32-CAM 安信可模組腳位設定 #define PWDN_GPIO_NUM 32 #define RESET_GPIO_NUM -1 #define XCLK_GPIO_NUM 0 #define SIOD_GPIO_NUM 26 #define SIOC_GPIO_NUM 27 #define Y9_GPIO_NUM 35 #define Y8_GPIO_NUM 34 #define Y7_GPIO_NUM 39 #define Y6_GPIO_NUM 36 #define Y5_GPIO_NUM 21 #define Y4_GPIO_NUM 19 #define Y3_GPIO_NUM 18 #define Y2_GPIO_NUM 5 #define VSYNC_GPIO_NUM 25 #define HREF_GPIO_NUM 23 #define PCLK_GPIO_NUM 22 void setup() { WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //關閉電源不穩就重開機的設定 pinMode(PIN_RADAR,INPUT); //Radar入力 Serial.begin(115200); Serial.setDebugOutput(true); //開啟診斷輸出 Serial.println(); //視訊組態設定 https://github.com/espressif/esp32-camera/blob/master/driver/include/esp_camera.h camera_config_t config; config.ledc_channel = LEDC_CHANNEL_0; config.ledc_timer = LEDC_TIMER_0; config.pin_d0 = Y2_GPIO_NUM; config.pin_d1 = Y3_GPIO_NUM; config.pin_d2 = Y4_GPIO_NUM; config.pin_d3 = Y5_GPIO_NUM; config.pin_d4 = Y6_GPIO_NUM; config.pin_d5 = Y7_GPIO_NUM; config.pin_d6 = Y8_GPIO_NUM; config.pin_d7 = Y9_GPIO_NUM; config.pin_xclk = XCLK_GPIO_NUM; config.pin_pclk = PCLK_GPIO_NUM; config.pin_vsync = VSYNC_GPIO_NUM; config.pin_href = HREF_GPIO_NUM; config.pin_sscb_sda = SIOD_GPIO_NUM; config.pin_sscb_scl = SIOC_GPIO_NUM; config.pin_pwdn = PWDN_GPIO_NUM; config.pin_reset = RESET_GPIO_NUM; config.xclk_freq_hz = 20000000; config.pixel_format = PIXFORMAT_JPEG; // // WARNING!!! PSRAM IC required for UXGA resolution and high JPEG quality // Ensure ESP32 Wrover Module or other board with PSRAM is selected // Partial images will be transmitted if image exceeds buffer size // // if PSRAM IC present, init with UXGA resolution and higher JPEG quality // for larger pre-allocated frame buffer. if(psramFound()){ //是否有PSRAM(Psuedo SRAM)記憶體IC config.frame_size = FRAMESIZE_UXGA; config.jpeg_quality = 10; config.fb_count = 2; } else { config.frame_size = FRAMESIZE_SVGA; config.jpeg_quality = 12; config.fb_count = 1; } //視訊初始化 esp_err_t err = esp_camera_init(&config); if (err != ESP_OK) { Serial.printf("Camera init failed with error 0x%x", err); ESP.restart(); } //可自訂視訊框架預設大小(解析度大小) sensor_t * s = esp_camera_sensor_get(); // initial sensors are flipped vertically and colors are a bit saturated if (s->id.PID == OV3660_PID) { s->set_vflip(s, 1); // flip it back s->set_brightness(s, 1); // up the brightness just a bit s->set_saturation(s, -2); // lower the saturation } // drop down frame size for higher initial frame rate s->set_framesize(s, FRAMESIZE_SVGA); //解析度 UXGA(1600x1200), SXGA(1280x1024), XGA(1024x768), SVGA(800x600), VGA(640x480), CIF(400x296), QVGA(320x240), HQVGA(240x176), QQVGA(160x120), QXGA(2048x1564 for OV3660) //s->set_vflip(s, 1); //垂直翻轉 //s->set_hmirror(s, 1); //水平鏡像 //閃光燈(GPIO4) ledcAttachPin(4, 4); ledcSetup(4, 5000, 8); WiFi.mode(WIFI_AP_STA); //其他模式 WiFi.mode(WIFI_AP); WiFi.mode(WIFI_STA); //指定Client端靜態IP //WiFi.config(IPAddress(192, 168, 201, 100), IPAddress(192, 168, 201, 2), IPAddress(255, 255, 255, 0)); for (int i=0;i<2;i++) { WiFi.begin(ssid, password); //執行網路連線 delay(1000); Serial.println(""); Serial.print("Connecting to "); Serial.println(ssid); long int StartTime=millis(); while (WiFi.status() != WL_CONNECTED) { delay(500); if ((StartTime+5000) < millis()) break; //等待10秒連線 } if (WiFi.status() == WL_CONNECTED) { //若連線成功 Serial.println(""); Serial.println("STAIP address: "); Serial.println(WiFi.localIP()); Serial.println(""); for (int i=0;i<5;i++) { //flash light 若連上WIFI設定閃光燈快速閃爍 ledcWrite(4,10); delay(200); ledcWrite(4,0); delay(200); } break; } } if (WiFi.status() != WL_CONNECTED) { //若連線失敗 for (int i=0;i<2;i++) { //若連不上WIFI設定閃光燈慢速閃爍 ledcWrite(4,10); delay(1000); ledcWrite(4,0); delay(1000); } ESP.restart(); } //設定閃光燈為低電位 pinMode(4, OUTPUT); digitalWrite(4, LOW); //傳送影像 Serial.println(sendCapturedImage2LineNotify(lineNotifyToken)); } void loop() { if (digitalRead(PIN_RADAR ) == 1) { ledcWrite(4,10); Serial.println(sendCapturedImage2LineNotify(lineNotifyToken)); ledcWrite(4,0); delay(72000); //You could only send up to 50 images to Line Notify in one hour. } } String sendCapturedImage2LineNotify(String token) { camera_fb_t * fb = NULL; fb = esp_camera_fb_get(); if(!fb) { Serial.println("Camera capture failed"); delay(1000); ESP.restart(); return "Camera capture failed"; } WiFiClientSecure client_tcp; client_tcp.setInsecure(); //run version 1.0.5 or above Serial.println("Connect to notify-api.line.me"); if (client_tcp.connect("notify-api.line.me", 443)) { Serial.println("Connection successful"); String message = "\nバス内で人の動きがありました"; String head = "--Taiwan\r\nContent-Disposition: form-data; name=\"message\"; \r\n\r\n" + message + "\r\n--Taiwan\r\nContent-Disposition: form-data; name=\"imageFile\"; filename=\"esp32-cam.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n"; String tail = "\r\n--Taiwan--\r\n"; uint16_t imageLen = fb->len; uint16_t extraLen = head.length() + tail.length(); uint16_t totalLen = imageLen + extraLen; client_tcp.println("POST /api/notify HTTP/1.1"); client_tcp.println("Connection: close"); client_tcp.println("Host: notify-api.line.me"); client_tcp.println("Authorization: Bearer " + token); client_tcp.println("Content-Length: " + String(totalLen)); client_tcp.println("Content-Type: multipart/form-data; boundary=Taiwan"); client_tcp.println(); client_tcp.print(head); uint8_t *fbBuf = fb->buf; size_t fbLen = fb->len; for (size_t n=0;n<fbLen;n=n+1024) { if (n+1024<fbLen) { client_tcp.write(fbBuf, 1024); fbBuf += 1024; } else if (fbLen%1024>0) { size_t remainder = fbLen%1024; client_tcp.write(fbBuf, remainder); } } client_tcp.print(tail); esp_camera_fb_return(fb); String getResponse="",Feedback=""; int waitTime = 10000; // timeout 10 seconds long startTime = millis(); boolean state = false; while ((startTime + waitTime) > millis()) { Serial.print("."); delay(100); while (client_tcp.available()) { char c = client_tcp.read(); if (state==true) Feedback += String(c); if (c == '\n') { if (getResponse.length()==0) state=true; getResponse = ""; } else if (c != '\r') getResponse += String(c); startTime = millis(); } if (Feedback.length()>0) break; } Serial.println(); client_tcp.stop(); return Feedback; } else { return "Connected to notify-api.line.me failed."; } } ```