リバースエンジニアリングプロジェクト。Bowflex Treadmill 22 から始まりましたが、Nautilus Inc.(Nautilus、Bowflex、Schwinn)が販売する任意のAndroid搭載機器に一般化されました。
これは主に Treadmill 22 と Treadmill 56 に適用されます。
モーターコントロールボードは Electronics Way Industry によって製造されています。
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)
の画像が見つかりました:
jadx-gui
を使用して NautilusLauncher.apk
を確認すると、Androidタブレットと「ユニバーサルコンソール」が230400 Baud のシリアル通信(/dev/ttyS4
を使用)で通信していることがわかります。これはここでは分析していません。これはAndroidと「ユニバーサルコンソール」間の通信を指しています。私たちは「ボタンパネルコントローラー」と「モーターコントローラーボード」間の通信を調査しているため、潜在的な故障点として3つのボードを除外しています。
トレッドミルベースとBowflexコントローラーボード間のケーブルにESP32またはCH340ベースのシリアルブリッジを直接接続しようとすると、トレッドミルベースが正しく初期化されず、その後さらに調査するためにロジックアナライザーを取得しました。
最近数週間、そして私がこれを始めてからほぼ3年後、多くの人々がこのプロジェクトの進捗について問い合わせてきました。これは、トレッドミルシステムがひどく、機械が故障し始めるのは時間の問題だったという私の最初の仮定を確認するものでした。ロジックアナライザーを活用する良い機会だと思い、これまでほこりをかぶっていたものを使用しました。
ロジックアナライザーをTXDおよびRXDライン(もちろんGNDにも)に接続することで、通信を中断することなく両者間のメッセージを即座に傍受できました。最初にESP32を使用できなかったのはインピーダンスの問題によるものだと思われます。数分の試行錯誤の後、以下のシリアル設定に到達しました:
- 2400 Baud
- フレームあたり8ビット
- ストップビット1
- パリティビット無し
- 最下位ビットを先に送信
- TXD: 反転信号
- RXD: 非反転信号
これらの設定により、明確に定義されたメッセージを確認できました。
起動プロセス中のUARTメッセージの傍受
すぐに気づいた点:
0x68
で始まります0x73
で始まります0x43
で終了しますこれを基に、メッセージを解読し、両者間で何が通信されているかを理解するプロセスが始まり、運動ルーチンの制御された変更が可能になります。
特定の速度に制御された変更を加えることで、モーターコントローラーボードに送信される以下の値を観察できます:
画面上の速度 | 送信されたメッセージ |
---|---|
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
を返すこともできますが、マイクロコントローラーでは実質的な利点がなく速度が遅くなります。
これにより、ボタンパネルの機能を再現し、マイクロコントローラーからトレッドミルを制御できるようになります。
— 続く —
©2022-2025 セバスティアン・バレネチェア. すべての権利を保有.
構築: Astro v5.5.4.