M5StickC Plus を振って出すおみくじ
新年といえば初詣。お参り先でおみくじを引く人も多いかもしれない。
今回は、そのようなアドバイスなどが書かれた本格的なおみくじではなく、キーホルダーであるような、逆さにして振ると運勢が書かれた棒が出てくる簡易的なおみくじを再現してみた。
M5StickC Plus の加速度センサ
M5StickC Plus には、加速度センサが入ったIMUが搭載されている。
今回は、このIMUを用いて「逆さにする」「振る」という操作を検出する。
ジャイロ加速度計(IMU) - M5StickC非公式日本語リファレンス
軸の向きを調べる
PlatformIO で以下のコードを書いて実行し、それぞれの軸がハードウェアのどの向きに対応しているかを調べた。
#include <M5StickCPlus.h>
unsigned long prevTime;
void setup() {
M5.begin();
M5.Lcd.setRotation(1);
M5.Lcd.setTextColor(WHITE);
M5.Lcd.setTextFont(4);
M5.Lcd.setTextDatum(3);
M5.Imu.Init();
prevTime = millis();
}
void loop() {
M5.update();
unsigned long currentTime = millis();
if (currentTime - prevTime >= 100UL) {
prevTime = currentTime;
float accelX = 0, accelY = 0, accelZ = 0;
M5.Imu.getAccelData(&accelX, &accelY, &accelZ);
M5.Lcd.fillScreen(BLACK);
int screenHeight = M5.lcd.height();
M5.Lcd.setCursor(16, screenHeight * 1 / 6);
M5.Lcd.printf("X:%6.3f", accelX);
M5.Lcd.setCursor(16, screenHeight * 3 / 6);
M5.Lcd.printf("Y:%6.3f", accelY);
M5.Lcd.setCursor(16, screenHeight * 5 / 6);
M5.Lcd.printf("Z:%6.3f", accelZ);
}
}
その結果、それぞれの軸の正の方向は以下のようになっていることがわかった。
X軸:右ボタンがある向き
Y軸:ホームボタンから液晶画面に向かう向き
Z軸:液晶画面正面の向き
なお、加速度センサにおいて、通常重力加速度は上方向に検出される。
これは、加速度検出用のおもりが重力により下に下がるのが、加速度センサが上方向に加速した際におもりは慣性の法則によりその場にとどまり、相対的に下に下がるのと同じように扱われるからであると考えられる。
「通常は利用しない」とされる関数を呼ばないと0しか返ってこなそう
M5StickC非公式日本語リファレンス の IMU::Init の解説には、
と書かれている。
しかし、上のコードの
M5.Imu.Init();
をコメントアウトすると、各軸の加速度として全てゼロが返ってくるようになってしまった。
よく見ると時々マイナスゼロになったので、全く動いていないわけではなさそうだが、これでは使いにくい。
「通常は利用しない」というのが嘘なのか、正常に加速度の値を返させるための (通常利用する) 他の方法があるのかは、今のところわかっていない。
ただし、m5-docs の IMU の Init() の解説には、「利用しない」的な記述は無い。
したがって、どちらかといえば「通常は利用しない」が嘘である疑いのほうが強い気がする。
重力加速度とそれ以外の分離
加速度センサで得られる加速度は、重力加速度 (≒向き) とそれ以外 (≒動き) の和になっている。
向きや動きを調べるため、これらを分離したい。
JavaScript では分けて取得する以下のAPIがあるので、分離は可能であると予想できる。
調べると、以下のページが見つかった。
【加速度センサー入門】~第10回 重力加速度を取り除いてみよう~ - 半導体事業 - マクニカ
このサイトは、
ハイパスフィルタを用いることで、加速度センサの測定値から重力以外の部分を取り出せる
ハイパスフィルタは、現在の測定値から前回の測定値を引くことで (簡易的に) 実現できる
と主張している。
そこで、今回はこの方針を用いて実装した。
さらに、重力以外の部分を取り出せたと仮定したとき、測定値から重力以外の部分を引くことで、重力を取り出せる。
今回は重力以外の部分を「現在の測定値 - 前回の測定値」で計算しているため、これの結果は結局前回の測定値になる。
とはいえ、もっといい方法に切り替える可能性を考慮し、前回の測定値を直接用いずに引き算を行うことにした。
今回の仕様
今回は、M5StickC Plus のホームボタンがある部分をおみくじの箱に見立て、液晶画面を下にして振るとランダムな運勢が書かれた棒が (液晶画面上に) 出てくる、という動作をさせる。
さらに、棒が出た後、ひっくり返すと棒が引っ込むようにする。
振ったかどうかの判定は、加速度の重力以外の部分の大きさ (3軸の成分からなる3次元ベクトルの長さ) が閾値を超えたら振ったとみなすことで行う。
振った際、箱の中で棒が動く音に見立てたブザーを鳴らし、さらに液晶画面が下になっていれば20%の確率で棒を出す。
このため、1回振るだけで棒が出てくることもあれば、何回も振らないと棒が出てこないこともある。
出てくる運勢は、
大吉
中吉
小吉
凶
大凶
から選ばれる。
成果物
mikecat/shake_omikuzi: M5StickC Plus を振って出す簡易おみくじ
M5StickC Plus を用いて簡易おみくじを作ることができた。