ESP32-CAM で動画ストリーミングサーバーを作る
環境
Windows10 Professional
Arduino IDE 1.8.13 + 追加ボード esp32 1.0.4
手順
必要なものを買う
ESP32-CAMにカメラを取り付ける
Arduino IDEでESP32を扱えるようにする
Arduino IDEでESP32のボードを選ぶ
スケッチ例 "CameraWebServer" を編集する
編集したCameraWebServerをESP32-CAMに書き込む
おまけ ESP32-CAMをAP(アクセスポイント)化する
必要なもの
ESP32-CAM 本体
USB-TTLコンバータ
メス-メスのジャンパーケーブルを5本
USBケーブル(UST-TTLコンバータ用)
パソコン
用意できたらなお良いもの
マルチメーター
ブレッドボード
ブレッドボード用電源モジュール
9V乾電池、モバイルバッテリーなどの独立した電源
必要なものを買う
1. ESP32-CAM 本体
ESP32-CAMには互換機がたくさんあります。代表的なのがAI Thinker社製のものです。
ただし、出回っているものの多くはフェイクです。左は正規品、中央と右はともに Amazon で私が購入したフェイクです。

中央のものは、外部アンテナとセットで買いました。外部アンテナが使えるよう、基板の抵抗チップが付け替えられた状態で売られています。

2. USB-TTLコンバータ
ESP32-CAMにはUSBポートがありません。このコンバータはESP32-CAMに5Vまたは3.3Vの電源を供給しつつ、パソコンとESP32-CAMの通信の仲立ちをします。Arduino IDEからESP32-CAMにスケッチをアップロードしたり、ESP32-CAMから送信されたデータを受信するのに必要です。送信(TX)、受信(RX)、電源(5V)、Ground(GND)の4本の線をESP32-CAMと接続します。
FTDI社製のチップを使っているものであれば間違いありません。CH340というチップを使っているものはトラブルが多いので避けた方がいいです。また、粗悪品は電源の出力が5Vを下回るものがあるので、買ったらマルチメーターで計測した方がよいです。

2. メス-メスのジャンパーケーブル
ESP32-CAMとUSB-TTLコンバーターを接続するのに使います。送信、受信、電源、Ground、リセット、合わせて5本必要です。

ESP32-CAMにカメラを取り付ける
ここは意外に重要なので読み飛ばさない方がいいです。
ラズベリーパイではコネクターの留め具は水平方向にスライドしますが、ESP32-CAMは違います。留め具は上蓋のようになっており、持ち上げて外す仕組みです。水平方向に無理にスライドすると留め具が壊れます。
本体上部にある差込口にカメラのケーブルを挿し込みます。黒い留め具を上に持ち上げると、垂直に立ちます。端子の上にカメラのケーブルを置いて、奥まで挿し込みます。最後に、留め具を倒せば取付完了です。ズレたまま倒すとケーブルを傷めるので慎重にしてください。

Arduino IDEでESP32を扱えるようにする
Arduino IDEでArduino以外のマイコンボードを扱えるようにするには、設定が必要です。
ES32シリーズをArduino IDEに追加するには 開発元の espressifが公開しているパッケージをダウンロード・インストールします。
[ファイル]-[環境設定]-[追加ボードマネージャのURL] に下のURLを貼り付け、OKを押すとダウンロードとインストールが始まります。
https://dl.espressif.com/dl/package_esp32_index.json
成功すると、[ツール]-[ボード]から、ESP32 Arduinoという項目が追加され、ESP32互換機が選べるようになります。

Arduino IDEでESP32のボードを選ぶ
[ツール]-[ボード]から、自分が使うESP32互換機を選びます。ここでは AI Thinker ESP32-CAMを選びます。

(注意)
後述のスケッチ例 CameraWebServerのソースコードの中では、初期設定でCAMERA_MODEL_WROVER_KIT が選択されています。しかし、この[ツール] - [ボード] でESP32 Wrover Module を選ぶと、いろいろとプロパティーを設定しなければならず、面倒です。下はESP32 Wrover Moduleを選んだ場合の正しい設定です。

スケッチ例 "CameraWebServer" を編集する
ここはとても重要です。
私は互換ボードに種類があることも知らず、この部分をおろそかにしていました。
その為、エラーがに次ぐエラーで何が原因か分からなくなり、買ったESP32-CAMが不良品だと思って、2回も買い換えてしまいました。
まず、サンプルスケッチを開きます。
[ファイル]-[スケッチ例]-[ESP32]-[Camera]-[CameraWebServer] を選びます。
スケッチが開いたら、自分が使っているESP32-CAMのボードを探し、先頭の // を取り除きます。
次に、CAMERA_MODEL_WROVER_KIT の先頭に // を追加します。
下は、AI Thinkerを使っている場合の例です。
<編集前>
// Select camera model
#define CAMERA_MODEL_WROVER_KIT
//#define CAMERA_MODEL_ESP_EYE
//#define CAMERA_MODEL_M5STACK_PSRAM
//#define CAMERA_MODEL_M5STACK_WIDE
//#define CAMERA_MODEL_AI_THINKER
<編集後>
// Select camera model
//#define CAMERA_MODEL_WROVER_KIT
//#define CAMERA_MODEL_ESP_EYE
//#define CAMERA_MODEL_M5STACK_PSRAM
//#define CAMERA_MODEL_M5STACK_WIDE
#define CAMERA_MODEL_AI_THINKER
次に、ESP32-CAMが参加する無線LAN(WiFii)のSSIDとパスワードを設定します。下の例はダミーです。
char* ssid = "RT-gbbf3g-a";
char* password = "2f5e6de9714147";
スケッチの編集はこれだけです。
スケッチ "CameraWebServer" をESP32-CAMに書き込む
ESP32-CAM、パソコン、USB-TTLコンバータ、必要ならUSBケーブルを用意します。
そして、ジャンパーケーブルを使ってESP32-CAMとUSB-TTLコンバータを次のように接続します。
USB-TTL ESP32-CAM
VCC --- 5V
GND --- GND
TX --- ROT
RX --- UOT
GND --- IO0

上の画像には映っていませんが、ESP32-CAMのIO0(アイオーゼロ)とGNDをつなぐのを忘れないように。
これがないと書き込めません。
最後に、USB-TTLコンバータをパソコンとつないで下さい。確実に5Vの電圧が供給されていなければなりません。
USBハブではなく、パソコン本体につなぐのが好ましいです。
マルチメーターがあれば、USB-TTLコンバータから5Vが出力されているか確認します。
USB-TTLコンバータのドライバーがパソコンにインストールされれば、パソコンのデバイスマネージャーでCOMポートとして認識されます。

このCOMポートの番号は控えておいて下さい。
次に、Arduino IDE の[ツール] - [シリアルポート]からこのCOMポート番号を選びます。
あとは、Arduino IDEでコンパイル、アップロードを行うだけです。
アップロード中に次のようなエラーが出る場合があります。
Connecting........_____....._____....._____....._____....._____....._____....._____
A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header
この場合の対処は、次の二つです。
1. ジャンパーケーブルの接続が送信受信がてれこになってないか、RSTとIO0が接続されているかを確かめる。
2. ESP32-CAM本体のRST(リセット)ボタンを押して、再度アップロードするか、アップロードが始まった時にRSTボタンを押します。
アップロードが進行している場合は次のように表示されます。
Writing at 0x001bc000... (98 %)
アップロードが終わると次のように表示されます。
Leaving...
Hard resetting via RTS pin...
アップロードが終わったら、RSTとIO0が接続されているジャンパーケーブルをはずします。
次に、Arduino IDE の[ツール] - [シリアルモニター]を開き、ESP32-CAMのRSTボタンを押します。
すると、ESP32-CAMからデータが送られ、次のように表示されます。
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1100
load:0x40078000,len:10088
load:0x40080400,len:6380
entry 0x400806a4
WiFiの接続に成功し、カメラサーバーが使える状態になると、続いて次のように表示されます。
........
WiFi connected
Starting web server on port: '80'
Starting stream server on port: '81'
Camera Ready! Use 'http://192.168.0.25' to connect
RST-IO0のジャンパーケーブルをはずすのを忘れると、このような表示が出ます。
waiting for download
また、スケッチの中で誤ったボードを選ぶと、このようなエラーになります。
[E] [camera.c:1085] esp_camera_init(): Camera probe failed with error 0x20001
Camera init failed with error 0x20001
同じLANに属しているパソコンやスマホのウェブブラウザーにIPアドレス 192.168.0.25 を入力します。
IPアドレスは環境によって異なります。また、その都度ルーターが割り当てるので、常に一定ではありません。
ESP32-CAMが正常に動作し、WiFiがつながっていれば、つぎのような画面になります。
一番下の、Stream ボタンを押すと動画のストリーミングが始まります。

Arduino IDEのシリアルモニターには次のように次々と画像が送信されている様子が表示されます。
20:03:02.031 -> Starting web server on port: '80'
20:03:02.031 -> Starting stream server on port: '81'
20:26:21.387 -> dhcps: send_offer>>udp_sendto result 0
20:26:25.256 -> dhcps: send_offer>>udp_sendto result 0
20:26:46.775 -> MJPG: 4085B 43ms (23.3fps), AVG: 43ms (23.3fps), 0+0+0+0=0 0
20:26:46.811 -> MJPG: 4111B 41ms (24.4fps), AVG: 42ms (23.8fps), 0+0+0+0=0 0
20:26:46.845 -> MJPG: 4093B 35ms (28.6fps), AVG: 39ms (25.6fps), 0+0+0+0=0 0
ウェブブラウザー上では、調整用のメニューの隣に、ストリーミングされている動画が表示されます。
これでとりあえず、目的は達成しました。

おまけ ESP32-CAMをAP(アクセスポイント)化する
AP(アクセスポイント)化すると何が嬉しいかというと、ESP32-CAMから流れる映像を、WiFiルーターを使わず、パソコンやスマホから直接見ることができるということです。
Arduino IDEで CameraWebServer スケッチを少し編集するだけで実現できます。
まず、SSIDとパスワードを決め、スケッチに描き込みます。
ここで気をつけないといけないのは、パスワードを空白にすると誰でもアクセスできてしまうことです。また、パスワードが8文字未満だと、SSIDが設定通りにならなかったり、ストリーミングも動かないことがあるようです。
とりあえずは、このような設定にしておきます。
const char* ssid = "ESP32-CAM";
const char* password = "12345678";
次に、下の箇所を削除、または、コメントアウトします
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.print("Camera Ready! Use 'http://");
Serial.print(WiFi.localIP());
Serial.println("' to connect");
削除した場所に次のコードを追加します。
WiFi.softAP(ssid, password);
IPAddress ip = WiFi.softAPIP();
Serial.print("IP Address as Access Point: ");
Serial.println(ip);
startCameraServer();
これで編集は終わりです。
後は同じようにスケッチをアップロードしてリセットボタンを押すだけです。
パソコンやスマホのWiFi接続に、さっき設定したSSIDが表示されます。
ESP32-CAM
パスワードを入力して接続に成功したら、今度はブラウザに次のIPアドレスを入力します。
192.168.4.1
操作画面が表示されたら同様にStreamボタンを押して下さい。
無事ストリーミングが始まると、Arduino IDEのシリアルモニターには次のように表示されます。
20:03:02.031 -> IP Address as Access Point: 192.168.4.1
20:03:02.031 -> Starting web server on port: '80'
20:03:02.031 -> Starting stream server on port: '81'
20:26:21.387 -> dhcps: send_offer>>udp_sendto result 0
20:26:25.256 -> dhcps: send_offer>>udp_sendto result 0
20:26:46.775 -> MJPG: 4085B 43ms (23.3fps), AVG: 43ms (23.3fps), 0+0+0+0=0 0
20:26:46.811 -> MJPG: 4111B 41ms (24.4fps), AVG: 42ms (23.8fps), 0+0+0+0=0 0
20:26:46.845 -> MJPG: 4093B 35ms (28.6fps), AVG: 39ms (25.6fps), 0+0+0+0=0 0
ESP32-CAMに9Vの電池や小型のバッテリー、あるいはモバイルバッテリーを組み合わせれば、場所を選ばす動画ストリーミングが利用できます。

(終わり)