- PVSM.RU - https://www.pvsm.ru -
Приехала ко мне недавно плата под названием Carduino Nano v7. И как-то так вдруг совпало, что примерно в это же время на панели своего авто я с удивлением обнаружил горящую лампочку Check Engine. «Это жжжжжж неспроста» — подумал я, и углубился в поиски. Оказалось, что ошибки можно прочитать без дополнительных устройств — самодиагностика в Форестерах очень проста и доступна любому. Причем здесь тогда Arduino? А при том, что прямым следствием поисков информации по диагностики явилось обнаружение существования такой забавной штуки, как Subaru Select Monitor версии 1, поддержкой протокола которой (забавной штуки) оснащены старые автомобили Subaru, еще до того, как в них появилась K-линия. Именно к таким автомобилям и относится мой Форестер. Вот и появилась у меня озорная мыслишка — реализовать некое подобие бортового компьютера на Arduino. Подобные проекты с обращением к K-линии я видел, а вот с SSM1 — только пара видео на YouTube, никакой конкретики. Поэтому придется делать все самому.
Скорость обмена 1953 бод (1953-8E1). ЭБУ принимает команду чтения данных и начинает сыпать в ответ данными из запрошенного адреса, пока не получит команду остановиться. Чтобы записать данные по адресу, необходимо сначала прочитать данные по этому же адресу. Чтобы запросить идентификатор ЭБУ, необходимо сначала прочитать данные с любого адреса.
В ответ на команды чтения и записи данных приходит следующий пакет данных:
Несмотря на то, что в моем авто присутствует разъем OBD2, в нем имеется полное наличие отсутствия контакта «K-линия».
В разъеме моего авто задействовано 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 как две коротких вспышки.
Итак, по действиям:
Пришлось еще немного погуглить, как объяснить 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 [2]
Обсуждение SSM1, информация о схемах переходников RS232-SSM1 и USB-SSM1 [3]
Автор: RSEvseev
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/arduino/12770
Ссылки в тексте:
[1] Три килограмма любопытства: http://habrastorage.org/storage2/d5e/dbe/dda/d5edbedda31448261847ff07877ab67d.png
[2] Информация о протоколе SSM1: http://www.alcyone.org.uk/ssm/protocol.html
[3] Обсуждение SSM1, информация о схемах переходников RS232-SSM1 и USB-SSM1: http://forums.drom.ru/subaru/t1151098889.html
Нажмите здесь для печати.