ESP32など

電子工作してます

Grove接続でTimer Cameraで撮影した画像をM5StackのLCDに表示する

概要

  • Timer Camera F/X、Unit Camなどで画像を撮影したものを、リアルタイム(一応動画っぽく)でM5Stackの画面に表示する。
  • 送信側、受信側どちらもArduino IDEで作成。
  • 撮影したjpegファイルデータのバイト列をシリアル通信(Grove接続)でそのまま渡す。
    • 同期取るために区切り文字の設定必要。
    • 送信側はjpegを撮影するごとに送信、受信側はjpegを受信するごとに表示。
  • 表示速度は遅い。シリアル通信なので、115200bps = 115.2kbps、画面表示の遅さも影響して4fps=4フレーム/1秒くらい。

Timer CameraとM5Stack

コード

送信側:Timer Camera / Unit Cam
#include "esp_camera.h"

void setup() {

  // USBシリアル通信(確認用)
  Serial.begin(115200);

  // GROVEのシリアル通信
  Serial1.begin(115200, SERIAL_8N1, 13, 4); // Timer Camera / Unit Cam

  // カメラ用パラメータ(Timer Camera / Unit Cam)
  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer   = LEDC_TIMER_0;
  config.pin_d0       = 32;
  config.pin_d1       = 35;
  config.pin_d2       = 34;
  config.pin_d3       = 5;
  config.pin_d4       = 39;
  config.pin_d5       = 18;
  config.pin_d6       = 36;
  config.pin_d7       = 19;
  config.pin_xclk     = 27;
  config.pin_pclk     = 21;
  config.pin_vsync    = 22;
  config.pin_href     = 26;
  config.pin_sccb_sda = 25;
  config.pin_sccb_scl = 23;
  config.pin_pwdn     = -1;
  config.pin_reset    = 15;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG; // jpeg出力
  config.frame_size   = FRAMESIZE_QVGA; // 320x240
  config.jpeg_quality = 30; // jpeg品質 0(高品質)~63(低品質)
  config.fb_count     = 2; // CAMERA_GRAB_LATEST設定時は2以上必要
  config.grab_mode    = CAMERA_GRAB_LATEST; // 最終フレームバッファだけを取得
  config.fb_location  = CAMERA_FB_IN_PSRAM; // PSRAM使用する(Timer Camera用)
//  config.fb_location  = CAMERA_FB_IN_DRAM; // PSRAM使用しない(Unit Cam用)

  // カメラ初期化
  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();
  s->set_vflip(s, 1);
}

void loop() {

  // 画像取得&送信
  camera_fb_t *fb = esp_camera_fb_get();
  if (fb) {

    // データ区切り用文字列(DATA)
    Serial1.print("DATA");

    // サイズ送信
    Serial1.write((byte *)&(fb->len), 4); // size_t(int) -> byte[4]で送信

    // データ送信
    Serial1.write(fb->buf, fb->len);

    // フレームバッファ開放
    esp_camera_fb_return(fb);
  }
}

受信側:M5Stack
#include <M5Stack.h>

uint8_t buf[10000];
size_t data_size;

void setup() {

  M5.begin();

  // USBシリアル通信(確認用)
  Serial.begin(115200);

  // GROVEのシリアル通信
  Serial1.begin(115200, SERIAL_8N1, 21, 22); // PORT-A(Red)(GPIO21, GPIO22)
}

void loop() {

  // データ区切り用文字列(DATA)
  if (Serial1.available() > 4){
    if (Serial1.read() == 'D') {
      if (Serial1.read() == 'A') {
        if (Serial1.read() == 'T') {
          if (Serial1.read() == 'A') {
            
            // サイズ取得
            Serial1.readBytes(buf, 4);
            data_size = buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24 ; // byte[4] -> size_t(int)

            // データ取得
            Serial1.readBytes(buf, data_size);

            // 画面表示
            M5.Lcd.drawJpg(buf, data_size, 0, 0, 320, 240);
          }
        }
      }
    }
  }

結果

  • 結構簡単なコードでできました。やっぱ遅いけど。
  • 早くするならWifi / Bluetoothなど使ったほうがいい。
    Timer CameraとM5Stackでの撮影