кстати раз 328 вытаскивается, просто соединяете к-лайн адаптер к пинам 0 и 1 и вытаскиваете атмегу, и получаете юсб-клайн адаптер - можно опендиагом работать.
не стоит в опендиаге определять к-лайн адаптер, не найдет он его. Но работать БУДЕТ.
Вот. Теперь сделаем маленький шаг вперёд. И 25 и 27 получается работает. Вчерашний протокол я прочитал так же пробежался по протоколу мозгов(АвтоВАЗ). Теперь мне получается нужно найти алгоритм запроса данных.
пробуем такой скетч. Подключаем связку к машине. опендиаг не трогаем, а просто открываем монитор порта в ардуино иде на скорости 9600 и смотрим что ответит блок
а вот скетч с периодическим запросом параметров. Уж что с ними делать сами разбирайтесь. (я в ответе от ЭБУ запарсил только t ДВС, см. строка 140) Кстати полезная ссылка
#include <SoftwareSerial.h>
SoftwareSerial K_LINE(10, 11); // RX, TX
const byte PCMaddress = 0x10; // адрес эбу
byte header = 0; // состояние заголовка
byte message_size = 0; // размер тела принимаемого сообщения, кол-во байт
byte j = 2; // инкремент
byte n = 2;
const byte bufsize = 140; // размер буфера принятого сообщения
byte buf [bufsize] = {0}; // буфер принятого сообщения
byte checksum = 0; // контрольная сумма входящего сообщения
uint32_t curmillis = 0; // снимок системного времени
byte delaybyte_TX = 0 ; // задержка между байтами отправляемого сообщения
byte waitbyte_RX = 1; // задержка, мс для успевания заполнения буфера RX (подрегулировать в зависимости от уровня жизнидеятельности на Марсе)
uint32_t timerdelay = 0; // таймер ожидания байт (для успевания заполнения буфера УАРТ)
bool Delay = 0; // таймер ожидания байт (для успевания заполнения буфера УАРТ)
#define TIMER_DELAY Delay = 0; timerdelay = curmillis // включение этого таймера
uint32_t prevRESETheader=0; // таймер сброса заголовка если в момент приёма сообщения данные оборвались
bool RESETheader_timer = 0; // таймер сброса заголовка если в момент приёма сообщения данные оборвались
uint32_t prevtimeRequest = 0;
uint16_t periodRequest = 1000; // периодичность запроса параметров ЭБУ, мс
bool Init = 0;
uint32_t prevInit = 0;
int Temperature;
//**************************** команды, посылаемые на ЭБУ
byte StartSession[] = {0x81}; // команда на старт диагностики (может также быть 82)
byte DataRequest[] = {0x21, 0x01}; // команда на запрос параметров
//****************************
void setup() {
Serial.begin(9600); // настойки монитора порта отладки
K_LINE.begin(10400); // настройки шины к-лайн
delay (2000);
}
void loop() {
curmillis = millis(); // снимок системного времени
K_LINEread(); // читаем шину к-лайн
if (curmillis - prevtimeRequest > periodRequest) { // периодически делаем запрос параметров
if (Init) SendMessage (DataRequest, sizeof (DataRequest));
else SendMessage (StartSession, sizeof (StartSession));
prevtimeRequest = curmillis;}
if (curmillis - prevInit > 10000) {Init =0; prevInit=curmillis;} // периодически делаем сброс инита, если ЭБУ не отвечает
}
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] = PCMaddress;
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]); i++;}}
if (i!=siZe-1) Checksum+=Mes[i];
else Mes[i] = Checksum;
K_LINE.write (Mes[i]);
}
}
void K_LINEread () {
if (K_LINE.available()){
// первый старт байт
if (header == 0 && Delay){TIMER_DELAY ; buf[0]=K_LINE.read();
if (!bitRead (buf[0],6) && bitRead (buf[0],7)){header = 1; RESETheader_timer=1; prevRESETheader = curmillis; }
}
// второй старт байт
if (header == 1 && Delay){TIMER_DELAY ; buf[1]=K_LINE.read(); if (buf[1]==0xF1){ header = 2;} else {header = 0; RESETheader_timer=0;}}
// третий старт байт
if (header == 2 && Delay){
TIMER_DELAY ;
buf[2]=K_LINE.read();
if (buf[2]==PCMaddress){ message_size = buf[0];
if (buf[0] !=0x80) {header = 4; message_size&=~0x80; j=3; n=3;}
else {header = 3; j=4;n=4;}
if (message_size > bufsize) message_size = bufsize; checksum = 0;} else {header = 0; RESETheader_timer=0; }
}
// если размер сообщения указан в дополнительном байте (нулевой байт 0x80) читаем этот дополнительный байт:
if (header == 3 && Delay){
TIMER_DELAY ;
buf[3]=K_LINE.read();
message_size = buf[3];
if (message_size > bufsize) message_size = bufsize;
checksum = 0; header = 4;
}
// пишем тело сообщения
if (header == 4 && Delay && j< message_size+n+1) {
buf[j] = K_LINE.read();
if (j<message_size+n) checksum+= buf[j]; // подсчёт КС
if (j==message_size+n) header = 5;
TIMER_DELAY ; j++;}
} // end of K_LINE.available()
// сообщение приняли, действуем
if (header == 5) {TIMER_DELAY ;
for(byte i = 0; i<n; i++) checksum+=buf[i]; // прибавляем к контрольной сумме старт байты
Serial.print (F("Receive from PCM: "));
for (byte i=0; i<message_size+n+1; i++) {if (buf[i]<= 0x0F) Serial.print (F("0")); Serial.print (buf[i], HEX); Serial.print(" ");} // Отладка в монитор порта
Serial.println();
// если контрольная сумма верна:
if (buf[message_size+n] == checksum) {
prevInit=curmillis; // сбрасываем таймер сброса инита, если получили хоть какое-то сообщение от ЭБУ
if (buf[n]==0xC1) Init=1; // если пришёл ответ на запрос инита, делаем инит прошёл успешно
// ниже если получили длинный ответ от ЭБУ с параметрами парсим его, я взял только температуру ДВС
else if (buf[n]==0x61 && buf[n+1]==0x01){ Temperature = buf[n+10]-40; Serial.print(F("TempEngine: ")); Serial.println (Temperature);}
// ТУТ ЧТО НИБУДЬ ДЕЛАЕМ КОГДА ПОЛУЧИЛИ СООБЩЕНИЕ ОТ ЭБУ
}
// если контрольная сумма не совпала:
//else Serial.println("CRC fail!!!" );
message_size = 0; header=0; RESETheader_timer=0; j=3; checksum = 0;
}
// таймер ожидания байт (для успевания появления данных в буфере UART)
if (!Delay && curmillis - timerdelay > waitbyte_RX) Delay = 1;
// таймер сброса заголовка если данные оборвались во время приёма заголовка
if (RESETheader_timer && curmillis - prevRESETheader > 500) {RESETheader_timer = 0; header = 0;}
}
кстати раз 328 вытаскивается, просто соединяете к-лайн адаптер к пинам 0 и 1 и вытаскиваете атмегу, и получаете юсб-клайн адаптер - можно опендиагом работать.
да
Взял #25 залил его подключил в 10 rx в 11 tx. Он сказал что обнаружил адаптер, но при попытке считать данные он пишет не удалось открыть порт.
С другой стороны если не так собрана схема то , по идее, она бы не показывала данные с блока?
Теперь пробуй 27))) Тоько про подключение 8,9 не забывай))
Попробовал #27 с изменением строчки. Так же говорит что адаптер есть а порт открыть не может
не стоит в опендиаге определять к-лайн адаптер, не найдет он его. Но работать БУДЕТ.
не стоит в опендиаге определять к-лайн адаптер, не найдет он его. Но работать БУДЕТ.
Вот. Теперь сделаем маленький шаг вперёд. И 25 и 27 получается работает. Вчерашний протокол я прочитал так же пробежался по протоколу мозгов(АвтоВАЗ). Теперь мне получается нужно найти алгоритм запроса данных.
Попробовал #27 с изменением строчки. Так же говорит что адаптер есть а порт открыть не может
скрин скиньте что говорит опендиаг, не понятно что вы имеете ввиду
пробуем такой скетч. Подключаем связку к машине. опендиаг не трогаем, а просто открываем монитор порта в ардуино иде на скорости 9600 и смотрим что ответит блок
Исполтзовал #41 скетч , только пины были 8 и 9.
Вот такое сообщение выдает. В самом низу окна Opendiag написаного : Не удалось открыть открыть порт
короче вот вам заготовка для работы с KWP протоколом. Она правильно читает и отсылает сообщения от ЭБУ, с проверкой контрольной суммы.
а вот скетч с периодическим запросом параметров. Уж что с ними делать сами разбирайтесь. (я в ответе от ЭБУ запарсил только t ДВС, см. строка 140) Кстати полезная ссылка
Спасибо! Все работает.(:
А если будем использовать к примеру мегу/due с ее хардварными сериалпортами - просто убираем //SoftwareSerial.h и меняем K_LINE. на Serial1 к примеру?
в общем да , только проще убрать две строки
и вместо них поставить
Спасибо! Вечером буду пробовать!