家庭用サイクルトレーナーにmicro:bitをつなぐ（その１）- ワイヤレス運動測量計から出力されるクランク回転センサーの信号をモニターする

# 家庭用サイクルトレーナーにmicro:bitをつなぐ（その１）

各種メーカーから家庭用サイクルトレーナーが販売されていますが、その中の１つに、**ワイヤレス運動測量計**付きのマグネット式の家庭用サイクルトレーナーがあります。
在宅勤務になり、外出も少なくなった今、室内で運動ができるようにと購入し、使用しています。

[リンク：今回、使用している家庭用サイクルトレーナー（Amazonの商品ページ）](https://amzn.to/3qPAFcN)

単に運動だけが目的ではありません。BBC micro:bitをつないでプログラミング自体を楽しんだり、バーチャルライドを楽しんだりしていこうと考えています。

## ワイヤレス運動測量計から出力されるクランク回転センサーの信号をモニターする

この記事では、家庭用サイクルトレーナーの**ワイヤレス運動測量計**にBBC micro:bitをつないでクランク回転センサーの信号をモニターできるようにします。

## 警告

* 分解すると販売店やメーカーなどの保証等を受けられなくなりますのでご注意ください。
* はんだ付けや配線などの電子工作時には、けが、やけど、火災等に注意してください。
* 無線モジュール及びアンテナ端子の改造はしないでください。

# デジタル信号等の取り出しと接続

**ワイヤレス運動測量計**の裏ブタを開けると、基板が見え、信号線の説明がプリントされています。**STEP**というプリントがされており、そこから出ている信号は、ペダルを回転させると変化するデジタル信号の出力がでているのではないかと想像しました。

それぞれの基板の穴からリード線をはんだ付けし、micro:bitの各端子へと接続します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/7790339a-8e37-f583-2792-1a5e03aaaf08.png)

|#|基板|micro:bit|補足|
|---|---|---|---|
|1|STEP|P2|STEPの下側。|
|2|VDD|3V|電源供給は、ワイヤレス運動測量計の乾電池か、micro:bitの電源入力のどちらかからとします。|
|3|GND|GND|写真ではSTEP上側から取得。VDDの左のGNDでも良い。|


# 組みつけ

配線が完了したら、裏ブタを取り付けます。micro:bitと電池ボックスの裏ブタとを固定する台座を3Dプリンターで作成し、組みつけました。配線は、ステレオ延長コードを使用し、micro:bitへの電源供給もかねて、抜き差しが簡単にできるようにしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/0de1dfb0-8f3b-f8ea-1755-8167f28d62e3.png)


# ソースコード

端子P2に接続したSTEP（下側）の信号線からどのような値が出力されているかを確認するソースコードです。
`MICROBIT_PIN_EVENT_ON_EDGE`で、立ち上がりと立ち下がりをイベントで検出し、そのタイムスタンプ（マイクロ秒）をシリアル通信でモニターできるようにしました。

ソースコードのビルドは、[Arm Mbed オンライン](https://ide.mbed.com/compiler/)で可能です。

**Source URL**に `https://github.com/jp-96/microbit-digital-capture.git` と入力し、`Program`としてインポートして、コンパイルします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/fcd33729-3aac-b888-9f0e-775ca4a43b18.png)


```main.cpp
#include "inttypes.h"
#include "MicroBit.h"

MicroBit uBit;
MicroBitPin sensorPin(MICROBIT_ID_IO_P2, MICROBIT_PIN_P2, PIN_CAPABILITY_DIGITAL);

uint64_t lastFallTimestamp=0;
uint64_t lastRiseTimestamp=0;
uint32_t fallCount=0;
MicroBitImage IMG_FALL("1,1,1,0,0\n0,0,1,0,0\n0,0,1,0,0\n0,0,1,0,0\n0,0,1,1,1\n");

void onEdgeSensorPin(MicroBitEvent e)
{
    int pinValue;
    uint64_t duration;
    switch (e.value)
    {
    case MICROBIT_PIN_EVT_FALL:
        pinValue = 0;
        lastFallTimestamp = e.timestamp;
        duration = lastFallTimestamp-lastRiseTimestamp;
        fallCount++;

        uBit.display.stopAnimation();
        uBit.display.scrollAsync(IMG_FALL,(int)(duration/15000),-1);
        break;
    
    case MICROBIT_PIN_EVT_RISE:
        pinValue = 1;
        lastRiseTimestamp = e.timestamp;
        duration = lastRiseTimestamp-lastFallTimestamp;
        break;
    
    default:
        return;
        break;
    }
    uBit.serial.printf("%"PRIu32", %"PRIu32", %d, %"PRIu32"\r\n"
        , fallCount, (uint32_t)e.timestamp, pinValue, (uint32_t)duration);
}

void setup(void)
{
    uBit.serial.printf("#, Timestamp, Digial, Duration, \r\n");

    uBit.messageBus.listen(MICROBIT_ID_IO_P2, MICROBIT_EVT_ANY, onEdgeSensorPin);
    sensorPin.getDigitalValue(PullUp);
    sensorPin.eventOn(MICROBIT_PIN_EVENT_ON_EDGE);

    uBit.display.scrollAsync("GO!");
}

int main()
{
    // Initialise the micro:bit runtime.
    uBit.init();

    create_fiber(setup);

    // If main exits, there may still be other fibers running or registered event handlers etc.
    // Simply release this fiber, which will mean we enter the scheduler. Worse case, we then
    // sit in the idle task forever, in a power efficient sleep.
    release_fiber();
}

```

# モニター結果

実際にUSBシリアル通信で、タイムスタンプをモニターして、CSV形式ファイルとして出力してみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/85bfa2ec-470b-72c6-8552-b23a42701441.png)

シリアル通信でモニターしたデータを確認すると、STEP信号は、通常 `High`(1)で、クランクのセンサーを検知すると、一定時間、`Low`(0)になるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/31f49c71-221b-c321-952d-4b768dd20425.png)

一部を拡大すると、およそ6000マイクロ秒間、`Low`になっていることが分かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/49858032-894a-cdb6-57f8-4763b602c9bd.png)


```モニター.csv
 #, Timestamp, Digial, Duration
 1, 17312157, 0, 17312157
 1, 17318549, 1, 6392
 2, 18678539, 0, 1359990
 2, 18684148, 1, 5609
 3, 20072057, 0, 1387909
 3, 20077870, 1, 5813
 4, 21419852, 0, 1341982
 4, 21426244, 1, 6392
 5, 22747612, 0, 1321368
 5, 22754059, 1, 6447
 6, 24094683, 0, 1340624
 6, 24100251, 1, 5568
 7, 25395638, 0, 1295387
 7, 25402086, 1, 6448
 8, 26674522, 0, 1272436
 8, 26680146, 1, 5624
 9, 27969881, 0, 1289735
 9, 27975505, 1, 5624
10, 29248047, 0, 1272542
10, 29253670, 1, 5623
11, 30539981, 0, 1286311
11, 30545925, 1, 5944
12, 31856147, 0, 1310222
12, 31862027, 1, 5880
13, 33115255, 0, 1253228
13, 33120757, 1, 5502
14, 34318002, 0, 1197245
14, 34324331, 1, 6329
15, 35565905, 0, 1241574
15, 35572232, 1, 6327
16, 36826930, 0, 1254698
16, 36833193, 1, 6263
17, 38118884, 0, 1285691
17, 38124321, 1, 5437
18, 39402478, 0, 1278157
18, 39407914, 1, 5436
19, 40704637, 0, 1296723
19, 40710898, 1, 6261
20, 42031297, 0, 1320399
20, 42037788, 1, 6491
21, 43308058, 0, 1270270
21, 43313624, 1, 5566
22, 44611223, 0, 1297599
22, 44616599, 1, 5376
23, 45893774, 0, 1277175
23, 45900165, 1, 6391
24, 47155187, 0, 1255022
24, 47161066, 1, 5879
25, 48386979, 0, 1225913
25, 48392802, 1, 5823
26, 49613840, 0, 1221038
26, 49620169, 1, 6329
27, 50865099, 0, 1244930
27, 50871363, 1, 6264
28, 52103054, 0, 1231691
28, 52108491, 1, 5437
29, 53319572, 0, 1211081
29, 53325130, 1, 5558
30, 54525752, 0, 1200622
30, 54531891, 1, 6139

```

## ケイデンスの算出

ケイデンス(RPM)を算出するには、'Low'(0)になったところから次に'Low'(0)になるまでの時間を求め、`High`(1)から`Low`(0)の出力が、1分間に何回発生するかを計算すればよいので、次の計算式で求められます。

> 計算式: ケイデンス(RPM) = 60000000 ÷ (T\<n\>-T\<n-1\>)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/60c3ef16-76d4-10b2-d4ad-b23a757829a8.png)


また、1回ごとにケイデンスを算出すると、ばらつきが発生します。そこで、反応が遅れる感じがありますが、次の計算式のように3回程度の平均値を使用すると扱いやすいと思います。

> 計算式: ケイデンス(RPM) = 3 × 60000000 ÷ (T\<n\>-T\<n-3\>)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/3dc063c5-5e2e-8cc4-7652-e0bdc6ed7010.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/c22ca41d-6665-1858-b282-63094d9e3e95.png)

# おわりに

・家庭用サイクルトレーナーのワイヤレス運動測量計とmicro:bitをつなぎました
・micro:bitのプログラミングは、Arm Mbed オンライン環境で行いました
・家庭用サイクルトレーナーのワイヤレス運動測量計からSTEP信号を取り出しました
・STEP信号からケイデンスを算出しました

[次回（その２）](https://qiita.com/jp-96/items/c494da04f04603ef258d)は、STEP信号からワイヤレス運動測量計に表示されているスピードをmicro:bitで推定してみます。

<!--
リンクを別タブで開く
https://qiita.com/yukichi/items/df4f5126f193a1c8efdb
-->
<script>
jQuery(document).ready(function(){
    jQuery('a[href^=http]')
    .not('[href*="'+location.hostname+'"]')
    .attr({target:"_blank"})
    .addClass("external")
    ;})  
</script>