試作2号機でもまずまずの結果が得られましたが,2つのESP32を使うのはコスト的によくないということで,
新たに M5camera を用意して制御系の1チップ化を図ります.
M5camera は PSRAM 搭載のため,これまでのカメラよりも高性能化が見込めるはずです.
親切に Type-C のケーブルまで付属.
試作2号機製作時に購入した Typc-C の変換アダプタが無駄に...
付属品は短いので購入したケーブルを使いますけどね.
試作2号機では結局使わなかったGROVEケーブルですが,
今回は Zumo32U4 との 通信用に使います.
Unit Camは
GPIO#17 と GPIO#16(Serial2のTXとRX)が出ていましたが,
M5cameraは
GPIO#4 と GPIO#13(I2CのSDAとSCL)が出ています.
先に完成した画像を以下に示します. M5camera に標準で付属している LEGO の固定パーツを活用するため,ちょこっと穴加工しました.
以下にハマった点を列挙します.
PSRAM搭載カメラなので,ESP32用のボードライブラリを2.01にアップグレードしました.詳細は試作1号機のページを参照.
ところが今度はNimBLE(1.33)を使ったスケッチがビルドできなくなる症状が発生.CPUが高負荷のままArduinoIDEが落ちてしまいます.
やむなくNimBLEの使用はあきらめ,ESP32標準のBLEライブラリに変更しました.ひな型は ESP32 BLE Arduino → BLE_uart をベースにしています.
後日談ですが,編集中にESP32用のボードライブラリが2.02へ,NimBLEも1.34にアップデートされていたので,いまならビルドできるかもしれません.
Arduino 1.8.19 で NimBLE のスケッチ例そのままでもビルドできませんでした.対応されるまで待つしかないですね.(2022/01/13)
これはプチハマリでした.PythonからM5cameraのBLEが見えないと怒られます. よくみるとMacアドレスが違いました. スケッチ書き込み時のMacアドレスは,24:62:ab:d9:dd:b0 なのに
BLE用のMacアドレスが 24:62:ab:d9:dd:b2 というオチ.いやがらせかよww
BLEの単体テストでは,GORVE端子のGPIO#4とGPIO#13をソフトウェアシリアルとして設定し,Zumo32U4 への指示を出していましたが, WiFiカメラとの組み合わせでソフトウェアシリアルが使えないことが判明しました.
SoftwareSerial mySerial(4, 13); // WiFiカメラと併用するとESP32がリブートを繰り返す
どうしようもないのでソフトウェアシリアルをあきらめ,本来の用途である I2C での通信に変更しました.
これがドハマりでした.というよりI2C通信の仕組みを正しく理解していなかったのが原因.
シリアル通信と同じように,垂れ流したデータを適当に受信すればいいだけのイメージでしたが,全く受信できない.
あげくに Wire.endTransmission() の戻り値(M5cameraがマスター)が,
ヘルプには 0~4 の定義しかないのに 5 を返します.エラーコードの調査のしようがなく途方に暮れておりました.
かなり悩みましたが,結局 "受信の割り込み" を定義することで正しく受信できるようになりました.
やみくもに Wire.available() で問い合わせてもマスターとのタイミングが合わないと読めないことがわかりました.
以下は Zumo32U4 (スレーブ)側の抜粋です.
#define I2C_ADDRESS 0x10
volatile byte var = 0;
void dataRecv(int)
{
if ( Wire.available() ) {
var = Wire.read();
ledRed(1);
}
}
void setup()
{
Wire.begin(I2C_ADDRESS); // slave
Wire.onReceive(dataRecv); // ISR
Serial.begin(9600);
while(!Serial);
}
void loop()
{
Serial.println(var, HEX);
ledRed(0);
delay(1000);
}
これらをふまえて書いたスケッチを公開します.
M5mario は M5camera に書き込むスケッチです.ボードは ESP32 Wrover Module を選択.ZumoMario は Zumo32U4 に書き込むスケッチです. 試作2号機まではSoftAPを設定してESP32自体をアクセスポイントにしていましたが, それでは遅いという情報を得たので,ノートPCをアクセスポイントに設定するよう変更しました. [設定]から[ネットワークとインターネット]を選択し[モバイルホットスポット]を有効にします. [ネットワーク名]と[パスワード]の情報を M5mario のスケッチに記述してください.
const char* ssid = "DESKTOP-O5GQ6F4 0443";
const char* password = "47Z}151g";
アクセスポイントをPC側にしても残念ながら明らかな速度アップは体感できませんでしたが, 1チップでそこそこの安定動作が実現できました. もう少しFPSを上げられないか検討課題です.
BLEserial3 のときに作ったPython のコード BLEjoy.py を少し改良しました.
pyGameのウィンドウがアクティブでないとゲームパッドの入力を受け付けてくれないので,せめてウィンドウを最前列に表示するように変更しました.
Windows 限定になってしまいますが,pyWin32 ライブラリを追加でインストールし,pygame.display.set_mode() のあとに2行追加します.
win32con と win32gui を import するのも忘れずに.
Python 3.8系から 3.10系にアップデートし,Bleak も 0.10.0 から 0.14.1 にアップデートすると,イベント関連でワーニングがでるようになりました.
将来的に書き方を変更する必要がありそうです.
screen = pygame.display.set_mode((320, 320))
hwnd = pygame.display.get_wm_info()['window']
win32gui.SetWindowPos(hwnd, win32con.HWND_TOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE|win32con.SWP_NOSIZE)
そもそもESP32と直接通信できるゲームパッドがあれば,こんなことをしなくてもいいんですけどね. テストで使用しているのは家で使っていた Nintendo Switch 用のゲームコントローラーです. Aボタンが壊れて学校に寄付www