M5StickCのジャイロセンサーで超簡単な縄跳びカウンターをつくる

コロナで外出自粛になり運動不足なので縄跳びを時々始めました。
頭の中で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ボタンでカウンターリセット

グラフ表示する部分はこちらを参考にさせて頂きました。ありがとうございます。

M5StickCで振動を測定する – AmbientでIoTをはじめよう – SwitchScience
http://pages.switch-science.com/letsiot/vibration/

使ってみる

まとめ

超簡単に縄跳びカウンターを作ることができました。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/

コメントを残す

メールアドレスが公開されることはありません。

2 × five =