DIY електроніка (CarPC, Arduino, Raspberry Pi, CAN, etc)

Як подружити Android систему з штатним підсилювачем

Опубліковано: 10 березня 23:58
Я їжджу на Citroen C5 (2G)
Львів, Україна

Корок за кроком рішення таки склалось в щось, що, нарешті, не соромно показати. Це рішення можна адаптувати не лише до Peugeot/Citroen з CAN2006, а й до низки інших автомобілів. Спорідненому Peugeot 508 першої генерації з системою JBL теж буде актуально, хоча з невеликими змінами, бо в цьому авто вже використовується CAN2010.

Якщо комусь цікаво з чого це все починалось, то можете подивитись записи в моєму бортжурналі:

Проблематика

Моє авто комплектується HiFi Philips системою з підсилювачем. Звучить воно цілком достатньо аби не кидатись в істериці переробляти все. Ця система керується головним пристроєм NG4 по CAN шині, іншими словами: гучність/еквалайзер/баланс/фейдер - це налаштування, які головний пристрій передає на підсилювач і той вже сам застосовує ці налаштування для обробки звуку, а сам головний пристрій віддає на підсилювач звичайний стереосигнал. Так от, китайські CAN адаптери не вміють працювати з цими налаштуваннями. Китайські CAN адаптери погано працюють з цими налаштуваннями: деякі взагалі не здатні запустити підсилювач, деякі мають фіксовану низьку гучність на підсилювачі, а найкращий з них мав якесь криве налаштування звуку, причому баланс/фейдер були налаштовані так аби грати позаду справа.

І тут є два варіанти розвитку подій:

1) Замінити штатний підсилювач (що робить більшість з тих, хто стикнувся з цією проблемою)

+ відносно просто

- втрата системних звуків і необхідність підлаштовувати штатні компоненти, або повністю їх замінити

2) спробувати подружити ці дві системи, якимись зовнішніми методами

+ залишається штатна система з системними звуками

- купа головного болю, відчаю, заперечення і прийняття неминучості заміни цього брухту на щось кастомне (а може і ні?)


Бажання залишити штатний підсилювач змусило мене піти другим варіантом.


Постановка задачі

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

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

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

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


Трішки про пакети CAN шини

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

  • 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

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

Для реалізації цього функціоналу будемо перевіряти пакет 0x0F6 можна почитати значення бітів за посиланням PSA CAN. Нас цікавить нульовий байт, а саме чи він містить значення 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 не містить в собі ідентифікатора увімкненого запалення.


Апаратна частина

Розроблятись такий модуль буде на базі Arduino і двох CAN адаптерів на базі контролерів MCP2515 та трансиверів MCP2551. Початкова схема (від руки) виглядає отак:



На цій схемі, окрім описаного вище, є ще модуль UART інтерфейсу та транзисторний ключ для комутації +12В - власний ремоут сигнал, котрий буде подаватись на китайський CAN адаптер, що дозволяє повністю вимикати його в режимі сну.

В оригінальний модулях MCP2515 використовується мікросхема трансивера TJA1050, котра трохи не підходить, бо вона не має режиму сну вона постійно буде їсти свої кілька мікроампер без потреби, тому заміняємо її на MCP2551.

Мікросхема MCP41100 це цифровий потенціометр, який буду використовувати для генерування електричного опору для імітації натискання кнопок.


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




Виглядає чудово!

Проте я допустив кілька помилок:

  • діоди UART модуля мають іншу полярність ніж потрібно
  • пін DTR взагалі не потрібно було розводити
  • спільна земля UART модуля з andrioid системою

Рішення:

  • перепаяти діоди в зворотній полярності ніж на схемі
  • коли немає живлення UART модуля, пін DTR підтягується до землі, що трігерить ресет плати arduino, що унеможливлює її запуск. Вирішилось випаюванням конденсатора C3 з плати, а прошити плату можна натисканням на кнопку. 
  • я хотів відмежувати UART модуль від живлення плати діодами і в мене це вдалось, проте я зовсім пропустив той момент, що через USB кабель підключення до магнітоли буде спільна земля - фіаско. Тому при підключенні до USB плата жере близько 40 мА в режимі очікування, що зовсім не ок. Довелось модифікувати сам кабель, щоб розривати петлю коли зникає живлення USB від магнітоли:

Або підключити плату до Android, налаштувати і відключити.

Сама плата спроектована таким чином, щоб використати готові модулі Arduino pro min, UART модуля на мікросхемі CP2102 та перенести всі елементи з обох готових CAN модулів з невеликим додаванням елементів:



Щоправда, я додатково замінив танталові (жовті) конденсатори на керамічні 10uF.

Результат:



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

Варто додати розшифрування пінів колодки:



Піни 10/9 поки не використовуються, це відгалуження від проводів RX/TX якими магнітола обмінюється даними з стандартним CAN модулем. Для майбутніх експериментів.


Далі розпаяв колодку і врізав її в шлейф проводів.



Для прошивки потрібно взяти скетч отут citroen can transceiver.


Програмна частина

Багато описувати не буду бо скетч вийшов об'ємним, кому буде цікаво той точно зможе його почитати. Я лиш акцентую лиш увагу на кількох моментах.

Об'єкт конфігурації.


Об'єкт конфігурації


Весь цей об'єкт записується в EEPROM плати arduino, при внесені зміни в структуру (не значень, а саме в структуру) цього налаштування потрібно не забути змінити номер версії конфіга.


Потенціометр для емуляції натискання кнопок.

Виділені червоним стовпці це "тапи" потенціометра MCP41100 для генерації опору. Перша цифра це тап для короткого натискання, друга - для довгого. Номери тапів обрано не довільно, а на основі мого невеликого дослідження:


Команди через Serial термінал.

При підключені через Serial потрібно встановити baud rate 38400. За допомогою команд можна отримати чи передати і зберегти нові налаштування. Для отримання поточних налаштувань використовується команда get config:


Отримана конфігурація


Що воно таке? Сам рядок конфігурації складається з трьох частин: {id};{data};{checksum}. checksum це сума числових номерів символів по ASCII таблиці з частини data і використовується для верифікації, чи отриманий рядок прийшов без битих символів.

  • 0x1e5;0x3f 0x3f 0x42 0x3f 0x44 0x40 0x40;2233 - налаштування CAN пакета підсилювача
  • 0x000;1 29 5;273 - налаштування принципу регулювання гучності підсилювача (перше число 0/1 - чи використовувати динамічну гучність, друге 0-30 - максимальна гучність підсилювача, третє 0-30 - мінімальна гучність підсилювача). Якщо перше число 0, то достатньо встановити друге число на потрібний рівень гучності, третє можна поставити щось довільне
  • 0x001;1752 88;351 - налаштування перехоплення кнопок. Перше число це сума кнопок (виділено зеленим на скріні об'єкта конфігурації) які хочемо перехоплювати для одинарного натискання, друге це сума кнопок, які хочемо перехоплювати для подвійного натискання.

Якщо не збираєтесь використовувати аплікацію для налаштувань, або маєте з нею є проблеми, а налаштувати потрібно, то верифікацію по checksum можна вимкнути, видаливши перевірку:


Валідація отриманого конфігу


Таким чином ручні налаштування можна буде робити значно простіше. Щоб передати налаштування просто візьміть отриманий рядок, який вас цікавить, внесіть зміни і відправте його знову в термінал. Arduino повинно застосувати налаштування моментально. Перевірити можна викликавши get config ще раз. Якщо налаштування влаштовують, то відправте в термінал save config аби поточні налаштування записались в пам'ять arduino. В цьому випадку плата повинна написати в термінал config saved.


Налаштування через аплікацію

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



Тут ніби все досить наглядно, єдине, що може бути не зовсім зрозуміло, це галочка "Use dynamic volume". Згоден, що назва не надто зрозуміла але суть така: в кан боксах XP є можливість прокидання вибраного рівня гучності з магнітоли в кан шину, а значить, що можна динамічно змінювати гучність на самому підсилювачі, а не тримати фіксовану гучність. І воно справді працює добре, єдине, що довелось додати можливість не опускати гучність нижче певного мінімуму і не підіймати вище певного максимуму.


Галочка Debug відкриває невеличке вікно з пакетами, якими обмінюються пристрої:



Ну і кнопочка налаштування кнопок керма:



Суть в тому, що при натисканні галочки навпроти відповідної кнопки вмикається перехоплювання CAN пакета з інформацією про дану кнопку, коли кнопка натиснута, то біт в пакеті підміняється на 0, натомість плата генерує опір по підключенню до KEY магнітоли. Тобто генерується аналоговий сигнал замість цифрового. Далі цю кнопку можна замапити в меню налаштувань кнопок керма самої android системи.

Налаштування застосовуються в реальному часі, проте щоб записати їх в пам'ять arduino потрібно натиснути кнопку Save config. Тоді після втрати живлення налаштування збережуться.


Аплікація лежить за тим же посиланням: citroen can transceiver.


Завершення

Було б значно простіше, якби подібний модуль можна було би просто купити. Проте, нажаль, доводиться з напилком допрацьовувати китайський пристрій. Якщо згадаю ще якісь речі то буду доповнювати.

0 0

Обговорення

Щоб залишати коментарі, потрібно авторизуватись.