前回までで、新しいマイコンを使って意のままにモータを動かし、その回転量を計ることができるようになった気がしました。
ESP32もArduinoIDEで開発ができるので、IMUによる姿勢角検出は元々のコードはちょっとの修正で流用が可能な気がしました。
が、どうやらそうも行きませんでした。
この辺り、実はあまり開発メモみたいなのを残しておらず解決もしていない、情報量ゼロに近い記事になってしまいそうなのですが、事例紹介程度に書き残そうと思います。
注意事項ですが、今にして振り返るとあまりミリミリとした原因調査・究明プロセスを踏めていなかったと反省しています。
もし同じ症状に遭った方は、改めて原因を探るのも面白いと思われます。
ちなみに、このシリーズで言うESP32は、僕が実際に倒立振子ロボットに使っている、スイッチサイエンスで取扱中のESPr developer 32を指します。
症状:I2C通信が止まってしまう
当時の記事で言及したかどうかは忘れましたが、マイコンとの通信はI2Cを使っていました。
ESP32でも、IMUが外付けのMPU9250に変わる以外は同じ構成で行けるだろうと思い、前回までで構築したモータ制御回路に更に追加してみました。
すると、何故か姿勢角計算が止まってしまう。10秒位は出力されますが、その後姿勢角が出なくなってしまいます。
そして一度出力されなくなると、その後はESP32をリセットしてもダメで、一度USBケーブルを抜いて電源を遮断しなければ、再度計測もできません。そして再計測しても10秒で止まってしまいます。
リセットした場合はうんともすんとも言わないわけではなく、使わしてもらっているMPU9250をArduinoで使用するライブラリで、MPU9250の初期化エラーコード:-1を吐いていました。
github.com
まとめると、
- I2CでIMUデータを取ると10秒くらいで止まってしまう
- 一度止まったらリセットしてもIMU初期化エラー(IMU向けの外部ライブラリ由来)が出て、再計測不可
- ESP32の電源を遮断して再度電源を入れれば、再計測可能だが、再び10秒くらいで止まる
エラーコードの中身
エラーコード:-1は何かというと、上記ライブラリの中身とMPU-9250のマニュアルとを見比べてみると、アドレス107(0x6b)のpower management 1というレジスタ(というのかな)に0x01を書き込むときにエラーが生じているようである。
0x01が何かというと、ここは僕自信よく理解していませんが、MPU9250のジャイロを動作させるタイマとして、外部のPLL(phase locked loop : 位相同期回路らしいが、どのようものかは不明)が使用可能であれば使用し、そうでなければ内蔵の発振子を使うというものらしいです。
本当にこの部分でエラーを吐いているのであれば、そういうエラーということだろうと思われます。
PLLが何なのかは勉強不足で全くわかりませんが・・・マイコンに繋いだ時点で、マイコン内蔵タイマを使うということは、その文字面だけ見ると、有り得そうではあります。
もしくは、上記のアドレス107に0x01を書き込むプロセス自体が初期化プロセスの最初段であることから、その前段階、I2C通信を開始する時点でエラーを吐いていることが考えられます(I2C通信開始に失敗している)。
初期化手順は
- SPIまたはI2C通信開始
- ジャイロのタイマ設定(失敗するとエラーコード:-1)
- I2Cのマスタモード始動(失敗するとエラーコード:-2)
以下略
というプロセスらしいので、ライブラリのソースを弄って初期化手順2と3を入れ替えてみるとかはやっても良かったかも知れません。
その場合、I2C通信開始に失敗していれば手順3を実行できなくなってエラーコードは−2となり、手順3をパスできているがタイマ設定に失敗しているということなら、エラーコードは-1となる気がしますが。。。。
類似の事例はあるか?
類似の事例としては以下のサイト様を見つけました。
www.mgo-tec.com
・・・が、どうも症状が若干異なる。
そして、このサイト様で紹介されている不具合は1年位前に修正されている様子もあります。
おそらくこの症状とは違うだろうと当たりをつけました。
原因究明
再びFTA(もどき)を使ってみて、原因究明を試みました。
docs.google.com
未検証の部分が多数あってなんとも間抜けな表になってしまいましたが、なんとなくライブラリが吐いたエラーコード的にも、タイマー周りな気がしました。
まさに未検証な部分ですね。
そしてそれ以上のことは残念ですがわかっていません。。。
ただ、Arduinoでも、内蔵タイマが複数あって、たとえばあるタイマをタイマ割り込みで使用してしまうと、特定のピンからPWM出力ができなくなってしまう等の縛りがあったと思うのです。
おそらくそれと同じ種類の不具合なのではないかと。
IMUから姿勢角通信のタイマー割り込みと、モータドライバへのPWM出力✕2、そしてI2C(で使っているかはわかりませんが)で、最大4つの内蔵タイマを使い得るわけで、よくよく考えてみると私にとっても初めての経験ですので・・・
じゃあどうするのか?
ArduinoMEGAでは全て安定動作することは確認済みです。
・・・が、回路のハンダ付けし直しの手間を考え、今回は「そもそもI2Cを使わない」という選択にしました。
過去の電子工作でも全てI2Cを使っていた私にとっては初めての試みですが、SPI通信を使ってIMU情報を取ることにしました。
I2C通信のほうが複数センサを接続する際に使用するピンが少なくて済む、そもそも対応するセンサの種類が多い等のメリットがある気がしましたが、それはまた後日考えようと思います。
I2CセンサインターフェースとしてもうひとつArduinoを積んでもいいですし。
通信をSPIにした結果、一瞬で上手く動くようになりました。
正しく原因究明ができなかったのは悔しいですが、先に進めることを優先しようと思います。