Subaru и Arduino: протокол SSM1. Рукопожатие

Исходные данные




Приехала ко мне недавно плата под названием Carduino Nano v7. И как-то так вдруг совпало, что примерно в это же время на панели своего авто я с удивлением обнаружил горящую лампочку Check Engine. «Это жжжжжж неспроста» — подумал я, и углубился в поиски. Оказалось, что ошибки можно прочитать без дополнительных устройств — самодиагностика в Форестерах очень проста и доступна любому. Причем здесь тогда Arduino? А при том, что прямым следствием поисков информации по диагностики явилось обнаружение существования такой забавной штуки, как Subaru Select Monitor версии 1, поддержкой протокола которой (забавной штуки) оснащены старые автомобили Subaru, еще до того, как в них появилась K-линия. Именно к таким автомобилям и относится мой Форестер. Вот и появилась у меня озорная мыслишка — реализовать некое подобие бортового компьютера на Arduino. Подобные проекты с обращением к K-линии я видел, а вот с SSM1 — только пара видео на YouTube, никакой конкретики. Поэтому придется делать все самому.

Краткое описание протокола SSM1


Скорость обмена 1953 бод (1953-8E1). ЭБУ принимает команду чтения данных и начинает сыпать в ответ данными из запрошенного адреса, пока не получит команду остановиться. Чтобы записать данные по адресу, необходимо сначала прочитать данные по этому же адресу. Чтобы запросить идентификатор ЭБУ, необходимо сначала прочитать данные с любого адреса.

Команды




В ответ на команды чтения и записи данных приходит следующий пакет данных:


И снова Форестер


Несмотря на то, что в моем авто присутствует разъем OBD2, в нем имеется полное наличие отсутствия контакта «K-линия».

  • Контакт 4 — заземление кузова
  • Контакт 5 — сигнальное заземление
  • Контакт 6 — линия CAN-High, J-2284
  • Контакт 7 — K-линия диагностики (ISO 9141-2 и ISO/DIS 14230-4)
  • Контакт 9 — тактовый сигнал SSM
  • Контакт 11 — тактовый сигнал SSM
  • Контакт 12 — SSM to ECM — линия передачи данных от дилерского диагностического прибора SSM в ЭБУ
  • Контакт 13 — ECM to SSM — линия передачи данных от ЭБУ в дилерский диагностический прибор SSM
  • Контакт 14 — линия CAN-Low, J-2284
  • Контакт 15 — L-линия диагностики (ISO 9141-2 и ISO/DIS 14230-4)
  • Контакт 16 — питание +12 от АКБ

В разъеме моего авто задействовано 4 контакта — 4,5,12,13 и 16.

Раз, два, три, четыре, пять — начинаем сопрягать


Донором разъема OBD2 послужил адаптер ELM327, купленный у братьев-китайцев, но абсолютно бесполезный для моего Форестера. Вскрытие показало, что почти все ноги, кроме тех, что нужно, распаяны для использования в самом ELM'е. Чтобы не спалить порты на ардуине, ноги с данными (12 и 13) будем подключать через резисторы — я использовал резисторы на 240 Ом. Землю подключим к обеим ногам с землей (4 и 5). Питать Arduino пока что будем от прикуривателя через USB-адаптер.

Итак, используем 3 провода:


По идее, на этом можно было бы остановиться, зашить в Arduino скетч типа

void setup()
	{
	    pinMode(0, INPUT);
	    pinMode(1, OUTPUT);
	}
	 
	void loop() 
	{
	}
	

и, подключив Arduino к ноутбуку, использовать его как обычный шнурок USB-Subaru с программами типа EvoScan и SelectMonitor. Но основной идеей был именно бортовой компьютер, так что продолжим.

Сочиняем скетч


Поскольку в заголовок данной статьи вынесено слово «рукопожатие», ограничимся именно рукопожатием между Форестером и Arduino — прочитаем ROM ID автомобиля. Дабы ограничиться уже собранной конструкцией, прочитанный ROM ID «промигаем» встроенным светодиодом Arduino, обозначив 1 как длинную вспышку, а 0 как две коротких вспышки.

Итак, по действиям:
  1. Устанавливаем режим обмена UART 1953-8E1
  2. На 3 секунды зажигаем светодиод
  3. Гасим светодиод и ждем 2 секунды
  4. Запрашиваем ROM ID
  5. Промигиваем ROM ID встроенным светодиодом Arduino

Пришлось еще немного погуглить, как объяснить Arduino, что мне нужен контроль четности, и, в результате, получился вот такой скетч:

int led = 13;

void setup()  {
  byte romid[3];

  // Устанавливаем скорость обмена
  Serial.begin(1953);
  // Включаем контроль четности: Even Parity
  UCSR0C = ( UCSR0C & ~_BV(UPM00) | _BV(UPM01) ); 

  pinMode(led, OUTPUT);

  // Зажигаем светодиод на 3 секунды
  digitalWrite(led, HIGH);
  delay(3000);
  // Гасим светодиод и ждем 2 секунды
  digitalWrite(led, LOW); 
  delay(2000);
  
  
  if (ECU_GetROMID(romid))  // Если ROM ID все-таки прочитали,
  {
    for (int i=0;i<3;i++) {
      show_byte(romid[i]);  // То промигаем его светодиодом
    }
  }
}

void loop() {
  // а здесь нам ничего не надо
}

void show_byte(byte b) {
  for (int i=7;i>=0;i--) {
    if (bitRead(b,i)==1) {     
      digitalWrite(led, HIGH);
      delay(1000);
      digitalWrite(led, LOW);
      delay(1000);
    } else {
      digitalWrite(led, HIGH);
      delay(300);
      digitalWrite(led, LOW);
      delay(200);
      digitalWrite(led, HIGH);
      delay(300);
      digitalWrite(led, LOW);
      delay(1200);
    }
  }
}

void ECU_Stop() {
  byte txbuf[4]={0x12,0x00,0x00,0x00};
  
  Serial.write(txbuf[0]);
  Serial.write(txbuf[1]);
  Serial.write(txbuf[2]);
  Serial.write(txbuf[3]);
  
  delay(50);
  
  Serial.flush();
}

boolean ECU_GetROMID(byte * buffer) {
  char readCmd[4] ={0x78,0x00,0x00,0x00};
  char romidCmd[4]={0x00,0x46,0x48,0x49};
  char romid[3]   ={0};

  ECU_Stop();

  Serial.write(readCmd[0]);
  Serial.write(readCmd[1]);
  Serial.write(readCmd[2]);
  Serial.write(readCmd[3]);
  
  
  int retries = 0;
  while (retries<8) {
    int nbytes = Serial.readBytes(romid,3);
    
    if ((nbytes == 3) && (romid[0]!=0x00))
      break;
    
    Serial.write(romidCmd[0]);
    Serial.write(romidCmd[1]);
    Serial.write(romidCmd[2]);
    Serial.write(romidCmd[3]);
    ++retries;
  }
  ECU_Stop();
  
  buffer[0] = romid[0];
  buffer[1] = romid[1];
  buffer[2] = romid[2];
  
  if (romid[0] == 0x00) {
    return false;
  }
  
  return true;
}


Результат


Заливаем данный скетч в Arduino, спускаемся в машину, подключаем разъем OBD2, включаем зажигание, подаем питание на Arduino и… начинаем вбивать нолики и единички в телефон, поскольку больше с собой ничего не взяли. Arduino весело проморгал мне комбинацию 1010 0011 0000 0001 0001 0111, что в переводе на общечеловеческий означает 0xA30117 — это и есть ROM ID моего Форестера. «Ну, здравствуй, 0xA30117! А меня Роман зовут.»

Послесловие


К сожалению, для большинства автомобилей с поддержкой SSM1 известно в лучшем случае только 18 адресов важных параметров — таких, как напряжение аккумулятора, обороты двигателя и прочее. Поэтому работы еще непаханное поле — считывание дампа памяти, поиск адресов с ошибками и т.д. Ну что ж — есть еще, к чему стремиться…

Используемые материалы


Информация о протоколе SSM1
Обсуждение SSM1, информация о схемах переходников RS232-SSM1 и USB-SSM1
Поделиться публикацией
Комментарии 10
    0
    Такой вот чайниковский вопрос — там на контактах 6 и 14 висит шина CAN. Она, насколько я понимаю, практически через все устройства машины проходит и по ней можно получить кучу всякой информации, и даже автомобилем управлять — ну, газ, «нажать», к примеру, если педаль электронная. Или я чего недопонимаю?
      0
      Шина CAN в моем авто отсутствует. Только SSM1. Иначе меня вполне бы устроил адаптер ELM327 и не пришлось бы использовать его в качестве донора.
      0
      Несмотря на то, что в моем авто присутствует разъем OBD2, в нем имеется полное наличие отсутствия контакта «K-линия».

      Я правильно понял, что разъем OBD2 разный бывает? В вашем случае без К-линии. А что за К-линия такая?
      Можно чуть подробней?
        0
        Разъем OBD2 — это просто стандартизированный разъем. А вот в зависимости от того, какие контакты в нем присутствуют — определяется, какая из диагностических линий будет использоваться. Это может быть K-линия, K+L линии, CAN или, как в моем случае, SSM1.

        K-линия — одна из диагностических линий — связь между электронными блоками управления компонентами автомобиля и диагностическим разъёмом. В основном используется в более-менее свежем отечественном автопроме (если мне не изменяет память — появилась там с приходом инжекторных моделей) и в группе VAG (Volkswagen, Audi, Seat, Skoda), хотя многие другие производители тоже не стесняются ее использовать, например Subaru в более свежих моделях.

        Большинство нынешних бортовых компьютеров поддерживают работу по K-линии, многие поддерживают так же CAN. А вот с SSM1 мне не попадались — иначе этой статьи бы не было.
          0
          Если хочется работать именно с K-линией, то нужно будет использовать микросхему-конвертер KKL-UART, например l9637d.
            0
            Уважаемый, скажите если знаете — а если хочется работать с CAN шиной, например на Mersedes, то где за это информацию можно добыть? Например продают различные CAN адаптеры для установки сигнализации. Что-то похожее но своими руками, для вопроса взаимодействия с машиной — было бы интересно узнать.
              0
              Ну, можно собрать адаптер Сидоренко (аналог ELM327 на PIC18F2455) — вполне себе вариант.
                0
                Спасибо, интересная ссылка.
        0
        Отлично. Вот только стоит подумать насчет подключить Ардуину через опторазвязку. Не исключено, что в разъеме опторазвязка уже стоит, но на всякий случай… бортовая сеть в машине — дело тонкое.
          0
          В принципе, можно попробовать.

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

        Самое читаемое