Aliexpressで見つけた格安カメラモジュールのESP32-CAMを入手したので試してみました。OV2640カメラモジュール付きで$7.5という激安っぷりです。
1.ESP-IDFのインストール
まずはファームウェアをビルドするために ESP-IDF をインストールします。
インストールは https://github.com/espressif/esp-idf に沿って行えば難しくありません。(初期のESP8266の頃に比べると随分簡単になったような気がします)
$ sudo apt-get install gcc git wget make libncurses-dev flex bison gperf python python-serial $ cd ~ $ mkdir -p ~/esp $ cd ~/esp $ tar -xzf ~/Downloads/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz
環境変数を設定するため、~/.profile に以下を書き足します。
export PATH="$PATH:$HOME/esp/xtensa-esp32-elf/bin" export IDF_PATH=~/esp/esp-idf
書き足したら、一旦ログアウトしてログインし直して、作業環境に反映させます。
2.ハードウェアの準備
ハードウェアの情報については、githubに上がっている仕様書を参考にしました。(※ダウンロードできなくなると手も足も出なくなるので同じものを113990580 ESP32-CAM Product Specificationに上げておきます。)
今回は、USBシリアル変換にFT234X使用のこちらを使いました。Linuxだといろいろトラブルが起きるのですが、セルフパワーで動かす分には大丈夫そうなので使ってみます。
ブレッドボード上にこんな感じで組んでみました。
シリアルの接続と、電源の供給(電源は仕様書の記載ではVccではなく5V端子に供給するようです)、それからブートローダモードにするためのIO0端子をGNDに落とす線の5本です。
3.サンプルのビルド
サンプルをビルドしてみます。
$ cd ~/esp $ git clone -b v3.1.3 --recursive https://github.com/espressif/esp-idf.git $ cp -r $IDF_PATH/examples/get-started/hello_world . $ cd ~/esp/hello_world $ make menuconfig
で環境設定をします。環境設定が完了したら、IO0端子をGNDに落とした状態でリセットボタンを押してブートローダモードに入ります。
※ウラ面なので、ブレッドボードに設置した状態だと大変です。リセットを押した瞬間に白色LEDが一瞬つくので、リセットを押せたかどうかは確認できます。
このとき、
$ screen /dev/ttyUSB0 115200
としてシリアルをモニタしておくと、以下の表示が出ますのでダウンロード待機状態であることが確認できます。
ets Jun 8 2016 00:22:57 rst:0x1 (POWERON_RESET),boot:0x3 (DOWNLOAD_BOOT(UART0/UART1/SDIO_REI_REO_V2)) waiting for download
screen コマンドを終了してから、
$ make flash
でビルドと書き込みを行います。完了したら、IO0のプルダウンを外してリセットするとシリアルに115200bps N81で以下のように繰り返し出力されます。
ets Jun 8 2016 00:22:57 rst:0xc (SW_CPU_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:2 load:0x3fff0018,len:4 load:0x3fff001c,len:5816 load:0x40078000,len:9188 load:0x40080000,len:6084 entry 0x4008032c I (29) boot: ESP-IDF v3.1.3 2nd stage bootloader I (29) boot: compile time 02:11:40 I (29) boot: Enabling RNG early entropy source... I (34) boot: SPI Speed : 40MHz I (38) boot: SPI Mode : DIO I (42) boot: SPI Flash Size : 4MB I (46) boot: Partition Table: I (49) boot: ## Label Usage Type ST Offset Length I (57) boot: 0 nvs WiFi data 01 02 00009000 00006000 I (64) boot: 1 phy_init RF data 01 01 0000f000 00001000 I (72) boot: 2 factory factory app 00 00 00010000 00100000 I (79) boot: End of partition table I (83) esp_image: segment 0: paddr=0x00010020 vaddr=0x3f400020 size=0x071cc ( 29132) map I (102) esp_image: segment 1: paddr=0x000171f4 vaddr=0x3ffb0000 size=0x022ac ( 8876) load I (106) esp_image: segment 2: paddr=0x000194a8 vaddr=0x40080000 size=0x00400 ( 1024) load I (110) esp_image: segment 3: paddr=0x000198b0 vaddr=0x40080400 size=0x06760 ( 26464) load I (130) esp_image: segment 4: paddr=0x00020018 vaddr=0x400d0018 size=0x11150 ( 69968) map I (155) esp_image: segment 5: paddr=0x00031170 vaddr=0x40086b60 size=0x02188 ( 8584) load I (164) boot: Loaded app from partition at offset 0x10000 I (164) boot: Disabling RNG early entropy source... I (166) cpu_start: Pro cpu up. I (170) cpu_start: Starting app cpu, entry point is 0x40080ea0 I (162) cpu_start: App cpu up. I (181) heap_init: Initializing. RAM available for dynamic allocation: I (187) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM I (193) heap_init: At 3FFB3300 len 0002CD00 (179 KiB): DRAM I (200) heap_init: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM I (206) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM I (212) heap_init: At 40088CE8 len 00017318 (92 KiB): IRAM I (219) cpu_start: Pro cpu start user code I (237) cpu_start: Starting scheduler on PRO CPU. I (0) cpu_start: Starting scheduler on APP CPU. Hello world! This is ESP32 chip with 2 CPU cores, WiFi/BT/BLE, silicon revision 1, 4MB external flash Restarting in 10 seconds... Restarting in 9 seconds... Restarting in 8 seconds... Restarting in 7 seconds... Restarting in 6 seconds... Restarting in 5 seconds... Restarting in 4 seconds... Restarting in 3 seconds... Restarting in 2 seconds... Restarting in 1 seconds... Restarting in 0 seconds... Restarting now.
ということで、Hello world!を出力後、再起動を繰り返します。
4.カメラにブラウザでアクセス
以下のサイトを参考にして行いました。(参考というか、Windows環境かLinux環境かの違い程度で概ねそのまんまですが)
https://robotzero.one/esp32-camera-module/
顔認識のサンプルをgitから引っ張ってきます。
$ cd /esp $ git clone --recursive https://github.com/espressif/esp-who.git
この中のCamera Web Server Exampleを動かしてみます
$ cd ~/esp/esp-who/examples/single_chip/camera_web_server/ $ make menuconfig
以下の項目を設定して保存します。
Serial flasher config —> Default serial port (Change to the port number shown in Device Manager – ie COM3) Camera Web Server —> WiFi Settings —> (Add your WiFi SSID and Password) Camera Web Server —> Camera Pins —> Select Camera Pinout —> (Select ESP32-CAM by AI-Thinker) Component config —> ESP32-specific —> SPI RAM config —> Type of SPI RAM chip (Auto-detect)
保存したら、ビルド&書き込みです。
$ cd ~/esp/esp-who/examples/single_chip/camera_web_server/ $ make flash
しかし、ここで
CC build/main/app_httpd.o ~/esp/esp-who/examples/single_chip/camera_web_server/main/app_httpd.c:15:29: fatal error: esp_http_server.h: No such file or directory compilation terminated. ~/esp/esp-idf/make/component_wrapper.mk:285: recipe for target 'app_httpd.o' failed make[1]: *** [app_httpd.o] Error 1 ~/esp/esp-idf/make/project.mk:468: recipe for target 'component-main-build' failed make: *** [component-main-build] Error 2
というエラーが発生してしまいました。
ぐぐると、esp-idfが古そうな感じです。しかし、
$ cd $IDF_PATH $ pwd ~/esp/esp-idf $ git fetch $ git checkout v3.1.3 HEAD is now at cf5dbadf4 Merge branch 'bugfix/backtrace_from_interrupts_backport_v3.1' into 'release/v3.1' $ git submodule update --init --recursive
としても更新してもダメでした。でも、よくみるとesp-whoディレクトリの下に、esp-idfが丸ごと含まれているっぽいです。ですので、こちらを IDF_PATH に設定して試してみます。
$ pwd ~/esp/esp-idf $ export IDF_PATH=~/esp/esp-who/esp-idf $ cd ~/esp/esp-who/examples/single_chip/camera_web_server/ $ make flash : : cryptography Please refer to the Get Started section of the ESP-IDF Programming Guide for setting up the required packages. Alternatively, you can run "/usr/bin/python -m pip install --user -r ~/esp/esp-who/esp-idf/requirements.txt" for resolving the issue. ~/esp/esp-who/esp-idf/make/project.mk:454: recipe for target 'check_python_dependencies' failed make: *** [check_python_dependencies] Error 1
ということで、python絡みで何か文句を言っています。結局は pip がないために依存関係が満たせていないようです。
$ cd ~/esp/esp-who/ $ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 1659k 100 1659k 0 0 8598k 0 --:--:-- --:--:-- --:--:-- 8554k $ sudo python get-pip.py $ /usr/bin/python -m pip install --user -r ~/esp/esp-who/esp-idf/requirements.txt
としてpipと必要なものをインストールした後、
$ cd ~/esp/esp-who/examples/single_chip/camera_web_server/ $ make flash
で無事にビルド&書き込みができました。
しかし、書き込んでIO0のプルダウンを外してリセットしてもSSIDが見えません。
$ screen /dev/ttyUSB0 115200
で見てみると、
: : I (307) wifi: Init static rx buffer size: 1600 I (317) wifi: Init static rx buffer num: 10 I (317) wifi: Init dynamic rx buffer num: 32 I (367) camera wifi: wifi_init_softap finished.SSID:ESP32-Camera password: � Bwownout detector was triggere� ets Jun 8 2016 00:22:57 rst:0xc (SW_CPU_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:6668 load:0x40078000,len:10976 : :
ということで、Wi-Fiの初期化のところでBrownout Detectでリブートを繰り返しています。
PCから長いUSBケーブルで給電とシリアルコンソール確認を兼ねているので、電源のインピーダンスが高いことは確かです。そこで、1000uFのコンデンサをVcc-GND間に追加したところ、Webサーバの起動まで進むようになりましたが、スマートフォンを帰属させるとやはりリブートしてしまいます。そこで、短いケーブルでACアダプタから直接給電したところ、192.168.4.1にブラウザでアクセスすると設定画面が表示され、Get stillでカメラ画像も取得できるところまで行きました。
しかし、それでも動作が不安定です。FT234Xのシリアル変換モジュールには100mAのポリスイッチが入っているので、こいつが悪さをしているのか、あるいはまだ電源のインピーダンスが高いのかわかりませんが、今日はここまでとします。今後、レスポンスがどのくらいなのか、確認はしてみたいと思います。
#どのくらいのパフォーマンスか見たいだけなので、もう少し試してみたら、積みボードになりそう。
ESP32-CAMって技適通ってくれてたら日本国内でもWiFi使えて、色々作れて助かるんですけど、電波の関係は難しくて困りますね。
そうですよね。
ちょっと動かしてみるだけで終わることが多いのですが、それで性能が安かろう悪かろうではない(=ちゃんと動く)なんてことがあったりすると、国内外のコスト差に打ちひしがれますね。
ESP32搭載のカメラでは、別の記事でも書いたTTGO T-Cameraは使えます。ちゃんと技適マーク付きのESP32のモジュールが載っていて、いまも3Dプリンタ監視のために動きっぱなしになってます。