ESP-IDFを使ってみる

USB HOST

ESP-IDF V4.4辺りから、ESP32-S2/S3でUSB HOSTを使うことができるようになりました。
今まであまり役に立つサンプルが有りませんでしたが、ESP-IDF V5.1ではUSBカメラを使って、
Video Streamingするサンプルがこ ちらに公開されています。

このサンプルはハードウェアに対する要求が大きく、PSRAMを実装しているESP32S2/S3が必要です。
こちらのボードを使いました。


このサンプルではlibuvc libraryを使って、USBカメラを制御しています。
UVCに対応していて、さらにMJPEGFormatのVideoStreamingに対応しているカメラが必要です。
家中のUSBカメラを試してみましたが、SANWA SUPPLY CMS-V30SETBKがこれに対応していました。
このカメラは以下の様にMicromediaのOEM製品で、複数のメーカのUSBカメラとして販売されていました。
しかし現在では中古以外では入手不可能です。
$ lsusb
Bus 001 Device 042: ID 0c45:6340 Microdia Camera

ファームをビルドして、以下のタイミングでサンプルに付属するplayer.pyを起動します。
player.pyはX-Window上にJPEGを表示するスクリプトで、Xの環境とopencv-pythonが必要です。
TeraTermなどのリモートターミナルでは動きません。


ファームをビルドして、Waiting for deviceが表示されたタイミングでカメラを刺すとこのように表示されます。


player.pyにVideo Streamingの結果が表示されます。
これは我が家のテレビをキャプチャーしているときのスクリーンショットです。




SANWA SUPPLY CMS-V30SETBKは以下の様に、640x480と320x240の2つの解像度をサポートしています。
DEVICE CONFIGURATION (0c45:6340/        S) ---
Status: idle
VideoControl:
        bcdUVC: 0x0100
VideoStreaming(1):
        bEndpointAddress: 129
        Formats:
        MJPEGFormat(1)
                  bits per pixel: 0
                  GUID: 4d4a5047000000000000000000000000 (MJPG)
                  default frame: 1
                  aspect ratio: 0x0
                  interlace flags: 00
                  copy protect: 00
                        FrameDescriptor(1)
                          capabilities: 00
                          size: 640x480
                          bit rate: 24576000-147456000
                          max frame size: 614400
                          default interval: 1/30
                          interval[0]: 1/30
                          interval[1]: 1/25
                          interval[2]: 1/20
                          interval[3]: 1/15
                          interval[4]: 1/10
                          interval[5]: 1/5
                        FrameDescriptor(2)
                          capabilities: 00
                          size: 320x240
                          bit rate: 6144000-36864000
                          max frame size: 153600
                          default interval: 1/30
                          interval[0]: 1/30
                          interval[1]: 1/25
                          interval[2]: 1/20
                          interval[3]: 1/15
                          interval[4]: 1/10
                          interval[5]: 1/5
                        StillFrameDescriptor
                          bEndPointAddress: 00
                          wWidth(1) = 640
                          wHeight(1) = 480
                          wWidth(2) = 320
                          wHeight(2) = 240
END DEVICE CONFIGURATION

こ ちらのREADMEに記載されていますが、320x240の時は30FPS、640x480の時は15FPSまで対応しています。
640x480でキャプチャーするときは、FPSも同時に30→15に変更する必要が有ります。
//#define FPS 30
//#define WIDTH 320
//#define HEIGHT 240
#define FPS 15
#define WIDTH 640
#define HEIGHT 480

コードを一部変更して640x480で試しましたが、問題なくキャプチャーできました。
但し、15FPSしか出ないので、ビデオの表示は遅いです。


このサンプルはUSBカメラの抜き差しに対応しています。
キャプチャー中にUSBカメラを抜くと、ちゃんとUSBのDisconnectを検出し、再びUSBカメラの接続待ちになります。



ほとんどのUVC対応カメラはVideoStreamingフォーマットとしてUncompressdフォーマットかMJPEGフォーマットに対 応していますが、
デフォルトのVideoStreamingフォーマットが決まっています。
v412-ctlなどを使って、デフォルトのVideoStreamingフォーマットを変更することができますが、この変更はUSBを抜くと元 に戻ります。
このサンプルでは、デフォルトのVideoStreamingフォーマットが、MJPEGフォーマットのカメラでないと、正しくキャプチャーが動 きません。

こちらはLogcoolのC270nを刺したときの表示です。
デフォルトのVideoStreamingフォーマットはUncompressdフォーマットとなっています。
uvc_get_stream_ctrl_format_size()のFremeFormatに UVC_COLOR_FORMAT_UNCOMPRESSED を指定すれば、
キャプチャーすることができますが、カメラが戻すFrameFormatがUVC_FRAME_FORMAT_YUYV(無圧縮のYUYV形式) になるので、
JPEGで表示するためには、YUYV→JPEGへの変換が必要になります。


こちらはLogcoolのC615を刺したときの表示です。
USBの認識時点でエラーになっています。


以下の値を大きくすることで回避できますが、USBドライバーの実装が不完全で、このカメラを使うことはできません。


USB HOSTが使えることで、色々な周辺機器が利用可能になりますが、USBドライバーの完成度が今一つで、
Linuxでは動いても、ESP-IDFでは動かないカメラが多数あります。



こちら
で公開されているサンプルはTCP/IPを使って画像を配信しているので、TCP/IPのレシーバーが必要になります。
そこで、このサンプルを元にHTTPを使って配信するアプリをこちらで 公開しています。
ブラウザーで画像を表示することができます。
オリジナルではMJPEGフォーマットのカメラしか対応していませんが、YUYV→JPEGへの変換を組み込んだので、
無圧縮フォーマットのカメラでも動作します。

続く...