ESP32で自作マウス~その2~
前回のあらすじ
前回はESP32でMPU60506軸センサーを使ってカーソルを動かしてみました。
今回は秋月電子で買ってきた新しい部品を使いつつ、続きをやっていこうと思います。
秋月で何を買ってきたのか
メインのものを挙げると、
BMX0559軸センサー
ロータリーエンコーダー
マイクロスイッチ×2
ADコンバーター
昇圧型DCDCコンバーター
ってとこです。この他にもいくつかセンサー等買ったんですが、試した(冷静に性能を比較した)結果BMX055でええやんという話になり、使うものはこれに絞られました。
役割を説明していくと、BMX055はもちろん加速度センサーのために買ったんですが、これ9軸なので姿勢推定ができるんですね。なので3次元マウスの実装では9軸全部使ってやろうと思います。
ロータリーエンコーダーはホイールに使うんですが、貫通型は軸見つけるのが面倒だったので、普通につまみに使うようなやつを横倒しにして使うことにしました。
マイクロスイッチは右・左クリック用なんですが、今後用途は変えるかもしれません。オムロンのやつで、0.49Nで動くので結構軽いです。
ADコンバーターはアナログセンサ用に買ったものでもあるんですが、電池駆動にするとき、電池の電圧を計測することで残量確認がしたいので買いました。
DCDCコンバーターは乾電池2本だと2.4Vしか出ないので、ESP32の動作に必要な3Vまで昇圧するのに使います。
では、本編に入っていきます。
加速度マウスの改善
前回も色々と工夫を施してギリ使い物になるぐらいにはしましたが、一点改善と一点変更を加えました。
改善ポイント:閾値の見直し
前回の工夫の中に「加速度が0なら静止しているものとする」というものがありましたが、この処理のせいで誤作動が生じることがありました。特にひどいのが、これのせいで余計に速度がリセットされて、マウスが動いているのと逆方向にカーソルが動くことがありました。
これを解決すべく、まずちゃんとセンサーの使用を確認したところ、静止時のオフセットが+-80mgとなっていたので、閾値を0.08m/s^2にしました。そのうえで、一時的に加速度が閾値を越えただけだとまた前回のようになりかねないので、以下の処理で加速度の平均みたいなモンを算出して使っています。
avg_accel[0] = (avg_accel[0] + accel[0]) / 2;
avg_accel[1] = (avg_accel[1] + accel[1]) / 2;
avg_accel[2] = (avg_accel[2] + accel[2]) / 2;
要は平均と今の加速度で平均とってるので、過去の加速度も考慮しつつ、自動的に新しい加速度にバイアスがかかるようになっています。これが5回連続で静止時の閾値を下回ったら静止とみなします。
これで逆行する動きも減って、かなりスムーズな動作が実現できました。
変更点:諸々の実装
3次元マウスを実装するに当たり、2次元マウスから切り替えるのが容易にするために、ループ関数内に処理を書くのではなく、別の関数mouse2dに処理を書き、これを割り込みで1000Hzで呼び出すことにしました。
これで割り込みがない間にCPUが回り続けることは無いと思うので、電力効率も上がるかなと思います。ちなみに割り込みにはTicker.hを使っています。
あと、キャリブレーションも正確に取るためにサンプル数を3から10に増やしたりしたり、3次元マウスのときに勝手にキャリブレーションしてしまわないようにBMX055構造体でキャリブレーションを実装するのではなく、キャリブレーション結果の配列を返すよう実装を替えました。
3次元マウス実装
2次元マウスの改善をしたので、今度は新たな機能であり、今回の自作マウスの売りでもある3次元(操作は2次元ですが)マウスを実装していこうと思います。
具体的には、BMX055の9軸センサーの値を取得し、MadgWickフィルターという手法を用いて姿勢推定をし、推定したピッチ角とロール角でマウスカーソルを制御します。
MadgWickフィルターについては他の記事で詳しいのが無限にあるので詳しくは解説しません(そもそも僕も軽く勉強しただけなので深い理解はしていない)が、要は誤差のあるセンサーデータを組み合わせうことで正確な姿勢を算出するものです。
この手のものにはカルマンフィルターという有名な手法があり、僕は最初これしか知らなかったのですが、MadgWickの方が精度が良く、計算コストも小さいとのことだったのでこちらにしました。
実装ですが、今回はMadgwickAHRSというライブラリで演算することにしました。いつもならこの手のライブラリは使わずに自力実装するんですが、そんな時間は無いので今回は我慢してライブラリに頼ります。
そして、ピッチ角とロール角でカーソルを制御すると書きましたが、これらをそのままスケール変換しただけだと、空中で使おうにもすぐカーソルが動いてしまい不便なので、-10〜10度の傾きは無視することにしました。その他の範囲については1/10した値を使用します。
まとめ
今回は3次元マウスの実装まで終えました。2次元マウスの方はぼちぼちの使用感でしたが、3次元マウスの方は結構いい精度で姿勢推定できるおかげで、かなりスムーズな動作が実現できました。
コードが結構長くなってきたので載せてませんが、引き続きGithubに上げてるのでそちらを見てください。
次回はクリックかホイールの実装をしようと思います。
この記事が気に入ったらサポートをしてみませんか?