Стало интересно сделать свой БК с
блекджеком и wifi несколько более расширенным функционалом, и для начала решил изучить протокол общения между контроллером и дисплеем. На удивление, готовых решений не нашлось. Самое близкое описание того, что мне требовалось, удалось найти в
данной теме. Ввиду того, что в моём случае несколько другой БК и контроллер, решил создать отдельную тему.
Собственно контроллер китайский безымянный, на 12 мосфетов, в голове используется μPD79F9211.
Дисплейный модуль к контроллеру подключен 5 проводами:
красный -- питание от батареи
черный -- земля
синий -- данные к БК
зеленый -- данные к контроллеру
белый -- сигнал зажигания от БК
Общение происходит по интерфейсу UART (уровни 3.3V), на скорости 1200 бод, пакетами по 15 байт.
Как такового общения не происходит, каждая сторона примерно по 5 раз в секунду отправляет текущее состояние.
Данные от контроллера к БКПосле включения питания, БК отправляет в линию 1 байт F5, затем начинают отправляться пакеты по 15 байт. Первый пакет отправляется пустой и похоже с неправильной контрольной суммой. Дальше пакеты идут с данными, и можно примерно понять их содержимое. Нулевым байтом идёт идентификатор (устройства, типа пакета), он не меняется. Первым байтом идёт порядковый номер пакета, циклически меняется от 0 до 255. Второй байт всегда ноль. Далее следует десять байт зашифрованных данных. В тринадцатом байте находится псевдослучайное число, которые выполняет роль ключа шифрования. В четырнадцатом байте записана контрольная сумма пакета.
Начнём разбор с
контрольной суммы, так как она считается уже от зашифрованного пакета. Считается она путём побитового сложения по модулю два (xor) всех байтов пакета. Например для второго пакета: 36^02^00^5c^5c^5c^00^5c^5c^5c^5c^d1^8d^5c = 68.
С
шифрованием всё тоже не сильно сложно. Для того, чтобы расшифровать данные, нужно вычесть по модулю 256 из каждого байта байт под номером 13. Соответственно для обратной процедуры требуется прибавить это значение и записать его по модулю 256. Пример расшифровки пакетов:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
00 01 00 23 23 23 00 23 23 23 23 23 23 23 37 => 00 01 00 00 00 00 00 00 00 00 00 00 00 00 37
36 02 00 5c 5c 5c 00 5c 5c 5c 5c d1 8d 5c 68 => 36 02 00 00 00 00 a4 00 00 00 00 75 31 00 0c
36 03 00 21 21 21 00 21 21 21 21 96 52 21 f1 => 36 03 00 00 00 00 df 00 00 00 00 75 31 00 d0
36 04 00 2a 2a 2a 00 2a 2a 2a 2a 9f 5b 2a f6 => 36 04 00 00 00 00 d6 00 00 00 00 75 31 00 cc
36 05 00 2f 2f 2f 00 2f 2f 2f 2f a4 60 2f f7 => 36 05 00 00 00 00 d1 00 00 00 00 75 31 00 c8
36 06 00 28 28 28 00 28 28 28 28 9d 59 28 f4 => 36 06 00 00 00 00 d8 00 00 00 00 75 31 00 cc
36 07 00 2d 2d 2d 00 2d 2d 2d 2d a2 5e 2d cd => 36 07 00 00 00 00 d3 00 00 00 00 75 31 00 a0
36 08 00 26 26 26 00 26 26 26 26 9b 57 26 f2 => 36 08 00 00 00 00 da 00 00 00 00 75 31 00 cc
36 09 00 2b 2b 2b 00 2b 2b 2b 2b a0 5c 2b c3 => 36 09 00 00 00 00 d5 00 00 00 00 75 31 00 98
36 0a 00 24 24 24 00 24 24 24 24 99 55 24 f0 => 36 0a 00 00 00 00 dc 00 00 00 00 75 31 00 cc
36 0b 00 29 29 29 00 29 29 29 29 9e 5a 29 f9 => 36 0b 00 00 00 00 d7 00 00 00 00 75 31 00 d0
36 0c 00 52 52 52 00 52 52 52 52 c7 83 52 7e => 36 0c 00 00 00 00 ae 00 00 00 00 75 31 00 2c
36 0d 00 57 57 57 00 57 57 57 57 cc 88 57 7f => 36 0d 00 00 00 00 a9 00 00 00 00 75 31 00 28
36 0e 00 50 50 50 00 50 50 50 50 c5 81 50 7c => 36 0e 00 00 00 00 b0 00 00 00 00 75 31 00 2c
36 0f 00 55 55 55 00 55 55 55 55 ca 86 55 75 => 36 0f 00 00 00 00 ab 00 00 00 00 75 31 00 20
Получив расшифрованные данные, можно продолжить их анализ.
На данный момент мне удалось определить, что байты 3-4-5 отвечают за отображение статусный иконок на дисплее:
бит -> байт | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
3 | круиз | ошибка двигателя | ошибка ручки газа | ошибка контроллера | батарея разряжена | круиз | - | ошибка двигателя |
4 | - | - | нажат тормоз | - | - | ошибка ручки газа | | |
5 | - | - | - | - | - | - | нажат тормоз | - |
Байт 6 до декода всегда 0, соответственно после декодирования выглядит как псевдослучайное число.
Байты 7-8 показывают текущую скорость, выраженную в непонятных пока мне величинах. Например если записать в 8 байт 10, то отображается скорость 01.0км/ч, если 15->01.5, если 100->10.5, если 200->21.0.
Байт 9 не понятно что показывает, но при вращении колеса вперёд меняется с 00 на 0A.
Байт 10 отвечает за индикатор потребляемой мощности в условных единицах. На экране отображается в виде шкалы с 10 делениями, каждое деление имеет размер 10 единиц, соответственно можно передавать значения от 0 до 100 с шагом 10.
Байты 11 и 12 за время исследования протокола не менялись и пока не очень понятно, за что отвечают.
Данные от БК к контроллеруПосле включения питания БК начинает примерно с той же скоростью отправлять пакеты той же длины контроллеру. Контрольная сумма считается аналогично. В отличии от получаемых пакетов, БК отправляет пакеты без шифрования, но в них по прежнему содержится псевдослучайное число в 5м байте, и контрольная сумма в 14 байте. Нулевой и первый байт пакета содержат идентификатор версии (протокола, устройства). Во втором байте передаётся порядковый номер пакета, который после включения начинается с 0x1a, доходит до 255 и продолжается с нуля. В третий, четвёртый и шестой байт записывается текущая передача (уровень максимальной поддержки), для уровня 0 передаётся значение 0, для 1-3, 2-6, 3-9, 4-12, 5-15. В байте 8 передаётся настройка P07 (ограничение максимальной скорости). В 9 байте передаются различные флаги (вкл\выкл света, круиза). 12 байт - число магнитов в колесе (настройка P02).
Пример пакетов:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
01 03 1a 03 03 7c 03 00 64 80 00 00 34 38 8f => 1 3 26 3 3 124 3 0 100 128 0 0 52 56 143
01 03 1b 03 03 61 03 00 64 80 00 00 34 38 93 => 1 3 27 3 3 97 3 0 100 128 0 0 52 56 147
01 03 1c 03 03 0a 03 00 64 80 00 00 34 38 ff => 1 3 28 3 3 10 3 0 100 128 0 0 52 56 255
01 03 1d 03 03 5f 03 00 64 80 00 00 34 38 ab => 1 3 29 3 3 95 3 0 100 128 0 0 52 56 171
01 03 1e 03 03 60 03 00 64 80 00 00 34 38 97 => 1 3 30 3 3 96 3 0 100 128 0 0 52 56 151
01 03 1f 03 03 65 03 00 64 80 00 00 34 38 93 => 1 3 31 3 3 101 3 0 100 128 0 0 52 56 147
01 03 20 03 03 5e 03 00 64 80 00 00 34 38 97 => 1 3 32 3 3 94 3 0 100 128 0 0 52 56 151