Edited at

サイクルコンピューターをガチで作ってみたら、割とできてしまったという話

(2019/6/19)すごい反響を頂き、ありがとうございます。プログラム公開を目指して準備中です。また、どこかのイベントで発表できる機会がないか探しています。また、5月で少し進化し、その成果をMIPカラー反射型液晶モジュールをRaspberry Pi Zeroで使うを公開しましたので、興味がある方は是非お試しください。


はじめに

Raspberry Pi Zero Wで、スポーツ自転車向けにサイクルコンピューターを作ってみました。

(I made a DIY GPS bike computer or cycling computer based on Raspberry Pi Zero W)



ANT+規格の専用センサーやGPSから取得したデータをリアルタイムに表示、記録し、Strava等の記録サイトにアップロードできる形式でログを書き出し、といった基本的な流れはできるようになっています。

この写真は都内から熱海を越えて西隣の丹那盆地まで走った時のもので(Stravaの走行ログ)、上がPioneer SGX-CA600、下が作成中のデバイス(Pi Zero Cyclecomputer)です。値の取得間隔やオートストップの処理等の違いから値が微妙にずれていますが、使える水準に達していると思います。

項目名
SGX-CA600
Pi Zero Cyclecomputer

距離 (Dist)
121.2 km
121.4 km

仕事量 (work)
2,461 kJ
2,393 kJ

実走行時間 (Time/Timer)
4時間56分50秒
4時間53分

獲得標高 (EleG/Ascend(※1))
1,000 m
708 m (※2)

※1 : 動詞ではなく名詞のAscentにすべきですね、修正済。

※2 : 概ね一致する予定でしたが、気圧センサのスパイク除去ロジックにバグがあり、終盤のヒルクライム中に横置き状態に陥りました、、、こちらも対応済。

バッテリーの内装、ケースの作成、細かい機能の作り込み、市販品にはない機能の作成が十分にできておらず、まだ完成には至っていませんが、「意外と作れてしまい、驚き」というのが率直な感想です。

個人がそれぞれの嗜好に合わせてデバイスを作れる時代は、少しずつやってくるのかもしれません。


なぜ作ろうとしたか

サイクリングという趣味を広く長く愉しむ過程、また、Linuxや多少のプログラミングの経験があるというバックグラウンドが合わさって、この形になりました。


サイクルコンピューターの進化

元々、サイクルコンピューターはモノクロ液晶にスピードや距離、時計を表示するものが大半で、機能が非常にシンプルな分、ボタン電池1個で鬼のように持つというのが特徴でした。

2010年よりちょっと前ぐらいでしょうか、サイクルコンピューターが高度化し始め、「高嶺の花」とも言える憧れのデバイスになります。

センサーがANT+規格により無線化


  • スピード&ケイデンスセンサーを始め、心拍計や、当時少しずつ広まりを見せ始めていたパワーメーターをまとめて扱えるように

  • トレーニングの観点が大幅に増え、データの蓄積や分析ができることから、練習熱心な層に人気が出ました

カラー液晶、バックライト、地図、ルート表示/ナビゲーション


  • 紙の地図やスマホいらずで、昼夜問わず進むべき道がわかるように

  • ブルベ等に参加する長距離ライダーや、ツーリングが好きな層に人気が出ました

いろいろな縁があって、ロードバイクを2006年から愉しんでいますが、パーツの交換はできることを広げるための重要な一要素です。今振り返ると、自分の体に合うサドル、ミドルグレード以上のホイール、地図付きサイクルコンピューターは行動範囲を大いに広げてくれました。


進化はどこへ向かう?

最近のサイクルコンピューター(略してサイコン)はスマホに影響されたのか、すっかりスマホのようになった感があります。


  • ナビ機能

  • Wifi、Bluetooth搭載

  • クラウド連携

  • アプリ連携

  • スマホの通知を表示

  • 同一機種間の連携機能

  • 独自アプリ対応 (GarminのConnect IQ)

処理量や消費電力の増加を受け、チップの高速化やバッテリー容量の大型化が進み、それでも稼働時間が短くなる場合は、画面の表示を切ってバッテリーを長持ちさせるパワーセーブ機能といった本末転倒な機能を持つ機種が登場し始めました。

さすがに、大手メーカーが出した直近の機種では操作性やバッテリーの持ちといった基本的な機能は大分改善されていますが、新機能の方向性は疑問符を持つようになりました。少し便利になったけどなくても困らない機能が多い、というのが正直なところです。地図搭載ほどのインパクトはここ数年、全く感じなくなりました。

個人的に欲しい機能は別にあって、ツーリングの例を挙げます。


  • 悪天候の時は、雨雲の位置や風向きは常に知りたいので、それを見やすい形で表示してほしい


    • 天気予報は不要で、現在地点周辺における直近の履歴と数時間先までの推移が知りたい



  • 道の駅やコンビニを収録してほしい


    • Garminの自作OSM地図でチューニングしきれば、Garminデバイスで一つの完成形を見ることはできるはず(未着手)




自分で作れそうな小型のハードが登場した


Intel Edison

2014年冬に知人の紹介でIntel Edisonに触れる機会がありました。切手サイズと言われた非常にコンパクトなサイズながら、CPUはx86互換、OSはLinux(Yocto Linux)、WifiとBluetoothを積んでいて、IoT時代の小型コンピューターと当時はよく宣伝されていました。

学生時代や仕事の中で、Linuxやプログラミングの経験が多少はあったので、ロードバイクに結びつくもの、すなわちサイクリングコンピューターを勉強がてら作ろうとしました。タッチスクリーン、ANT+、GPSがあれば一通りのことができるデバイスが出来上がります。

しかし、Yocto Linuxはパッケージの追加が容易ではない、システム容量が2GBしかないため空き容量がすぐになくなる、ハードの拡張性も悪い点に苦しめられ、挫折しました。(自分の過去の投稿に跡が残っています)


Raspberry Pi Zero

1年後の2015年冬、Raspberry Pi Zeroが発売され、その小ささからすぐに飛びつきました。Intel Edisonと比べると、OSやパッケージがよく整備され、pHAT等のハードウェアモジュールや、国内外の情報が比較対象にならないほど多いことに当時は少し感動していました。

そんな中、いろいろと弄っていたら、必要な要素を結びつけることができてしまいました。


  • Pythonで使用できるGUIライブラリのPyQt5で、ストップウォッチを作った



    • こちらを参照しました。感謝です。



  • サイズを調整し、タッチスクリーン(PiTFT 2.4)で全画面表示

  • ANT+心拍センサーの値を読めるようにし、ストップウォッチに組み込んだ


    • ANT+スピード、ケイデンス、パワーの読み取りもその後実装



  • GPSや気圧計を繋ぎ、表示できるようにした

  • 記録、書き出し機能をつけた


    • まずは実質XMLな.tcx形式

    • .tcx形式ではサイズが膨らむので、バイナリの.fit形式にも対応



小型コンピュータボード、ディスプレイ、ANT+、GPS、記録と書き出しまで全て結び付けたものを未だに誰も作っていないので、これは自分が作るしか!と思い、道半ばですが今に至りました。まずは基本的な部分をしっかりと作りこみ、その上で欲しい機能の実装や他スポーツへの展開を考える、という段取りで進めています。

類似の作成例としては、古くはBuild a Readable Bicycle Computer、一番近いプロジェクトはOpen Cycling Computerあたりです。


Linuxとプログラミングの知識があれば、意外と作れる

当初、この手のものを作るのは、大学の工学科等、それなりのバックグラウンドがないとできないという先入観を持っていました。しかし、Raspberry Pi Zeroを使い始めてからは、Raspberry Piが持つエコシステムを大いに活用し、随分と敷居を下げてもらった印象があります。

Linuxとプログラミングの知識でここまで大体来れてしまったことは自分でも驚きでした。プログラミングとハードを一緒に勉強する形として、本当にありな形だと思っています。

手と頭と脚がバランスよく要りますが、いい感じに趣味が進化したと思っています。


実装した機能について

ここから細かい話に入ります。


ストップウォッチ機能

一式作ると結構な分量です。


  • ラップ

  • 最大値


    • [全体 / ラップ / 直前ラップ] × [心拍、スピード、ケイデンス、パワー]



  • 平均値


    • [全体 / ラップ / 直前ラップ] × [心拍、スピード、ケイデンス、パワー]



  • 積算値


    • [全体 / ラップ / 直前ラップ] × [距離、仕事量、獲得標高(上昇量、下降量)]



  • 記録


    • sqlite3で常に記録

    • 中断、電源断を跨いだ再開も可。上記の最大/平均/積算も復元。



  • 書き出し


    • .tcx形式、.fit形式



fitファイルをStravaにアップロードした例 (冒頭のライド)




各種センサーとの通信


  • ANT+


    • 心拍 / スピード / ケイデンス / パワー(キャリブレーションは未対応)

    • センサーのスキャン・ペアリング機能



  • GPS


    • 距離、速度

    • ANT+が使用できない時に代替



  • I2C


    • 気圧と温度から高度を算出し、獲得標高や斜度を求める (獲得標高や斜度は使える水準に達するまで相当な労力が必要だったので、追って解説予定)




表示機能


紐地図 ※実装途中

現在地点、.tcx形式のルートファイルの内容、今まで通ってきた軌跡を表示

将来的には、QMLの地図に置き換えを検討中


コースプロファイル ※実装途中

.tcx形式のルートファイルによるコースプロファイル、現在地点を表示


直近のパワー、心拍のグラフ


別の人のパワー、心拍を表示

適当に3つずつ表示。(下記スクリーンショットの中段、下段。上段は自分の値)


  • ANT+のcontinuous scanモードを使用


    • センサーIDと値がセットで取得可、心拍とパワーだけピックアップ

    • 同時に50センサーぐらいは処理できることは確認済み



  • 2~3名で走っている状態なら、安定して表示可


    • ただ、消費電力が激しいので長時間の使用は不向き

    • 普通にセンサーの追加登録という形でで2人目、3人目の表示機能の作成を検討中




ハードウェア構成

現時点での部品の構成は以下です。合計で1万円ちょっとです。



※ジャンパピンやソケットを使う部品は、何時間も走行していると振動でたまに瞬断し、その後は値が取れなくなります。この対策として、直接半田付けをしています。例えば、後述するPiTFTはRaspberry Pi Zero側につけた40ピンのヘッダーに直接半田付けをしています。microUSBはコネクタで接続する運用をしていますが、隙間を緩衝材的なもので埋め、上からテープで固定しています。


Raspberry Pi Zero W ($10)


  • 公式サイト

  • 互換品や別のモジュールは数あれど、サイズの小ささ、消費電力小、I/F豊富、wifi&BTあり、SDカード使用可から、これ一択


PiTFT 2.4 ($35)


  • 公式サイト

  • 2.4インチは横幅がジャストサイズ、ボタン4つ含む

  • 1番のバッテリー食いパーツ。とはいえ、サイズの小ささから消費電力はまだマシな方。2.8、3.2、3.5インチになるにつれて結構増える。IPS液晶にするともっと増える。

  • カラーとタッチパネルを一旦やめ、e-inkのPaPiRus ePaper/eInk スクリーンハットを試し中



    • 登場から2年近く経って、ライブラリ周りがだいぶ改善され、代替を本当に検討できる状況になっていました。ようやくpython3系に対応、高速な画面更新メソッドが実装された(Papirus.partial_update(), Papirus.fast_update())、フレームバッファーの画面をまるごとコピーができるコマンドが開発中(papirus-framepush、ただし既に存在するpapirus-fbcopyを改変すれば使えそう)、という状況です。

    • GUIの画面を定期的に画像に変換しその画像を描画、または上述のフレームバッファーからのコピーを行うと、今回使用しているGUIライブラリのQt(PyQt)をそのまま使い回すことができそうです。オリジナルの描画ライブラリを1から作成する必要はないですね。気が遠くなるので敬遠していました。



  • Garminが使っているような反射型液晶のモジュールが出てくれば一変するはず




USB ANT+ドングル


GPSモジュール


センサー(I2C接続)



  • Enviro pHATを使用 (¥2,000)


    • 気圧センサー、加速度センサー、地磁気センサー、照度センサー

    • せっかく加速度と地磁気があるのなら、ジャイロもつければ良かったのにと思います



  • 今は気圧センサーのみ使用し、高度を計算


    • 加速度と地磁気は使用できるよう、準備中

    • 加速度:停止検知 (停止時にGPSの位置がぶれるのを改善できる見込み、斜度の補正にも使えるか?)

    • 地磁気:進行方向 (GPSでも取れるので2者で合成し、地図上で向きを示す機能をつける程度?)




今後

バッテリー内蔵と防水ケース作成に向け、最適解を検討中です。

バッテリーは現在モバイルバッテリーを使っていますが、ハブダイナモから半永久的に取得も検討しています。ディスクロード用にハブダイナモ付きのカーボンホイールをのむラボ様に組んでいただきました。


ソフトウェア構成

開発が実機上に閉じないように、クロスプラットフォームのものを念頭に選択しています。


Python (3系)


  • スクリプト言語でコンパイル不要、導入のしやすさ、守備範囲の広さより

  • ANT+の通信は openantforkしたものを使用


    • スキャン機能を追加



  • GPSはgps3を使用 (裏でgpsdが動作)

  • I2Cは、パラメータの設定に問題なければ提供ライブラリを使用



  • グラフ描画は pyqtgraphforkしたものを使用


    • コースプロフィールを描画するために一部改変 (台形状に特定の色を塗りたいため)



  • 他は定番もの


    • numpy、sqlite3、標準ライブラリ等




PyQt


  • クロスプラットフォームのGUIライブラリであるQtのPythonバインディング

  • 現在はQtWidgetsを使用だが、オフライン地図やスワイプ操作が扱えるQMLに移行予定

  • Raspbian StretchのQtのバージョンは5.7と古すぎるため、自力で最新版に上げるかRaspbian Buster(5.11)まで待つ必要あり


    • 別のGUIライブラリであるkivyも試す予定あり




起動まわり


  • 現時点はデスクトップアプリという形


    • Raspbian Desktopを一度起動した後、Pi Zero Cyclecomputerを起動



  • 上記だと起動までの道のりが長すぎるので、


    • Rasbian Liteで起動をsystemdでサービス化し、

    • Xを介さずlinuxfbで直接PiTFTに描画するやり方でも運用中



  • 最終的にはOSをRasbianではなく、組み込み向けLinuxのBuildrootを検討中


今後


Tensorflow Liteで何かしら判断してくれるもの

自分の走行データは10年分程度蓄積しているので、自分の考え方を再現させたい。

(データの意味づけをどうするか、というところはありますが)


雨雲、風速を地図に重ねて描画

とっくに実装されていてもいいかと思うのですが、意外とされていない。


Strava Heatmapを使ったルート検索

すごいことを考えている人が既にいます。


リアルタイムアップロード

Ambientを用いて一度実装しましたが、自分の走行データを自分が見る限りだと機能が重複し、あまり意味を成しません。したがって、


  • データを送る人と見る人は違う想定を置く

  • 見るだけではなく、使い道に特化し、双方向のやり取り

としたほうが意味がありそうです。考えている使い道は以下です。


  • エンデューロのレース ※走行中に通信していいか、ルールは要確認


    • ほぼリアルタイム(10秒間隔等)で位置、パワー、心拍を送信

    • 「交代して/交代しろ」ボタン、「OK/NO」ボタン

    • メッセージ読み上げ



  • 目的地で人が待っている場合


    • 一定の時間内で到着する見込みなら、数分間隔(5分間隔等)で位置を送信

    • 待っている人からメッセージを受信してスクロールして表示 or 読み上げ



おそらく、別のサービスを使うか、自前で実装することになりそうです。

もてぎエンデューロの例

地図はマーカーしか打てないため、同じところをぐるぐる回るレースでは相性が悪かったです。

(それでも1周分に点を絞っていますが、衛星写真に毎回切り替えないとコースが表示されない)

なので、地形(標高データ)+αで認識してました。




別スポーツへの展開(パラグライダー)

パラグライダーでも、GPSバリオメーターというGPSと気圧高度計を積んだ小型のロガーが使われています。

サイクルコンピューターと同じく、まずは基本的な動作をしっかりと再現し、市販品にはない機能を作れないかチャレンジしてみたいと考えています。紹介をいただいた人によると、いろいろな情報を組み合わせて飛行中にサーマル(上昇風)の位置を予測をしたいとのこと。

追加した項目


  • 上昇速度 (Vertical Speed)

  • 累積標高 (Accumulated Altitude): 自転車とは異なり、上昇分と下降分の総和

  • 滑空比 (Glide Ratio): 1m下降した時に進んだ水平距離。斜度の逆数


構築手順

ソースコード含め、今後記載していきます。