Timer Camera Xで定点観測カメラを作る(その2)
前回からの続きです。
前回は以下の1、2を作ったので、今回は3を作ります。
- Node-REDでhttpで画像を送受信し、表示する環境を作る
- TimerCameraXで撮影した画像をPC上で確認する
- TimerCameraXからhttpでNode-REDに画像を送信する
- TimerCameraXをディープスリープさせて定期的に撮影するようにする
- AWS部分を作り、node-redから画像を送信する
- TimerCameraXとAWSをつなぐ
3. TimerCameraXからhttpでNode-REDに画像を送信する
撮影してbase64にしてシリアルモニタに表示するところまでは前回作ったので、今回はbase64のデータをhttp POSTします。
http post arduino
で検索します。
2番目に出てきたここが良さそうです。ちょうどNode-REDとやりとりするサンプルがあります。
http POSTの方法として以下の3通りがあるようです。
- URLに埋め込む
- JSONオブジェクトを送る
- プレーンテキストを送る
まずは一番簡単そうな3のプレーンテキストを試してみます。 これだけで送れそうですね。
#include <HTTPClient.h> http.begin(serverName); http.addHeader("Content-Type", "text/plain"); int httpResponseCode = http.POST("Hello, World!");
これの"Hello, World!"
の部分をbase64の文字列に置き換えれば行けちゃいそうなので試してみます。
serverNameにはNode-REDの画像受信のURLを入れます。
char *serverName = "http://192.168.0.16:1880/image";
ということで以下がコード全体です。前回printのために終端文字を入れていたのがここでもそのまま使えました。 printしていたbase64buffをそのままhttp.POSTしたらできちゃいました。
#include "esp_camera.h" #include <WiFi.h> #include <HTTPClient.h> #include <base64.hpp> #include "camera_pins.h" const char* ssid = ""; const char* password = ""; void setup() { Serial.begin(115200); Serial.setDebugOutput(true); Serial.println(); 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; config.frame_size = FRAMESIZE_UXGA; config.jpeg_quality = 10; config.fb_count = 2; // camera init esp_err_t err = esp_camera_init(&config); if (err != ESP_OK) { Serial.printf("Camera init failed with error 0x%x", err); return; } sensor_t * s = esp_camera_sensor_get(); //initial sensors are flipped vertically and colors are a bit saturated s->set_vflip(s, 1);//flip it back s->set_brightness(s, 1);//up the blightness 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_QVGA); if (ssid=="") WiFi.begin(); else WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); } void loop() { camera_fb_t *fb = esp_camera_fb_get(); if ( fb ) { Serial.printf("width: %d, height: %d, buf: 0x%x, len: %d\n", fb->width, fb->height, fb->buf, fb->len); unsigned int base64_length = encode_base64_length(fb->len); unsigned char *base64buff = new unsigned char[base64_length+1]; base64buff[base64_length] = '\0'; encode_base64(fb->buf, fb->len, base64buff); char *serverName = "http://192.168.0.16:1880/image"; HTTPClient http; http.begin(serverName); http.addHeader("Content-Type", "text/plain"); int httpResponseCode = http.POST(reinterpret_cast<char*>(base64buff)); Serial.printf("%d", httpResponseCode); delete [] base64buff; esp_camera_fb_return(fb); } delay(100); }
せっかくなのでカメラから送信してNode-REDのダッシュボードに表示した画面を貼ってみます。 Macではshift+command+5で範囲を指定したスクリーンキャプチャ動画が取れるみたいです。
範囲を指定して、キャプチャボタンを押したのですが、止め方がわからない・・・と思ったら、タッチバーに停止ボタンがありました。 撮影完了したらgif動画に変換します。 今後のことも考えてffmpegを入れておきます。 ちょうど以下のサイトにffmpegをインストールしてmovをgifに変換するサンプルがあったので、その通り実行してgif動画を作成します。
というわけで、今回の成果物です。 思ったより簡単にTimerCameraXから定期的に画像を送信することができました。
無事やりたいことに近づいています。 次回はTimerCameraの名前の通り、定期的にディープスリープして撮影する部分を試してみます。 電源周りは全くわかっていないので、できるかどうか、、、