Оглавление:

Пользовательский Arduino для сохранения кнопок CAN на рулевом колесе с новой автомобильной стереосистемой: 9 шагов (с изображениями)
Пользовательский Arduino для сохранения кнопок CAN на рулевом колесе с новой автомобильной стереосистемой: 9 шагов (с изображениями)

Видео: Пользовательский Arduino для сохранения кнопок CAN на рулевом колесе с новой автомобильной стереосистемой: 9 шагов (с изображениями)

Видео: Пользовательский Arduino для сохранения кнопок CAN на рулевом колесе с новой автомобильной стереосистемой: 9 шагов (с изображениями)
Видео: Обновления CarBusAnalyzer. CANDB\OpenDBC, CAN-FD... 2024, Июль
Anonim
Пользовательский Arduino для сохранения кнопок на рулевом колесе с новой автомобильной стереосистемой
Пользовательский Arduino для сохранения кнопок на рулевом колесе с новой автомобильной стереосистемой
Пользовательский Arduino для сохранения кнопок на рулевом колесе с новой автомобильной стереосистемой
Пользовательский Arduino для сохранения кнопок на рулевом колесе с новой автомобильной стереосистемой
Пользовательский Arduino для сохранения кнопок на рулевом колесе с новой автомобильной стереосистемой
Пользовательский Arduino для сохранения кнопок на рулевом колесе с новой автомобильной стереосистемой

Я решил заменить оригинальную автомобильную стереосистему в моем Volvo V70 -02 на новую, чтобы я мог наслаждаться такими вещами, как mp3, bluetooth и громкой связи.

В моей машине есть элементы управления стереосистемой на рулевом колесе, которые я хотел бы по-прежнему использовать. Я не ожидал, что это будет проблемой, потому что на рынке есть несколько адаптеров, которые должны быть совместимы с моей машиной. Однако вскоре я узнал, что это не так! (Похоже, что адаптеры для V70 могут иметь проблемы с автомобилями -02 из-за немного другого протокола CAN.)

Так что же тогда делать? Сохранить старую стереосистему? Жить жизнью с неработающими кнопками? Конечно, нет! Если на рынке нет работающего адаптера, нам придется его создать!

Это руководство может быть применено (с некоторыми изменениями) к автомобилям, где кнопки на рулевом колесе обмениваются данными по шине CAN.

Шаг 1. Узнайте, как отправлять команды на стереосистему

Узнайте, как отправлять команды на стерео
Узнайте, как отправлять команды на стерео
Узнайте, как отправлять команды на стерео
Узнайте, как отправлять команды на стерео

Первое, что вам нужно сделать, это выяснить, какой тип удаленного входа ожидает стерео. Обычно производители не сообщают вам об этом, и у вас, вероятно, нет доступа к работающим пультам дистанционного управления для обратного проектирования.

Пульт дистанционного управления для моей новой стереосистемы (Kenwood) состоит из одного провода, и я не смог найти никакой информации о том, как он работает. Однако он также имеет разъем 3,5 мм для удаленного ввода. Я тоже ничего не мог узнать об этом. Но есть некоторая информация о разъеме 3,5 мм для других производителей, предполагающая, что разные команды идентифицируются путем приложения определенного сопротивления между наконечником и гильзой (и, возможно, между кольцом и гильзой). Например. https://forum.arduino.cc/index.php?topic=230068.0. Поэтому я решил попробовать, снабдив его макетной платой, связкой резисторов и 3,5-миллиметровым штекером, подключенным к стереосистеме и подключенным к макетной плате. Сначала ничего не распознавалось, но в стереосистеме есть меню «режима обучения», в котором команды можно было успешно настраивать, прикладывая различное сопротивление. Успех!

Однако позже я обнаружил, что сделал здесь ошибку: не все команды, которые, казалось, запоминала стереосистема, действительно работают. Например. 30 кОм было обнаружено в режиме обучения, но не работало позже, а для некоторых команд, которые я установил, разница сопротивлений была настолько мала, что позже была запущена неправильная команда.

Поэтому я рекомендую вам использовать макет с резисторами и кнопками переключения для всех удаленных команд, которые вы хотите обрабатывать, и фактически проверить, что все они будут работать.

Если ваша автомобильная стереосистема не может принимать входной сигнал таким же образом, вам придется выяснить, как она работает, чтобы вы могли адаптировать это решение. Если вы вообще не можете понять, значит, у вас проблема.

Шаг 2. Узнайте, где подключиться к CAN-шине

Узнайте, где подключиться к CAN-шине
Узнайте, где подключиться к CAN-шине

Вам нужно найти хорошее место для подключения к CAN-шине. Поскольку вы заменяете старую стереосистему, которая обменивается данными по CAN, вы сможете найти ее за стереосистемой. Шина CAN состоит из пары скрученных проводов (CAN-L и CAN_H). Чтобы убедиться в этом, обратитесь к электросхеме вашего автомобиля.

Шаг 3: обратное проектирование сообщений CAN

Обратный инжиниринг сообщений CAN
Обратный инжиниринг сообщений CAN

Если Google не может сказать вам, какие сообщения CAN вы должны прослушивать, вам нужно будет подключиться к шине CAN и выполнить некоторую обратную разработку. Я использовал Arduino Uno и CAN-щит. (На самом деле вам не нужен щит CAN, как вы увидите позже, вместо этого вы можете использовать некоторые дешевые компоненты на макетной плате.)

Проконсультируйтесь с Google, чтобы узнать, какую скорость передачи данных следует использовать при подключении к автомобилю. (Обычно вы обнаружите, что есть высокоскоростная и низкоскоростная CAN-сеть. Вы подключаетесь к низкоскоростной сети.)

Вам также необходимо запрограммировать Arduino для регистрации всех сообщений CAN через последовательный интерфейс, чтобы вы могли сохранить их в файл журнала на своем компьютере. Стандартная IDE Arduino не сохраняет данные в файл журнала, но вы можете использовать, например, Вместо этого замазывайте.

Перед тем, как вы начнете писать свою программу, вам необходимо установить библиотеку CAN_BUS_Shield.

Вот несколько псевдокодов, которые помогут вам начать работу с вашей программой:

настраивать()

{инициализировать последовательное соединение инициализировать библиотеку CAN} loop () {если получено сообщение CAN {прочитать запись журнала формата сообщения CAN записать запись журнала в последовательный порт}}

Подсказки:

Вы будете использовать экземпляр класса MCP_CAN для доступа к функциям библиотеки CAN:

MCP_CAN m_can;

Инициализировать CAN:

в то время как (m_can.begin ()! = CAN_OK)

{задержка (1000); }

Проверьте и прочтите сообщения CAN:

в то время как (m_can.checkReceive () == CAN_MSGAVAIL)

{// Получить идентификатор CAN, длину сообщения и данные сообщения m_can.readMsgBufID (& m_canId, & m_msgLen, m_msgBuf); // Что-то делаем с данными сообщения здесь}

Если вам нужна дополнительная помощь, вы можете найти ссылку на мою программу на более позднем этапе. Библиотека экрана CAN также включает пример. Или проверьте инструкции mviljoen2, которые включают аналогичный шаг.

Сначала вам понадобится справочный файл, который поможет отфильтровать данные. Переключите зажигание в режим радио и записывайте все в течение пары минут, не нажимая никаких кнопок.

Затем для каждой кнопки начните регистрацию, нажмите кнопку и прекратите регистрацию.

Когда вы закончите, вам нужно отфильтровать все, что есть в вашем журнале ссылок, из журналов кнопок, чтобы найти своих кандидатов. Я обнаружил, что осталось еще много сообщений, поэтому я сделал больше журналов и затем потребовал, чтобы «кандидаты на команду A были во всех файлах кнопок A и ни в одном из справочных файлов». Это оставило мне лишь несколько возможностей попробовать.

Журналы будут содержать много сообщений, поэтому вам нужно будет написать какую-нибудь программу для этого или, возможно, использовать Excel. (Я использовал программу с очень жестко запрограммированными условиями для своих нужд, поэтому боюсь, что не могу предложить программу, которую вы могли бы использовать.)

Предупреждение: нельзя быть уверенным, что кнопка всегда будет выдавать идентичное сообщение. Некоторые биты могут содержать увеличивающиеся счетчики и т. Д. (Однако вы можете за исключением того, что идентификатор сообщения будет таким же.)

Если у вас есть Volvo V70 -02, это то, что вам нужно:

  • Идентификатор сообщения: 0x0400066Byte0: 0x00, 0x40, 0x80 или 0xc0 (все равно)
  • Байт1: 0x00 (все равно)
  • Байт2: 0x00 (все равно)
  • Байт3: 0x00-0x07 (все равно)
  • Байт4: 0x1f (все равно)
  • Байт5: 0x40 (все равно)
  • Байт6: 0x40 (все равно)
  • Байт7: идентификатор кнопки: 0x77 = увеличение громкости, 0x7b = уменьшение громкости, 0x7d = следующая дорожка, 0x7e = предыдущая дорожка.

Если вы считаете, что нашли команды, было бы неплохо изменить программу, чтобы она регистрировала только интересные сообщения. Посмотрите на окно журнала последовательного порта, нажимая кнопки, чтобы убедиться, что вы определили правильные сообщения.

Шаг 4. Аппаратный прототип

Аппаратный прототип
Аппаратный прототип

Ваше оборудование должно уметь:

  1. Определить команды, полученные на шине CAN
  2. Отправлять команды в другом формате в стерео

Если у вас достаточно места, вы можете использовать Arduino и CAN-экран для первой части и подключить дополнительное оборудование для второй. Однако есть и недостатки:

  • Стоимость CAN щита
  • Размер
  • Блок питания Arduino не будет доволен, если он будет подключен напрямую к вашим автомобилям 12 В (он, вероятно, будет работать, но его срок службы, вероятно, сократится).

Поэтому вместо этого я использовал следующее:

  • Atmega 328, «мозг Arduino». (Есть несколько вариантов, возьмите тот, который равен тому, который есть на Arduino Uno. Вы можете купить его с загрузчиком Arduino или без него.)
  • Кристалл 16 МГц + конденсаторы для тактового сигнала.
  • MCP2551 CAN-трансивер.
  • MCP2515 CAN контроллер.
  • TSR1-2450, преобразует 6.5-36V в 5V. (Не используется в прототипе, потому что программное обеспечение не заботится об источнике питания.)
  • Переключатель CD4066B, который будет использоваться при отправке команд на стерео.
  • Пара резисторов. (Значения можно будет найти на схемах Eagle на более позднем этапе.)

Эта конфигурация хороша тем, что она полностью совместима с Arduino и библиотекой щита CAN.

Если вы хотите работать с более чем четырьмя кнопками, вы можете подумать об использовании чего-то другого, кроме CD4066B. CD4066B можно описать как четыре переключателя в одном, каждый из которых управляется одним из выводов Atmegas GPIO. К каждому переключателю подключен резистор, который можно использовать для управления сопротивлением, используемым в качестве входа для стерео. Таким образом, его можно легко использовать для отправки четырех разных команд. Если их объединить, можно получить дополнительные значения сопротивления. Здесь и проявляется ошибка, о которой я упоминал ранее. У меня четыре кнопки, но я планировал реализовать две из них как долгое и короткое нажатие, чтобы давать мне шесть разных команд. Но в конце концов я обнаружил, что не могу найти комбинацию резисторов, которая дала бы мне шесть рабочих комбинаций. Возможно, вместо этого можно было бы подключить аналоговый выходной сигнал к стерео (наконечник 3,5 мм). (Обратите внимание, что Atmega не имеет аналоговых выходов, поэтому потребуется дополнительное оборудование.)

Для тестирования я также сделал простой симулятор «автомобиль и стерео», который можно было подключить к моему прототипу. Это упрощает отладку, и если вам не нравится сидеть в машине и программировать, я могу порекомендовать это.

Прототип показан на изображении на нижней макетной плате. Для питания, программирования и последовательной регистрации он подключен к Arduino Uno, где был удален чип Atmega.

Верхний макет представляет собой симулятор автомобиля + стерео, который будет использоваться для первоначального тестирования прототипа.

Прототип + симулятор предназначен для работы следующим образом:

  • Нажмите одну из кнопок переключателя на плате симулятора. (Это кнопки вашего рулевого колеса.)
  • Когда программа симулятора обнаруживает нажатие кнопки, она будет посылать соответствующее сообщение CAN каждые 70 мс, пока кнопка нажата. (Поскольку журналы, которые я взял ранее, показали, что именно так он работает в моей машине.) Он также будет отправлять множество «нежелательных» CAN-сообщений для имитации другого трафика на шине.
  • Сообщения CAN отправляются по шине CAN.
  • CAN сообщения принимаются прототипом.
  • MCP2515 выдает все несвязанные сообщения на основе идентификатора сообщения.
  • Когда MCP2515 получает сообщение, которое необходимо обработать, он указывает, что у него есть сообщение в очереди.
  • Atmega прочитает сообщение и решит, какую кнопку следует считать активной.
  • Atmega также будет отслеживать, когда было получено последнее сообщение, через определенное время кнопка будет считаться отпущенной. (Сообщения CAN указывают только на то, что кнопка нажата, а не на то, что она была нажата или отпущена.)
  • Если кнопка считается активной, то будут активированы один или несколько переключателей в CD4066B.
  • Симулятор (теперь действующий как ваша стереосистема) обнаружит, что между наконечником и гильзой приложено сопротивление. (Наконечник подключен к 3,3 В и через резистор к выводу аналогового входа. Если команда не активна, этот вывод будет читать 3,3 В, когда команда активна, значение станет ниже и идентифицирует команду.
  • Пока команда активна, также будет активирован соответствующий светодиод. (Есть шесть светодиодов, потому что я планировал использовать разные длинные / короткие нажатия для двух своих кнопок.)

Дополнительные сведения о прототипе оборудования см. В схемах Eagle на более позднем этапе.

Дополнительные сведения об оборудовании платы симулятора:

  • Кристалл 16 МГц
  • Конденсаторы 22 пФ
  • Светодиодные резисторы следует выбирать в зависимости от свойств светодиода.
  • Резистор подключен к A7 и 3,3 В, выберите, например, 2кОм (не критично).
  • Резисторы, подключенные к MCP2551 и MCP2515, являются подтягивающими / понижающими. Выберите, например, 10 кОм.

(Или вы можете использовать экран CAN для «CAN части» симулятора, если хотите.)

При проектировании оборудования важно знать, как контакты Atmega сопоставляются с контактами Arduino.

(Не подключайте какие-либо светодиоды напрямую к CD 4066B, он может работать только с низким током. Я попробовал это, когда впервые протестировал выход, и микросхема пришла в негодность. Хорошо, что я купил пару из них только потому, что они такие дешевые.)

Шаг 5: Программирование предохранителей

Возможно, вы заметили на предыдущем шаге, что у прототипа нет отдельных компонентов для генерации тактового сигнала для MCP2515. Это потому, что в качестве тактового сигнала Atmega уже используется кристалл с частотой 16 МГц, который мы можем использовать. Но мы не можем просто подключить его напрямую к MCP2515, и по умолчанию на Atmega нет тактового сигнала.

(Если хотите, можете пропустить этот шаг и вместо этого добавить дополнительное оборудование часов.)

Однако мы можем использовать так называемое «программирование предохранителей», чтобы включить тактовый сигнал на одном из контактов GPIO.

Сначала вам нужно будет найти файл с именем «boards.txt », используемый вашей IDE Arduino. Вам нужно будет скопировать запись для Arduino Uno, дать ей новое имя и изменить значение low_fuses.

Моя новая доска выглядит так:

########################################################################## ############ # На основе Arduino Uno # Изменения: # low_fuses изменено с 0xff на 0xbf для включения тактовой частоты 16 МГц # на Atmega PB0 / вывод 14 = Arduino D8

clkuno.name = Выход из строя (Arduino Uno)

clkuno.upload.protocol = arduino clkuno.upload.maximum_size = 32256 clkuno.upload.speed = 115200 clkuno.bootloader.low_fuses = 0xbf clkuno.bootloader.high_fuses = 0xde clkuno.bootloader..bootloader.file = optiboot_atmega328.hex clkuno.bootloader.unlock_bits = 0xff clkuno.bootloader.lock_bits = 0xcf clkuno.build.mcu = atmega328p clkuno.build.f_cpu = 16000000L clkuno.build.f_cpu = 16000000ild clkuno.clkunari.o.

##############################################################

Обратите внимание, что выход часов активируется установкой его управляющего бита в 0.

Когда вы создали новую плату в файле конфигурации плат, вам нужно будет записать новый загрузчик на Atmega. Есть разные способы сделать это, я использовал метод, описанный в

После этого не забудьте выбрать новый тип платы, а не Arduino Uno, при загрузке программы в Atmega.

Шаг 6: Программное обеспечение

Программное обеспечение
Программное обеспечение

Пора сделать глупое железо умным, добавив немного программного обеспечения.

Вот псевдокод прототипа:

lastReceivedTime = 0

lastReceivedCmd = none cmdTimeout = 100 setup () {включить сторожевой таймер, настроить контакты D4-D7 в качестве выходных контактов инициализировать CAN настроить фильтр CAN} loop () {сбросить сторожевой таймер, если (сообщение CAN получено) {для каждой команды кнопки {если сообщение CAN принадлежит команда кнопки {lastReceivedTime = now lastReceivedCmd = cmd}}} if now> lastReceivedTime + cmdTimeout {lastReceivedCmd = none} для каждой команды кнопки {если lastReceivedCmd - команда кнопки {установить вывод вывода команды = on} else {установить вывод вывода вывода команды = off }}}

cmdTimeout определяет, как долго мы должны ждать, прежде чем считать, что последняя активная кнопка была отпущена. Поскольку команды сообщения CAN кнопки отправляются примерно каждые 70 мс, она должна быть больше, чем это, с некоторым запасом. Но если он слишком большой, будет задержка. Так что 100 мс кажутся хорошим кандидатом.

Но что такое сторожевой пес? Это небольшая полезная аппаратная функция, которая может спасти нас в случае сбоя. Представьте, что у нас есть ошибка, приводящая к сбою программы, пока активна команда увеличения громкости. Тогда мы бы получили стерео на максимальной громкости! Но если сторожевой таймер не сбрасывается на определенное время, он решит, что произошло что-то непредвиденное, и просто выполнит сброс.

установка void ()

{// разрешить максимум 250 мс для цикла wdt_enable (WDTO_250MS); // другие материалы для инициализации} void loop () {wdt_reset (); // делаем что-нибудь}

CAN фильтр? Что ж, вы можете настроить контроллер CAN так, чтобы он отбрасывал все сообщения, не соответствующие фильтру, чтобы программе не приходилось тратить время на сообщения, которые нам не нужны.

беззнаковая длинная маска = 0x1fffffff; // Включаем в маску все 29 бит заголовка

беззнаковый длинный filterId = 0x0400066; // Нас интересует только идентификатор сообщения CAN m_can.init_Mask (0, CAN_EXTID, mask); // Маска 0 применяется к фильтру 0-1 m_can.init_Mask (1, CAN_EXTID, mask); // Маска 1 применяется к фильтру 2-5 m_can.init_Filt (0, CAN_EXTID, filterId); m_can.init_Filt (1, CAN_EXTID, filterId); m_can.init_Filt (2, CAN_EXTID, filterId); m_can.init_Filt (3, CAN_EXTID, filterId); m_can.init_Filt (4, CAN_EXTID, filterId); m_can.init_Filt (5, CAN_EXTID, filterId);

См. Код библиотеки CAN и документацию по контроллеру CAN для получения дополнительных сведений о том, как настроить фильтр + маску.

Вы также можете настроить контроллер CAN на создание прерывания при получении сообщения (которое не отфильтровано). (Не включен в приведенный выше пример, но в моей программе есть некоторый код для него.) В этом случае он на самом деле не добавляет никакого значения, и это может сбить с толку, если вы не привыкли к программированию.

Итак, это был в итоге прототип программного обеспечения. Но нам также понадобится код для платы симулятора:

lastSentTime = 0

minDelayTime = 70 setup () {настраивает контакты A0-A5 в качестве выходных контактов, настраивает контакты D4-D7 как входные контакты с внутренним подтягиванием. init CAN} loop () {отправить "мусор" может msg установить activeButton = none для каждой кнопки {если кнопка нажата {установить activeButton = button}} if activeButton! = none {если сейчас> lastSentTime + minDelayTime {отправить команду кнопки может сообщать } установить lastSentTime = now} бесценно = прочитать контакт A7 foreach (cmd) {if (min <бес <max) {led on} else {led off}} подождать 1 мс}

Это будет непрерывно отправлять «нежелательные» сообщения CAN примерно каждые мс, а при нажатии кнопки соответствующая команда каждые 70 мс.

Возможно, вам потребуется зарегистрировать ввод на выводе A7, нажимая разные кнопки, чтобы найти подходящие значения для переменных min и max, принадлежащих каждой кнопке. (Или вы можете рассчитать это, но на самом деле чтение ввода даст вам более точные значения.)

Вы должны быть немного осторожны при программировании режимов вывода. Если вы случайно установите контакты, предназначенные для использования внутреннего подтягивания в качестве выходных контактов, тогда вы создадите потенциальный ярлык, который повредит ваш Arduino, когда вы установите высокий выход.

Если вы хотите проверить мои программы, их можно скачать здесь:

  • Программа журнала сообщений CAN
  • Программа для доски тренажера
  • Программа для прототипа / финальной платы

Вы должны знать, что эти программы на самом деле не соответствуют псевдокоду здесь, они содержат много "лишних" вещей, которые на самом деле не нужны, и если вы не знакомы с объектно-ориентированным программированием, их, вероятно, будет немного трудно читать..

Шаг 7: Последнее оборудование

Последнее оборудование
Последнее оборудование
Последнее оборудование
Последнее оборудование
Последнее оборудование
Последнее оборудование

Когда вы довольны своей программой (не забудьте протестировать прототип в машине после окончательного тестирования с помощью платы симулятора), пора конструировать реальное оборудование.

Здесь у вас есть три варианта:

  • Быстро и грязно - спаяйте все вместе на макете печатной платы.
  • Hardcore DIY - протравите свою собственную печатную плату.
  • Ленивый способ - заказать профессиональную печатную плату для пайки компонентов.

Если никуда не торопитесь, могу порекомендовать последний вариант. Если вам нужна только такая маленькая печатная плата, ее очень дешево заказать из Китая. (И тогда вы, вероятно, получите штук десять или около того, чтобы вы могли позволить себе некоторые ошибки при пайке.)

Для заказа печатных плат вам необходимо отправить свой дизайн в формате Gerber. Для этого есть различное программное обеспечение. Я использовал Eagle, который могу порекомендовать. Вы можете рассчитывать на несколько часов, чтобы изучить его, но тогда он отлично работает. Для таких небольших досок вы можете использовать его бесплатно.

Будьте осторожны, когда будете делать дизайн. Не стоит ждать доставки четыре недели только для того, чтобы узнать, что вы сделали что-то не так.

(Если у вас есть хорошие навыки пайки, вы можете спроектировать компоненты для поверхностного монтажа и получить действительно небольшой адаптер. Я этого не делал.)

Тогда закажите, например, в https://www.seeedstudio.com/fusion_pcb.html. Следуйте инструкциям по созданию файлов Gerber из вашего дизайна. Вы также можете предварительно просмотреть результат, чтобы убедиться, что он в порядке.

(В конце концов, мне пришлось выбрать для R4-R7 резисторы, отличные от тех, что указаны на схеме. Вместо этого я использовал 2 кОм, 4,7 кОм, 6,8 кОм и 14,7 кОм.)

И помните - не путайте нумерацию контактов Atmega с нумерацией контактов Arduino!

Я рекомендую вам не паять чип Atmega напрямую, а использовать гнездо. Тогда вы сможете легко удалить его, если вам понадобится перепрограммировать.

Шаг 8: Установка автомобиля

Крепление автомобиля
Крепление автомобиля
Крепление автомобиля
Крепление автомобиля

А теперь самое интересное - установите его в машину и начните пользоваться! (После того, как вы сделали / купили для него футляр.)

Если вы уже полностью протестировали прототип на своей машине, все должно работать отлично.

(Как я уже упоминал ранее, я этого не сделал, поэтому мне пришлось заменить некоторые резисторы и внести некоторые изменения в свою программу.)

Также подумайте, следует ли устанавливать его за стереосистемой или где-нибудь еще. Я нашел хорошее место над перчаточным ящиком, откуда я могу достать его из перчаточного ящика, ничего не разбирая. Это может быть полезно, если я решу обновить его позже.

Наконец-то мои кнопки снова работают! Как я мог прожить без них два месяца?

Шаг 9: Будущие улучшения

Как уже упоминалось, если я сделаю его версию 2.0, я заменю 4066B чем-то другим (возможно, цифровым потенциометром) для большей гибкости.

Вы также можете сделать много других вещей. Например. добавьте модуль bluetooth и сделайте приложение для удаленного управления телефоном. Или модуль GPS, тогда, когда вы находитесь рядом с домом, вы можете автоматически увеличить громкость и отправить сообщение CAN «окна опущены», чтобы все ваши соседи могли наслаждаться вашей прекрасной музыкой.

Рекомендуемые: