コロナで外出自粛になり運動不足なので縄跳びを時々始めました。
頭の中で100回ごとにカウントするのですが、2セット目か3セット目かすぐに判らなくなります。
M5StickCには6軸センサーが内蔵されていることを思い出し、腕時計式の縄跳びカウンターを作ってみました。
6軸IMUセンサー MPU6886
MStickCにはIMU(Inertial Measurement Unit)が内蔵されています。加速度3軸と角速度(ジャイロセンサー)3軸の計6軸です。
最近のMStickCのIMUには MPU6886 が、旧モデルには SH200Q が使用されています。本体裏面に「6-Axix IMU MPU6886」と表示されています。
公式サンプルで6軸センサーを試してみる
加速度とジャイロを表示するサンプルです。
振り回すと当然数値が変わるのですが、リアルタイムの数値表示で文字も小さいので動かしている間はどの軸の値が変化しているか目で追えません。
サンプル MPU6886.ino
https://github.com/m5stack/M5StickC/blob/master/examples/Basics/MPU6886/MPU6886.ino
センサー出力をシリアルプロッタに出力して変化を見る
こちらの記事が大変参考になりました。ありがとうございます。
M5StickCの6軸IMU MPU6886を調べる – Lang-ship
https://lang-ship.com/blog/work/m5stickc-imu-mpu6886/
加速度とジャイロの出力をシリアルプロッターに出すことで、Arduino IDE側でグラフ表示されます。LCD見なくてもよいです。素晴らしい。
腕に取り付けたM5StickCを縄跳びするように振り回すとジャイロのY軸(上画像では赤色グラフ)の変化が大きい様なので、このパラメータを使用することにしました。
ジャイロY軸のみのグラフはこちら。(青色)
縄跳び回数カウントアルゴリズム
手を振り回すことでジャイロY軸が +600 ~ -600 の間で変化していることが判りましたので、
超単純に以下のアルゴリズムで回数を計測します。
・400を超えたらup (350に修正しました)
・-400を下回ったらdown
・upを観測した後にdownを検出したら1回としてカウントアップ
プログラム
GitHub – github.com/tyamazoe/JumpCounter
https://github.com/tyamazoe/JumpCounter
#include <M5StickC.h>
#define UPPER_LIMIT 350.0 // jump up threshold
#define LOWER_LIMIT -400.0 // jump down threshold
#define SAMPLE_PERIOD 20 // sampling msec
#define SAMPLE_SIZE 150 // 20ms x150 = 3sec
#define X0 5 // chart horizontal start
#define MINZ -600 // chart vertical max
#define MAXZ 600 // chart vertical min
float gyroX = 0.0F;
float gyroY = 0.0F;
float gyroZ = 0.0F;
float gY[SAMPLE_SIZE];
int mode = 0;
uint16_t counter = 0;
int upcount = 0;
int gcounter = 0;
void setup() {
M5.begin();
Serial.begin(115200);
M5.Axp.ScreenBreath(8);
M5.Lcd.setRotation(3);
M5.Lcd.fillScreen(BLACK);
M5.IMU.Init();
}
void loop() {
M5.update();
// get gyro data
M5.IMU.getGyroData(&gyroX, &gyroY, &gyroZ);
Serial.printf("%6.2f\n", gyroY);
// check jump up
if (gyroY > UPPER_LIMIT) {
upcount++;
}
// jump down and count
if (gyroY < LOWER_LIMIT && upcount > 0) {
upcount = 0;
counter++;
}
// Display counter
if (mode == 0) {
M5.Lcd.setTextSize(4);
M5.Lcd.setCursor(0, 20);
M5.Lcd.printf(" %4d", counter);
}
// Draw glaph
else if (mode == 1) {
if (++gcounter > SAMPLE_SIZE) {
gcounter = 0;
M5.Lcd.fillScreen(BLACK);
}
else {
gY[gcounter] = gyroY;
int y0 = map((int)(gY[gcounter - 1]), MINZ, MAXZ, M5.Lcd.height(), 0);
int y1 = map((int)(gY[gcounter]), MINZ, MAXZ, M5.Lcd.height(), 0);
M5.Lcd.drawLine(gcounter - 1 + X0, y0, gcounter + X0, y1, GREEN);
M5.Lcd.setTextSize(2);
M5.Lcd.setCursor(0, 0);
M5.Lcd.printf("%4d", counter);
}
}
// BtnA change display mode
if (M5.BtnA.wasPressed()) {
mode = mode ? 0 : 1;
M5.Lcd.fillScreen(BLACK);
}
// BtnB reset counter
if (M5.BtnB.wasPressed()) {
counter = 0;
M5.Lcd.fillScreen(BLACK);
}
delay(SAMPLE_PERIOD);
}
Aボタンで表示モード切り替え
Bボタンでカウンターリセット
Aボタンで表示モード切り替え
Bボタンでカウンターリセット pic.twitter.com/flJ6xZqVlY— 山添 知久(zoe)/IoT (@zoe6120) January 10, 2021
グラフ表示する部分はこちらを参考にさせて頂きました。ありがとうございます。
M5StickCで振動を測定する – AmbientでIoTをはじめよう – SwitchScience
http://pages.switch-science.com/letsiot/vibration/
使ってみる
跳んでみるテスト。そこそこ正確。
LCDはScreenBreath(8)に設定したので昼の屋外には暗くてちょっと見えにくい。#縄跳びカウンター #M5StickC pic.twitter.com/11IXJoG1sS— 山添 知久(zoe)/IoT (@zoe6120) January 9, 2021
センサー値をグラフ表示するモードを追加した。
手を振り回すと値の変化が現れるけども動かしてる間は見えないね。 pic.twitter.com/OHYdo79RyF— 山添 知久(zoe)/IoT (@zoe6120) January 9, 2021
まとめ
超簡単に縄跳びカウンターを作ることができました。M5StickCのリストバンドを有効活用できたのも嬉しいです。
手の振りが小さいとカウントしないことがありますが、100回単位の数え忘れ対策には問題ないレベルにはカウントできます。
しきい値を調整したり、他のパラメータも加味すればより精度の高いカウンターが作れそうです。
振動や動きを検出する用途にも色々応用できそうです。
参考リンク
M5StickCの6軸IMU MPU6886を調べる – Lang-ship
https://lang-ship.com/blog/work/m5stickc-imu-mpu6886/
M5StickCで振動を測定する – AmbientでIoTをはじめよう – SwitchScience
http://pages.switch-science.com/letsiot/vibration/