Citroen C5 (2G) (Малий)

Android: запуск підсилювача і перевизначення кнопок керма

Я їжджу на Citroen C5 (2G)
Львів, Україна

Якби я натрапив на подібний матеріал, коли встановляв собі магнітолу на 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, то зрозуміло, що відповідає біту 011 1100 що відповідає значенню -3, а 40 відповідає біту 100 0000 що відповідає +1.

Іншими словами: налаштувати фейдер неможливо, налаштувати баланс з певним костилем - так. Посунувши в цьому меню баланс на 1 вправо і трішки приглушивши правий канал в налаштуваннях еквалайзера самої Android системи можна добитись адекватного балансу. Регулювання басу також доступне з кроком 4, все інше в цьому меню не працює.

Були й інші баги. 

  • Коли просиналась магнітола, то часто не було звуку, потрібно було клацнути на регулювання гучності на кермі
  • Короткочасно стрибав баланс звуку при перемиканні радіостанцій, деколи звук пропадав повністю (потрібно було перемкнутись між станціями, аби звук появився)
  • Часто не було чутно співрозмовника, якщо вхідний дзвінок надійшов коли гучність на магнітолі була виставлена в 0 (регулювання гучності після надходження дзвінка не допомагало)
  • Кнопка List, Phone, Voice Assist, Source на кермі відкривали телефон і кнопки неможливо перевизначити, оскільки вони також працюють по CAN шині (хотілось би мати кнопку навігації на кермі)

Так я і їздив весь цей час поки не натрапив в інтернеті на модуль CANHacker зроблений з Arduino UNO і CAN модуля на MCP2515.

CAN модуль на базі Arduino UNO і MCP2515

 

Виявилося, що ним можна не лише читати шину, а й посилати в шину відповідні пакети. Тут і народилась думка, що можна побороти основні баги пов'язані зі звуком, надсилаючи в шину відповідні пакети. Аби це стало реальністю потрібно було вирішити наступні проблеми:

  • Заблокувати пакети пов'язані з підсилювачем, які CAN адаптер надсилає в шину автомобіля, аби не було конфліктів
  • Заблокувати пакети кнопок керма, які читає адаптер, розібрати їх і створити певний опір на вході KEY1 або KEY2, щоб кнопку можна було налаштувати в стандартному меню налаштувань керма

На думку спадало лише одне: CAN адаптер повинен спілкуватись з шиною через "посередника", котрий буде вмикатись в розріз між шиною автомобіля і адаптером магнітоли і буде регулювати які пакети дозволено йому читати чи відправляти. Виявилося, що це цілком реально, хороші люди навіть написали цілу бібліотеку, для Arduino і 2х модулей MCP2515 MCP_CAN.

Для реалізації проекту і, додатково, модуля для CANHacker нам буде потрібно (все це спокійно купується в інтернеті):

  • Arduino Nano - 2 шт
  • CAN модуль на MCP2515 - 3 шт
  • Провідники Dupont тато-мама - 20 шт
  • Плати паяв між собою використовуючи 10-жильний шлейф 28AWG з кроком 1.18мм
  • 2 USB кабелі mini-USB або micro-USB залежно від модифікації плат Arduino Nano
  • Роз'єми JST-SM 2-pin 2.54мм - 5 комплектів
  • Модуль потенціометра на мікросхемі x9c104
  • Якась пластикова коробка

Схема рівно така ж як і на малюнку вище, всі піни окрім INT і CS підключаються однаково. INT і CS другого модуля кинув на 3 і 9 піни Arduino. Отак виглядає готовий варіант:

Варіант модуля на Arduino UNO

Обов'язково ставимо перемичку, як показано на останньому фото, на модуль, котрий буде підключатись до CAN адаптера магнітоли.

Для перехоплення пакетів кнопок керма, нам знадобиться цифровий потенціометр, я купив модуль на базі мікросхеми x9c104, вона мала повинна мати 100 кроків регулювання опору в діапазоні 1 кОм - 100 кОм. Однак мій варіант має лише 32 кроки, скоріш за все китайська перемаркована схема. По факту діапазон виявився в межах 3 кОм - 99 кОм. Магнітола вже погано реагує на значення понад 30 кОм, тому якщо потрібно перехопити декілька кнопок, то цієї мікросхеми буде достатньо, але якщо мова буде йти про десяток кнопок, то краще заморочитись з чимось на кшталт мікросхеми MCP4011. Вона має 256 кроків регулювання в діапазоні 0,4 кОм - 100 кОм.

Потенціометр під'єднав за схемою:

Схема підключення потенціометра

Далі, коли все під'єднано, схема обробки повідомлень від Comfort шина до CAN адаптера магнітоли буде виглядати наступним чином:

Схема обробки пакетів на Arduino

На схемі приклад перехоплення однієї кнопки List (0x21F, 0 байт), проте я додатково перехоплюю і обидві кнопки на "стрикозі" Voice Assist (0x221, 0 байт) та Source (0x0A2, 1 байт).

В принципі, таким підходом можна перехопити будь-яку кнопку, згенерувати опір через потенціометр і далі замапити її в стандартному меню.

Отакий вигляд отримав майже готовий девайс:

Майже готовий девайс )

Трохи про підключення. 

Живитись це діло буде від бортової мережі, не від магнітоли, не від ремоут сигналу з CAN адаптера, оскільки перерва живлення Arduino призведе до того, що CAN адаптер не запуститься, після увімкнення запалювання, і не згенерує ремоут сигнал на магнітолу. Тому в фіналі для живлення схеми додав ще понижувальний DC/DC  перетворювач HW-613 через запобіжник в 100 мА. Після чого запакував все в пластикову коробочку:

Схема в пластикові коробці

 

Як видно на фото, всі підключення зробив через роз'єми, аби полегшити підключення, причому вхід і вихід CAN шини зробив так, аби їх не можна було сплутати. Зробив маніпуляції з жгутом проводів, впаявши такі ж роз'єми:

Жгут проводів

Оскільки був в наявності фільтр живлення магнітоли, то поставив його на основний жгут проводів:

Фільтр живлення магнітоли

 

По апаратні частині завершили, тепер переходимо до програмної. Отже, модуль повинен реалізовувати наступний функціонал:

  • Вмикати підсилювач коли вмикається запалювання
  • Вимикати підсилювач коли вимикається запалювання із затримкою (3 сек)
  • Відправляти в CAN шину пакети з правильними налаштуваннями підсилювача
  • Мати можливість легко внести зміни в конфігурації цих пакетів
  • Зберігати зміни налаштувань в разі втрати живлення
  • Блокувати пакети пов'язані з налаштуваннями підсилювача, які відправляє в шину CAN адаптер магнітоли
  • Перехоплювати натискання певних кнопок керма, генерувати опір на потенціометрі для можливості налаштування кнопки в меню магнітоли

Першим ділом, за допомогою CANHacker, були виявлені пакети для керування підсилювачем:

eb05b6634b1c69e790481677a4f2f59d.webp

  • 0x1A5 - пакет довжиною в 1 байт, періодом в 500 мс який визначає встановлену гучність, діапазон значень 0x00 - 0x1E, що в десяткові системі означає 0 - 30
  • 0x165 - пакет довжиною в 4 байти, періодом в 100 мс який визначає чи головний пристрій увімкнено і, своєю чергою, дає команду на увімкнення підсилювача
  • 0x1E5 - пакет довжиною в 7 байт, періодом в 500 мс який містить налаштування:
    • 0 біт - баланс, діапазон 0x36 - 0x48, що відповідає діапазону регулювання від -9 до 9 в меню стандартної голови
    • 1 біт - фейдер, діапазон 0x36 - 0x48, що відповідає діапазону регулювання від -9 до 9 в меню стандартної голови
    • 2 біт - бас, діапазон 0x36 - 0x48, що відповідає діапазону регулювання від -9 до 9 в меню стандартної голови
    • 3 біт - не використовується, стандартне значення 0x3F
    • 4 біт - високі частоти, діапазон 0x36 - 0x48, що відповідає діапазону регулювання від -9 до 9 в меню стандартної голови
    • 5 біт - конфігурація loudness + speed dependent volume: 
      • не вибрано нічого = 0x00
      • лише loudness = 0x40
      • лише speed dependent volume = 0x07
      • обидва = 0x47
    • 6 біт - пресет еквалайзера (значення відрізняються від значень розписаних у PSA CAN):
      • Lineral = 0x50
      • Classic = 0x44
      • Jazz = 0x48
      • Rock/Pop = 0x4C
      • Techno = 0x54
      • Vocal = 0x50

Для себе конфігурацію зробив наступною:

  • 0x1E5: {0x3F, 0x3E, 0x43, 0x3F, 0x44, 0x47, 0x40} бланс 0, фейдер -1, бас +4, 0, високі +5, loudness = true і speed dependent volume = true, еквалайзер Lineral
  • 0x1A5: {0x14} гучність на рівні 20 з 30
  • 0x165: {0xC0, 0x00, 0x40, 0x00} просто залишив рівно таким, яким його згенерувала стандартна магнітола

Далі реалізував написав метод, який відправляє ці пакети з періодом періодов в CAN шину і не пропускати пакети з такими ж ідентифікаторами від CAN адаптера магнітоли. Додатково написав декілька методів для роботи з налаштуваннями:

  • Запис конфігурації в EEPROM пам'ять на самому Arduino
  • Завантаження конфігурації з пам'яті, якщо така збережена
  • Отримання поточної версії конфігурації через послідовне з'єднання
  • Оновлення конфігурації через послідовне з'єднання

робота з налаштуваннями

Увімкнення/вимкнення. 

Arduino буде під'єднано напряму до бортової мережі, тобто живлення буде постійне, навіть коли запалювання вимкнено, а значить є потреба зупиняти надсилання пакетів аби підсилювач вимикався після вимкнення запалювання, але з затримкою в 3 секунди, оскільки магнітола ще близько 3 секунд працює.

Для реалізації цього функціоналу будемо перевіряти пакет 0x0F6 можна почитати значення бітів за посиланнями вище. Нас цікавить 0 байт, а саме чи він містить значення 0x08. Оскільки цей байт може й іншу інформацію окрім значення запалювання, то доведеться робити побітову перевірку. 

Формування значення для кожного біту відбувається шляхом додавання значень відповідних налаштувань. Значення вибирається не довільно, а завжди 2^x. Якщо правило не виконується, то, імовірно, не передбачено передачу кількох налаштувань одночасно. Приклад в двійкові системі:

  • 2^0 = 0000 0001
  • 2^1 = 0000 0010
  • 2^2 = 0000 0100
  • 2^3 = 0000 1000
  • ...

Допустимо значення для увімкненого запалювання 0x08 і значення для того чи двигун запущено 0x02, то результат буде 0x02 + 0x08 = 0x0A (значення в HEX). Переведемо отриманий результат в бінарну систему:

  • 0x0A = 1010
  • 0x08 = 1000

Побітове "І" розраховується так: зіставляються відповідні біти з обох значень, якщо обидва = 1, то результат також одиниця, інакше = 0 в нашому випадку результат буде 1000. Це не нуль і це означає що байт 0x0A містить в собі байт 0x08.

Інший приклад. Допустимо цей байт містить інформацію про увімкнені фари (2^2) 0x04 і протитуманки (2^4) 0x10, сума буде 0x04 + 0x10 = 0x14. Переводимо в бінарну систему:

  • 0x14 = 0001 0100
  • 0x08 = 0000 1000

Зіставляємо біти і отримуємо значення 0000 0000 = 0. Тобто байт 0x14 не містить в собі ідентифікатора увімкненого запалення.

Для кнопок керма спокійно можна не робити побітову перевірку, а просто порівнювати байт, оскільки натискання декількох кнопок на кермі одночасно є малоймовірним, та й потенціометр в нас один і він не зможе генерувати декілька опорів одночасно. Тому так і робив :).

Трохи про налаштування кнопок. В скечі є конфігурація кнопок, де потрібно вказати id пакета, номер байту (в якому зашита конфігурація кнопки), саме значення байту і крок опору на потенціометрі:

 9403b98adeec5918e323c1b4d6e04d21.webp

З кроком потенціометра може знадобиться трохи погратись, оскільки деякі кроки можуть припадати на границю, де магнітола не буде чітко розуміти яка ж кнопка натиснута і треба збільшити крок. Наприклад крок 12 і 13 спокійно можуть сприйматись магнітолою як та ж кнопка, тому для наступної краще поставити крок 14.

Тепер можна підключати абсолютно будь-який CAN адаптер для магнітоли і підсилювач буде працювати коректно.

Скеч для Arduino можна взяти тут: Citroen Can Transceiver. Також, для зручності, поклав папку з усім на Google Drive. Потрібно пам'ятати, що скрипт по своїй суті універсальний і може бути адаптований до більшості авто. Також можна використовувати лише частину функціоналу, наприклад, лише для перехоплення кнопок керма.

Є ще такий момент, що магнітола працює з CAN адаптером по UART інтерфейсу і якщо розібратись в командах, то можна надсилати дані про натиснуті кнопки напряму до MCU в обхід резистивного інтерфейсу. В принципі, так можна обробляти і багато інших даних аж до повної відмови від стандартного CAN адаптера. Але це вже трохи інша історія в які потрібно розбиратись.

По багах які були описані на початку статті:

  • Виправлено
  • Виправлено
  • Виправлено, але ще тестується
  • Виправлено

В процесі написання статті знайшов аплікацію Serial Manager котра написана для Android пристроєм простими командами по Serial і мапити їх на різні функції. Виглядає значно перспективніше ніж цифровий потенціометр :). Буду пробувати налаштовувати в майбутньому.

Що далі:

  • Доробити зберігання стану налаштувань кнопок керма
  • Можливість реалізувати кнопки керма на Serial Manager
  • Прикрутити якийсь режим енергозбереження для Arduino

Ніби все. Коментуйте ;)


PS: інформація про потенціометр не актуальна. Читайте продовження тут.

Пробіг 254000 км.
Опубліковано: 31 жовтня 2023р. 23:39
Подія: 30 жовтня 2023р. 10:13
5 0 2

Коментарі

Щоб залишати коментарі, потрібно авторизуватись.
Ух!
Дуже цікаво.
Теж додам в закладки.
Нещодавно саме вперше знайомився з CAN шиною, прилаштував iDrive від БНВ щоб керувати ГП на базі планшету. В майбутній авто скоріш зха все постане питання зчитати коди заводських кнопок керма та керувати ними планшет.
14 листопада 2023р. 17:12
Я їжджу на Citroen C5 (2G)
Boobler, досить цікаво. Є якесь додаткове ПЗ для планшета?
14 листопада 2023р. 21:29
Mykhailo, так. Це ASUS Nexus 2012 з кастомною прошивкою. Для нього та 2013 версії є так звана прошивка від Тімура. Специфіка прошивки в тому що він максимально адаптований під медіа пристрій в авто. Наприклад, при подачі живлення від ACC на OTG він прокидається з глибокого сну, під'єднує зовнішній DAC, Arduino (для роботи з штатними кнопками авто), палту відеозахвату (для камери заднього виду при подачі живлення на плату), USB Stick з музикою, відкриває медіа плеер і продовжує грати той трек на якому "заснув" минулого вимкнення. Я собі побудував таку системку і користувався досить довго. Переваги - все модульне отже можна зібрати будь якого рівня якості систему (нажаль окрім планшета бо для інших настільки кастомізованих прошивок я не знайшов). Моєю метою був гарний дисплей та висока якість звука (система працювала з гарним DLS на 5 каналів, та кмоплектом Focal з сабом). Потім я вирішив продавати авто і зняв систему за для встановлення в інше авто....а потім преедумав продавати авто до стабілізації ситуації та вирішив трохи повивчати CAN щоб у новому авто можна було керувати планшетом з шини а не резистивними кнопками яких там скоріш за все не буде. А з приводу керування планшетом з Ардуїнки - там є стара бібліотека, що підтримується лише на старій IDE, вона дозволяє емулювати мультімедіа кнопки клавіатури. https://youtu.be/JRqcK5nezuc?si=MKulBUEqNkRki6q2
15 листопада 2023р. 11:33
Я їжджу на Nissan X-Trail IV
Потяг взакладки, боюсь на настуному авто доведеться з цим розібратися так само глибоко. Чудовий допис!
04 листопада 2023р. 14:46
Я їжджу на Citroen C5 (2G)
yuzo, дякую.
04 листопада 2023р. 16:27