こんにちは PMの後藤です。
Cerevoではミニ四駆を改造してWi-Fiラジコン化するMKZ4という製品があります。今回それをさらに改造して、Wi-FiマイコンとしてポピュラーなESP32にカメラがついたモジュールを利用し、カメラからのライブ画像を見ながらスマートフォン経由で運転できるラジコンを作ってみました。
以前、ドローンで有名だったParrot社のJumping Sumoという2輪の製品がありましたが、ちょうど同じようなことをやってみたことになります。
また、今回はIoT製品でありがちなIoTデバイス+アプリという構成は取らず、Wi-FiマイコンのESP32で簡易HTTPサーバを動かすことによりアプリなしで、スマートフォンのブラウザ経由で動かすUIを構築しました。IoTデバイスでは往々にしてアプリの開発や長期運用時のメンテが問題になることがあり、ローカルかつWebブラウザ経由でちょっとした制御を行うというのは選択肢として便利なのではないかと思います。
目次
設計検討
オリジナルのMKZ4ではEspressif社のWi-Fiマイコン、ESP8266をWi-Fiアクセスポイント兼HTTPサーバとし、スマートフォンから操作することでミニ四駆操作を行う構成をとっています。今回は類似の構成を取り、ESP32のArduinoサンプルの中にあるWi-Fi経由でブラウザでカメラ映像を送るHTTPカメラサーバをベースに改造し、MKZ4に搭載されているESP8266ではモータとサーボの制御を担当させて、両者間をUARTシリアルで通信させることにしました。
ESP32は非常に高性能なのでHTTPカメラサーバとして動作させつつ、ミニ四駆のモータとサーボを制御する性能も十分にあるのですが、今回使用したM5CameraXユニットではGroveポートが一つ出ているだけの構成となっており制御に使えるのが2ピンしかなかったため、モータとサーボ制御はオリジナルのMKZ4と同様にESP8266側で担当する構成としました。
基本的に実装はESP-IDFですが、Arduinoでプロジェクトを作っているので、ESP-IDF環境を構築されていない方でも気軽にビルドしていただけると思います。ビルドの方法についてはプロジェクト内のread.meを参照してください。
実装
カメラサーバ ⇄ Webブラウザ間通信
ArduinoESP32のサンプルコードにあるカメラサーバのコードをベースにして、Webブラウザとカメラモジュール間の通信を実装しました。
既存のMKZ4のコードではsubmitでWebブラウザ - Webサーバ(ESP8266)通信を実装しています。submitはHTMLで気軽に実装し易い一方、ページ遷移またはリロードが回避できないため、カメラからのストリーミングを行い、さらにブラウザから操作値を連続的に投げる今回の構成とは相いれないものとなります。
一方、上記のHTTPカメラサーバのサンプルコードではJavaScriptのFetch APIを使っています。一旦それを参考にしてFetchで通信を実装をしてみましたが、カメラからのストリーミングを止めずにWebサーバ側と通信できた一方、ミニ四駆への制御値をWebサーバへ高頻度で送ろうとするとFetchのレスポンスが追い付かない状況が発生しました。これはESP32の処理能力がさほど高くないためと考えられます。FetchでもPOSTメソッドを使えば多少改善が期待出来そうですが、今回は連続的にデータを流す場合に有利なWebsocketを使うことにしました。
以前、別のプロジェクトでESP32のWebサーバとブラウザのクライアント間をWebsocketで繋いだことがあり、非常に遅延の少ない通信ができたため、今回もWebsocketでの通信実装を試みました。以前に実装した際はArduinoのAsyncWebServerライブラリを使用したのですが、Release-v4.2以降のESP-IDFではHTTPサーバにWebsocketが対応しているためそれを利用しています。
また、カメラサーバサンプルではアクセスポイント名とパスワードをコードに入れて、すでにあるWi-Fiネットワークに接続するようになっています、ESP32はアクセスポイントとしても動かすことができるため、今回はアクセスポイントモードでカメラサーバとして動作するよう変更を加えています( WIFIAP_ENABLED で切り替え可能)。ほかにもサンプルにあったFaceDetect関係の機能を切ったりしています。
UIの実装
スマートフォンからの操作を前提とし、カメラ画像の表示とタッチ位置によるコントロールを実装しました。カメラのパラメータ設定はサンプルの構成をそのまま使用しています。
なお、上記のArduinoESP32のカメラサーバのサンプルコードではHTMLがGZIP圧縮された形式になっており、これでは変更のしようが無いため一度PCのブラウザにてカメラサーバにアクセスし、HTMLを平文で読み出した上で書き換えています。
スマートフォンからの操作を考えていたので操作エリアを作り、ontouchmoveでタッチ位置に応じたX, Y座標をWebsocketで送るようにしました。フォーマットは±100のタッチ座標をカンマ区切りでStringでそのまま送る、という単純な(何も考えていない)構成になっています。
カメラサーバ(ESP32) ⇄ MKZ4(ESP8266)間通信
カメラサーバ側にはMKZ4コントローラ基板との通信をUARTで実装しました。データの種類が一つだけで、さほど通信量も多くないため、一応ヘッダとフッタをつけただけのStringを流すだけにしました。
//Header: "A", Footer: "\n"
A50,-10\n
MKZ4コードの改良
- 現状のMKZ4コードではWebサーバも動かしているのですが、今回の構成ではWebサーバはESP32側で動かすためWebサーバ周りを全て止めています。
- また、ステアリング用のサーボ制御機能がブロッキング命令となっており、制御値が連続的に飛んでくる構成では不都合があったため、ArduinoのServo.hを使用するように変更しました。
- 他にもモータ制御で使っているi2cのモータドライバへ固定値を渡していたため速度制御データが書き込めるよう変更を加えています。
- Webサーバの代わりにESP32からUARTで制御値を受け、モータとサーボを制御するループを組みました。
配線・組み立て、そして電源ON
M5Cameraへ4.5Vを給電する必要があるため、MKZ4基板から電池の4.5VとUARTを取り出してGroveコネクタ出しを行いました。
- MKZ4とESP32をつなぐUARTコネクタを外した状態で電源を投入します。
- UARTコネクタを接続し、MKZ4基板上のLEDが点灯することを確認します。
- スマートフォンから”mkz4cam”というアクセスポイント名をさがし、接続します。接続確立まですこし時間が掛かるかもしれません。
- 「インターネットに接続されていません」というメッセージが出た場合は「接続を継続する」を選択します。
- Webブラウザを起動し、192.168.4.1へアクセスします。(APモードの場合)
- 青い画面が表示されたら左上のSettingsメニューを開き、メニューの一番下の”Start Stream”を押す。
- 画面にカメラからの映像が表示され、更新されていることを確認。
- 画面下部の十字エリア中心部をタッチし(指を離さないまま)上の方にスライドします。MKZ4のモーターが回りましたか?
- 下方向にスライドさせるとモーターが反転して回ります。
- 同様に左右方向に指をスライドさせるとステアリングが動きます。
- All right! Let’s ride! 🚗🌫
ウゴイタ
(デスクがごちゃごちゃですみません)
課題&考察
- Wi-Fiが2.4GHz帯なのでオフィスエリアでWi-Fiアクセスポイントが周囲に数多く存在しているときは非常につながりにくくなります。
- 電源投入時にMKZ4側のUARTコネクタを接続しているとMKZ4が起動しません。おそらくピンの初期化がうまくいっていないので、ちょっと改善したいところです。
- ストリーミングは解像度にもよりますが、体感10FPS程度という感じでした。高速で車を走らせるには不向きですが、レスポンスは悪くなく、ラジコン操作としては成立しているかなと思います。
- ESP32等でHTTPサーバを動かし、スマートフォンのブラウザから操作するUIはアプリを作るよりメンテナンスの手間がかからず有利だなと再認識しました。この構成でどこまで凝ったUIが作り込めるか、今後掘ってみたいなと思います。
今回組んだプログラムはGitHubにて公開していますので、皆さんもぜひ挑戦してみてください。(PlatformIOまたはArduinoでビルドできます)
MKZ4について
MKZ4はタミヤ製のワイルドミニ四駆をベースに改造するキットです。単体で購入する場合は、別途ワイルドミニ四駆をご購入いただく必要があります。
Cerevoではワイルドミニ四駆とのセット販売も行っていますので「すぐに作ってみたい!」という方は、セットがおすすめです。
エンジニア積極採用中
現在Cerevoでは各種エンジニアの採用、またハードウェア共同開発・受託開発を絶賛募集しております。それぞれご関心お持ちいただける方は、以下の専用お問い合わせフォームよりご連絡お待ちしております。
- 現在募集している職種
https://cerevo.com/recruit/
- ハードウェア共同開発および受託開発のご相談
https://cerevo.com/contact/
著者プロフィール
- 開発部でプロジェクトマネージャをしています。