Некоторое время назад я сказал: "«Тюнить» авто лично мне как-то не интересно...", но «никогда не говори „никогда“». Звезды встали в таком порядке, что пришлось экстренно сменить машину Peugeot 307sw на Mazda5.
Машина ездит, все хорошо, но некоторые «плюшки», которые были в прежней машине штатно, почему-то отсутствовали в текущей.
Одна из таких полезных вещей — парктроник. Установка парктроника не является проблемой, но вот как-то «неродной» дисплей парктроника меня в салоне не устраивал. Внутренний перфекционист был жутко против «чужеродного тела».
Некоторое время погуглил и узнал, что, оказывается, несколько лет назад один товарищ из СПб сделал специальное «дополнение», которое с одной стороны подключалась к блоку парктроника, с другой — к машине. И при этом информация с парктроника выводилась на штатный дисплей.
Казалось бы, надо купить, поставить и расслабиться, но тот проект «умер», автор на контакт не выходит: купить — нельзя.
Но это ж не наш метод… раз нельзя купить, значит, можно «изобрести заново» (и прокачать свои навыки по программированию микроконтроллеров).
Часть первая: Парктроник
Сначала нужно было выбрать парктроник. В исходном проекте использовался Parkmaster (модель, которая уже была совершенно недоступна — снята с производства). Пришлось выбирать из того, что можно свободно приобрести. Выбор пал на Parkmaster 4-DJ-06 (та же марка — была надежда, что «кто-то его уже расковырял, значит, я тоже смогу», но по сравнению с исходной моделью — «повышена скорость обнаружения препятствий, улучшена стабильность, датчики новой конструкции с эффективным отводом воды и т.п.»).
Первое, что было сделано — разобран дисплейчик и изучено подключение кабеля к нему. Обнаружилось, что дисплей подключен 5 проводами: GND, +5V, DATA, CS, CLK. Те, кто знаком с шиной SPI, сразу заметят некоторое сходство (у парктроника DATA = MOSI). Связь дисплея с основным блоком — одностороняя (основной блок — master, дисплей — slave), поэтому до «полноценного» SPI не хватает одного проводника (MISO).
Подключение осциллографа полностью подтвердило эту гипотезу:
Канал A — CS, B — CLK, D — DATA.
Дальше — дело техники: надо было придумать, каким образом «снять» все кодовые посылки и декодировать то, что там передается.
Про реверс-инжиниринг протокола другого парктроника уже говорили, поэтому подобно описывать это не буду, лишь приведу ссылку на ветку форума, где «родилась истина» для моего конкретного случая (там же есть и код, с помощью которого велся «захват» кодовых посылок. Мой ник на том форуме — ustas).
Работа была достаточно рутинная, но для того, чтобы сделать все «красиво и интересно» использовал два прерывания. Первое прерывание следило за CS, второе — за CLK. Больше в этой части ничего особенно интересного не было.
Пару выходных дней, несколько вечеров и у меня был уже готовый прототип на макетке (с ардуино-nano), который уверенно получал данные от основного блока парктроника и производил их декодирование. Выбор парктроника оправдался — даже уровни согласовывать не пришлось.
После этого парктроник был установлен в автомобиль и основное место разработки переместилось туда.
Часть вторая: Слушаем
Параллельно узнал много нового о том, что практически все современные машины в большой степени являются «компьютерами» на колесах, даже «сетью компьютеров»: поскольку почти все более-менее «умные» блоки подключены к единой CAN-шине и с ее помощью «общаются между собой».
Вообще в автомобилях обычно присутствуют две шины: HS-CAN и MS-CAN (высокоскоростная и среднескоростная шина, соответственно). Первая в бОльшей степени относится к работе двигателя и смежных систем, вторая — ее еще называют «шина комфорта» — относится к различным сервисным функциям (музыкальная система, «приборка», световые приборы, климат, двери и т.п.).
В моей машине дисплей как раз подключен к MS-шине — эта шина стала «целевой» для моего проекта. Безусловно, нужна дополнительная информация. Производители, безусловно, владеют всей необходимой информацией, но совершенно не торопятся ею делиться (хотя ситуация начинает меняться, но не в моем случае).
Отправной точкой стала вот эта страница, на которой представлены некоторые идентификаторы сообщений и то, какие данные в этих сообщениях закодированы. В комментариях к этой записи тоже нашлись полезные заметки.
Перед тем, как что-то посылать в шину, решил, что сначала следует «послушать» свою машину и убедиться, что представленная информация соответствует действительности.
Поскольку не было под рукой соответствующего шида с CAN-интерфейсом, от «ардуины» пришлось отказаться (да и все равно для установки в машину решил сделать соответствующее устройство) — развел несложную плату, на которой содержался бы МК (atmega328p), контроллер CAN-шины (MCP2515/MCP2551), пищалка… и… часовой модуль.
Что не собирай на avr, а в итоге все равно получаются часы
с радиолюбительских форумов
Ну вот кто бы мог подумать, что у машины, которая произведена в этом тысячелетии есть часы, но нет календаря? Поскольку я тот еще склеротик — решил, что календарь мне точно не помешает, поэтому DS1307 тоже «прописался» на плате устройства.
Схема устройства совершенно не блещет какой-то оригинальностью: используются типовые схемы включения всех составляющих (из их даташитов). На всякий случай вывел почти все свободные порты ввода-вывода на дополнительный разъем (вдруг что-то еще придет в голову в процессе реализации?). Естественно, для программатора развел ICSP.
Питание решено взять от USB-зарядки, поэтому на плате есть miniUSB-разъем. От блока парктроника (в процессе его установки) проложил дополнительный кабель, который «дублирует» основной кабель между дисплеем и парктроником (чтобы можно было одновременно иметь подключение как штатного дисплейчика парктроника, так и моего «изделия»). Кабель взял первый попавшийся… Вы же не очень удивитесь узнав, что это оказался длинный пачкорд? Поэтому на плате есть соответствующий разъем (черный, слева). Форму платы продиктовал имеющийся корпус.
На первом этапе решил (для простоты) подключиться к диагностическому разъему, благо в нем MS-шина присутствует. Где именно в разъеме следует искать, подсмотрел тут.
С аппаратной частью, надеюсь, все понятно… переходим к софту. Для работы с CAN-шиной воспользовался готовой библиотекой. Тестовые примеры очень помогли — они позволили практически сразу начать «слушать». Единственное, что пришлось поправить — указать в скетче правильную скорость MS-шины (CAN_125KBPS).
Данные о том, где искать сообщения дисплея — полностью подтвердились (для проверки включил штатную магнитолу в режим радиоприемника и выбрал радиостанцию, которая через RDS выводила только свое название и дальше нашел соответствующие посылки). Нашлись две посылки, в которых были закодировано это название (в первой посылке — первые 7 символов, во второй — оставшиеся 5 символов).
Часть третья: Говорим
Первые попытки отправить сообщения на дисплей потерпели неудачу. Штатный дисплей авто просто игнорировал мои посылки.
Для того, чтобы разобраться с этой проблемой (да и для удобства) — на «разборке» приобрел дисплей от Mazda3 (существенно более распространенная запчасть, чем аналогичный от Mazda5). Наиболее заметное отличие дисплеев — это цвет подсветки (Mazda5 — зеленый, Mazda3 — красный). Остальное практически идентично и я надеялся, что отличия только «косметические» (и оказался прав).
Собрал дома небольшой тестовый стенд, состоящий из моего устройства и этого дисплея. Отработка на стенде — значительно комфортнее, чем в машине, зимой на улице.
Параллельно нашел замечательный комментарий:
You can send the 3 frames with the following IDs:
0x28F: LCD settings and probably some other settings (you just send the same data you receive in a normal 0x28f frame).
0×290: 0xC0 (first byte) followed by first 5 alfanum signs
0×291: 0×85 (first byte) followed by the next 7 alfanum signsall of them, just after you receive the 0×291 frame id sent by the HU. This will make your text being visible with almost no flicker at all.
The reason for sending the 0x28F is that it is required for displaying the 0×290 and 0×291 text, otherwise the LCD seems to simply ignore the 0×290 and 0×291.
Another method would be to set a timer with a 150ms interrupt and send the 3 frames described above.…
0x28F frame content that I have used:
hex: D1 00 00 00 80 00 00 01
Таким образом, для того, чтобы дисплей отобразил передаваемый текст нужно передавать три посылки (при первых тестах я передавал только две и из-за этого дисплей отказывался отображать мой текст).
Но почему-то дома на стенде и правильная последовательность не отрабатывала — дисплей оставался пустым. Сходил в машину: тот же код — отработал отлично. Стал разбираться и понял, что для тестового стенда не хватает на шине резистора в 120 Ом (между CAN-H и CAN-L). Как только поставил этот резистор — дисплей «ожил».
Часть четвертая: Логика
Я очень осторожно отношусь к различного рода «тюнингу» и считаю, что если и делать его, то только таким образом, чтобы это выглядело как «штатная функциональность».
Наблюдение за работой штатного дисплея подсказало логику, которую я захотел реализовать: как только на дисплее надпись не меняется более 5 секунд, то можно вывести «свою» информацию (например, дату), но если «машина хочет что-то сказать» (новая информация) — тут же убрать «нештатное» сообщение и вывести информацию от машины.
Естественно, при парковке такую логику соблюсти невозможно, в этом случае на дисплей должна выводиться только информация с парктроника).
В домашних условиях написал основную часть кода, на тестовом дисплее все выглядело более-менее прилично. Но после визита в машину, вылезли серьезные…
Часть пятая: «Грабли»
Проблема заключалась в том, что штатная магнитола «флудит» в шину своими сообщениями на дисплей с периодом примерно раз в 150мс (даже если информация на дисплее не менялась). Это приводило к тому, что «нештатные» сообщения практически сразу же «перетирались» штатными.
Тут началась «гонка вооружений сообщений». Немного изменил схему своего устройства, задействовал для отслеживания сообщений на дисплей прерывание и пытался тут же отправить свое сообщение (чтобы «перетирать» штатное сообщение своим).
Подход, возможно, сработал бы на более быстром МК, но быстродействия атмеги не хватило — периодически «проскакивали» штатные сообщения и это приводило к очень неприятной для взгляда «мешанине» сообщений (особенно с учетом того, что текст передается двумя порциями: иногда возникала ситуация, что первая часть сообщения — от машины, а вторая — от моего модуля).
В общем, работает, но совсем не так, как хотелось бы.
Для решения этой проблемы надо было как-то «оторвать» слишком «разговорчивую» магнитолу от шины.
Можно было бы поставить «реле», которое бы отключало магнитолу от CAN-шины в моменты отображения нештатной информации, но это бы нарушило логику (например, я бы начал изменять громкость, при этом штатно на дисплей выводится сообщение типа «VOL 7» с соответствующим уровнем и это сообщение было бы пропущено).
Т.е. надо было решить задачку: слушать CAN-шину, анализировать сообщения и передавать нужные сообщения на дисплей.
«Правильно заданный вопрос – половина ответа». Придумал, что надо добавить второй CAN-интерфейс. При этом мое устройство включается «в разрез» CAN-шины между машиной и дисплеем. Устройство «слушает» то, что сообщает машина (и вообще берет из шины все, что нужно), проводится анализ данных и только нужное передается на дисплей.
Чтобы не переделывать плату полностью — сделал «шилд» (как раз пригодились разведенные дополнительные порты ввода/вывода и ICSP), ведь контроллер CAN-шины подключается к МК через SPI-шину.
Получилось вот такое устройство:
Для удобства ICSP сделал «сквозным», чтобы не надо было каждый раз разбирать «бутерброд» для обновления прошивки.
Часть шестая: Тесты
В домашних условиях мой прототип только «снимал» данные с пакртроника, но ничего не было сделано по «визуализации» результата. Как только основные проблемы с устройством устранены и уже «зафиксирована» схема подключения — воссоздал работу дисплейчика парктроника на штатном дисплее. Получилось вот так:
На видео видно, что вывод практически идентичен, и в некоторых случаях на дисплее Mazda информация появляется на доли секунды раньше (что совсем неплохо).
После того, как были отлажены основные части прошивки, решил установить свою разработку в машину, чтобы уже устроить серьезную тестовую эксплуатацию.
И тут обнаружилась следующая проблема:
Пропала информация блока климат-контроля (правая часть дисплея). Как оказалось, это не единственная пропажа — маршрутный компьютер тоже отказался показывать свою информацию.
Это не было большой неожиданностью, поскольку в прошивке я «следил» только за сообщениями на центральную часть дисплея (принимал, анализировал и при необходимости — выводил на дисплей), все остальные сообщения — просто игнорировались.
Очевидно, что надо было найти идентификаторы сообщений, которые содержали «пропавшую» информацию. Это не заняло много времени.
- 0x38A обязательная отправка, без этого не работает маршрутник
- 0x400 данные маршрутника
- 0x3BA климат
- 0x201 текущие параметры (скорость, обороты)
После того, как в код прошивки добавлены правила для прямой трансляции собщений с этими идентификаторами на дисплей — все заработало так, как надо.
Часть седьмая: "… и поскакал!"
В процессе поиска различной информации зарегистрировался на форуме владельцев Mazda5 — поделился своими наработками, показал, как получается. Оказалось, что этот проект интересен не только мне. В конференции помогали искать необходимую информацию, подсказывали возможные функции.
В ходе обсуждения выяснилось, что не во всех комплектациях есть маршрутный компьютер, но замена дисплея на другой — добавляет эту функцию. Это говорило о том, что данные есть в шине, а функцию отображения в каких-то комплектациях реализовали, в других — нет (причем, это реализовано в прошивке дисплея).
Проверил эту гипотезу и убедился, что она верна. Достаточно просто получилось выделить следующие данные:
- средняя скорость,
- мгновенный расход топлива,
- средний расход топлива,
- запас хода на остатке топлива.
«Копнул» чуть глубже — обнаружились еще и текущие данные: скорость, обороты двигателя.
- включал логирование всех сообщений (чтобы объем данных для анализа был не слишком большим — ограничивал временной интервал в 5-10 секунд),
- в отведенное для теста время поднимал и опускал «ручник»,
- полученные данные загружал в Excel,
- включал «автофильтр»,
- обнаруживал идентификатор сообщений, где данные изменялись (при таких «атомарных» действиях обычно изменялся один бит),
- выделял такие идентификторы сообщений (обычно такой идентификатор был один),
- включал в прошивке «фильтрацию» (чтобы фиксировались только «интересные» сообщения),
- повторял анализ с отфильтрованными данными.
В ходе таких исследований сообщений выяснил, что в шине есть информация о состоянии всех дверей авто, стояночного тормоза, «поворотников» и т.п.
Раз данные есть — нужно их как-то использовать.
Сразу же добавил своему модулю функцию оповещения о незакрытых дверях на скорости выше 10 км/ч.
Да, на приборной панели есть штатный индикатор незакрытых дверей, но он только сигнализирует об этом факте, но не уточняет, какая именно дверь не закрыта.
Потом вспомнил, что на Peugeot была штатная функция автоматического запирания дверей на скорости. Очевидно, что тут тоже такую же функцию добавить… но уже не на прототипе (к сожалению, управление центральным замком в Mazda невозможно через CAN-шину, хотя в некоторых других машинах это вполне реально).
Таким образом, список функций несколько расширился:
- парктроник,
- календарь,
- вывод данных маршрутного компьютера,
- контроль открытых дверей,
- автозапирание дверей на скорости,
- автоприглушение музыки при парковке (чтобы лучше слышать «пищалку» парктроника),
- контроль напряжения бортовой сети.
Поскольку результат моей работы заинтересовал соконфетников — решил полностью переделать схему устройства (сделав его «одноплатным» и «самодостаточным»): включил все необходимые интерфейсы, мощные транзисторные ключи, DC/DC-преобразователь питания. При этом сделал плату первоначального размера:
Естественно, пригодились все полученные знания в процессе создания и эксплуатации прототипа (тот же резистор на 120Ом в CAN-шине для работы дисплея).
При этом получилось, что все подключения к проводке машины можно было сделать непосредственно за дисплеем (там очень объемная пустая ниша и присутствуют все необходимые сигнальные провода).
В качестве «защиты» сделал дополнительные площадки для подключения «альтернативной» батареи резервного питания часового модуля (вдруг зимой резервная батарейка CR1225 будет «замерзать» и часы будут сбиваться) и выносной «пищалки».
Часть восьмая: Продакшн
Плата получилась довольно компактная благодаря тому, что перешел на типоразмер 0603 (в прототипе был 0805), довольно много переходных отверстий (хотя и многократно оптимизировал трассировку), дорожки/зазоры — 0.2мм. В принципе, можно было изготовить и дома ЛУТом, но проект и так занял слишком много моего времени, решил, что гораздо проще будет кому-то заплатить, чтобы плату сделали в нужном количестве и распаяли компоненты (было 9 заинтересованных соконфетников, «плюс» для моего авто вместо прототипа).
Подобный опыт заказа в «поднебесной» у меня уже был — доверил это «своему» подрядчику. Получилось относительно бюджетно (дешевле, чем просто закупить комплектующие в московских магазинах), но не слишком (маленькая партия). Оплату производства сделал на средства, собранные с желающих («микро-краудфандинг»).
Устройства произвели не слишком оперативно — на это ушло почти 3 недели. Но почта увеличила срок ожидания еще почти на месяц. Но не будем о грустном, поскольку получилось неплохо:
Замена прототипа на «заводское» изделие заняло у меня примерно полчаса (при этом еще и производилась фотосъемка процесса — чтобы облегчить его для пользователей). Но не все прошло гладко: функция автоприглушения музыки на моей конкретной магнитоле не заработала (бережливые японцы, к моему сожалению, не распаяли цепь System Mute). Зато управление замков дверей заработало сразу (правда, после довольно тщательного изучения электросхемы авто и поиска «того самого» провода, который отвечает за запирание).
Часть девятая: Настройки
Из-за того, что устройство должно ставиться в машины разных комплектаций (и разным пользователям), необходимо было придумать, как реализовать режим настройки (включение/отключение нужных сообщений, функций, установку даты/времени). Безусловно, «для себя» я бы вообще над этой задачей не стал бы задумываться — нет ничего проще, чем подключить программатор, но не в этом случае. Нужно думать о «потребителях» устройства.
При этом, согласно части «Логика», все должно выглядеть максимально штатно и без добавления дополнительных кнопок в салон (даже скрытой установки). И тут удачно вспомнилось, что можно легко получить данные о состоянии дверей, стояночного тормоза, «поворотников», причем, у последних в шине состояние полностью повторяло состояние ламп («моргал» соответствующий бит в посылке).
Вход в режим настроек реализовал по «шаманской» последовательности: на стоящей машине (нулевая текущая скорость) надо приоткрыть водительскую дверь (следим за ее состоянием) и в течение 15 секунд с момента открытия дверей три раза поднять-опустить ручник. После этого на дисплее появляется надпись «SETUP?» и для подтверждения — закрыть водительскую дверь. Т.е. «неслучайная» последовательность действий (которую вряд-ли случайно кто-то воспроизведет в режиме нормальной эксплуатации авто).
Перемещение по «меню настроек» с помощью подрулевого переключателя указателей поворота: левый — вниз, правый — вверх. Включение/выключение функций/сообщений — ручником.
Словесное описание выглядит очень сложным, но в реальной эксплуатации все гораздо проще (напротив машины — забор из поликарбоната, обратите внимание на отражение — видно, когда используются «поворотники»):
Вообще было достаточно сложно и интересно было придумывать реализацию такого меню, когда доступен дисплей в одну строку и всего в 12 символов.
Несколько дней тестировал изделие в своем авто — никаких нареканий, все работает отлично.
Часть десятая: Продолжение?
На текущий момент все платы отправлены их новым владельцам. Как только они будут установлены, надеюсь, получу дополнительные отзывы.
Перед отправкой успел одну из плат подключить к Mazda CX-7 — почти все заработало сразу (некоторые данные маршрутного компьютера закодированы чуть иначе), но в целом — подключение прошло успешно.
Сейчас устройство (с текущей прошивкой) проверено на Mazda3, 5, 6 (там где дисплеи похожи на те, что я использовал в процессе разработки).
После адаптации прошивки, думаю, устройство может оказаться полезным практически на любом современном авто, где вывод на дисплей (или приборную панель) осуществляется через MS-CAN.
Часть последняя: Arduino?
После прочтения такой длинной записи (прошу прощения за это у тех, кто дочитал), может возникнуть вопрос: «При чем тут Arduino?».
Ответ очень прост: все программирование я делал в среде Arduino.
После этого некоторые могут начать «кидаться в меня помидорами», но мое личное мнение: лучше использовать тот инструмент, что доступен и знаком.
Arduino — один из таких инструментов, который с одной стороны позволяет новичкам очень быстро и относительно просто приобщиться к такой интересной области, как программирование микроконтроллеров, а «наборы» и «шилды» — еще и существенно расширить область применения «железа» в своих проектах (хотя это и недешево).
Arduino (в моем понимании) — эдакий фреймворк для «быстрого старта».
Безусловно, использование профессиональных инструментов могло бы помочь реализовать необходимый функционал быстрее/лучше/более оптимально (нужное подчеркнуть), но для «проекта выходного дня» это может быть избыточно.
Дерзайте!
И еще раз то, ради чего все затевалось:
Дисплей заметно расширил свои возможности по отображению полезной (и не очень) информации, в салоне не добавилось ничего «чужеродного», при этом все штатные функции полностью сохранены.
P.S. Если будут желающие — выложу схему, плату, BOM (поддержу «open hardware»).
P.P.S. Прошивку выкладывать в открытый доступ не буду.
Автор: avstepanov