volshebnik писал(а):
По UART 9600 скорость, можно любой переходник CH340 через терминал снимите логи с заблокированного и с рабочего аккумулятора, там по шине как понял передается инфа по аутентификации серийный номер, имя и информация о заряде аккумулятора. В принципе можно разобрать этот протокол если найти людей на 4pda или на форумах кто разобрал протокол по UART Xiaomi Mijia M365 там каждая команда у них расписана. Если время есть создайте тему на их форуме кто по самокатам прошивки разбирал, может найдутся толковые спецы кто поможет.
Этот обмен надо смотреть не осциллографом, и не терминалом, а логическим анализатором. Причем принимать надо обе линии одновременно, и TX, и RX (это для батареи есть линии приема и передачи, а для стороннего наблюдателя здесь сигнал на каждой линии). Тогда будут видны не отдельные байты, а пакеты, и оба направления обмена, что позволит увидеть взаимосвязь данных на линиях RX и TX с действиями. Ко мне, правда, попал не G10, а G9 (у которого нет дисплея, а скорость переключается механическим переключателем), но принципиально у этих моделей все одинаково.
Параметры порта:
Скорость, бит/с: 9600
Данные, бит: 8
Четность: нет
Стоп-бит: 1
Порядок передачи битов: LSB-First
Порядок передачи байтов: Little-Endian
В качестве общего провода был использован минус батареи.
Все логи сняты при заряде батареи близком к максимальному, но некоторые на первом цикле после ручной балансировки при неправильно откалиброванном индикаторе уровня заряда (одно мигающее деление).
Протокол на самом деле симплексный, несмотря на раздельные линии приема-передачи, обмен идет в режиме запрос-ответ, и перекрывающихся по времени пакетов на линиях TX/RX нет.
Время начала обмена (старт-бит первого байта первого пакета) принималось за 0 мс, далее записывалось все что происходило на RX и TX с фиксацией времени старта каждого байта относительно начала обмена, запись велась до окончания обмена. Пакетом считается все, что передается по одной и той же линии с интервалом, не превышающим 2 мс (между стартовыми битами), так как внутри некоторых пакетов бывают паузы длительностью около 1 мс. Ответом на пакет считался пакет на другой линии, приходящий не позднее, чем через 15 мс (между стартовыми битами первых байтов пакета).
При старте на линии RX проскакивает ошибочный байт 0xFF (или несколько), это не реальная передача, а просто момент появления на линии питания, принимаемый анализатором за стартовый бит (я не стал убирать это из расшифровки).
Похоже, все управление пылесосом осуществляет контроллер батареи. Обмен данными между батареей и пылесосом начинается после появления положительного напряжения на линии PO (нажатие кнопки) или на C+ (подключение зарядника). При начале обмена батарея включает MOSFET разрядной цепи (включен в минусовой провод), подавая напряжение на силовые контакты разъема, и включает светодиоды индикации уровня заряда. Обмен на шине продолжается пока нажата клавиша, и еще примерно 10 секунд после ее отпускания (при отсутствии других действий). По завершении обмена батарея отключает MOSFET разрядной цепи и индикацию уровня заряда. После подключения зарядника обмен также продолжается около 10 секунд, хотя индикаторы уровня заряда работают дольше, примерно минуту.
В обмене есть два типа пакетов.
Пакет типа 1.
Всегда одинаков для попавшего ко мне G9:
TX: 0x5A 0x31 0x30 0x38 0x4D 0x33 0x2C 0x30 0x39 0x31 0x32 0x0D 0x0A 0x00
В ASCII это Z108M3,0912<CR><LF><Null> (очевидно просто Null-terminated строка с завершающим Enter-ом из кода на Си).
На Reddit упоминается эта же строка, но не указано для какой именно модели пылесоса/батареи.
В первом приведенном выше логе от volshebnik этот пакет тоже есть, но отличается одной цифрой: Z109M3,0912<CR><LF><Null>. Возможно зависит от модели батареи. Во втором логе, похоже, начало обмена с этим пакетом пропущено.
Пакеты типа 1 передаются батареей по линии TX в начале обмена (за исключением одного случая, о котором ниже). Здесь явно нет никаких служебных полей типа адресов, длин или контрольных сумм, зато все символы, кроме завершения строки, отображаемые. Никакого ответа на пакеты типа 1 пылесос не дает, и назначение этих пакетов для меня осталось непонятно. Возможно это какой-то технологический идентификатор.
При нажатии клавиши (при появлении положительного напряжения на линии PO), если на этот момент обмена данными не было, пакет передается дважды с интервалом около 60 мс. Если после предыдущего нажатия или другого действия прошло менее 10 секунд, и обмен данными в момент нажатия уже шел, пакет передается однократно.
При подключении/отключении зарядника (появление или пропадание напряжения на линии C+), независимо от наличия/отсутствия обмена, пакет передается однократно, за исключением случая, когда зарядник отключается при уже погасших индикаторах уровня заряда (это более примерно минуты после подключения), в таком случае обмен не начинается.
Отпускание клавиши (пропадание напряжения на линии PO) не приводит к началу обмена данными.
Нажатие клавиши при подключенном заряднике приводит к началу обмена, но в этом единственном случае пакет типа 1 не передается, обмен сразу начинается с пакетов типа 2.
Пакет типа 2.
Байт 1: всегда 0xAC.
Байт 2: адрес получателя или назначение пакета, наблюдаются байты 0x01, 0x02 и 0x03. В дальнейшем я буду называть это адресом.
Байт 3: длина поля данных в байтах (N).
Байты 4..(N+3) - поле данных.
Байты N+4 и N+5 - контрольная сумма пакета без первого байта (обычная сумма байтов со 2-го по (N+3)-й). Байт N+4 - старшие разряды контрольной суммы, N+5 - младшие.
Циклический обмен пакетами типа 2 начинается сразу же после передачи батареей пакетов типа 1. Пакеты с адресами 0x01 и 0x03 отправляет контроллер батареи по линии TX, пакет с адресом 0x02 приходит к батарее по линии RX (очевидно от контроллера мотора). Пакеты типа 2 всегда появляются в следующем порядке: 0x03-0x01-0x02, причем пакет с адресом 0x02 является ответом на пакет с адресом 0x01. Ответа на пакет с адресом 0x03 нет (во всяком случае нет в моем G9, а в G10 на него, возможно, отвечает дисплей). Последовательность 0x03-0x01-0x02 появляется после пакета типа 1 через 60 мс и повторяется 4 раза с этим же периодом 60 мс, после чего период повторения увеличивается до 300 мс. Обмен продолжается до тех пор, пока не будет отпущена клавиша, и еще около 10 секунд после этого. Если в процессе обмена клавиша будет нажата повторно, батарея снова передает пакет типа 1, и затем заново повторяется цикл следования пакетов типа 2 (4 раза с периодом 60 мс, далее 300 мс), отсчет таймаута до окончания обмена также начинается заново. Интервал между началом пакетов 0x03-0x01 и 0x01-0x03 примерно одинаков, то есть 30 мс для первых четырех пакетов и 150 мс для последующих. Интервал между началом пакетов 0x01-0x02 всегда составляет порядка 10 мс, то есть задержка ответа (от окончания пакета 0x01 до начала пакета 0x02) примерно 2 мс.
В логах от volshebnik, если я правильно понимаю, данные сняты только с линии TX, поэтому пакетов ответа от мотора (с адресом 0x02) там нет.
Пакет с адресом 0x01 адресован контроллеру мотора и передает команду на включение/выключение.
Поле данных состоит из трех байтов.
Байт 1: состояние линии PO (клавиша включения), 0x10 - на линии нет напряжения (клавиша не нажата), 0x13 - на линии напряжение батареи (клавиша нажата).
Байт 2: всегда 0x00.
Байт 3: всегда 0x00.
Пакет с адресом 0x02 - ответ мотора на пакет с адресом 0x01, он адресован батарее.
Поле данных состоит из 6 байтов.
Байты 1..3 - обороты двигателя (оборотов в минуту). Знаковое целое число 20 бит, Little-Endian. Значение 0 соответствует 0 об/мин. Значение LSB - 1 об/мин.
Байт 4: всегда 0x00.
Байт 5: температура мотора (градусы Цельсия). Беззнаковое целое число 8 бит. Значение 0 соответствует температуре -60 градусов Цельсия. Значение LSB - 1 градус Цельсия. Диапазон измерения -60..+115 градусов.
Байт 6: всегда 0x00.
Пакет с адресом 0x03 очевидно адресован дисплею G10, которого в G9 нет. Соответственно, в моих логах нет и ответа на этот пакет.
Поле данных пакета с адресом 0x03 состоит из 7 байтов.
Байт 1: всегда 0x03.
Байт 2: заряд батареи (проценты). Беззнаковое целое число 8 бит. Значение LSB - 1%. Диапазон 0..100%.
Байт 3: не опознан, во втором и третьем пакете после старта мотора здесь передается 0x02, в остальных пакетах 0x00. Возможность разобраться за что отвечает этот байт оставлю владельцам G10.
Байт 4: ошибки, 0x00 - ошибок нет, 0x0D - ошибка получения данных от мотора, появляется в пакетах через 2 секунды после команды включения мотора, если не приходят ответы от него (наверное есть и другие коды, но я таковых не наблюдал).
Байт 5: состояние линии C+ (подключение зарядника), 0x01 - зарядник подключен (на линии напряжение порядка 31,45 В), 0x02 - зарядник не подключен (напряжения на линии нет).
Байт 6: всегда 0x00.
Байт 7: всегда 0x00.
Если отключить линию TX, то мотор не стартует, так как к нему не проходят команды на включение/выключение (пакеты тип 2 с адресом 0x01). Никаких ошибок батарея не показывает. Если отключить линию RX, то батарея не будет получать данных от мотора (пакеты тип 2 с адресом 0x02). Сам мотор при этом стартует, но через 2 секунды из пакетов с адресом 0x01 исчезает код его включения (независимо от состояния клавиши), а в пакете с адресом 0x03 появляется код ошибки. Соответственно мотор останавливается, а красный светодиод на батарее мигает 5 раз. Восстановление линий восстанавливает нормальную работу.
У меня батарея была не заблокирована, просто значительно сократилось время работы (примерно 3 минуты на средних оборотах). После разборки выявился сильный дисбаланс (элементы Samsung), выравнивание их внешним зарядником без отключения от батареи вернуло время работы в норму. На первом после балансировки разрядном цикле индикатор все время показывал одно мигающее деление, но после полного цикла разряд-заряд откалибровался сам собой. На будущее к батарее был добавлен балансир на основе HY2213, однако выяснилось, что с системой заряда этой батареи балансир такого типа не работает вообще. Балансир подобного типа включает разряд ячейки током около 70 мА по достижении напряжения ячейки 4,21 В, и продолжает разряд до 4,19 В. Через батарею при этом продолжает протекать зарядный ток, но ток этот должен быть меньше или равен разрядному, чтобы ячейка разряжалась или хотя бы перестала заряжаться, иначе BMS отключит батарею по превышению напряжения этой ячейки. Зарядник данной батареи, похоже, заряжает ее только в режиме CC (заряд большим постоянным током), игнорируя стадию CV (дозаряд малым током при постоянном напряжении). Соответственно, когда штатная схема заряда прекращает работу, напряжение на наиболее заряженной ячейке составляет примерно 4,1 В, и ни до какой балансировки дело не доходит. В данном случае мог бы помочь балансир другого типа (работающий независимо от напряжения на ячейке), но габариты таковых больше, а места для него в батарее не слишком много. Поэтому пришлось сделать цепь дозаряда батареи постоянным напряжением - со входа C+ на плюс батареи последовательно резистор 65 Ом и два диода (обычные, не Шоттки, и именно два последовательно, потому что в целях защиты нужно обеспечить соответствующее падение напряжения).
Если что, вот идентификационные номера пылесоса и батареи (ничего из этого в обмене не присутствует):
Vacuum Cleaner: Mi G9
Model: MJSCXCQ1T
SN: 28829/00038452
SKU: BHR4368GL
Battery Pack: 7INR19/65
Model: P2045-7S1P-BC
Production Date: 01/2021
SN: 28829/00038452
SKU: BHR4368GL
Все снятые логи с расшифровкой прицеплены. Дальше сами ;-)
Вот, к примеру, короткое включение на высокой скорости. К сожалению здесь шрифт не моноширинный, так что лучше открывайте текстовые файлы из вложенного зипа блокнотом, или импортируйте в эксель.
Лог пакетов
TIME(ms) TX/RX DATA
0 TX: 5A 31 30 38 4D 33 2C 30 39 31 32 0D 0A 00
0 RX: FF
69 TX: 5A 31 30 38 4D 33 2C 30 39 31 32 0D 0A 00
119 TX: AC 03 07 03 64 00 00 02 00 00 00 73
149 TX: AC 01 03 13 00 00 00 17
159 RX: AC 02 06 0F FF FF 00 AF 00 02 C4
179 TX: AC 03 07 03 64 02 00 02 00 00 00 75
208 TX: AC 01 03 13 00 00 00 17
219 RX: AC 02 06 00 02 1C 00 53 00 00 79
246 TX: AC 03 07 03 64 02 00 02 00 00 00 75
268 TX: AC 01 03 13 00 00 00 17
279 RX: AC 02 06 00 0A 0C 00 52 00 00 70
298 TX: AC 03 07 03 64 00 00 02 00 00 00 73
327 TX: AC 01 03 13 00 00 00 17
338 RX: AC 02 06 00 38 B8 00 52 00 01 4A
476 TX: AC 03 07 03 64 00 00 02 00 00 00 73
642 TX: AC 01 03 13 00 00 00 17
652 RX: AC 02 06 01 6F 66 00 52 00 01 30
793 TX: AC 03 07 03 64 00 00 02 00 00 00 73
951 TX: AC 01 03 13 00 00 00 17
962 RX: AC 02 06 01 B1 EC 00 54 00 01 FA
1100 TX: AC 03 07 03 64 00 00 02 00 00 00 73
1258 TX: AC 01 03 13 00 00 00 17
1269 RX: AC 02 06 01 BF 88 00 55 00 01 A5
1407 TX: AC 03 07 03 64 00 00 02 00 00 00 73
1565 TX: AC 01 03 13 00 00 00 17
1576 RX: AC 02 06 01 C1 A4 00 56 00 01 C4
1714 TX: AC 03 07 03 64 00 00 02 00 00 00 73
1863 TX: AC 01 03 13 00 00 00 17
1874 RX: AC 02 06 01 C1 D6 00 57 00 01 F7
2011 TX: AC 03 07 03 64 00 00 02 00 00 00 73
2160 TX: AC 01 03 13 00 00 00 17
2170 RX: AC 02 06 01 C2 5F 00 58 00 01 82
2308 TX: AC 03 07 03 64 00 00 02 00 00 00 73
2457 TX: AC 01 03 13 00 00 00 17
2467 RX: AC 02 06 01 C5 3C 00 59 00 01 63
2605 TX: AC 03 07 03 64 00 00 02 00 00 00 73
2754 TX: AC 01 03 13 00 00 00 17
2765 RX: AC 02 06 01 C6 13 00 5A 00 01 3C
2903 TX: AC 03 07 03 64 00 00 02 00 00 00 73
3051 TX: AC 01 03 13 00 00 00 17
3062 RX: AC 02 06 01 C6 78 00 5A 00 01 A1
3200 TX: AC 03 07 03 64 00 00 02 00 00 00 73
3348 TX: AC 01 03 10 00 00 00 14
3363 RX: AC 02 06 01 15 34 00 5B 00 00 AD
3497 TX: AC 03 07 03 64 00 00 02 00 00 00 73
3645 TX: AC 01 03 10 00 00 00 14
3657 RX: AC 02 06 00 00 04 00 5B 00 00 67
3794 TX: AC 03 07 03 64 00 00 02 00 00 00 73
3943 TX: AC 01 03 10 00 00 00 14
3954 RX: AC 02 06 00 00 04 00 5B 00 00 67
4091 TX: AC 03 07 03 63 00 00 02 00 00 00 72
4240 TX: AC 01 03 10 00 00 00 14
4250 RX: AC 02 06 00 00 04 00 5B 00 00 67
4388 TX: AC 03 07 03 63 00 00 02 00 00 00 72
4537 TX: AC 01 03 10 00 00 00 14
4548 RX: AC 02 06 00 00 04 00 5A 00 00 66
4686 TX: AC 03 07 03 63 00 00 02 00 00 00 72
4834 TX: AC 01 03 10 00 00 00 14
4845 RX: AC 02 06 00 00 04 00 5A 00 00 66
4983 TX: AC 03 07 03 63 00 00 02 00 00 00 72
5131 TX: AC 01 03 10 00 00 00 14
5141 RX: AC 02 06 00 00 04 00 5A 00 00 66
5280 TX: AC 03 07 03 63 00 00 02 00 00 00 72
5428 TX: AC 01 03 10 00 00 00 14
5438 RX: AC 02 06 00 00 04 00 5A 00 00 66
5577 TX: AC 03 07 03 63 00 00 02 00 00 00 72
5726 TX: AC 01 03 10 00 00 00 14
5736 RX: AC 02 06 00 00 04 00 59 00 00 65
5874 TX: AC 03 07 03 63 00 00 02 00 00 00 72
6023 TX: AC 01 03 10 00 00 00 14
6033 RX: AC 02 06 00 00 04 00 59 00 00 65
6171 TX: AC 03 07 03 63 00 00 02 00 00 00 72
6320 TX: AC 01 03 10 00 00 00 14
6330 RX: AC 02 06 00 00 04 00 59 00 00 65
6469 TX: AC 03 07 03 63 00 00 02 00 00 00 72
6617 TX: AC 01 03 10 00 00 00 14
6627 RX: AC 02 06 00 00 04 00 59 00 00 65
6766 TX: AC 03 07 03 63 00 00 02 00 00 00 72
6914 TX: AC 01 03 10 00 00 00 14
6924 RX: AC 02 06 00 00 04 00 59 00 00 65
7063 TX: AC 03 07 03 63 00 00 02 00 00 00 72
7211 TX: AC 01 03 10 00 00 00 14
7222 RX: AC 02 06 00 00 04 00 59 00 00 65
7360 TX: AC 03 07 03 63 00 00 02 00 00 00 72
7509 TX: AC 01 03 10 00 00 00 14
7519 RX: AC 02 06 00 00 04 00 59 00 00 65
7657 TX: AC 03 07 03 63 00 00 02 00 00 00 72
7806 TX: AC 01 03 10 00 00 00 14
7816 RX: AC 02 06 00 00 04 00 59 00 00 65
7954 TX: AC 03 07 03 63 00 00 02 00 00 00 72
8103 TX: AC 01 03 10 00 00 00 14
8113 RX: AC 02 06 00 00 04 00 59 00 00 65
8252 TX: AC 03 07 03 63 00 00 02 00 00 00 72
8400 TX: AC 01 03 10 00 00 00 14
8410 RX: AC 02 06 00 00 04 00 59 00 00 65
8549 TX: AC 03 07 03 63 00 00 02 00 00 00 72
8697 TX: AC 01 03 10 00 00 00 14
8708 RX: AC 02 06 00 00 04 00 59 00 00 65
8846 TX: AC 03 07 03 63 00 00 02 00 00 00 72
8995 TX: AC 01 03 10 00 00 00 14
9005 RX: AC 02 06 00 00 04 00 59 00 00 65
9143 TX: AC 03 07 03 63 00 00 02 00 00 00 72
9292 TX: AC 01 03 10 00 00 00 14
9302 RX: AC 02 06 00 00 04 00 59 00 00 65
9440 TX: AC 03 07 03 63 00 00 02 00 00 00 72
9589 TX: AC 01 03 10 00 00 00 14
9599 RX: AC 02 06 00 00 04 00 59 00 00 65
9737 TX: AC 03 07 03 63 00 00 02 00 00 00 72
9886 TX: AC 01 03 10 00 00 00 14
9896 RX: AC 02 06 00 00 04 00 59 00 00 65
10035 TX: AC 03 07 03 63 00 00 02 00 00 00 72
10183 TX: AC 01 03 10 00 00 00 14
10194 RX: AC 02 06 00 00 04 00 59 00 00 65
10332 TX: AC 03 07 03 63 00 00 02 00 00 00 72
10480 TX: AC 01 03 10 00 00 00 14
10491 RX: AC 02 06 00 00 04 00 59 00 00 65
10629 TX: AC 03 07 03 63 00 00 02 00 00 00 72
10778 TX: AC 01 03 10 00 00 00 14
10788 RX: AC 02 06 00 00 04 00 5A 00 00 66
10926 TX: AC 03 07 03 63 00 00 02 00 00 00 72
11075 TX: AC 01 03 10 00 00 00 14
11085 RX: AC 02 06 00 00 04 00 5A 00 00 66
11224 TX: AC 03 07 03 63 00 00 02 00 00 00 72
11372 TX: AC 01 03 10 00 00 00 14
11383 RX: AC 02 06 00 00 04 00 5A 00 00 66
11521 TX: AC 03 07 03 63 00 00 02 00 00 00 72
11669 TX: AC 01 03 10 00 00 00 14
11680 RX: AC 02 06 00 00 04 00 5A 00 00 66
11818 TX: AC 03 07 03 63 00 00 02 00 00 00 72
11966 TX: AC 01 03 10 00 00 00 14
11977 RX: AC 02 06 00 00 04 00 5A 00 00 66
12115 TX: AC 03 07 03 63 00 00 02 00 00 00 72
12264 TX: AC 01 03 10 00 00 00 14
12274 RX: AC 02 06 00 00 04 00 5A 00 00 66
12412 TX: AC 03 07 03 63 00 00 02 00 00 00 72
12561 TX: AC 01 03 10 00 00 00 14
12571 RX: AC 02 06 00 00 04 00 5A 00 00 66
12709 TX: AC 03 07 03 63 00 00 02 00 00 00 72
12858 TX: AC 01 03 10 00 00 00 14
Расшифровка
___TYPE_1__ ________________________TYPE_2_________________________________
__________ADDR_03__________ __ADDR_01__ ______ADDR_02______
TIME [3] BAT ??? ERR CRG [0] [0] MTR [0] [0] RPM [0] TEMP [0]
----- --- --- --- --- --- --- --- --- --- --- ------ --- ---- ---
0 Z108M3,0912
69 Z108M3,0912
119 100 +++ -1 115
179 100 +++ +++ 540 23
246 100 +++ +++ 2572 22
298 100 +++ 14520 22
476 100 +++ 94054 22
793 100 +++ 111084 24
1100 100 +++ 114568 25
1407 100 +++ 115108 26
1714 100 +++ 115158 27
2011 100 +++ 115295 28
2308 100 +++ 116028 29
2605 100 +++ 116243 30
2903 100 +++ 116344 30
3200 100 70964 31
3497 100 4 31
3794 100 4 31
4091 99 4 31
4388 99 4 30
4686 99 4 30
4983 99 4 30
5280 99 4 30
5577 99 4 29
5874 99 4 29
6171 99 4 29
6469 99 4 29
6766 99 4 29
7063 99 4 29
7360 99 4 29
7657 99 4 29
7954 99 4 29
8252 99 4 29
8549 99 4 29
8846 99 4 29
9143 99 4 29
9440 99 4 29
9737 99 4 29
10035 99 4 29
10332 99 4 29
10629 99 4 30
10926 99 4 30
11224 99 4 30
11521 99 4 30
11818 99 4 30
12115 99 4 30
12412 99 4 30