hogehoge, world.

米国カリフォルニアのソフトウェアエンジニアがIT・自転車・音楽・天体写真・語学などについて書く予定。

M5Atom Matrixでボールころころ

M5Atom Matrixを買ってすぐの習作として作った「ボールころころするやつ」の解説をしてみる。加速度センサーの値を使って物体の加減速や跳ね返りのシミュレーションを行なう簡単なコードなので、プログラミング学び始めの人の資料にでもなればと思う。初期化と表示処理がM5Atom固有なので、そこだけ修正すればM5StickC等他のモデルで動くものに改造できるだろう。

youtu.be

ソースコードは以下のものである。

ArduinoPlayGround/BallRoll.ino at d583c4d4fa55d30a90f14e0af73d9fc636b4a2b2 · tomoto/ArduinoPlayGround · GitHub

Setup

3行目あたり。Serial, LEDディスプレイ, 加速度センサーの3点セットを初期化する。M5Atom以外のボードを使うなら適宜コードを変えること。

ボタンの処理

35行目あたり。ボタンが押されたらボールの座標(x,y)を中心(0,0)に戻し、速度(dx,dy)をゼロにリセットする。

加速度センサー読み取り

40行目あたり。加速度センサーの値を(ax, ay, az)に読み込む。

ボールはXY平面にへばりついてころころする(Z軸方向には移動しない)ので、axとayの値だけを使用し、azの値は使わずに捨てる。

f:id:tomoto335:20210314203113p:plain

(上の図では静止中を想定して「重力」と言っているが、動かしていれば慣性力や遠心力もかかる。)

加速度による速度の変化

41行目あたり。XY平面方向の加速度(ax, ay)を速度(dx, dy)に加え、加速度による速度の変化を計算する。

加速度の大きさがある程度以上でないと無視する、つまり感度に「遊び」を与える。遊びがないと「水平に保ってボールを静止させる」ようなことが難しすぎてできなくなる。

(ax, ay)を(dx, dy)にそのまま加算すると速度や座標がすぐに何千何万という大きな値までぶっ飛んでしまうので、SCALEを掛けて小さくし、感度を下げる。SCALEの値は試行錯誤でいい感じに決める。

座標の計算

42行目当たり。座標(x, y)に速度(dx, dy)を加えて座標の変化を計算する。

摩擦による減速の計算

43行目当たり。速度(dx, dy)にDECAYを掛けて摩擦による速度の減衰を計算する。これがないと「つるつるの板の上のパチンコ玉」のように一旦動き出したら止まらず操作しにくい。DECAYの値は試行錯誤でいい感じに決める。

f:id:tomoto335:20210314210103p:plain

壁の跳ね返りの計算

45行目当たり。ボールはXY座標の値がおよそ±2.5の範囲の小さな箱庭内で動いており、その範囲を超えそうになった場合、超えないように押し留めるとともに速度の向きを反転して「壁による跳ね返り」をシミュレートする。

速度の向きを反転する際にはBOUNCEを掛け、運動エネルギーのロス(非弾性衝突)をシミュレートする。BOUNCEの値は試行錯誤でいい感じに決める。1.0に近いほどロスが少なく、スーパーボールのようによく跳ねる。

f:id:tomoto335:20210314211202p:plain

色の計算

50行目当たり。ボールの地の色を青と緑の間でゆったりと変化させる。(時間と共に変化するサイン波を計算し、その山を切り詰めて青成分と緑成分を決めている。)

f:id:tomoto335:20210314212034p:plain

また、速度が上がるにつれて赤くなるようにする。地の色が青のときは青→マゼンタ→赤、緑のときは緑→黄→赤と変化する。

表示 

57行目のあたり。XY座標値はおよそ±2.5の範囲なので、これに2.5を足して0~4の整数に変換し、その位置のLEDを点灯させる。

この処理はM5Atom固有なので別のボードで動かすときには適宜書き換えること。なおM5AtomのLEDライブラリは品質が悪く、RGBの順序がおかしいので惑わされないように。

delayを入れて繰り返し 

62行目のあたり。動きは滑らかな方がうれしく、最低でも60FPSくらいは出したい。delayを10msにしておき、100FPS近く出ることを期待。