логотип проекта fl3xbl0w

Контроллер двигателя беговой дорожки - fl3xbl0w

Выпущено 28 мая 2022 г.

Проект реверс-инжиниринга. Начался с беговой дорожки Bowflex 22, но впоследствии был обобщен для любой машины на Android, продаваемой компанией Nautilus Inc. (Nautilus, Bowflex, Schwinn).

Это в основном относится к Treadmill 22 и Treadmill 56.

Плата управления двигателем производится компанией Electronics Way Industry.

Плата управления двигателем B017D

Учитывая сервисный мануал, предоставленный Nautilus Inc. (резервная копия на archive.org):

Электрическая схема беговой дорожки

Фокусируясь конкретно на этой части:

Коммуникационный путь беговой дорожки

Мы можем идентифицировать “коммуникационный кабель”, который соединяет плату управления двигателем, как кабель с 5 контактами. Есть только один 5-контактный разъем. Я пометил кабели соответствующими цветами (данные и переключатель оптоизолированы):

Цвет кабеляМетка
красныйGND
белыйRXD
черныйTXD
желтый+12
зеленыйSW

Плата не подключена напрямую к консоли Android.

Единственный 5-контактный разъем от Molex. Поиск в Google по запросу “маленькие разъемы Molex” привел меня к изображению того, что они называют Molex Micro-Fit 3.0 Single Row (5-Pin), который используется для подключения платы управления двигателем:

Разъем Molex Micro-Fit 3.0

Ссылка на AliExpress

Посмотрев в NautilusLauncher.apk с помощью jadx-gui, я вижу, что они связывают Android-планшет с их “Универсальной консолью” через последовательный порт со скоростью 230400 бод (используя /dev/ttyS4). ЭТО не то, что мы анализируем здесь. Это относится к связи между Android и “Универсальной консолью”. Мы исследуем связь между “Контроллером кнопочной панели” и “Платой управления двигателем”, тем самым исключая три платы как потенциальные точки отказа.

Попытка напрямую подключить ESP32 или мост на базе CH340 к кабелям между основанием беговой дорожки и платой управления Bowflex привела к некорректной инициализации основания беговой дорожки, после чего я приобрел логический анализатор для дальнейшего исследования.

Обновление 2025

В последние недели, почти три года после того, как я начал этим заниматься, несколько человек связались со мной, чтобы узнать о прогрессе в этом направлении, подтвердив мое первоначальное предположение, что система беговой дорожки ужасна и что это было лишь вопросом времени, прежде чем машины начнут выходить из строя. Похоже, это было хорошее время, чтобы использовать мой логический анализатор, который до сих пор только собирал пыль.

Подключив логический анализатор к линиям TXD и RXD (и GND, конечно), я сразу же смог начать перехват сообщений между обеими сторонами без прерывания связи. Полагаю, изначально я не мог использовать ESP32 из-за проблем с импедансом. После нескольких минут проб и ошибок, я пришел к следующей конфигурации последовательного порта:

- 2400 бод
- 8 бит на кадр
- 1 стоповый бит
- Без бита четности
- Отправка младшего значащего бита первой
- TXD: инвертированный сигнал
- RXD: не инвертированный сигнал

С этими настройками я мог четко видеть определенные сообщения.

Перехват сообщений UART

Перехват сообщений UART во время процесса загрузки

Некоторые вещи, которые я заметил сразу:

  • Все сообщения, отправленные кнопочной панелью, начинаются с 0x68
  • Все сообщения, отправленные платой управления двигателем, начинаются с 0x73
  • Сообщения обеих сторон заканчиваются на 0x43
  • Обычно сообщения от кнопочной панели отправляются через 100 мс после получения сообщения от платы управления двигателем
    • За исключением процесса загрузки, где в одном случае разница составляет 300 мс
  • Шум на линиях связи невероятен, что затрудняет чтение сообщений

Исходя из этого, начинается процесс расшифровки сообщений и понимания того, что передается между обеими сторонами, внося контролируемые изменения в тренировочную программу.

Перехват изменений скорости

Внося контролируемые изменения в определенные скорости, можно наблюдать следующие значения, отправляемые на плату управления двигателем:

Скорость на экранеОтправленное сообщение
0.0 км/ч (ожидание или пауза)0x68 0x08 0x80 0x50 0x00 0x0A 0x00 0x00 0xE2 0x43
2.0 км/ч0x68 0x08 0x80 0x50 0x14 0x0A 0x00 0x00 0xF6 0x43
3.0 км/ч0x68 0x08 0x80 0x50 0x1D 0x0A 0x00 0x00 0xFF 0x43
5.0 км/ч0x68 0x08 0x80 0x50 0x31 0x0A 0x00 0x00 0x13 0x43

Можно заметить, что изменяются байты 5 и 9. Байтов 5, по-видимому, соответствует скорость в шестнадцатеричном формате, а байт 9, вероятно, является контрольной суммой.

Преобразование значений байта 5 в десятичное:

Скорость на экранеШестнадцатеричноеДесятичное
0.0 км/ч (ожидание или пауза)0x000
2.0 км/ч0x1420
3.0 км/ч0x1D29
5.0 км/ч0x3149

Распаковав некоторые части системы Android несколько лет назад, я вспомнил, что при настройке машины в метрической системе приложение Bowflex внутренне выполняет преобразование из метрической в имперскую систему для связи с “UCB”. Плата управления двигателем, по-видимому, использует метрическую систему, и, очевидно, происходит потеря точности при преобразовании из метрической в имперскую систему, а затем обратно в метрическую (что ожидает плата управления двигателем), поскольку все обрабатывается с точностью до 1 десятичного знака. Так сложно было сделать это правильно, Nautilus?

Учитывая это, и если применить коэффициент масштабирования 10, это идеально соответствует значениям, отправляемым на плату управления двигателем. Поэтому формула будет:

Десятичное значение = Скорость в км/ч × 10

Перехват изменений наклона

Следуя тому же процессу, что и со скоростью, можно наблюдать следующие значения, отправляемые на плату управления двигателем:

Наклон на экранеОтправленное сообщение
-5°0x68 0x08 0x80 0x50 0x1D 0x00 0x00 0x00 0xF5 0x43
0x68 0x08 0x80 0x50 0x1D 0x32 0x00 0x00 0x27 0x43
0x68 0x08 0x80 0x50 0x1D 0x8C 0x00 0x00 0x81 0x43

В этом случае байт 6, по-видимому, соответствует наклону в шестнадцатеричном формате, и это подтверждает, что байт 9 является контрольной суммой.

Преобразование значений байта 6 в десятичное:

Наклон на экранеШестнадцатеричноеДесятичное
-5°0x000
0x3250
0x8C140

Формула, которая идеально соответствует значениям, отправляемым на плату управления двигателем:

Десятичное значение = (Угол + 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-2025 Себастьян Барренечеа. Все права защищены.

Создано с использованием Astro v5.6.1.