fl3xbl0wプロジェクトロゴ

トレッドミルモーターコントローラー - fl3xbl0w

リリース日: 2022年5月28日

リバースエンジニアリングプロジェクト。Bowflex Treadmill 22 から始まりましたが、Nautilus Inc.(Nautilus、Bowflex、Schwinn)が販売する任意のAndroid搭載機器に一般化されました。

これは主に Treadmill 22 と Treadmill 56 に適用されます。

モーターコントロールボードは Electronics Way Industry によって製造されています。

モーターコントローラーボード B017D

Nautilus Inc. が提供する サービスマニュアル (archive.org のバックアップ)を参照してください:

トレッドミルの電気図

特にこの部分に焦点を当てます:

トレッドミルの通信経路

モーターコントローラーを接続する「通信ケーブル」が5ピンケーブルであることが確認できます。5ピンコネクタは1つだけです。 ケーブルには対応する色でラベルを付けています(データとスイッチはオプトアイソレートされています):

ケーブルの色 ラベル
赤 GND
白 RXD
黒 TXD
黄 +12
緑 SW

ボードはAndroidコンソールに直接接続されていません。

唯一の5ピンコネクタはMolex製です。「small Molex connectors」でGoogle検索すると、モーターコントローラーボードを接続するために使用されている Molex Micro-Fit 3.0 Single Row (5-Pin) の画像が見つかりました:

Molex Micro-Fit 3.0 コネクタ

AliExpressリンク

jadx-gui を使用して NautilusLauncher.apk を確認すると、Androidタブレットと「ユニバーサルコンソール」が230400 Baud のシリアル通信(/dev/ttyS4 を使用)で通信していることがわかります。これはここでは分析していません。これはAndroidと「ユニバーサルコンソール」間の通信を指しています。私たちは「ボタンパネルコントローラー」と「モーターコントローラーボード」間の通信を調査しているため、潜在的な故障点として3つのボードを除外しています。

トレッドミルベースとBowflexコントローラーボード間のケーブルにESP32またはCH340ベースのシリアルブリッジを直接接続しようとすると、トレッドミルベースが正しく初期化されず、その後さらに調査するためにロジックアナライザーを取得しました。

更新 2025

最近数週間、そして私がこれを始めてからほぼ3年後、多くの人々がこのプロジェクトの進捗について問い合わせてきました。これは、トレッドミルシステムがひどく、機械が故障し始めるのは時間の問題だったという私の最初の仮定を確認するものでした。ロジックアナライザーを活用する良い機会だと思い、これまでほこりをかぶっていたものを使用しました。

ロジックアナライザーをTXDおよびRXDライン(もちろんGNDにも)に接続することで、通信を中断することなく両者間のメッセージを即座に傍受できました。最初にESP32を使用できなかったのはインピーダンスの問題によるものだと思われます。数分の試行錯誤の後、以下のシリアル設定に到達しました:

- 2400 Baud
- フレームあたり8ビット
- ストップビット1
- パリティビット無し
- 最下位ビットを先に送信
- TXD: 反転信号
- RXD: 非反転信号

これらの設定により、明確に定義されたメッセージを確認できました。

UARTメッセージの傍受

起動プロセス中のUARTメッセージの傍受

すぐに気づいた点:

  • ボタンパネルから送信されるすべてのメッセージは 0x68 で始まります
  • モーターコントローラーボードから送信されるすべてのメッセージは 0x73 で始まります
  • 両者からのメッセージは 0x43 で終了します
  • 一般的に、ボタンパネルからのメッセージはモーターコントローラーボードからのメッセージ受信後100ms後に送信されます
    • 起動プロセス中は、ある場合で300msの差があります
  • 通信ラインのノイズが非常に多く、メッセージの読み取りが困難です

これを基に、メッセージを解読し、両者間で何が通信されているかを理解するプロセスが始まり、運動ルーチンの制御された変更が可能になります。

速度変更の傍受

特定の速度に制御された変更を加えることで、モーターコントローラーボードに送信される以下の値を観察できます:

画面上の速度 送信されたメッセージ
0.0 km/h (待機中または一時停止中) 0x68 0x08 0x80 0x50 0x00 0x0A 0x00 0x00 0xE2 0x43
2.0 km/h 0x68 0x08 0x80 0x50 0x14 0x0A 0x00 0x00 0xF6 0x43
3.0 km/h 0x68 0x08 0x80 0x50 0x1D 0x0A 0x00 0x00 0xFF 0x43
5.0 km/h 0x68 0x08 0x80 0x50 0x31 0x0A 0x00 0x00 0x13 0x43

バイト5とバイト9が変化していることが観察できます。バイト5は16進数での速度、バイト9はチェックサムのようです。

バイト5の値を10進数に変換:

画面上の速度 16進数 10進数
0.0 km/h (待機中または一時停止中) 0x00 0
2.0 km/h 0x14 20
3.0 km/h 0x1D 29
5.0 km/h 0x31 49

Androidシステムの一部を数年前にデコンパイルした際、Bowflexアプリケーションがメートル法から帝国単位への変換を内部的に行い、「UCB」と通信していることを思い出しました。モーターコントローラーボードはメートル法を使用しており、メトリックからインペリアル、そして再びメトリックへの変換で精度が失われているようです(ボードが期待するのは、1桁の小数点精度で処理されるものです)。正しく行うのがそれほど難しかったのでしょうか、Nautilusさん?

これを考慮すると、スケーリングファクターとして10を適用すると、モーターコントローラーボードに送信される値に完全に一致します。したがって、式は次のようになります:

10進数の値 = 速度(km/h)× 10

傾斜変更の傍受

速度と同じプロセスを使用して、モーターコントローラーボードに送信される以下の値を観察できます:

画面上の傾斜 送信されたメッセージ
-5° 0x68 0x08 0x80 0x50 0x1D 0x00 0x00 0x00 0xF5 0x43
0° 0x68 0x08 0x80 0x50 0x1D 0x32 0x00 0x00 0x27 0x43
9° 0x68 0x08 0x80 0x50 0x1D 0x8C 0x00 0x00 0x81 0x43

この場合、バイト6は16進数での傾斜を示しており、バイト9がチェックサムであることが確認できます。

バイト6の値を10進数に変換:

画面上の傾斜 16進数 10進数
-5° 0x00 0
0° 0x32 50
9° 0x8C 140

モーターコントローラーボードに送信される値に完全に一致する式は次のとおりです:

10進数の値 = (角度 + 5) × 10

チェックサム

これはマイクロコントローラーにおける簡単で標準的なチェックサムのようで、メッセージのすべてのバイトを加算し、256に達するとオーバーフローします。単純な表現としては次のようになります:

uint8_t calculateChecksum(uint8_t *msg) {
  return msg[1] + msg[2] + msg[3] + msg[4] + msg[5] + msg[6] + msg[7];
}

uint8_t を返り値の型として使用することで、オーバーフローが自然に発生します。for loop を使用して値を合計し sum % 256 を返すこともできますが、マイクロコントローラーでは実質的な利点がなく速度が遅くなります。

次のステップ

  • 起動プロセスの論理的な理解を深める、または少なくとも再現する
  • セーフティキー(衣類に取り付ける赤いもの)とのやり取りをキャプチャする
  • モーターコントローラーボードから送信されるメッセージを解釈する(ボタンパネルから送信されるメッセージと大きくは変わらないはず)

これにより、ボタンパネルの機能を再現し、マイクロコントローラーからトレッドミルを制御できるようになります。

– 続く –

コンテンツの翻訳者: o1-mini

©2022-2026 セバスティアン・バレネチェア. すべての権利を保有.

構築: Astro v7.3.2.