Получение данных по K-Line автомобиля - ISO 14230 KWP 10.4 Kbaud. ARDUINO

Holodz
Offline
Зарегистрирован: 16.07.2022

Всем привет. Уже находил на данном форуме темы по ISO 14230, но там идет общение в основном по протоколу OBD2 (стандартному), в моем случае автомобиль Renault, видимо использует свои "адреса и данные". Никак не могу реализовать скейтч на Arduino Mega 2560, ну никак не работает...

Для общения по K-линии использую MC33290. Предоставляю лог общения ELM327 с машиной:

############################################################
#connect to: SCAN Addr:7A Protocol:KWP2000
############################################################
>[00:23:41.468]AT SH 81 7A F1
<[0.025]AT SH 81 7A F1
OK

>
>[00:23:41.493]AT SW 96
<[0.015]AT SW 96
OK

>
>[00:23:41.508]AT WM 81 7A F1 3E
<[0.015]AT WM 81 7A F1 3E
OK

>
>[00:23:41.523]AT IB10
<[0.016]AT IB10
OK

>
>[00:23:41.539]AT ST FF
<[0.014]AT ST FF
OK

>
>[00:23:41.553]AT AT 0
<[0.036]AT AT 0
OK

>
>[00:23:41.589]AT SP 4
<[0.026]AT SP 4
OK

>
>[00:23:41.615]AT IIA 7A
<[0.018]AT IIA 7A
OK

>
>[00:23:41.633]AT SI
<[2.832]AT SI
BUS INIT: ...ERROR

>
>[00:23:44.465]AT SP 5
<[0.025]AT SP 5
OK

>
>[00:23:44.491]AT FI
<[0.423]AT FI
BUS INIT: OK

>
>[00:23:44.914]AT AT 1
<[0.025]AT AT 1
OK

>
>[00:23:44.939]10C0
<[1.266]10C0
50 

>
>[00:23:46.205]2180
<[1.232]2180
61 80 82 00 50 78 00 18 30 33 37 82 00 30 93 18 00 CB B2 00 74 0D 7D 07 21 B2 

>

По итогу, что я определил точно:

1. ELM327 спокойно общается и получает данные по команде AT SP 5 (то есть - ISO 14230-4 KWP [fast init, 10.4 Kbaud]).

2. 7A - адрес блока ЭБУ двигателя

3. В конце отправляется команда 2180 и получается ответ 61 80 82 00 50 78 00 18 30 33 37 82 00 30 93 18 00 CB B2 00 74 0D 7D 07 21 B2, по конечному итогу нужно чтобы так и получилось. 2180 - это что-то типа "раздела" в блоке ЭБУ "7А", т.к. помимо 2180, можно отправить - 21AA, 21AB, 21AC, 2179, 21A9 и так далее. В ответ приходит строка. Что именно в ответе приходит (в длинной строке) я знаю, и формулы есть для расшифровки и перевода, все есть. Не получается только отправить это все по K-Линии чтобы получить ответ...

 

Кстати, скачал на телефон Bluetooth Terminal, подключился к ELM327. Настройки выставлены следующие: 

- Baud Rate : 10400

- Data Bits : 8

- Stop Bits : 1

- Parity : none

Достаточно было отправить вот эти 3 строчки, чтобы получить нужный мне ответ, а именно:

AT SH 81 7A F1

AT WM 81 7A F1 3E

2180 (или 21AA, 21AB, 21A9 и тд)

 

Holodz
Offline
Зарегистрирован: 16.07.2022

Если кто поможет разобраться,  смогу отблагодарить даже финансово, если будете не против!!! 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Ну так и пробуйте отправлять 81 7A F1

Сначала 300 мс HIGH на линии TX, потом 25 мс LOW, потом 25 мс HIGH. Потом сразу Serial.begin(10400) и посылаем байты...

MaksVV
Offline
Зарегистрирован: 06.08.2015

можно также заснифить что реально на клайне происходит между елм и pcm

Holodz
Offline
Зарегистрирован: 16.07.2022

Доброе времени суток.

Можно по подробнее про то, как это сделать?

У меня автомобиль Renault и тут по К-Линии они общаются по "своему" как то. То есть о чем я. Если я начну через обычную программу OBD2 проверять параметры - мне не 1 параметр не покажет. У рено своя база, и я использую приложение PYCLIP с оригинальной базой дилерского CLIPa. И ELM327 общается через эту программу по своему, ну опять же, какие команды она посылает и так далее, я уже в 1 посте выложил. Интересно было бы посмотреть что конкретно запрашивает у К-Линии, потому что в логах ELM327 много лишнего, хотя в 1 посте во 2 коде я с помощью всего 3 строчек смог получить в ответ нужную мне строку.

Holodz
Offline
Зарегистрирован: 16.07.2022

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

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Можно использовать Saleae Logic или подобный девайс и снять сигнал с самой линии K-line. Только надо уровень сигнала согласовать с уровнем Saleae Logic...

MaksVV
Offline
Зарегистрирован: 06.08.2015

проверяейте

#define PCM_ADDRESS 0x7A
#define K_LINE Serial2  // тут выбираем Serial, на котором висит Клайн адаптер
#define TX 16           // и соответствующий ему  пин TX

#define PID_PERIOD_ms 100 // выбираем периодичность диагн запросов


byte bus_init = 0; 
#define INIT_END  9
#define NEED_INIT 1

const byte BEGIN[]         {0x10, 0xC0};
const byte PID[]           {0x21, 0x80};


void setup() {
 Serial.begin(9600); delay (1000);
 
 bus_init =NEED_INIT; 
}

void fastInit(){
     static uint32_t timerInit = 0; 
     if (bus_init==NEED_INIT) {K_LINE.end(); pinMode (TX, OUTPUT); digitalWrite(TX, 0); timerInit = millis(); bus_init++;}
else if (bus_init==2 && millis() - timerInit>24) {timerInit = millis(); digitalWrite(TX, 1); bus_init++; }
else if (bus_init==3 && millis() - timerInit>24) {K_LINE.begin (10400); bus_init=INIT_END;}
}

void sendMessage(const byte *command, const size_t size)
{
  const byte siZe = size+4;
  byte Mes[siZe];
  byte Checksum = 0;
  for(byte i=0; i<siZe; i++) 
  {
    if (i==0) {Mes[i]=size; bitWrite(Mes[i], 7 , 1);}
    if (i==1) Mes[i] = PCM_ADDRESS;
    if (i==2) Mes[i] = 0xF1;    
    if (i==3) {for (byte t=0; t<size; t++ ) {Mes[i]=command[t]; Checksum+=Mes[i] ;K_LINE.write (Mes[i]); K_LINE.read(); i++;}}
    if (i!=siZe-1) Checksum+=Mes[i];
    else Mes[i] = Checksum;    
    K_LINE.write (Mes[i]); K_LINE.read();
  }
}

void read_KLINE()
{
  static byte header = 0;             // состояние заголовка 
  static byte message_size = 0;       // размер тела принимаемого сообщения, кол-во байт
  static byte j = 1;                  // инкремент
  static byte n = 3;
  const byte bufsize = 60;            // размер буфера принятого сообщения
  static byte buf [bufsize] = {0};    // буфер принятого сообщения
  static byte checksum = 0;           // контрольная сумма входящего сообщения
  static uint32_t prevRESETheader=0;  // таймер сброса заголовка если в момент приёма сообщения данные оборвались
  static bool RESETheader_timer = 0;  // таймер сброса заголовка если в момент приёма сообщения данные оборвались

if (K_LINE.available()){
    

 // первый старт байт
 if (header == 0){buf[0]=K_LINE.read();  
         if (!bitRead (buf[0],6) && bitRead (buf[0],7)){header = 1; RESETheader_timer=1; prevRESETheader = millis();}
         
         }                  
 // второй старт байт
 else if (header == 1){buf[1]=K_LINE.read(); if (buf[1]==0xF1){ header = 2;} else {header = 0; RESETheader_timer=0;}} 

 // третий старт байт
 else if (header == 2){ 
  buf[2]=K_LINE.read(); 
  if (buf[2]==PCM_ADDRESS){ 
  if (buf[0] !=0x80) {header = 4; message_size=buf[0]; bitWrite(message_size,7,0); n=3;}
  else {header = 3; n=4;}
  if (message_size > bufsize) message_size = bufsize;  checksum = 0;} else {header = 0; RESETheader_timer=0; }
  
                          }  
// если размер сообщения указан в дополнительном байте (нулевой байт 0x80) читаем этот дополнительный байт:
else if (header == 3){
  buf[3]=K_LINE.read(); 
  message_size = buf[3];
  if (message_size > bufsize) message_size = bufsize;  
  checksum = 0; header = 4;  
                         }

  // пишем тело сообщения 
 else if (header == 4 && j<= message_size+1) {
 buf[j+n-1] = K_LINE.read(); 
 if (j<message_size+1) checksum+= buf[j+n-1]; // подсчёт КС
 if (j==message_size+1) header = 5; 
  j++;} 

 } // end of K_LINE.available()

 // сообщение приняли, действуем
 if (header == 5) {  

for(byte i = 0; i<n; i++) checksum+=buf[i]; // прибавляем к контрольной сумме старт байты

 // если контрольная сумма верна: 
if (buf[message_size+n] == checksum) 
{
  for (byte i=0; i<message_size+n+1; i++) {if (buf[i]<=0xF)Serial.print ("0"); Serial.print (buf[i], HEX); Serial.print(" ");}
  Serial.println();
  if (buf[n]== 0x61 && buf[n+1]==0x80)   {Serial.println("Receive PID 2180");} //тут обрабатываем полученный ответ на PID 2180
 }     
    
// если контрольная сумма не совпала: 
//else Serial.println("CRC fail!!!" );
message_size = 0; header=0; RESETheader_timer=0; j=1; checksum = 0;
 }
// таймер сброса заголовка если данные оборвались по середине сообщения
if (RESETheader_timer && millis() - prevRESETheader > 500) {Serial.println("timeout"); message_size = 0; RESETheader_timer = 0; header = 0;checksum = 0;j=1;}   

}


 
void loop() 
{
fastInit();     
read_KLINE();
if (bus_init==INIT_END) {sendMessage (BEGIN, sizeof(BEGIN));bus_init++;}
static uint32_t prevtimePID = 0;
if (millis()-prevtimePID>PID_PERIOD_ms) {prevtimePID= millis();sendMessage (PID, sizeof(PID)); }
}

 

Holodz
Offline
Зарегистрирован: 16.07.2022

Komandir пишет:

Можно использовать Saleae Logic или подобный девайс и снять сигнал с самой линии K-line. Только надо уровень сигнала согласовать с уровнем Saleae Logic...

 

Я так понимаю данная программа работает только с USB?

MaksVV
Offline
Зарегистрирован: 06.08.2015

Просьба отписаться по результатам моего скетча. Мега спокойно справится со сниффом если что

Holodz
Offline
Зарегистрирован: 16.07.2022

MaksVV пишет:

проверяейте

#define PCM_ADDRESS 0x7A
#define K_LINE Serial2  // тут выбираем Serial, на котором висит Клайн адаптер
#define TX 16           // и соответствующий ему  пин TX

#define PID_PERIOD_ms 100 // выбираем периодичность диагн запросов


byte bus_init = 0; 
#define INIT_END  9
#define NEED_INIT 1

const byte BEGIN[]         {0x10, 0xC0};
const byte PID[]           {0x21, 0x80};


void setup() {
 Serial.begin(9600); delay (1000);
 
 bus_init =NEED_INIT; 
}

void fastInit(){
     static uint32_t timerInit = 0; 
     if (bus_init==NEED_INIT) {K_LINE.end(); pinMode (TX, OUTPUT); digitalWrite(TX, 0); timerInit = millis(); bus_init++;}
else if (bus_init==2 && millis() - timerInit>24) {timerInit = millis(); digitalWrite(TX, 1); bus_init++; }
else if (bus_init==3 && millis() - timerInit>24) {K_LINE.begin (10400); bus_init=INIT_END;}
}

void sendMessage(const byte *command, const size_t size)
{
  const byte siZe = size+4;
  byte Mes[siZe];
  byte Checksum = 0;
  for(byte i=0; i<siZe; i++) 
  {
    if (i==0) {Mes[i]=size; bitWrite(Mes[i], 7 , 1);}
    if (i==1) Mes[i] = PCM_ADDRESS;
    if (i==2) Mes[i] = 0xF1;    
    if (i==3) {for (byte t=0; t<size; t++ ) {Mes[i]=command[t]; Checksum+=Mes[i] ;K_LINE.write (Mes[i]); K_LINE.read(); i++;}}
    if (i!=siZe-1) Checksum+=Mes[i];
    else Mes[i] = Checksum;    
    K_LINE.write (Mes[i]); K_LINE.read();
  }
}

void read_KLINE()
{
  static byte header = 0;             // состояние заголовка 
  static byte message_size = 0;       // размер тела принимаемого сообщения, кол-во байт
  static byte j = 1;                  // инкремент
  static byte n = 3;
  const byte bufsize = 60;            // размер буфера принятого сообщения
  static byte buf [bufsize] = {0};    // буфер принятого сообщения
  static byte checksum = 0;           // контрольная сумма входящего сообщения
  static uint32_t prevRESETheader=0;  // таймер сброса заголовка если в момент приёма сообщения данные оборвались
  static bool RESETheader_timer = 0;  // таймер сброса заголовка если в момент приёма сообщения данные оборвались

if (K_LINE.available()){
    

 // первый старт байт
 if (header == 0){buf[0]=K_LINE.read();  
         if (!bitRead (buf[0],6) && bitRead (buf[0],7)){header = 1; RESETheader_timer=1; prevRESETheader = millis();}
         
         }                  
 // второй старт байт
 else if (header == 1){buf[1]=K_LINE.read(); if (buf[1]==0xF1){ header = 2;} else {header = 0; RESETheader_timer=0;}} 

 // третий старт байт
 else if (header == 2){ 
  buf[2]=K_LINE.read(); 
  if (buf[2]==PCM_ADDRESS){ 
  if (buf[0] !=0x80) {header = 4; message_size=buf[0]; bitWrite(message_size,7,0); n=3;}
  else {header = 3; n=4;}
  if (message_size > bufsize) message_size = bufsize;  checksum = 0;} else {header = 0; RESETheader_timer=0; }
  
                          }  
// если размер сообщения указан в дополнительном байте (нулевой байт 0x80) читаем этот дополнительный байт:
else if (header == 3){
  buf[3]=K_LINE.read(); 
  message_size = buf[3];
  if (message_size > bufsize) message_size = bufsize;  
  checksum = 0; header = 4;  
                         }

  // пишем тело сообщения 
 else if (header == 4 && j<= message_size+1) {
 buf[j+n-1] = K_LINE.read(); 
 if (j<message_size+1) checksum+= buf[j+n-1]; // подсчёт КС
 if (j==message_size+1) header = 5; 
  j++;} 

 } // end of K_LINE.available()

 // сообщение приняли, действуем
 if (header == 5) {  

for(byte i = 0; i<n; i++) checksum+=buf[i]; // прибавляем к контрольной сумме старт байты

 // если контрольная сумма верна: 
if (buf[message_size+n] == checksum) 
{
  for (byte i=0; i<message_size+n+1; i++) {if (buf[i]<=0xF)Serial.print ("0"); Serial.print (buf[i], HEX); Serial.print(" ");}
  Serial.println();
  if (buf[n]== 0x61 && buf[n+1]==0x80)   {Serial.println("Receive PID 2180");} //тут обрабатываем полученный ответ на PID 2180
 }     
    
// если контрольная сумма не совпала: 
//else Serial.println("CRC fail!!!" );
message_size = 0; header=0; RESETheader_timer=0; j=1; checksum = 0;
 }
// таймер сброса заголовка если данные оборвались по середине сообщения
if (RESETheader_timer && millis() - prevRESETheader > 500) {Serial.println("timeout"); message_size = 0; RESETheader_timer = 0; header = 0;checksum = 0;j=1;}   

}


 
void loop() 
{
fastInit();     
read_KLINE();
if (bus_init==INIT_END) {sendMessage (BEGIN, sizeof(BEGIN));bus_init++;}
static uint32_t prevtimePID = 0;
if (millis()-prevtimePID>PID_PERIOD_ms) {prevtimePID= millis();sendMessage (PID, sizeof(PID)); }
}

 

 

Спасибо огромное за предоставленный код, НО, данный вариант использует MC33290 или нет? Т.к. у меня на Arduino через данную микруху приходит: RX и TX, а K-Line от автомобиля собственно идет сначала на саму ногу MC33290. От RX MC33290 я подаю на D9, а TX MC33290 на D8

 

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

Все правильно так и надо

Holodz
Offline
Зарегистрирован: 16.07.2022

MaksVV пишет:
Все правильно так и надо

Подскажите, на данном фото RX от микрухи MC33290 подается на RX пина Arduino, а TX от микрухи подается на RST (Reset?), почему так или это не правильное подключение? Я просто как выше написал, от TX микрухи подал на D8, а RX от микрухи подал на D9

Holodz
Offline
Зарегистрирован: 16.07.2022

Ну я так понимаю по Вашему примеру (Serial2), TX я вешаю на 16, а RX на 17

MaksVV
Offline
Зарегистрирован: 06.08.2015

На картинке выше неправильно вы смотрите. Там подключено к тх и rх (подпись пина сверху) а крайний тх сбоку подписано. На меге, да, подключать на 16тх и 17rх

MaksVV
Offline
Зарегистрирован: 06.08.2015

MaksVV пишет:
Все правильно так и надо

Ну имелось ввиду так и надо - это через интерфейс клайн соединяться, а не напрямую к ардуине. Но не к ногам D8 и D9 трансивер клайн цеплять. Так как у вас мега, там 4 аппаратных сериал порта, их и нужно использовать. Например Serial2

MaksVV
Offline
Зарегистрирован: 06.08.2015

И имейте ввиду, насколько помню правильное подключение tx ардуино соединяем с tx 33290. А Rx c Rx. Т.е. НЕ перекрёстное подключение

Holodz
Offline
Зарегистрирован: 16.07.2022

MaksVV пишет:
И имейте ввиду, насколько помню правильное подключение tx ардуино соединяем с tx 33290. А Rx c Rx. Т.е. НЕ перекрёстное подключение

 

Да, правильно помните, так и есть, выход MC33290 TX к TX Arduino, соответственно RX к RX. Завтра попробую - отпишусь.

Holodz
Offline
Зарегистрирован: 16.07.2022

MaksVV пишет:

проверяейте

#define PCM_ADDRESS 0x7A
#define K_LINE Serial2  // тут выбираем Serial, на котором висит Клайн адаптер
#define TX 16           // и соответствующий ему  пин TX

#define PID_PERIOD_ms 100 // выбираем периодичность диагн запросов


byte bus_init = 0; 
#define INIT_END  9
#define NEED_INIT 1

const byte BEGIN[]         {0x10, 0xC0};
const byte PID[]           {0x21, 0x80};


void setup() {
 Serial.begin(9600); delay (1000);
 
 bus_init =NEED_INIT; 
}

void fastInit(){
     static uint32_t timerInit = 0; 
     if (bus_init==NEED_INIT) {K_LINE.end(); pinMode (TX, OUTPUT); digitalWrite(TX, 0); timerInit = millis(); bus_init++;}
else if (bus_init==2 && millis() - timerInit>24) {timerInit = millis(); digitalWrite(TX, 1); bus_init++; }
else if (bus_init==3 && millis() - timerInit>24) {K_LINE.begin (10400); bus_init=INIT_END;}
}

void sendMessage(const byte *command, const size_t size)
{
  const byte siZe = size+4;
  byte Mes[siZe];
  byte Checksum = 0;
  for(byte i=0; i<siZe; i++) 
  {
    if (i==0) {Mes[i]=size; bitWrite(Mes[i], 7 , 1);}
    if (i==1) Mes[i] = PCM_ADDRESS;
    if (i==2) Mes[i] = 0xF1;    
    if (i==3) {for (byte t=0; t<size; t++ ) {Mes[i]=command[t]; Checksum+=Mes[i] ;K_LINE.write (Mes[i]); K_LINE.read(); i++;}}
    if (i!=siZe-1) Checksum+=Mes[i];
    else Mes[i] = Checksum;    
    K_LINE.write (Mes[i]); K_LINE.read();
  }
}

void read_KLINE()
{
  static byte header = 0;             // состояние заголовка 
  static byte message_size = 0;       // размер тела принимаемого сообщения, кол-во байт
  static byte j = 1;                  // инкремент
  static byte n = 3;
  const byte bufsize = 60;            // размер буфера принятого сообщения
  static byte buf [bufsize] = {0};    // буфер принятого сообщения
  static byte checksum = 0;           // контрольная сумма входящего сообщения
  static uint32_t prevRESETheader=0;  // таймер сброса заголовка если в момент приёма сообщения данные оборвались
  static bool RESETheader_timer = 0;  // таймер сброса заголовка если в момент приёма сообщения данные оборвались

if (K_LINE.available()){
    

 // первый старт байт
 if (header == 0){buf[0]=K_LINE.read();  
         if (!bitRead (buf[0],6) && bitRead (buf[0],7)){header = 1; RESETheader_timer=1; prevRESETheader = millis();}
         
         }                  
 // второй старт байт
 else if (header == 1){buf[1]=K_LINE.read(); if (buf[1]==0xF1){ header = 2;} else {header = 0; RESETheader_timer=0;}} 

 // третий старт байт
 else if (header == 2){ 
  buf[2]=K_LINE.read(); 
  if (buf[2]==PCM_ADDRESS){ 
  if (buf[0] !=0x80) {header = 4; message_size=buf[0]; bitWrite(message_size,7,0); n=3;}
  else {header = 3; n=4;}
  if (message_size > bufsize) message_size = bufsize;  checksum = 0;} else {header = 0; RESETheader_timer=0; }
  
                          }  
// если размер сообщения указан в дополнительном байте (нулевой байт 0x80) читаем этот дополнительный байт:
else if (header == 3){
  buf[3]=K_LINE.read(); 
  message_size = buf[3];
  if (message_size > bufsize) message_size = bufsize;  
  checksum = 0; header = 4;  
                         }

  // пишем тело сообщения 
 else if (header == 4 && j<= message_size+1) {
 buf[j+n-1] = K_LINE.read(); 
 if (j<message_size+1) checksum+= buf[j+n-1]; // подсчёт КС
 if (j==message_size+1) header = 5; 
  j++;} 

 } // end of K_LINE.available()

 // сообщение приняли, действуем
 if (header == 5) {  

for(byte i = 0; i<n; i++) checksum+=buf[i]; // прибавляем к контрольной сумме старт байты

 // если контрольная сумма верна: 
if (buf[message_size+n] == checksum) 
{
  for (byte i=0; i<message_size+n+1; i++) {if (buf[i]<=0xF)Serial.print ("0"); Serial.print (buf[i], HEX); Serial.print(" ");}
  Serial.println();
  if (buf[n]== 0x61 && buf[n+1]==0x80)   {Serial.println("Receive PID 2180");} //тут обрабатываем полученный ответ на PID 2180
 }     
    
// если контрольная сумма не совпала: 
//else Serial.println("CRC fail!!!" );
message_size = 0; header=0; RESETheader_timer=0; j=1; checksum = 0;
 }
// таймер сброса заголовка если данные оборвались по середине сообщения
if (RESETheader_timer && millis() - prevRESETheader > 500) {Serial.println("timeout"); message_size = 0; RESETheader_timer = 0; header = 0;checksum = 0;j=1;}   

}


 
void loop() 
{
fastInit();     
read_KLINE();
if (bus_init==INIT_END) {sendMessage (BEGIN, sizeof(BEGIN));bus_init++;}
static uint32_t prevtimePID = 0;
if (millis()-prevtimePID>PID_PERIOD_ms) {prevtimePID= millis();sendMessage (PID, sizeof(PID)); }
}

 

 

Подскажите пожалуйста, а как можно параллельно смотреть что происходит (ответы и тд) через монитор порта в Arduino? Я подключаю к машине (ардуино и микрочип так же питаю с машины через делитель напряжения для теста - на выходе получается 8 вольт), с другой стороны к микрухе понятно подаю 5 вольт, RX и TX на Serial2 Меги (16 и 17), по итогу на МК Ардуино мигают очень быстро светодиоды на ардуинке, как только к ардуино подключаю с одной стороны кабель и с другой стороны кабеля к компьютеру, чтобы прочитать чтобы открыть монитор порта, там пусто и ничего нет, и при этом скейт походу останавливается, т.к. светодиоды горят постоянно

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

На какой скорости запущен монитор порта ???

в коде есть строка Serial.begin(9600)

Holodz
Offline
Зарегистрирован: 16.07.2022

Komandir пишет:

На какой скорости запущен монитор порта ???

в коде есть строка Serial.begin(9600)

 

Так и есть, монитор порта на 9600. Почему то когда USB-UART подключаю между МК и ноутбуком, светодиоды перестают мигать, видимо в тот момент и перестает работать

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Разве МЕГА не выводит через свой USB-UART ??? Что то вы не так соединяете !!!

12 вольтовую часть микрухи питайте от авто

5 вольтовую часть микрухи питайте от МЕГА

Есть же картинка в #12 и там все красиво с питанием.

в 39 и 42 строке надо добавить дубль вывода в Serial того что летит в K_LINE и того что читается ...

Holodz
Offline
Зарегистрирован: 16.07.2022

Komandir пишет:

Разве МЕГА не выводит через свой USB-UART ??? Что то вы не так соединяете !!!

12 вольтовую часть микрухи питайте от авто

5 вольтовую часть микрухи питайте от МЕГА

Есть же картинка в #12 и там все красиво с питанием.

в 39 и 42 строке надо добавить дубль вывода в Serial того что летит в K_LINE и того что читается ...

 

Я так и делаю, 12 вольт питаю и МК Мега и часть микрухи (1 ногу), правда не от 12 вольт, а через делитель напряжения где то на 8 вольт, т.к. на заглушенном авто у меня 12.4 на аккуме, многовато... А с другой стороны ногу микрухи я питаю от 5 вольт ардуино.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

А теперь посмотрите картинку в #12 и прочитайте что я написал в #21 !!! Найдите +100500 отличий !!!

Или МЕГА не работает от USB ???

Holodz
Offline
Зарегистрирован: 16.07.2022

Komandir пишет:

А теперь посмотрите картинку в #12 и прочитайте что я написал в #21 !!! Найдите +100500 отличий !!!

Или МЕГА не работает от USB ???

 

Мега в теории может работать от USB, но я питаю ее от от автомобильной сети (8 В). То есть мне сделать как на картинке, массу от автомобиля кинуть на ардуино, 8 вольт от авто кинуть на 1 ногу микрухи, а 5В от МК кинуть на ногу микрухи где должны быть 5В и тем самым ардуино запитать от USB (от ноутбука)?

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

8 вольт идут НАХ...

На первую ногу микрухи подключается "+" (ПЛЮС) бортовой сети авто без делителей и других ваших фантазий !!! (по даташиту там в пике можно 45 вольт подать)

От ваших 8 вольт внутренняя логика микрухи вообще видимо не стартует !!!

GND конечно же общая.

Всё остальное питается от +5 Arduino, запитанной через USB.

 

Заливаем скетч и отключаем USB.

Включаем зажигание.

Подключаем USB и открываем монитор порта ...

Holodz
Offline
Зарегистрирован: 16.07.2022

Komandir пишет:

8 вольт идут НАХ...

На первую ногу микрухи подключается "+" (ПЛЮС) бортовой сети авто без делителей и других ваших фантазий !!! (по даташиту там в пике можно 45 вольт подать)

От ваших 8 вольт внутренняя логика микрухи вообще видимо не стартует !!!

GND конечно же общая.

Всё остальное питается от +5 Arduino, запитанной через USB.

 

Заливаем скетч и отключаем USB.

Включаем зажигание.

Подключаем USB и открываем монитор порта ...

 

Ого, даже так. Сейчас попробую как вы написали

Holodz
Offline
Зарегистрирован: 16.07.2022

Komandir пишет:

8 вольт идут НАХ...

На первую ногу микрухи подключается "+" (ПЛЮС) бортовой сети авто без делителей и других ваших фантазий !!! (по даташиту там в пике можно 45 вольт подать)

От ваших 8 вольт внутренняя логика микрухи вообще видимо не стартует !!!

GND конечно же общая.

Всё остальное питается от +5 Arduino, запитанной через USB.

 

Заливаем скетч и отключаем USB.

Включаем зажигание.

Подключаем USB и открываем монитор порта ...

 

Начал через сериал принт смотреть "шаги", которые выполняются. По итогу в sendMessage вот что:

Если вывести K_LINE.read, что ответ пишет -1

Holodz
Offline
Зарегистрирован: 16.07.2022

Holodz
Offline
Зарегистрирован: 16.07.2022

В buf[1] 130 и т.к. условие не проходит, то header 0 ставит и так по кругу

 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Что у вас в голове ??? Программирование - это не ваше !!!

Holodz
Offline
Зарегистрирован: 16.07.2022

Komandir пишет:

Что у вас в голове ??? Программирование - это не ваше !!!

 

Я полностью запутался, по итогу просто по кругу циклично крутится одно и тоже в коде, и не проходит для дальнейших действий.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Код без ваших правок как себя ведет ?

Holodz
Offline
Зарегистрирован: 16.07.2022

Komandir пишет:

Код без ваших правок как себя ведет ?

 

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

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Вы так вставили serial.print что поломали логику программы !!!

Holodz
Offline
Зарегистрирован: 16.07.2022

Komandir пишет:

Вы так вставили serial.print что поломали логику программы !!!

 

Да это я понял уже... 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018
void sendMessage(const byte *command, const size_t size)
{
  const byte siZe = size + 4;
  byte Mes[siZe];
  byte Checksum = 0;
  Serial.println("Start sending:");
  for (byte i = 0; i < siZe; i++)
  {
    if (i == 0) {
      Mes[i] = size;
      bitWrite(Mes[i], 7 , 1);
    }
    if (i == 1) Mes[i] = PCM_ADDRESS;
    if (i == 2) Mes[i] = 0xF1;
    if (i == 3) {
      for (byte t = 0; t < size; t++ ) {
        Mes[i] = command[t];
        Checksum += Mes[i] ;
        K_LINE.write (Mes[i]);
        Serial.print(" write: ");
        Serial.println(Mes[i], HEX);
        Serial.print(" read: ");
        Serial.println(K_LINE.read(), HEX);
        i++;
      }
    }
    if (i != siZe - 1) Checksum += Mes[i];
    else Mes[i] = Checksum;
    K_LINE.write (Mes[i]);
    Serial.print(" write: ");
    Serial.println(Mes[i], HEX);
    Serial.print(" read: ");
    Serial.println(K_LINE.read(), HEX);
  }
}

Замените функцию в исходном коде и попробуйте ... что на выходе ?

Holodz
Offline
Зарегистрирован: 16.07.2022

Komandir пишет:

void sendMessage(const byte *command, const size_t size)
{
  const byte siZe = size + 4;
  byte Mes[siZe];
  byte Checksum = 0;
  Serial.println("Start sending:");
  for (byte i = 0; i < siZe; i++)
  {
    if (i == 0) {
      Mes[i] = size;
      bitWrite(Mes[i], 7 , 1);
    }
    if (i == 1) Mes[i] = PCM_ADDRESS;
    if (i == 2) Mes[i] = 0xF1;
    if (i == 3) {
      for (byte t = 0; t < size; t++ ) {
        Mes[i] = command[t];
        Checksum += Mes[i] ;
        K_LINE.write (Mes[i]);
        Serial.print(" write: ");
        Serial.println(Mes[i], HEX);
        Serial.print(" read: ");
        Serial.println(K_LINE.read(), HEX);
        i++;
      }
    }
    if (i != siZe - 1) Checksum += Mes[i];
    else Mes[i] = Checksum;
    K_LINE.write (Mes[i]);
    Serial.print(" write: ");
    Serial.println(Mes[i], HEX);
    Serial.print(" read: ");
    Serial.println(K_LINE.read(), HEX);
  }
}

Замените функцию в исходном коде и попробуйте ... что на выходе ?

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

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Убил ???

Holodz
Offline
Зарегистрирован: 16.07.2022

Komandir пишет:

Убил ???

Нет, тут точно потерял, пришёл домой, а в переходнике уже микрухи нет, пошёл искать, а толку, размер с ноготочек)

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Да уж ...

Резистор на 510 ом так же нужен !!! (Я что то не уловил есть/был он или нет)

Holodz
Offline
Зарегистрирован: 16.07.2022

Komandir пишет:

Да уж ...

Резистор на 510 ом так же нужен !!! (Я что то не уловил есть/был он или нет)

Да, конечно был, между питанием от авто и К линие) как на схеме впрочем. Но начал менять тестером напряжение между 1 и 3 пином (питание от авто и масса) напряжение было что то около 7-8 вольт, очень странно, хотя на выходе с ОБД2 разъёма автомобиля 12.2 вольта

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Проверяйте соединения - так просадить АКБ даже стартер не может !!!

MaksVV
Offline
Зарегистрирован: 06.08.2015

Щас поправлю код чтобы лог подробнее был. и соберите адаптер на lm393. Продаётся за 10копеек в любом радио магазе. 

Holodz
Offline
Зарегистрирован: 16.07.2022

MaksVV пишет:

Щас поправлю код чтобы лог подробнее был. и соберите адаптер на lm393. Продаётся за 10копеек в любом радио магазе. 

Хорошо, спасибо, буду ждать код с более подробными логами) 

MaksVV
Offline
Зарегистрирован: 06.08.2015

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

MaksVV
Offline
Зарегистрирован: 06.08.2015

скетч с логами. Если не заработает, поиграться с периодом фаст инит (выбирается вверху скетча, пробовать 24, 25, 23 мс). А вообще нужен снифф. 

#define PCM_ADDRESS 0x7A // тут выбираем адрес ЭБУ
#define K_LINE Serial2   // тут выбираем Serial, на котором висит Клайн адаптер
#define TX 16            // и соответствующий ему  пин TX

#define PID_PERIOD_ms 1000 // выбираем периодичность диагн запросов
#define INIT_PERIOD_ms 25   // выбираем длительность импульсов fastinit


byte bus_init = 0; 
#define INIT_END  9
#define NEED_INIT 1

const byte BEGIN[]         {0x10, 0xC0};
const byte PID[]           {0x21, 0x80};


void setup() {
 Serial.begin(9600); delay (2000);
 
 bus_init =NEED_INIT; 
}

void fastInit(){
     static uint32_t timerInit = 0; 
     if (bus_init==NEED_INIT) {K_LINE.end(); pinMode (TX, OUTPUT); digitalWrite(TX, 0); timerInit = millis(); bus_init++;}
else if (bus_init==2 && millis() - timerInit>INIT_PERIOD_ms) {timerInit = millis(); digitalWrite(TX, 1); bus_init++; }
else if (bus_init==3 && millis() - timerInit>INIT_PERIOD_ms) {K_LINE.begin (10400); bus_init=INIT_END; Serial.println("Fast init 25msLOW 25msHIGH");}
}

void sendMessage(const byte *command, const size_t size)
{
  Serial.println(); Serial.print("               Send to PCM:  ");
  const byte siZe = size+4;
  byte Mes[siZe];
  byte Checksum = 0;
  for(byte i=0; i<siZe; i++) 
  {
    if (i==0) {Mes[i]=size; bitWrite(Mes[i], 7 , 1);}
    if (i==1) Mes[i] = PCM_ADDRESS;
    if (i==2) Mes[i] = 0xF1;    
    if (i==3) {for (byte t=0; t<size; t++ ) 
        {Mes[i]=command[t]; Checksum+=Mes[i] ; 
        Serial.print(Mes[i],HEX); 
        Serial.print(" "); 
        K_LINE.write (Mes[i]);  K_LINE.read(); 
        i++;}}
    if (i!=siZe-1) Checksum+=Mes[i];
    else Mes[i] = Checksum;    
    Serial.print(Mes[i],HEX); 
    Serial.print(" "); 
    K_LINE.write (Mes[i]);  K_LINE.read();
  }
  Serial.println();
}

void read_KLINE()
{
  static byte header = 0;             // состояние заголовка 
  static byte message_size = 0;       // размер тела принимаемого сообщения, кол-во байт
  static byte j = 1;                  // инкремент
  static byte n = 3;
  const byte bufsize = 60;            // размер буфера принятого сообщения
  static byte buf [bufsize] = {0};    // буфер принятого сообщения
  static byte checksum = 0;           // контрольная сумма входящего сообщения
  static uint32_t prevRESETheader=0;  // таймер сброса заголовка если в момент приёма сообщения данные оборвались
  static bool RESETheader_timer = 0;  // таймер сброса заголовка если в момент приёма сообщения данные оборвались

if (K_LINE.available()){
    

 // первый старт байт
 if (header == 0){buf[0]=K_LINE.read(); Serial.print("Receive from PCM: "); Serial.print(buf[0],HEX); Serial.print(" "); 
         header = 1; RESETheader_timer=1; prevRESETheader = millis();
         
         }                  
 // второй старт байт
 else if (header == 1){buf[1]=K_LINE.read(); Serial.print(buf[1],HEX);  Serial.print(" "); if (buf[1]==0xF1){ header = 2;} else {Serial.println(" MessageReset"); header = 0; RESETheader_timer=0;}} 

 // третий старт байт
 else if (header == 2){ 
  buf[2]=K_LINE.read();Serial.print(buf[2],HEX); Serial.print(" ");  
  if (buf[2]==PCM_ADDRESS){ 
  if (buf[0] !=0x80) {header = 4; message_size=buf[0]; bitWrite(message_size,7,0); n=3;}
  else {header = 3; n=4;}
  if (message_size > bufsize) message_size = bufsize;  checksum = 0;} else {Serial.println(" MessageReset"); header = 0; RESETheader_timer=0; }
  
                          }  
// если размер сообщения указан в дополнительном байте (нулевой байт 0x80) читаем этот дополнительный байт:
else if (header == 3){
  buf[3]=K_LINE.read(); Serial.print(buf[3],HEX); Serial.print(" "); 
  message_size = buf[3];
  if (message_size > bufsize) message_size = bufsize;  
  checksum = 0; header = 4;  
                         }

  // пишем тело сообщения 
 else if (header == 4 && j<= message_size+1) {
 buf[j+n-1] = K_LINE.read(); Serial.print(buf[j+n-1],HEX);  Serial.print(" "); 
 if (j<message_size+1) checksum+= buf[j+n-1]; // подсчёт КС
 if (j==message_size+1) header = 5; 
  j++;} 

 } // end of K_LINE.available()

 // сообщение приняли, действуем
 if (header == 5) {  

for(byte i = 0; i<n; i++) checksum+=buf[i]; // прибавляем к контрольной сумме старт байты

//for (byte i=0; i<message_size+n+1; i++) {if (buf[i]<=0xF)Serial.print ("0"); Serial.print (buf[i], HEX); Serial.print(" ");}


 // если контрольная сумма верна: 
if (buf[message_size+n] == checksum) 
 {
    Serial.print("           CheckSUM good!" );
    if (buf[n]== 0x61 && buf[n+1]==0x80)   {Serial.println("Receive PID 2180");} //тут обрабатываем полученный ответ на PID 2180
 }     
    
// если контрольная сумма не совпала: 
else Serial.print("           CheckSUM fail!!!" );
message_size = 0; header=0; RESETheader_timer=0; j=1; checksum = 0;
Serial.println();
 }
// таймер сброса заголовка если данные оборвались по середине сообщения
if (RESETheader_timer && millis() - prevRESETheader > 500) {Serial.println("timeout"); message_size = 0; RESETheader_timer = 0; header = 0;checksum = 0;j=1;}   

}


 
void loop() 
{
fastInit();     
read_KLINE();
if (bus_init==INIT_END) {sendMessage (BEGIN, sizeof(BEGIN));bus_init++;}
static uint32_t prevtimePID = 0;
if (millis()-prevtimePID>PID_PERIOD_ms) {prevtimePID= millis();sendMessage (PID, sizeof(PID)); }
}

 

Holodz
Offline
Зарегистрирован: 16.07.2022

MaksVV пишет:

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

Я ведь могу проснифить через обычный OBD2 - USB адаптер. То есть не через ELM327 блютуз, а именно через USB напрямую к ноутбуку? Или это будет не то?

MaksVV
Offline
Зарегистрирован: 06.08.2015

Вы можете засниффить через юсб-клайн адаптер. Так будет правильней назвать

MaksVV
Offline
Зарегистрирован: 06.08.2015

Не пойму в чем проблема засниффить через вашу ардуину мега, к которой уже сделан клайн

MaksVV
Offline
Зарегистрирован: 06.08.2015

скетч сниффера 

#define K_LINE Serial2

void setup() 
{
 Serial.begin (115200);
 Serial.println("Sniffer Start:");
 Serial.println();
K_LINE.begin (10400);
}

void loop() {
while(1){
static uint32_t prevTime = 0 ;
static bool timer = 0; 
if (K_LINE.available()) 
  {
    Serial.print(K_LINE.read(),HEX);Serial.print ("  "); 
    prevTime=millis(); timer = 1;
  }
if (timer && millis()-prevTime>10) 
  {
    timer = 0; Serial.print("    "); Serial.print (millis()); Serial.println (" ms");Serial.println(); 
  }   
  
  }
}