04.M5Cameraで前回の変更


04.M5Cameraで前回の変更

前回のCameraWebServerをPCからの設定をせずスケッチで設定します。

ボードの設定

Arduino IDE > ツールは以下に設定(前回と同じです)
  • ボード:"ESP32 Wrover Module"
  • Upload Speed:"921600"
  • Flash Frequency:"80MHz"
  • Flash Mode:"QIO"
  • Partition Scheme:"Huge APP(3MB No OTA/1MB SPIFFS)"
  • Core Debug Level:"なし"
  • シリアルポート:"(確認したポート)"

操作方法

  1. M5Cameraにスケッチを書込みます。
  2. シリアルモニタに「'http://192.168.68.63'に接続してください。」と表示されると、PCから同URLを開きます。
  3. スケッチで全設定をしているので、PCではでシャッター(再読込み)のみです。

設定項目

スケッチでは以下の項目を設定しています。
  • config.frame_size = FRAMESIZE_UXGA; //(1600x1200=1.9M), SXGA(1280x1024=1.3M), XGA(1024x768=0.8M), SVGA(800x600=0.5M), VGA(640x480=0.3M), CIF(400x296=0.1M), QVGA(320x240=77k), HQVGA(240x176=42k), QQVGA(160x120=19k)
  • config.jpeg_quality = 10; //(0-63)小さいほど高品質
  • config.fb_count = 1; //複数の場合i2sは連続モード
  • s->set_brightness(s, 0); //明るさ(-2~2)
  • s->set_contrast(s, 2); //コントラスト(-2~2)
  • s->set_saturation(s, 2); //彩度(-2~2)2の方が鮮やか
  • s->set_special_effect(s, 0); //0=特殊効果なし,1=ネガ,2=白黒,3=赤,4=緑,5=青,6=茶
  • s->set_whitebal(s, 1); //?(0,1)
  • s->set_awb_gain(s, 1); //ホワイトバランス(0,1)
  • s->set_wb_mode(s, 0); //上記1の時(0=自動,1=晴れ,2=曇り,3=Office,4=家)
  • s->set_exposure_ctrl(s, 1); //自動露出1(0,1)
  • s->set_aec2(s, 1); //自動露出2(0,1)
  • s->set_ae_level(s, 0); //自動露出1が1の時、露出レベル(-2~2)
  • s->set_aec_value(s, 300); //露出(0-1200)
  • s->set_gain_ctrl(s, 1); //自動ゲイン制御(0,1)
  • s->set_agc_gain(s, 0); //ゲイン(0-30)
  • s->set_gainceiling(s, (gainceiling_t)0); //ゲイン(0-6)
  • s->set_bpc(s, 0); //?(0,1)
  • s->set_wpc(s, 1); //?(0,1)
  • s->set_raw_gma(s, 1); //?(0,1)
  • s->set_lenc(s, 1); //レンズ補正(0,1)
  • s->set_hmirror(s, 0); //左右反転(0,1)
  • s->set_vflip(s, 0); //180°回転(0,1)
  • s->set_dcw(s, 1); //?(0,1)
  • s->set_colorbar(s, 0); //カラーバー表示(0=off,1=on)

変更箇所

前回のスケッチからの変更内容です。

1.camera_pins.h

各カメラモデルのpin定義ファイルです。5Cameraの「CAMERA_MODEL_M5STACK_V2_PSRAM」以外を削除してinoファイルへ移動し、このファイルは削除しました。

2.CameraWebServer.ino

CAMERA_MODEL_M5STACK_V2_PSRAM以外や、PSRAMなしや、OV3660の場合の処理を削除しました。app_httpd.cppを修正後にここへ移動しました。

3.camera_index.h

ファイルには、2つのデータがあり、両方ともindex_handler()から呼び出しています。
  • index_ov2640_html_gz[]
    #define index_ov2640_html_gz_len 4316
  • index_ov3660_html_gz[]
    #define index_ov3660_html_gz_len 4408
htmlのメニュー表示でgz形式で圧縮されています。このファイルは削除しました。

4.app_httpd.cpp

まず、ov36600を削除します。

使用している関数は、以下でした。
  • startCameraServer()
    [ここから開始]
    CameraWebServer.inoで呼出し
  • ra_filter_init()
    [RAフィルター初期化]
    startCameraServer()で呼び出し
  • startCameraServer()で呼出し
    • capture_handler()
      [キャプチャハンドラ]
    • stream_handler()
      [ストリームハンドラ]
    • cmd_handler()
      [cmdハンドラ]
    • status_handler()
      [ステータスハンドラ]
    • index_handler()
      [インデックスハンドラ]
  • ra_filter_run()
    [RAフィルター実行]
    stream_handler()で呼出し
  • draw_face_boxes()
    [フェイスボックスを描く]
    capture_handler() と stream_handler()で呼出し
  • run_face_recognition()
    [顔認識実行]
    capture_handler() と stream_handler()で呼出し
  • jpg_encode_stream()
    [jpgエンコードストリーム]
    capture_handler()で呼出し
  • rgb_print()
    [RGBをprintする]
    rgb_printf() と run_face_recognition()で呼出し
  • rgb_printf()
    [RGBのprintf]
    run_face_recognition()で呼出し
HTTP ServerのAPI Referenceを読んでもよくわかりませんでした。
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/protocols/esp_http_server.html

webをいろいろ検索し参考にして修正し、inoファイルに移動しました。

スケッチ

2ケ所のxxxxxには自分のwifiのssidと、そのpasswordを記入します。

// M5Cameraで撮影し、シリアルモニタに表示されたURLをPCで写真表示
// このスケッチで設定をして、PCではでシャッター(再読込み)のみ
#include <WiFi.h>            // wifi
#include <esp_http_server.h> // ESP32用軽量Webサーバー
#include <esp_camera.h>      // ESPの標準カメラライブラリ
#include <Arduino.h>         // Arduino
//CAMERA_MODEL_M5STACK_V2_PSRAM(M5Camera verB)の場合
#define PWDN_GPIO_NUM     -1
#define RESET_GPIO_NUM    15  // pin番号
#define XCLK_GPIO_NUM     27
#define SIOD_GPIO_NUM     22
#define SIOC_GPIO_NUM     23
#define Y9_GPIO_NUM       19
#define Y8_GPIO_NUM       36
#define Y7_GPIO_NUM       18
#define Y6_GPIO_NUM       39
#define Y5_GPIO_NUM        5
#define Y4_GPIO_NUM       34
#define Y3_GPIO_NUM       35
#define Y2_GPIO_NUM       32
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     26
#define PCLK_GPIO_NUM     21
const char* ssid = "xxxxx";         // 自分のSSID
const char* password = "xxxxx";     // そのパスワード
httpd_handle_t camera_httpd = NULL; //

static esp_err_t capture_handler(httpd_req_t *req) {  //
  camera_fb_t * fb = NULL;            // バッファのクリア
  esp_err_t res = ESP_OK;             // resの初期値
  fb = esp_camera_fb_get();           // 画像の取込み
  if (!fb) {                          // データが無い場合
    Serial.println("失敗 キャプチャ");  // シリアルモニタに表示
    httpd_resp_send_500(req);         // HTTP500のヘルパー関数
    return ESP_FAIL;
  }
  httpd_resp_set_type(req, "image/jpeg");  // HTTPコンテンツタイプ設定API
  Serial.print("幅=");                     // シリアルモニタに表示
  Serial.println(fb->width);               // シリアルモニタに表示
  res = httpd_resp_send(req, (const char *)fb->buf, fb->len); //完全なHTTP応答を送信するためのAPI
  esp_camera_fb_return(fb); //esp_camera_fb_get()で割当てたメモリを解放
  return res;
}

void startCameraServer() {
  httpd_config_t config = HTTPD_DEFAULT_CONFIG();  //
  httpd_uri_t capture_uri = {                      //
    .uri       = "/",                              //
    .method    = HTTP_GET,                         //
    .handler   = capture_handler,                  // 関数へ
    .user_ctx  = NULL                              //
  };
  if (httpd_start(&camera_httpd, &config) == ESP_OK) {      //Webサーバーを起動
    httpd_register_uri_handler(camera_httpd, &capture_uri); //URIハンドラーを登録
  }
}

void setup() {
  Serial.begin(115200);    // シリアル通信のbpsを指定
  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;         // 20MHz
  config.pixel_format = PIXFORMAT_JPEG;
  config.frame_size = FRAMESIZE_UXGA;  // 1600x1200
  config.jpeg_quality = 10;          // (0-63)小さいほど高品質
  config.fb_count = 1;   // 複数の場合i2sは連続モード,JPEGで使用

  esp_err_t err = esp_camera_init(&config); // カメラ初期化
  if (err != ESP_OK) {                      // エラーの場合
    Serial.printf("エラー カメラ初期化 0x%x", err); // シリアルモニタに表示
    return;
  }

  sensor_t * s = esp_camera_sensor_get();  // センサーの構造体へのポインタ取得
  s->set_brightness(s, 0);     // 明るさ(-2~2)
  s->set_contrast(s, 2);       // コントラスト(-2~2)
  s->set_saturation(s, 2);     // 彩度(-2~2)
  s->set_special_effect(s, 0); // (0:特殊効果なし,1:ネガ,2:白黒,3:赤,4:緑,5:青,6:茶)
  s->set_whitebal(s, 1);       // ?(0,1)
  s->set_awb_gain(s, 1);       // ホワイトバランス(0,1)
  s->set_wb_mode(s, 0);        // 上記1の時(0:自動,1:晴れ,2:曇り,3:Office,4:家)
  s->set_exposure_ctrl(s, 1);  // 自動露出1(0,1)
  s->set_aec2(s, 1);           // 自動露出2(0,1)
  s->set_ae_level(s, 0);       // 自動露出1が1の時、露出レベル(-2~2)
  s->set_aec_value(s, 300);    // 露出(0-1200)
  s->set_gain_ctrl(s, 1);      // 自動ゲイン制御(0,1)
  s->set_agc_gain(s, 0);       // ゲイン(0-30)
  s->set_gainceiling(s, (gainceiling_t)0);  // ゲイン(0-6)
  s->set_bpc(s, 0);            // ?(0,1)
  s->set_wpc(s, 1);            // ?(0,1)
  s->set_raw_gma(s, 1);        // ?(0,1)
  s->set_lenc(s, 1);           // レンズ補正(0,1)
  s->set_hmirror(s, 0);        // 左右反転(0,1)
  s->set_vflip(s, 0);          // 180°回転(0,1)
  s->set_dcw(s, 1);            // ?(0,1)
  s->set_colorbar(s, 0);       // カラーバー表示(0=off,1=on)

  WiFi.begin(ssid, password);            // wifiに接続
  while (WiFi.status() != WL_CONNECTED) {// wifiに接続されてなければ
    delay(500);                          // 0.5秒待つ
    Serial.print(".");                   // シリアルモニタに表示
  }
  Serial.println("WiFiに接続");    // シリアルモニタに表示
  startCameraServer();            // 関数へ
  Serial.print("'http://");       // シリアルモニタに表示
  Serial.print(WiFi.localIP());   // 割り当てられているIPアドレス
  Serial.println("'に接続してください。"); // シリアルモニタに表示
}

void loop() {
  delay(10000);                    // 10秒待つ
}