M5stackCore2でスポーツセンシング

# M5stackを使って自宅で楽しく運動を
私たちが健康を保つために必要なものとしてよく挙げられるものの中に「運動」があります。
しかし、最近では外に出る機会が減少したり、在宅勤務が増加したりなど、体を動かす習慣が少なくなっている人が多い印象を受けます。
それに伴い、自宅でも運動を楽しめるコンテンツが増えてきています。
そこで「運動量が減った」、「運動をしたくても続かない」といった人に向けて、M5stackCore2やprocessingを使って自宅で飽きずに運動できるものは作れないかと考え、スポーツセンシングとアートを組み合わせ楽しく運動できるプロダクトの制作に挑戦してみました。

プロダクトのイメージとしては
- スポーツセンシング×ジェネラティブアート
- M5stackCore2で運動情報を測定（データ送信はBluetoothシリアル通信を使用）
- PCで映像を楽しみながら運動できる（運動の状況によって映像が変化する）
を想定しながら進めていきました。

今回も[前回](https://qiita.com/KechanaGohan/items/9b78bda3db15e4bc3aad)に引き続き、先輩と分担してプロダクトを制作していきました。
先輩の記事は[こちら](https://qiita.com/nanano08/items/2ad178b1f27649413d74)になります。
私は主にM5stackCore2側の機能の実装を担当したため、ここではM5stackCore2にフォーカスして記載します。

構成や使用方法、コードは[こちら](https://github.com/KechanaGohan/SportsSensing)に格納しています。

# 構成
#### 全体構成
~~~
M5StackCore2ーー[Bluetoothシリアル通信]ーー＞Python(PC)ーー[OSC通信]ーー＞Processing(PC)
//[Bluetoothシリアル通信]までが担当箇所
~~~
M5StackCore2では
- 運動情報の取得
- 運動回数、運動時間の測定
- 上記データを送信（Bluetoothシリアル通信）
が行われます。
#### 機能
今回は4種類の運動（ウォーキング、スクワット、ランジ、サイドプランク）を行える機能を備えました。
（人間の体は6~7割が下半身の筋肉​だそうで、下半身中心のメニューにしました。）
M5stackCore2で運動の選択、開始、終了の操作が可能です。
運動選択後に10秒のカウントダウンを挟み、計測がスタートします。
この間にレッグバンドにM5stackCore2を装着します。
※ウォーキングのみ手にM5stackCore2を持った状態で運動をします。
#### 作業内容
1. Bluetoothでの通信
2. M5stackCore2加速度センサーの使用
3. Bluetoothでセンサー情報を送信
4. M5stackCore2側のメニュー画面
#### 使用したもの
- [M5stackCore2](https://www.switch-science.com/products/6530)
- Bluetooth接続可能なPC
- M5stackCore2装着用のレッグバンド
※レッグバンドはちょうどいいものがなかったため、100均のものを組み合わせて自作しました(^^;
# 1.Bluetoothでの通信
Bluetoothシリアル通信については主にサンプルスケッチ``SerialToSerialBT``をベースにしています。
また接続方法も含め[こちら](https://qiita.com/ta-oot/items/2d74409cca729629595e)の記事も参考にさせていただきました。
Bluetoothシリアル通信のみ確認したい場合は以下のコードで十分でした。
~~~
#include "BluetoothSerial.h"
#include <M5Core2.h>

BluetoothSerial SerialBT;

void setup() {
  M5.begin();
  SerialBT.begin("ESP32test"); //Bluetooth device name
}

void loop() {
  SerialBT.println("Hello World!");
  delay(1000);
}
~~~
ペアリングが完了するとBluetooth仮想COMポートが追加されるので、対象のポートを確認し、"Hello World!"と表示されれば確認は完了です。
（私は今回Tera Termを使用して受信確認を行いました。）
# 2.M5stackCore2加速度センサーの使用
#### センサー使用方法
今回はM5stackCore2内臓のMPU6886を使用しています。
主に参考にさせていただいたのは[こちら](https://logikara.blog/3_axis_monitor/#mokuji_3)の記事です。
上記記事の「動作確認用プログラム」を書き込み、M5stackCore2を色々な角度、速さで動かしてみると、動きに合わせてグラフが変化している様子がシリアルモニタで確認できます。
実際にセンサーのデータを取得しているのは以下の部分なので、こちらを応用して書いていきました。
~~~
M5.IMU.getAccelData(&accX, &accY, &accZ);   // 加速度データ取得
M5.IMU.getGyroData(&gyroX, &gyroY, &gyroZ); // 角速度データ取得
M5.IMU.getAhrsData(&pitch, &roll, &yaw);    // 姿勢角データ取得

float x_angle = atan2(accX, accZ) * 180.0 / PI; // X-Z加速度から角度に換算
float y_angle = atan2(accY, accZ) * 180.0 / PI; // Y-Z加速度から角度に換算
~~~
#### 運動計測方法
「動作確認用プログラム」を使って、実際に4種類の運動状況を計り、運動計測の目安を決定しました。
##### スクワット
`roll < 45`を目安に回数をカウントするように制作しました。
bool変数`SquatRotated`をおくことで`roll < 45`の場合に連続でカウントされないようにしています。
##### ランジ
`y_angle < 45`,`y_angle > 100`を目安に回数をカウントするように制作しました。
（片足ずつ踏み込むことを想定しています。）
bool変数`LungeRotated`をおくことで`y_angle < 45`,`y_angle > 100`の場合に連続でカウントされないようにしています。
##### サイドプランク
サイドプランクについては運動時間を計測する方向で作りました。
運動データから運動の状態を判断するのではなく、M5stackCore2がストップウォッチの役割をしています。
##### ウォーキング
ウォーキングに関しては自分で計測した運動データからコードに起こすことがうまくいかなかったので、[こちら](https://qiita.com/ufoo68/items/d0d12c666a19405c5625)の記事を参考にさせていただきました。
GitHubにおいてあるコードにコメントを付けていますが、これは私が記事の内容を確認し自身の解釈で付けたコメントになるので、ウォーキングの詳細については実際に記事を読んでいただくのが一番良いと思います。
# 3.Bluetoothでセンサー情報を送信
データ受信側を作成している先輩と相談して、以下のかたちでデータを送信することにしました。
~~~
//以下ランジの場合
//Bluetoothでペアリングしたデバイスにデータを送信
SerialBT.printf("4, 0, 0, 0, 0, %02d, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f\n", Lunge_count, accX, accY, accZ, gyroX, gyroY, gyroZ, pitch, roll, yaw, x_angle, y_angle);
//運動の内容,カウントダウン,ウォーキング回数,スクワット回数,サイドプランク時間,ランジ回数,accX, accY, accZ, gyroX, gyroY, gyroZ, pitch, roll, yaw, x_angle, y_angle
//0 運動なし,1 ウォーキング,2 スクワット,3 サイドプランク,4 ランジ,100 result
~~~
データ送信時のフォーマット指定子については主に以下の記事を参考にさせていただきました。
- [フォーマット指定子一覧](https://www.k-cube.co.jp/wakaba/server/format.html)
- [Arduinoでsprintfの書式とfloatの扱い方、0埋めとか](https://kurobekoblog.com/arduino_sprint)
# 4.M5stackCore2側のメニュー画面
構成>機能 でも少し触れましたが、M5stackCore2では運動の選択、開始、終了の操作が可能です。操作イメージは以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611628/e8674ca8-fdf2-4963-914d-dd81bbf9a79a.png)
できるだけユーザが操作しやすいように図形も使ってみました。
図形の表示方法については主に[こちら](https://logikara.blog/lovyangfx_m5stack/)を参考にさせていただきました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611628/fa84719c-5f69-34be-34a6-9fdde2342cd1.png" width=50%>
# そして完成へ
運動の回数、時間がM5stackCore2でカウントされ、PC側にデータが渡り、映像にも反映されていることを確認できました。
![Videotogif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611628/bf655cb9-af2d-58e8-b4d3-7764f2294abc.gif)
![Videotogif (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611628/f97fa692-d3b4-80bb-219f-c3abe73c7a73.gif)
# まとめ
今回のプロダクト制作は、前回のペット体重計に比べてM5stackCore2にフォーカスしてプログラミングの学習を行うことができたと思います。
特に今回勉強になった内容は以下の3つでした。
- Bluetoothシリアル通信
- フォーマット指定子
- sprite（画面ちらつき防止）

反省点としては主に以下の2つです。
1. コントローラーとしての機能をM5側に寄せる
2. 認識合わせ

1については、運動終了後にresultをsキー押下で保存できる機能を付けているのですが、基本操作がM5stackCore2のため、操作をすべてM5stackCore2側でできるよう統一したほうが使いやすかったなと。
2については、プロダクト制作後半で成果物の認識にずれが生じるといったことがあり、目標期日直前でバタバタしてしまいました...最初のイメージをしっかりと合わせ、変更点がある場合はすぐに共有、少しでもイメージ違うと感じた場合は確認、こういった基本的な部分の大切さをすごく感じました。

また、成果物に関してはもっとコンセプトを明確にして、それに沿った遊び心溢れるものにできたら面白そうだなと思いました。

このほかにも、時間があればタッチパネルや日本語表示を試したいと思っていたので、今後機会があれば積極的に試してみたいと思います！