susutex’s blog

毎日更新は諦めたが自転車、電子工作、プログラミングとかについて書くかもしれないブログ

BLEのCycling Speed and Cadence Serviceについて調べる

susutex.hatenablog.com

でリードスイッチを取り付けて数ヶ月、回路とプログラムはシリアル経由でPCのターミナルに速度とパワーを表示するところまでできていた。しかし、このままでは見づらいので表示機を追加しなきゃなあと思ったところで配線作業がすごく面倒で放置していた。

再開しようと思ったものの表示器を作るのがあまりにも面倒すぎ、nRF51822に移植してBLEでサイコンアプリに表示するほうが楽なんじゃないかと思い始めた。以前書いたプログラムはmbed compilerを使ってFRDM-KL25用に書いたが、デバイス特有の機能は使わないようにしていたので移植は容易だろう。

susutex.hatenablog.com

過去の自分の記事とソースコードを眺めてサービスの実装方法を思い出す。

 

スピードセンサに実装するServiceはCycling Speed and Cadence(以下CSC)。

https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.service.cycling_speed_and_cadence.xml

 

CSCに最低限必要なCharacteristicsは"CSC Feature"と"CSC Measurement"。

 

CSC Feature

https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.csc_measurement.xml

中身は16bitの"CSC Feature"だけ。以下3つのビットがあり残り13ビットはReserved。

  • Wheel Revolution Data Supported : センサがホイールの回転数=速度情報をサポートしているか
  • Crank Revolution Data Supported : センサがクランクの回転数=ケイデンスをサポートしているか
  • Multiple Sensor Locations Supported : よくわからん。多分いらないので0にしておく。

今回は速度のみのサポートなのでWheel Revolution Data Supportedを1にする。

 

CSC Measurement

https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.csc_measurement.xml

スピードとケイデンスの情報が入っている。スピード情報のみをサポートする場合、以下3つのフィールドが必要。

  • Flags(8bit) : CSC Measurement内にスピードとケイデンスの情報のうちどれが入っているのかを示す。
  • Cumulative Wheel Revolutions(32bit) : 累積ホイール回転数?
  • Last Wheel Event Time(16bit) : 単位1/1024[s]。最後にホイール回転数増加を検出した時間?

Flagsは中身がCSC Featureと重複しているが、CSC Measurementの先頭で以降にどれだけの量のデータがあるかわからないと困るんだろう。多分。

CSC Measurementのページだけ見ても説明不足で後者二つの値の意味がいまいちわからない。それぞれの名前から、Cumulative Wheel Revolutionsは累積ホイール回転数、Last Wheel Event Timeは最後にホイール回転数増加を検出した時間であり、センサはそれらを定期的に送信、サイコンアプリ側でそれらの変位とサイコンアプリ側で設定されているホイール外周径から速度を計算するのだろうと推測した。Cumulative Wheel Revolutionsを5、Last Wheel Event Timeを1024ずつ増やしながら送信をし、サイコンアプリ側のホイール外周設定を2096mmとすると、速度は

2096 * 5 / (1024/1024) * 3600 / 10000000= 37.728[km/h]

で計算されるはず。

 

送信データの並べ方

地味に詰まったのがCSC Measurementのデータの入れ方である。

フィールドは8bit, 32bit, 16bitのフィールドなので7octet(byteは厳密にはビット数が決まってないので通信系ではoctetというらしく、BLEのページもoctetと書いてあるのでそれに従う)というとても中途半端な量な上、32bitと16bitのフィールドが32bitアラインメント境界をまたぐ。しばらくC言語でプログラムを書いていなかったのでどうすればいいのかわからず、結局アプリ側ではそれぞれ8, 32, 16bitの変数として扱い、送信直前にuint8_tの配列に地道に並べる方法を取ることにした。

さて、並べるのは良いが、どう並べればいいのか。CSC Measurementのページには

"The fields in the above table are in the order of LSO to MSO. Where LSO = Least Significant Octet and MSO = Most Significant Octet."

とある。最初どういう意味なのかわからずサイコンアプリの表示を見ながらいろいろ試行錯誤した結果、配列の先頭から

Flag | Cumulative Wheel Revolutions | Last Wheel Event Time

の順で並べ、複数octetに渡るデータはLittle endianで並べ、Cumulative Wheel Revolutionsを5、Last Wheel Event Timeを1024ずつ増やしながら送信すると、アプリ側に前述の計算と一致する37.8[km/h]が表示された。

 

f:id:susutex:20170823204822p:plain

値の意味は推測どおりのようだ。今回は使用しないがクランク側にも同様にCumulative Crank RevolutionsとLast Crank Event Timeというフィールドがあるので、ケイデンスセンサを作る場合も同じようにすればよいのだろう。

 

Cycling Power Service内にもWheel Revolution Dataがある

CSC Measurementのフィールドの意味、Characteristics内に複数のフィールドがある場合と複数octetに渡るフィールドがある場合のデータの並べ方について理解を深めることができた。以前作成した速度検出プログラムは速度検出方法が少し違うので手直しが必要だが、それほど大きな手間ではないだろう。

と、ここまで調べたところでCycling Power Service内にもWheel Revolution Dataがあることに気づいてしまった。多分こっちに入れれば別途CSC Serviceを実装する必要がない。最終的に推定パワーも表示できるようにするならば、プログラムの手直しの前にCycling Power Serviceの内容を調べておいて、できれば一気に実装してしまったほうが楽そうだ。