Делаем звуки поворотников с помощью Arduino

Имеется автомобиль Ravon R4, он же Chevrolet Cobalt в детстве. И чтобы жизнь мёдом не казалась от владения столь прекрасным пепелацем, подкинули нам искусственную сложность: при замене штатной магнитолы исчезают звуки поворотников. В статье по ссылке подобрано разобрана суть проблемы, а здесь мы будем её решать несколько костыльным путём.

Требования

  • Автомобиль Chevrolet Cobalt в комплектации LTZ или Ravon R4 любой комплектации;
  • Любой программируемый микроконтроллер, я использую Arduino UNO;
  • MCP2515 - CAN-контроллер с интерфейсом SPI;
  • DFPlayer Mini - аппаратный проигрыватель MP3 файлов с последовательным интерфейсом управления;
  • Любой динамик для воспроизведения звуков.

Стоимость такого удовольствия следующая: Arduino (250 руб.), MCP2515 (130 руб.), DFPlayer (60 руб.), динамик (50 руб.). Итого 490 рублей.

Подключение

Схема подключения Arduino и MCP2515 для автомобиля Chevrolet Cobalt и Ravon R4
Итоговая схема подключения

Начнем с CAN-декодера. Прежде чем начать с ним работать, я по советам других пользователей сразу перепаял кварцевый резонатор c 8мГц на 16мГц. У платы MCP2515 в сторону шины два вывода: CAN High и CAN Low. Работать мы будем с шиной SWCAN, которая по своей природе является однопроводной. Значит, CAN High подключаем к шине, CAN Low на землю. Тут уже присутствуют варианты:

  • Взять SWCAN с диагностической колодки, пин №5. Там же кинуть землю;
  • Взять SWCAN с разъема для магнитолы, в нем он находится под номером №14, а земля №38:
Разъем подключения магнитолы Chevrolet Cobalt LTZ и Ravon R4

Другой стороной MCP2515 подключаем к нашему микроконтроллеру — Arduino UNO. Делаем это как показано на схеме:

Подключение MCP2515 к Arduino UNO
  • INT => D2;
  • SCK => D13;
  • SI — D11;
  • SO — D12;
  • CS — D10;
  • GND — GND;
  • VCC — 5V.

MP3 проигрыватель управляется по последовательному порту через пины RX и TX. По факту RX не используется, управление одностороннее. В случае с Arduino можно использовать как физический интерфейс, размещенный на пинах D0 (RX) и D1 (TX) Ардуины, так и воспользовавшись библиотекой SoftwareSerial поднять программный интерфейс на любом цифровом пине. Я выбрал второй вариант и использовал для него пин D6. При первом подключении я столкнулся с помехами на динамик, решением оказалось TX пин подключить через 1кОм резистор. Подключаем проигрыватель так:

  • VCC — 5V;
  • GND — GND;
  • TX — D6;
  • SPK_1 и SPK_2 — на динамик.

На этом подключение заканчивается и мы переходим к теории о шине SWCAN.

SWCAN шина и используемые в ней коды

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

В интернете мне удалось найти два кода соответствующих включению и выключению звука поворотников, но для меня так же критичны звуки незакрытых дверей и непристегнутого ремня. Потому пришлось прибегнуть к самостоятельному “отлову” необходимых кодов. Для этого я использовал программу Can Hacker и залитый соответствующий скетч в ардуино.

Перехват кодов SWCAN с помощью CAN Hacker на Ravon R4
Интерфейс программы CAN Hacker во время перехвата кодов SWCAN Ravon R4

Проехавшись буквально пять минут, создавая ситуация для воспроизведения нужных мне звуков я вывел искомые значения. С радостью делюсь ими с вами (если вдруг, вы найдете еще какие-нибудь интересные значения, не поленитесь поделиться ими с нами :) ):

Поворотник (включить):Extended ID: 0×10400060 DLC: 5 Data: 0×82 0×08 0×01 0xFF 0xD4
Поворотник (выключить):Extended ID: 0×10400060 DLC: 5 Data: 0×81 0×08 0×01 0xFF 0xD5
Открытая водительская дверь на зажигании (включить):Extended ID: 0×10400040 DLC: 5 Data: 0×86 0x3C 0xFF 0xFF 0×58
Открытая водительская дверь на зажигании (выключить):Extended ID: 0×10400040 DLC: 5 Data: 0×86 0x3C 0×00 0xFF 0×58
Сброс одометра (единократный щелчок):Extended ID: 0×10400060 DLC: 5 Data: 0×85 0x1E 0×01 0×33 0×38
Непристегнутый ремень на скорости выше 20км/ч (включить):Extended ID: 0×10400058 DLC: 5 Data: 0×87 0×65 0×64 0xFF 0×05
Непристегнутый ремень на скорости выше 20км/ч (выключить):Extended ID: 0×10400058 DLC: 5 Data: 0×87 0×65 0×00 0xFF 0×05
Тройной писк при открытой двери в движении (единократно):Extended ID: 0×10400060 DLC: 5 Data: 0×86 0×28 0×04 0xFF 0×88
Движение на стояночном тормозе (включить):Extended ID: 0×10400060 DLC: 5 Data: 0×86 0x1E 0xFF 0xFF 0×78
Движение на стояночном тормозе (выключить):Extended ID: 0×10400060 DLC: 5 Data: 0×86 0x1E 0×00 0xFF 0×78

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

Скетч для Arduino

В Arduino IDE устанавливаем необходимые для работы библиотеки:

Подготавливаем MicroSD флеш-карту для проигрывателя: форматируем в FAT32 и копируем в её корень файлы звуков строго под названием 0001.mp3, 0002.mp3, …, 000n.mp3. Для начала можете воспользоваться звуками, которые подготовил я:

Скачать “Скетч декодера SWCAN-шины Chevrolet Cobalt и Ravon R4 вместе со звуками.” CANBus_decoder_cobalt_r4.zip – Загружено 453 раза – 1 МБ

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

Флешку вставляем в DFPlayer Mini и заливаем предложенный мною скетч для Arduino:

#include <mcp_can.h>
#include <SPI.h>

#include <SoftwareSerial.h>
#include <DFMiniMp3.h>

long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
char msgString[128];

#define CAN0_INT 2                              // Set INT to pin 2
MCP_CAN CAN0(10);                               // Set CS to pin 10

class Mp3Notify
{
public:
  static void OnError(uint16_t errorCode)
  {
    Serial.println();
    Serial.print("Com Error ");
    Serial.println(errorCode);
  }

  static void OnPlayFinished(uint16_t globalTrack)
  {
    Serial.println();
    Serial.print("Play finished for #");
    Serial.println(globalTrack);   
  }

  static void OnCardOnline(uint16_t code)
  {
    Serial.println();
    Serial.print("Card online ");
    Serial.println(code);     
  }

  static void OnCardInserted(uint16_t code)
  {
    Serial.println();
    Serial.print("Card inserted ");
    Serial.println(code); 
  }

  static void OnCardRemoved(uint16_t code)
  {
    Serial.println();
    Serial.print("Card removed ");
    Serial.println(code);  
  }
};

SoftwareSerial secondarySerial(5, 6); // RX, TX
DFMiniMp3<SoftwareSerial, Mp3Notify> mp3(secondarySerial);

void setup()
{
  Serial.begin(115200);

  mp3.begin();
  mp3.setVolume(30);
  
  if(CAN0.begin(MCP_ANY, CAN_33K3BPS, MCP_16MHZ) == CAN_OK)
    Serial.println("MCP2515 Initialized Successfully!");
  else
    Serial.println("Error Initializing MCP2515...");
  
  CAN0.setMode(MCP_NORMAL);                     // Set operation mode to normal so the MCP2515 sends acks to received data.
  pinMode(CAN0_INT, INPUT);                            // Configuring pin for /INT input
  Serial.println("Start detect codes for Cobalt/R4...");
}

void loop()
{
  if(!digitalRead(CAN0_INT))                         // If CAN0_INT pin is low, read receive buffer
  {
    CAN0.readMsgBuf(&rxId, &len, rxBuf);      // Read data: len = data length, buf = data byte(s)
    if((rxId & 0x80000000) == 0x80000000) {     // Determine if ID is standard (11 bits) or extended (29 bits)
      if ((rxId & 0x1FFFFFFF) == 272629856) {
        // Поворотники
        if (rxBuf[0] == 0x82) {
          mp3.stop();
          mp3.playMp3FolderTrack(4);
        }
        if (rxBuf[0] == 0x81) {
          mp3.stop();
          mp3.playMp3FolderTrack(5);
        }
        // Одометр
        if (rxBuf[0] == 0x85) {
          mp3.stop();
          mp3.playMp3FolderTrack(7);
        }
        // Открытая дверь на драйве
        if (rxBuf[0] == 0x86 && rxBuf[1] == 0x28) {
          mp3.stop();
          mp3.playMp3FolderTrack(9);
        }
        // Движение на ручнике
        if (rxBuf[0] == 0x86 && rxBuf[1] == 0x1E && rxBuf[2] == 0xFF) {
          mp3.stop();
          mp3.playMp3FolderTrack(1);
        }
        if (rxBuf[0] == 0x86 && rxBuf[1] == 0x1E && rxBuf[2] == 0x00) {
          mp3.stop();
        }
      }
      if ((rxId & 0x1FFFFFFF) == 272629824) {
        // Открытая водительская дверь на зажигании
        if (rxBuf[0] == 0x86 && rxBuf[2] == 0xFF) {
          mp3.stop();
          mp3.playMp3FolderTrack(6);
        }
        if (rxBuf[0] == 0x86 && rxBuf[2] == 0x00) {
          mp3.stop();
        }
      }
      if ((rxId & 0x1FFFFFFF) == 272629848) {
        // Ремень на скорости выше 20кмч
        if (rxBuf[0] == 0x87 && rxBuf[2] == 0x64) {
          mp3.stop();
          mp3.playMp3FolderTrack(8);
        }
        if (rxBuf[0] == 0x87 && rxBuf[2] == 0x00) {
          mp3.stop();
        }
      }
    } else
      sprintf(msgString, "Standard ID: 0x%.3lX       DLC: %1d  Data:", rxId, len);
    
    if((rxId & 0x40000000) == 0x40000000){    // Determine if message is a remote request frame.
      sprintf(msgString, " REMOTE REQUEST FRAME");
    } else {
      for(byte i = 0; i<len; i++){
        sprintf(msgString, " 0x%.2X", rxBuf[i]);
      }
    }
  }
}

Запитываем Ардуину любым удобным способом (хоть спецификации и позволяют запитать её от 12 вольт, что совпадает с бортовой сетью автомобиля, делать этого не рекомендуется — рано или поздно она сгорит) и проверяем работу наших звуков.

9 ответов к «Делаем звуки поворотников с помощью Arduino»

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

  2. Здравствуйте. Не совсем понимаю строки:
    if((rxId & 0×80000000) == 0×80000000) { // Determine if ID is standard (11 bits) or extended (29 bits)
    if ((rxId & 0x1FFFFFFF) == 272629856)
    Откуда цифры 272629856?
    Делаю подобный проект, только вот собираюсь ловить сигнал с кнопок руля и управлять кнопками на Блютуз модуле. Не подскажите в таком случае, у меня сигнал 3С4(ID) 2(DLC) 00 08 00(DATA), как написать этот кусок кода под мой сигнал? Спасибо.
    ПС: автомобиль другой.

  3. Уважаемый автор! Сохранился ли у Вас can dump с низко скоростной шины? Пытаюсь вкорячить в авто магнитолу с блютуз и CAN шиной. Блокировку снял, но магнитола отключается через 10 минут работы. Пытаюсь сделать CAN sender. Поделитесь если есть записанная трасса CAN сообщений. Нужно подать сигнал АСС в шину. Спасибо.

  4. Подскажите как выставить в программе CanHacker 2.00.01 скорость 33.3kbps.
    В ней есть настройка “User Def” но значение не могу вычесть калькулятором.

Добавить комментарий

Ваш адрес email не будет опубликован.