Хронологія:
Якби я натрапив на подібний матеріал, коли встановляв собі магнітолу на Andrioid, то це зекономило б мені купу часу, нервів і грошей. А тепер до суті справи ;)
Минуло вже трохи часу після встановлення голови на Android, накопичився досвід і бажання виправити основні недоліки.
Основною проблемою було нормально "завести" звук від штатного підсилювача Phillips, яким комплектується моє авто. Підсилювач керується по CAN шині і по ній отримує наступні параметри: гучність, баланс, фейдер, буст низьких і високих частот, пресет еквалайзера, лауднес, регулювання гучності відносно швидкості авто. Отже, стояло завдання знайти адаптер, який дозволив би голові нормально працювати з налаштуваннями підсилювача.
Спробував я, на той час, 3 адаптери: Raise PSA-RZ-15, XP PA-SS-05 і Hiworld PAF 1.21. Hiworld взагалі не зміг увімкнути звук, Raise увімкнув, але звук був дуже тихим, а от XP зміг увімкнути підсилювач, відносно коректно регулювати гучність і навіть передати ламані налаштування еквалайзера. Це був єдиний варіант адаптера з яким можна було жити.
В чому були його основні проблеми? Ламані налаштування зашиті таким чином, що балас встановлений на -3 вліво і фейдер на -3 назад. З даним CAN адаптером в розділі налаштувань автомобіля відкривається новий пункт: Amplifier Settings, котрий дозволяє крутити ці моменти, але китайці не були б китайцями якби там все працювало нормально. Суть в тому, що кожна поділка рухала відповідне налаштуванням з кроком 4.
Ось фото, де налаштування балансу і фейдера виставлені в 0 і збоку пакет, який адаптер передає в CAN шину автомобіля:
А ось фото, де баланс і фейдер посунуті на +1:
Пакети з CAN шини читались за допомогою програми CANHacker і простої бриблуди зпаяної з Arduino і модуля на MCP2515.
Так от, якщо заглянути в розшифровку бітів пакета 0x1E5 PSA CAN, то зрозуміло, що 3С відповідає біту 011 1100 що відповідає значенню -3, а 40 відповідає біту 100 0000 що відповідає +1.
Іншими словами: налаштувати фейдер неможливо, налаштувати баланс з певним костилем - так. Посунувши в цьому меню баланс на 1 вправо і трішки приглушивши правий канал в налаштуваннях еквалайзера самої Android системи можна добитись адекватного балансу. Регулювання басу також доступне з кроком 4, все інше в цьому меню не працює.
Були й інші баги.
Так я і їздив весь цей час поки не натрапив в інтернеті на модуль CANHacker зроблений з Arduino UNO і CAN модуля на MCP2515.
Виявилося, що ним можна не лише читати шину, а й посилати в шину відповідні пакети. Тут і народилась думка, що можна побороти основні баги пов'язані зі звуком, надсилаючи в шину відповідні пакети. Аби це стало реальністю потрібно було вирішити наступні проблеми:
На думку спадало лише одне: CAN адаптер повинен спілкуватись з шиною через "посередника", котрий буде вмикатись в розріз між шиною автомобіля і адаптером магнітоли і буде регулювати які пакети дозволено йому читати чи відправляти. Виявилося, що це цілком реально, хороші люди навіть написали цілу бібліотеку, для Arduino і 2х модулей MCP2515 MCP_CAN.
Для реалізації проекту і, додатково, модуля для CANHacker нам буде потрібно (все це спокійно купується в інтернеті):
Схема рівно така ж як і на малюнку вище, всі піни окрім INT і CS підключаються однаково. INT і CS другого модуля кинув на 3 і 9 піни Arduino. Отак виглядає готовий варіант:
Обов'язково ставимо перемичку, як показано на останньому фото, на модуль, котрий буде підключатись до CAN адаптера магнітоли.
Для перехоплення пакетів кнопок керма, нам знадобиться цифровий потенціометр, я купив модуль на базі мікросхеми x9c104, вона мала повинна мати 100 кроків регулювання опору в діапазоні 1 кОм - 100 кОм. Однак мій варіант має лише 32 кроки, скоріш за все китайська перемаркована схема. По факту діапазон виявився в межах 3 кОм - 99 кОм. Магнітола вже погано реагує на значення понад 30 кОм, тому якщо потрібно перехопити декілька кнопок, то цієї мікросхеми буде достатньо, але якщо мова буде йти про десяток кнопок, то краще заморочитись з чимось на кшталт мікросхеми MCP4011. Вона має 256 кроків регулювання в діапазоні 0,4 кОм - 100 кОм.
Потенціометр під'єднав за схемою:
Далі, коли все під'єднано, схема обробки повідомлень від Comfort шина до CAN адаптера магнітоли буде виглядати наступним чином:
На схемі приклад перехоплення однієї кнопки List (0x21F, 0 байт), проте я додатково перехоплюю і обидві кнопки на "стрикозі" Voice Assist (0x221, 0 байт) та Source (0x0A2, 1 байт).
В принципі, таким підходом можна перехопити будь-яку кнопку, згенерувати опір через потенціометр і далі замапити її в стандартному меню.
Отакий вигляд отримав майже готовий девайс:
Трохи про підключення.
Живитись це діло буде від бортової мережі, не від магнітоли, не від ремоут сигналу з CAN адаптера, оскільки перерва живлення Arduino призведе до того, що CAN адаптер не запуститься, після увімкнення запалювання, і не згенерує ремоут сигнал на магнітолу. Тому в фіналі для живлення схеми додав ще понижувальний DC/DC перетворювач HW-613 через запобіжник в 100 мА. Після чого запакував все в пластикову коробочку:
Як видно на фото, всі підключення зробив через роз'єми, аби полегшити підключення, причому вхід і вихід CAN шини зробив так, аби їх не можна було сплутати. Зробив маніпуляції з жгутом проводів, впаявши такі ж роз'єми:
Оскільки був в наявності фільтр живлення магнітоли, то поставив його на основний жгут проводів:
По апаратні частині завершили, тепер переходимо до програмної. Отже, модуль повинен реалізовувати наступний функціонал:
Першим ділом, за допомогою CANHacker, були виявлені пакети для керування підсилювачем:
Для себе конфігурацію зробив наступною:
Далі реалізував написав метод, який відправляє ці пакети з періодом періодов в CAN шину і не пропускати пакети з такими ж ідентифікаторами від CAN адаптера магнітоли. Додатково написав декілька методів для роботи з налаштуваннями:
Увімкнення/вимкнення.
Arduino буде під'єднано напряму до бортової мережі, тобто живлення буде постійне, навіть коли запалювання вимкнено, а значить є потреба зупиняти надсилання пакетів аби підсилювач вимикався після вимкнення запалювання, але з затримкою в 3 секунди, оскільки магнітола ще близько 3 секунд працює.
Для реалізації цього функціоналу будемо перевіряти пакет 0x0F6 можна почитати значення бітів за посиланнями вище. Нас цікавить 0 байт, а саме чи він містить значення 0x08. Оскільки цей байт може й іншу інформацію окрім значення запалювання, то доведеться робити побітову перевірку.
Формування значення для кожного біту відбувається шляхом додавання значень відповідних налаштувань. Значення вибирається не довільно, а завжди 2^x. Якщо правило не виконується, то, імовірно, не передбачено передачу кількох налаштувань одночасно. Приклад в двійкові системі:
Допустимо значення для увімкненого запалювання 0x08 і значення для того чи двигун запущено 0x02, то результат буде 0x02 + 0x08 = 0x0A (значення в HEX). Переведемо отриманий результат в бінарну систему:
Побітове "І" розраховується так: зіставляються відповідні біти з обох значень, якщо обидва = 1, то результат також одиниця, інакше = 0 в нашому випадку результат буде 1000. Це не нуль і це означає що байт 0x0A містить в собі байт 0x08.
Інший приклад. Допустимо цей байт містить інформацію про увімкнені фари (2^2) 0x04 і протитуманки (2^4) 0x10, сума буде 0x04 + 0x10 = 0x14. Переводимо в бінарну систему:
Зіставляємо біти і отримуємо значення 0000 0000 = 0. Тобто байт 0x14 не містить в собі ідентифікатора увімкненого запалення.
Для кнопок керма спокійно можна не робити побітову перевірку, а просто порівнювати байт, оскільки натискання декількох кнопок на кермі одночасно є малоймовірним, та й потенціометр в нас один і він не зможе генерувати декілька опорів одночасно. Тому так і робив :).
Трохи про налаштування кнопок. В скечі є конфігурація кнопок, де потрібно вказати id пакета, номер байту (в якому зашита конфігурація кнопки), саме значення байту і крок опору на потенціометрі:
З кроком потенціометра може знадобиться трохи погратись, оскільки деякі кроки можуть припадати на границю, де магнітола не буде чітко розуміти яка ж кнопка натиснута і треба збільшити крок. Наприклад крок 12 і 13 спокійно можуть сприйматись магнітолою як та ж кнопка, тому для наступної краще поставити крок 14.
Тепер можна підключати абсолютно будь-який CAN адаптер для магнітоли і підсилювач буде працювати коректно.
Скеч для Arduino можна взяти тут: Citroen Can Transceiver. Також, для зручності, поклав папку з усім на Google Drive. Потрібно пам'ятати, що скрипт по своїй суті універсальний і може бути адаптований до більшості авто. Також можна використовувати лише частину функціоналу, наприклад, лише для перехоплення кнопок керма.
Є ще такий момент, що магнітола працює з CAN адаптером по UART інтерфейсу і якщо розібратись в командах, то можна надсилати дані про натиснуті кнопки напряму до MCU в обхід резистивного інтерфейсу. В принципі, так можна обробляти і багато інших даних аж до повної відмови від стандартного CAN адаптера. Але це вже трохи інша історія в які потрібно розбиратись.
По багах які були описані на початку статті:
В процесі написання статті знайшов аплікацію Serial Manager котра написана для Android пристроєм простими командами по Serial і мапити їх на різні функції. Виглядає значно перспективніше ніж цифровий потенціометр :). Буду пробувати налаштовувати в майбутньому.
Що далі:
Ніби все. Коментуйте ;)
PS: інформація про потенціометр не актуальна. Читайте продовження тут.
Пробіг 254000 км.
Дуже цікаво.
Теж додам в закладки.
Нещодавно саме вперше знайомився з CAN шиною, прилаштував iDrive від БНВ щоб керувати ГП на базі планшету. В майбутній авто скоріш зха все постане питання зчитати коди заводських кнопок керма та керувати ними планшет.