Бортовой компьютер для Опель Зафира.

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

Библиотека софт сериал не совместима с тв оут. Надо ждать мегу и использовать хард сериал

Targitai
Offline
Зарегистрирован: 05.10.2018

Опаньки, вот это обнадежил. А Мега пришла буквально позавчера. Я просто такого нюанса как-то не учел, и думал вдруг втиснемся в память Уно. Но если такие пироги, перехожу на нее.

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

По идее по протоколу ТС делали считывание ошибок. Там определенные биты отвечают за пассивный DTC или активный. Но тут видимо чето отличается, поэтому он не пишет passive или active

Targitai
Offline
Зарегистрирован: 05.10.2018

На Мега запустилось, но буковки прыгают каждый раз при посылке запроса.... Как там на hardvare serial перейти?

Все, разобрался. #define mySerial Serial1

Как-то Оп-ком и Опель-сканер смотрят активная или пассивная. Да в принципе, не большая проблема. Если на приборке Джеки-чан горит, значит есть активная ошибка. Если посыпался ворох, то стер и смотришь что вылезет снова. 

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

Дак считай ошибку когда она активна и когда пассивна, посмотрим что там в ответе отличается.

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

Targitai пишет:

В конечном скече нужно будет делать проверку и  fastinit(); повторять если, например, после пяти секунд отправки запроса Init ничего не меняется. Мало ли из-за чего связь прервется. Сейчас, например, если включить Дуню, а потом зажигание, то ничего не добьешья.

так попробуй 

#include <Button.h>
Button test;

#define BUTTON_PIN 4       // пин подключения тактовой кнопки
#define BUTTON 0           // программный номер кнопки

//#define ARDUINO_MEGA       // закоментировать эту строку если НЕ будем мегу использовать

#ifdef ARDUINO_MEGA
  #define K_LINE Serial3 
  #define TX 14
#else 
  #include <SoftwareSerial.h>
  #define RX 12
  #define TX 13
  SoftwareSerial K_LINE   (RX, TX); 
#endif
  
 byte messageInit[] =      {0x81,0x11,0xF1,0x81,0x04};                // запрос инициализации
 byte messagePids[] =      {0x82,0x11,0xF1,0x21,0x01,0xA6};           // запрос пид 2101
 byte messagePresent[] =   {0x81,0x11,0xF1,0x3E,0xC1};                // запрос присутствия
 byte messageRead_DTC [] = {0x84,0x11,0xF1,0x18,0x00,0xFF,0x00,0x9D}; // запрос ошибок
 byte messageErase_DTC[] = {0x83,0x11,0xF1,0x14,0xFF,0x00,0x98};      // запрос стирания ошибок
 
 uint32_t curmillis =0;      // снимок текущего времени 
 
 uint32_t prevRequest = 0;   // таймер периодических запросов
 int RequestPeriod = 100;    // периодичность запросов , мс
 
 uint32_t prevRESETheader=0; // таймер сброса заголовка если в момент приёма заголовка данные оборвались
 bool RESETheader_timer;     // таймер сброса заголовка если в момент приёма заголовка данные оборвались
 
 uint32_t prev_NOanswer=0;   // таймер контроля неответов от ЭБУ после запросов
 bool NOanswer_timer = 0;    // таймер контроля неответов от ЭБУ после запросов
 byte noanswers = 0;         // количество подряд неответов от ЭБУ 
 
 uint32_t timerdelay = 0;    // таймер ожидания байт (для успевания появления данных в буфере UART)
 bool Delay = 0;             // таймер ожидания байт (для успевания появления данных в буфере UART)
 byte waitbyte_RX = 1;       // задержка, мс для успевания появления данных в буфере RX 
                             // (подрегулировать в зависимости от уровня жизнидеятельности на Марсе) 
 #define TIMER_DELAY Delay = 0; timerdelay = curmillis  // включение этого таймера
  
 byte delaybyte_TX  = 1;     // задержка между посылкой байт в запросе, мс

// возможные варианты запросов на ЭБУ: 
 enum REQUEST
{
 INIT_bus,
 INIT,
 PID,
 DTCREAD,
 DTCERASE,
 PRESENT
   } ;

byte request = INIT;      // переменная, показывающая какой запрос будем делать

byte header = 0;          // состояние заголовка
byte message_size = 0;    // размер тела сообщения
byte j = 3;               // инкремент
byte n = 3;               // количество старт байт
const byte bufsize = 100; // размер буфера принятого сообщения
byte buf [bufsize] = {0}; // буфер принятого сообщения
byte crc =0;              // байт контрольной суммы 

// переменные трип компьютера 

 float MAP = 0;            //13 байт   Датчик абсолютного давления
 float SysVolt = 0;        //14 байт   Напряжение в сети
 int TempAir = 0;          //16 байт   Температура воздуха в градусах
 int Temp = 0;             //18 байт   Температура охлаждающей жидкости в градусах
 int EngLoad = 0;          //20 байы   нагрузка на двигатель
 byte Throtle = 0;         //28 байт   Открытие дроссельной заслонки в процентах
 unsigned int RPM = 0;     //30 байт   Обороты двигателя
 unsigned int Speed = 0;   //29 байт   Скорость а/м
 float InjPulse = 0;       //31 байт   Время впрыска форсунок
 unsigned int IdleAir = 0; //32 байт   Клапан холостого хода, шаги
 unsigned int O2sens = 0;  //35 байт   Лямбда мВ
 unsigned int O2int = 0;   //36 байт   Интегратор лямда, шагов
 float FuelRatio = 0;      //41 байт   Соотношение воздуха/топлива
 int STFT = 0;             //          Краткосрочная коррекция топлива
 

void setup() {
  
  delay(3000);
 
 // ниже настройки кнопок 
test.NO();                       // кнопка нормально разомкнутая 
test.pullUp();                      // внутренняя подтяжка к питанию вкючена
test.duration_bounce       (  50);  // время антидребезга, мс
test.duration_click_Db     ( 250);  // время дабл клика,   мс
test.duration_inactivity_Up(5000);
test.duration_inactivity_Dn(1000);
test.duration_press        ( 500);  // время длительного нажатия, мс
test.button(BUTTON_PIN);            // подключенные кнопки (пишутся через запятую)  
   
   Serial.begin(115200);
   K_LINE.begin(10400);
   pinMode(TX, OUTPUT);
   fastinit();
             }

void loop() {
curmillis = millis(); // снимок текущего времени

if (test.event_click_Dn (BUTTON))  {request = DTCREAD; RequestPeriod  = 1000;}   // если было короткое   нажатие на тактовую кнопку запросим DTC
if (test.event_press_long (BUTTON)){request = DTCERASE; RequestPeriod = 1000;}   // если было длительное нажатие на тактовую кнопку удалим   DTC

if (curmillis - prevRequest > RequestPeriod && header == 0) {
        
        NOanswer_timer = 1; prev_NOanswer = curmillis; //т.к. сейчас будем делать запрос, то запускаем таймер контроля неответов 
        
        if (request == INIT_bus)  fastinit();    
   
   else if (request == INIT){       
         Serial.println ("Otpravil zapros Init");
         for (byte i = 0; i<sizeof(messageInit); i++) {K_LINE.write(messageInit[i]); delay (5);}
         delay (55);        }
         
   else if (request == PID){       
         //Serial.println ("Otpravil zapros 21 01");
         for (int i = 0; i < sizeof(messagePids); i++) {K_LINE.write(messagePids[i]); delay (delaybyte_TX); }} 
   
   else if (request == DTCREAD)  {
         Serial.println ("Otpravil zapros DTC read");  
         for (int i = 0; i < sizeof(messageRead_DTC); i++)  {K_LINE.write(messageRead_DTC[i]);  delay (delaybyte_TX); }}
      
   else if (request == DTCERASE) {
         Serial.println ("Otpravil zapros DTC clear"); 
         for (int i = 0; i < sizeof(messageErase_DTC); i++) {K_LINE.write(messageErase_DTC[i]); delay (delaybyte_TX); }}
   
   
   prevRequest = curmillis;
                                                             }
  
   //разбор входящих сообщений      
    receive ();  
             }


//стартовая инициализация PCM на 7 пине ОБД (fast init - 25ms LOW 25ms HIGH)
 
 void fastinit() {
   digitalWrite (TX, HIGH);  // makes K-line high 3
   delay(360);             // wait for K-line to be clear 3
   digitalWrite (TX, LOW);  // makes K-line low  3
   delay(25);
   digitalWrite (TX, HIGH); // makes K-line high  3
   delay(25);               //last delay before first message
   K_LINE.begin(10400);  // baud rate of the OBD
   request = INIT; RequestPeriod = 500;
 }
 
 //получение данных от ЭБУ, разборка входящих сообщений
 
 void receive () {
 
 if (K_LINE.available() ){
    

 // первый старт байт
 if (header == 0 && Delay){TIMER_DELAY ; buf[0]=K_LINE.read();  
         if (buf[0]!=0xFF && bitRead (buf[0],7)){header = 1; RESETheader_timer =1; prevRESETheader = curmillis; 
         Serial.print (buf[0], HEX);  Serial.print (" "); }}                  

 // второй старт байт
 if (header == 1 && Delay){TIMER_DELAY ; buf[1]=K_LINE.read(); Serial.print (buf[1], HEX);  Serial.print (" ");if (buf[1]==0xF1){ header = 2;} else {header = 0; RESETheader_timer = 0;}} 

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

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

 // сообщение приняли, действуем
 if (header == 5) {TIMER_DELAY ;  
 Serial.println();  
 NOanswer_timer = 0; noanswers = 0;    // сбрасываем таймер контроля неответов 

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

 // если контрольная сумма верна: 
if ( crc == buf[message_size+n]) {Serial.println("Received message is OK! Checksum is correct!" );  // Если КС совпала, тут чёнибудь нужное делаем
    
    
      if (buf[n]==0xC1 && buf[n+1]==0xEF && buf[n+2]==0x8F) {request = PID; RequestPeriod = 100; Serial.println ("     Initialization OK!!!!:  "); }
 else if (buf[n]==0x58 && buf[n+1]==0x00) {Serial.println ("     NO DTC  ");      request = PID; RequestPeriod = 100;}
 else if (buf[n]==0x58 && buf[n+1] >0x00) {Serial.println ("     DTC is found!"); request = PID; RequestPeriod = 100;
 
 for (byte i=0; i<buf[n+1]; i++ ) {
    

     Serial.print("ERROR ");
     Serial.print (i+1);
     
  if (!bitRead(buf[n+2+(i*3)],6) && !bitRead(buf[n+2+(i*3)],7)) Serial.print(": P");
  if (bitRead(buf[n+2+(i*3)],6) && !bitRead(buf[n+2+(i*3)],7))  Serial.print(": C");
  if (!bitRead(buf[n+2+(i*3)],6) && bitRead(buf[n+2+(i*3)],7))  Serial.print(": B");
  if (bitRead(buf[n+2+(i*3)],6) && bitRead(buf[n+2+(i*3)],7))   Serial.print(": U");

  if (buf[n+2+(i*3)]<=0x0F) Serial.print("0"); 
  Serial.print (buf[n+2+(i*3)],HEX);
  if (buf[n+3+(i*3)]<=0x0F) Serial.print("0");
  Serial.print (buf[n+3+(i*3)],HEX);
    
  if (!bitRead(buf[n+4+(i*3)],6) && bitRead(buf[n+4+(i*3)],7)){
     Serial.print(" -Passive-");} 
  if (bitRead(buf[n+4+(i*3)],7) && bitRead(buf[n+4+(i*3)],6)) {
     Serial.print(" -Active-");} 
     
     Serial.println();
  

  }                                          } 
                  

  
 else if (buf[n]==0x54 && buf[n+1]==0xFF && buf[n+2]==0x00){ Serial.println ("     DTC CLEARED  "); request = PID; RequestPeriod = 100;}
 
 else if (buf[n]==0x61 && buf[n+1]==0x01) {               Serial.println ("     Receive DATA");
      
 MAP = ((uint16_t)buf[n+9]*1.04/255.0);                  //13 байт   Датчик абсолютного давления 102mbar
 SysVolt = ((float)buf[n+10]/10.00);                    //14 байт   Напряжение в сети 12.1v
 {double t , cel , drob ;
   t = (buf[n+12]*191ul/255.0)-40;                         //16 байт   Температура воздуха в градусах 50
   drob = modf(t, &cel); if (drob>=0.5) cel++;
 TempAir = cel;}
 {double t , cel , drob ;
 t = (buf[n+14]*191ul/255.0)-40;                           //18 байт   Температура охлаждающей жидкости в градусах104
 drob = modf(t, &cel); if (drob>=0.5) cel++;
 Temp = cel;}             
 EngLoad = ((uint16_t)buf[n+16]*100/255);               //20 байы   нагрузка на двигатель7%
 Throtle = ((uint16_t)buf[n+24]*100/255);               //28 байт   Открытие дроссельной заслонки в процентах 0
 RPM = ((uint32_t)buf[n+26]*6375ul/255ul);              //30 байт   Оборогты двигателя 0
 Speed = (buf[n+25]);                                   //29 байт   Скорость 0
 InjPulse = ((float)buf[n+27]*21.8/255.0);              //31 байт   Время впрыска форсунок 11.9
 IdleAir = (buf[n+28]);                                 //32 байт   Клапан холостого хода, шаги 38
 O2sens =(uint32_t) buf[n+31]*1127ul/255ul;             //35 байт   Лямбда мВ 380
 O2int = (buf[n+32]);                                   //36 байт   Интегратор лямда, шагов 128
 FuelRatio = ((float)buf[n+37]/10.00);                  //41 байт   Соотношение воздуха/топлива 12.3
 STFT = (((uint16_t)buf[n+32]-128)*100/128);        //          Краткосрочная коррекция топлива
 
  Serial.print(" MAP=");Serial.print(MAP);Serial.print(" Battery=");Serial.print(SysVolt);
  Serial.print(" Air=");Serial.print(TempAir);Serial.print(" Temp=");Serial.print(Temp);
  Serial.print(" EngLoad=");Serial.print(EngLoad);Serial.print(" Throtle=");Serial.print(Throtle);
  Serial.print(" RPM=");Serial.print(RPM); Serial.print(" Speed=");Serial.print(Speed);
  Serial.print(" Inj=");Serial.print(InjPulse);Serial.print(" IdleAir=");Serial.print(IdleAir);
  Serial.print(" O2sens=");Serial.print(O2sens);Serial.print(" O2int=");Serial.print(O2int);
  Serial.print(" FuelRatio=");Serial.print(FuelRatio);Serial.print(" STFT=");Serial.println(STFT);
   
   
   }
  
}   

// если контрольная сумма не совпала: 
else Serial.println("CRC fail!!!" );
message_size = 0; header=0; RESETheader_timer = 0; j=3; crc = 0;
}

// таймер ожидания байт (для успевания появления данных в буфере UART)
if (!Delay && curmillis - timerdelay > waitbyte_RX) Delay = 1; 

// таймер сброса заголовка если данные оборвались во время приёма заголовка
if (RESETheader_timer && curmillis - prevRESETheader > 500) {RESETheader_timer = 0; header = 0;}   
 
// если нет ответа после запроса: +1 к счетчику неответов. Если накопилось 6 и более: делаем реинит.  
if (NOanswer_timer && curmillis - prev_NOanswer > RequestPeriod - RequestPeriod/8) {NOanswer_timer = 0; noanswers++; 
     if (noanswers>=6) { noanswers = 0; request = INIT_bus;}         }
 
 }             

 

Targitai
Offline
Зарегистрирован: 05.10.2018

По софт-сериал коннектится, а по хардварному - нет. Кстати, на Дуне написано пин 18 - RX1, 19 - TX1. Но все равно никак. Пишет только «отправил запрос инит». Т.е. в скетче ставил 19. Поменял местами пины, ну а вдруг. Просто увидел ещё что шлёт запрос 81 11 F1 81Otpravil zapros Init и тд.

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

походу есть китайские меги с перепутанными TX1 и RX1 судя по фотам в сети. Поменяй на TX3 RX3

строка 10 и 11 будет

#define K_LINE Serial3
#define TX 14

Targitai
Offline
Зарегистрирован: 05.10.2018

Менял на Serial2. Попробую, конечно, на 3 поменять...

Читаю, у многих проблемы с хардварными 10400 бод. Как бы проверить двумя Дунями? На столе, так сказать

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

#1306 поправил на сериал3. Должно работать. Внимательней с подключением. А на софтверном работало на этом же скетче?

Targitai
Offline
Зарегистрирован: 05.10.2018

Значится, по софтсериал. Работает. Но повторное подключение при обрыве связи не происходит. Решил проблему добавление задержки  в строке 116 перед fastinit: 

if (request == INIT_bus) {Serial.println ("Fastinit");delay(1000); fastinit();} 

Так отлично работает.

Теперь оп хардварному. Если оставить все как есть то выдает только следующее:

Otpravil zapros Init
81 11 F1 81 Otpravil zapros Init
81 11 F1 81 Otpravil zapros Init
81 11 F1 81 Otpravil zapros Init
81 11 F1 81 Otpravil zapros Init
81 11 F1 81 Otpravil zapros Init
81 11 F1 81 Fastinit
Otpravil zapros Init
81 11 F1 81 Otpravil zapros Init
81 11 F1 81 Otpravil zapros Init
81 11 F1 81 Otpravil zapros Init
81 11 F1 81 Otpravil zapros Init
81 11 F1 81 Otpravil zapros Init
81 11 F1 81 Fastinit
Otpravil zapros Init

Почему мы вообще видим часть запроса инициализации?

Далее я предположил, что это из-за того, что мы сперва стартуем наш серийный порт, а потом уже на скорости 10400 шлем fastinit, и действительно оказалось это так. В общем, вот скетч:

#include <Button.h>
Button test;

#define BUTTON_PIN 4       // пин подключения тактовой кнопки
#define BUTTON 0           // программный номер кнопки

#define ARDUINO_MEGA       // закоментировать эту строку если НЕ будем мегу использовать

#ifdef ARDUINO_MEGA
  #define K_LINE Serial3 
  #define TX 14
#else 
 #include <SoftwareSerial.h>
 #define RX 12
 #define TX 13
 SoftwareSerial K_LINE   (RX, TX); 
#endif
  
 byte messageInit[] =      {0x81,0x11,0xF1,0x81,0x04};                // запрос инициализации
 byte messagePids[] =      {0x82,0x11,0xF1,0x21,0x01,0xA6};           // запрос пид 2101
 byte messagePresent[] =   {0x81,0x11,0xF1,0x3E,0xC1};                // запрос присутствия
 byte messageRead_DTC [] = {0x84,0x11,0xF1,0x18,0x00,0xFF,0x00,0x9D}; // запрос ошибок
 byte messageErase_DTC[] = {0x83,0x11,0xF1,0x14,0xFF,0x00,0x98};      // запрос стирания ошибок
 
 uint32_t curmillis =0;      // снимок текущего времени 
 
 uint32_t prevRequest = 0;   // таймер периодических запросов
 int RequestPeriod = 100;    // периодичность запросов , мс
 
 uint32_t prevRESETheader=0; // таймер сброса заголовка если в момент приёма заголовка данные оборвались
 bool RESETheader_timer;     // таймер сброса заголовка если в момент приёма заголовка данные оборвались
 
 uint32_t prev_NOanswer=0;   // таймер контроля неответов от ЭБУ после запросов
 bool NOanswer_timer = 0;    // таймер контроля неответов от ЭБУ после запросов
 byte noanswers = 0;         // количество подряд неответов от ЭБУ 
 
 uint32_t timerdelay = 1;    // таймер ожидания байт (для успевания появления данных в буфере UART)
 bool Delay = 1;             // таймер ожидания байт (для успевания появления данных в буфере UART)
 byte waitbyte_RX = 1;       // задержка, мс для успевания появления данных в буфере RX 
                             // (подрегулировать в зависимости от уровня жизнидеятельности на Марсе) 
 #define TIMER_DELAY Delay = 0; timerdelay = curmillis  // включение этого таймера
  
 byte delaybyte_TX  = 1;     // задержка между посылкой байт в запросе, мс

// возможные варианты запросов на ЭБУ: 
 enum REQUEST
{
 INIT_bus,
 INIT,
 PID,
 DTCREAD,
 DTCERASE,
 PRESENT
   } ;

byte request = INIT;      // переменная, показывающая какой запрос будем делать

byte header = 0;          // состояние заголовка
byte message_size = 0;    // размер тела сообщения
byte j = 3;               // инкремент
byte n = 3;               // количество старт байт
const byte bufsize = 100; // размер буфера принятого сообщения
byte buf [bufsize] = {0}; // буфер принятого сообщения
byte crc =0;              // байт контрольной суммы 

// переменные трип компьютера 

 float MAP = 0;            //13 байт   Датчик абсолютного давления
 float SysVolt = 0;        //14 байт   Напряжение в сети
 int TempAir = 0;          //16 байт   Температура воздуха в градусах
 int Temp = 0;             //18 байт   Температура охлаждающей жидкости в градусах
 int EngLoad = 0;          //20 байы   нагрузка на двигатель
 byte Throtle = 0;         //28 байт   Открытие дроссельной заслонки в процентах
 unsigned int RPM = 0;     //30 байт   Обороты двигателя
 unsigned int Speed = 0;   //29 байт   Скорость а/м
 float InjPulse = 0;       //31 байт   Время впрыска форсунок
 unsigned int IdleAir = 0; //32 байт   Клапан холостого хода, шаги
 unsigned int O2sens = 0;  //35 байт   Лямбда мВ
 unsigned int O2int = 0;   //36 байт   Интегратор лямда, шагов
 float FuelRatio = 0;      //41 байт   Соотношение воздуха/топлива
 int STFT = 0;             //          Краткосрочная коррекция топлива
 

void setup() {
  
  delay(3000);
 
 // ниже настройки кнопок 
test.NO();                       // кнопка нормально разомкнутая 
test.pullUp();                      // внутренняя подтяжка к питанию вкючена
test.duration_bounce       (  50);  // время антидребезга, мс
test.duration_click_Db     ( 250);  // время дабл клика,   мс
test.duration_inactivity_Up(5000);
test.duration_inactivity_Dn(1000);
test.duration_press        ( 500);  // время длительного нажатия, мс
test.button(BUTTON_PIN);            // подключенные кнопки (пишутся через запятую)  
   
   Serial.begin(115200);
  
   pinMode(TX, OUTPUT);
  Serial.println ("Fastinit");
   fastinit();
    K_LINE.begin(10400);
             }

void loop() {
curmillis = millis(); // снимок текущего времени

if (test.event_click_Dn (BUTTON))  {request = DTCREAD; RequestPeriod  = 1000;}   // если было короткое   нажатие на тактовую кнопку запросим DTC
if (test.event_press_long (BUTTON)){request = DTCERASE; RequestPeriod = 1000;}   // если было длительное нажатие на тактовую кнопку удалим   DTC

if (curmillis - prevRequest > RequestPeriod && header == 0) {
        
        NOanswer_timer = 1; prev_NOanswer = curmillis; //т.к. сейчас будем делать запрос, то запускаем таймер контроля неответов 
        
        if (request == INIT_bus) {K_LINE.end();Serial.println ("Fastinit");delay(1000); fastinit();K_LINE.begin(10400);}    
   
   else if (request == INIT){       
         Serial.println ("Otpravil zapros Init");
         for (byte i = 0; i<sizeof(messageInit); i++) {K_LINE.write(messageInit[i]); delay (5);}
         delay (55);        }
         
   else if (request == PID){       
         //Serial.println ("Otpravil zapros 21 01");
         for (int i = 0; i < sizeof(messagePids); i++) {K_LINE.write(messagePids[i]); delay (delaybyte_TX); }} 
   
   else if (request == DTCREAD)  {
         Serial.println ("Otpravil zapros DTC read");  
         for (int i = 0; i < sizeof(messageRead_DTC); i++)  {K_LINE.write(messageRead_DTC[i]);  delay (delaybyte_TX); }}
      
   else if (request == DTCERASE) {
         Serial.println ("Otpravil zapros DTC clear"); 
         for (int i = 0; i < sizeof(messageErase_DTC); i++) {K_LINE.write(messageErase_DTC[i]); delay (delaybyte_TX); }}
   
   
   prevRequest = curmillis;
                                                             }
  
   //разбор входящих сообщений      
    receive ();  
             }


//стартовая инициализация PCM на 7 пине ОБД (fast init - 25ms LOW 25ms HIGH)
 
 void fastinit() {
   digitalWrite (TX, HIGH);  // makes K-line high 3
   delay(360);             // wait for K-line to be clear 3
   digitalWrite (TX, LOW);  // makes K-line low  3
   delay(25);
   digitalWrite (TX, HIGH); // makes K-line high  3
   delay(25);               //last delay before first message
   K_LINE.begin(10400);  // baud rate of the OBD
   request = INIT; RequestPeriod = 500;
 }
 
 //получение данных от ЭБУ, разборка входящих сообщений
 
 void receive () {
 
 if (K_LINE.available() ){
    

 // первый старт байт
 if (header == 0 && Delay){TIMER_DELAY ; buf[0]=K_LINE.read();  
         if (buf[0]!=0xFF && bitRead (buf[0],7)){header = 1; RESETheader_timer =1; prevRESETheader = curmillis; 
         Serial.print (buf[0], HEX);  Serial.print (" "); }}                  

 // второй старт байт
 if (header == 1 && Delay){TIMER_DELAY ; buf[1]=K_LINE.read(); Serial.print (buf[1], HEX);  Serial.print (" ");if (buf[1]==0xF1){ header = 2;} else {header = 0; RESETheader_timer = 0;}} 

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

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

 // сообщение приняли, действуем
 if (header == 5) {TIMER_DELAY ;  
 Serial.println();  
 NOanswer_timer = 0; noanswers = 0;    // сбрасываем таймер контроля неответов 

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

 // если контрольная сумма верна: 
if ( crc == buf[message_size+n]) {Serial.println("Received message is OK! Checksum is correct!" );  // Если КС совпала, тут чёнибудь нужное делаем
    
    
      if (buf[n]==0xC1 && buf[n+1]==0xEF && buf[n+2]==0x8F) {request = PID; RequestPeriod = 100; Serial.println ("     Initialization OK!!!!:  "); }
 else if (buf[n]==0x58 && buf[n+1]==0x00) {Serial.println ("     NO DTC  ");      request = PID; RequestPeriod = 100;}
 else if (buf[n]==0x58 && buf[n+1] >0x00) {Serial.println ("     DTC is found!"); request = PID; RequestPeriod = 100;
 
 for (byte i=0; i<buf[n+1]; i++ ) {
    

     Serial.print("ERROR ");
     Serial.print (i+1);
     
  if (!bitRead(buf[n+2+(i*3)],6) && !bitRead(buf[n+2+(i*3)],7)) Serial.print(": P");
  if (bitRead(buf[n+2+(i*3)],6) && !bitRead(buf[n+2+(i*3)],7))  Serial.print(": C");
  if (!bitRead(buf[n+2+(i*3)],6) && bitRead(buf[n+2+(i*3)],7))  Serial.print(": B");
  if (bitRead(buf[n+2+(i*3)],6) && bitRead(buf[n+2+(i*3)],7))   Serial.print(": U");

  if (buf[n+2+(i*3)]<=0x0F) Serial.print("0"); 
  Serial.print (buf[n+2+(i*3)],HEX);
  if (buf[n+3+(i*3)]<=0x0F) Serial.print("0");
  Serial.print (buf[n+3+(i*3)],HEX);
    
  if (!bitRead(buf[n+4+(i*3)],6) && bitRead(buf[n+4+(i*3)],7)){
     Serial.print(" -Passive-");} 
  if (bitRead(buf[n+4+(i*3)],7) && bitRead(buf[n+4+(i*3)],6)) {
     Serial.print(" -Active-");} 
     
     Serial.println();
  

  }                                          } 
                  

  
 else if (buf[n]==0x54 && buf[n+1]==0xFF && buf[n+2]==0x00){ Serial.println ("     DTC CLEARED  "); request = PID; RequestPeriod = 100;}
 
 else if (buf[n]==0x61 && buf[n+1]==0x01) {               Serial.println ("     Receive DATA");
      
 MAP = ((uint16_t)buf[n+9]*1.04/255.0);                  //13 байт   Датчик абсолютного давления 102mbar
 SysVolt = ((float)buf[n+10]/10.00);                    //14 байт   Напряжение в сети 12.1v
 {double t , cel , drob ;
   t = (buf[n+12]*191ul/255.0)-40;                         //16 байт   Температура воздуха в градусах 50
   drob = modf(t, &cel); if (drob>=0.5) cel++;
 TempAir = cel;}
 {double t , cel , drob ;
 t = (buf[n+14]*191ul/255.0)-40;                           //18 байт   Температура охлаждающей жидкости в градусах104
 drob = modf(t, &cel); if (drob>=0.5) cel++;
 Temp = cel;}             
 EngLoad = ((uint16_t)buf[n+16]*100/255);               //20 байы   нагрузка на двигатель7%
 Throtle = ((uint16_t)buf[n+24]*100/255);               //28 байт   Открытие дроссельной заслонки в процентах 0
 RPM = ((uint32_t)buf[n+26]*6375ul/255ul);              //30 байт   Оборогты двигателя 0
 Speed = (buf[n+25]);                                   //29 байт   Скорость 0
 InjPulse = ((float)buf[n+27]*21.8/255.0);              //31 байт   Время впрыска форсунок 11.9
 IdleAir = (buf[n+28]);                                 //32 байт   Клапан холостого хода, шаги 38
 O2sens =(uint32_t) buf[n+31]*1127ul/255ul;             //35 байт   Лямбда мВ 380
 O2int = (buf[n+32]);                                   //36 байт   Интегратор лямда, шагов 128
 FuelRatio = ((float)buf[n+37]/10.00);                  //41 байт   Соотношение воздуха/топлива 12.3
 STFT = (((uint16_t)buf[n+32]-128)*100/128);        //          Краткосрочная коррекция топлива
 
  Serial.print(" MAP=");Serial.print(MAP);Serial.print(" Battery=");Serial.print(SysVolt);
  Serial.print(" Air=");Serial.print(TempAir);Serial.print(" Temp=");Serial.print(Temp);
  Serial.print(" EngLoad=");Serial.print(EngLoad);Serial.print(" Throtle=");Serial.print(Throtle);
  Serial.print(" RPM=");Serial.print(RPM); Serial.print(" Speed=");Serial.print(Speed);
  Serial.print(" Inj=");Serial.print(InjPulse);Serial.print(" IdleAir=");Serial.print(IdleAir);
  Serial.print(" O2sens=");Serial.print(O2sens);Serial.print(" O2int=");Serial.print(O2int);
  Serial.print(" FuelRatio=");Serial.print(FuelRatio);Serial.print(" STFT=");Serial.println(STFT);
   
   
   }
  
}   

// если контрольная сумма не совпала: 
else Serial.println("CRC fail!!!" );
message_size = 0; header=0; RESETheader_timer = 0; j=3; crc = 0;
}

// таймер ожидания байт (для успевания появления данных в буфере UART)
if (!Delay && curmillis - timerdelay > waitbyte_RX) Delay = 1; 

// таймер сброса заголовка если данные оборвались во время приёма заголовка
if (RESETheader_timer && curmillis - prevRESETheader > 500) {RESETheader_timer = 0; header = 0;}   
 
// если нет ответа после запроса: +1 к счетчику неответов. Если накопилось 6 и более: делаем реинит.  
if (NOanswer_timer && curmillis - prev_NOanswer > RequestPeriod - RequestPeriod/8) {NOanswer_timer = 0; noanswers++; 
     if (noanswers>=6) { noanswers = 0; request = INIT_bus;}         }
 
 }             

С этим скетчем получаем вот такую картину:

Fastinit
Otpravil zapros Init
81 11 F1 81 83 F1 11 C1 EF 8F C4 
Received message is OK! Checksum is correct!
     Initialization OK!!!!:  
82 11 F1 21 A6 B0 F1 11 FA 76 84 98 8A F 97 2D 80 12 84 8 82 11 F1 21 A6 B0 F1 11 FA 76 84 98 8A F 97 2D 80 12 84 8 82 11 F1 21 A6 B0 F1 11 FA 76 84 98 8A F 97 2D 80 12 84 8 82 11 F1 21 A6 B0 F1 11 FA 76 84 98 8A F 97 2D 80 12 84 8 82 11 F1 21 A6 B0 F1 11 FA 76 84 98 8A F 97 2D Fastinit
Otpravil zapros Init
80 12 84 34 82 11 F1 21 A6 B0 F1 11 FA 76 84 98 8A F 97 2D 80 72 81 11 F1 81 Otpravil zapros Init
81 11 F1 81 83 F1 11 C1 EF 8F C4 
Received message is OK! Checksum is correct!
     Initialization OK!!!!:  
82 11 F1 21 A6 B0 F1 11 FA 76 84 98 8A F 97 2D 80 12 84 8 82 11 F1 21 A6 B0 F1 11 FA 76 84 98 8A F 97 2D 80 12 84 8 82 11 F1 21 A6 B0 F1 11 FA 76 84 98 8A F 97 2D 80 12 84 8 82 11 F1 21 A6 B0 F1 11 FA 76 84 98 8A F 97 2D 80 12 84 8 82 11 F1 21 A6 B0 F1 11 FA 76 84 98 8A F 97 2D Fastinit
Otpravil zapros Init
80 12 84 27 82 11 F1 21 A6 B0 F1 11 FA 76 84 98 8A F 97 2D 81 11 F1 81 Otpravil zapros Init
81 11 F1 81 83 F1 11 C1 EF 8F C4 
Received message is OK! Checksum is correct!
     Initialization OK!!!!:  
82 11 F1 21 A6 B0 F1 11 FA 76 84 98 8A F 97 2D 80 12 84 8 82 11 F1 21 A6 B0 F1 11 FA 76 84 98 8A F 97 2D 80 12 84 8 82 11 F1 21 A6 B0 F1 11 FA 76 84 98 8A F 97 2D 80 12 84 8 82 11 F1 21 A6 B0 F1 11 FA 76 85 98 8A F 97 2D 80 12 84 8 82 11 F1 21 A6 B0 F1 11 FA 76 84 98 8A F 97 2D Fastinit
Otpravil zapros Init
80 12 82 11 F1 21 B0 F1 11 61 1 1 1 70 22 0 0 0 FA 76 3F 6F 85 98 8A F 34 0 0 0 0 0 1E 0 0 0 97 2D 0 65 12 0 76 0 8 34 0 0 81 11 F1 81 4 Otpravil zapros Init
81 11 F1 81 83 F1 11 C1 EF 8F C4 
Received message is OK! Checksum is correct!
     Initialization OK!!!!:  
82 11 F1 21 A6 B0 F1 11 FA 76 85 98 8A F 97 2D 80 12 84 8 82 11 F1 21 A6 B0 F1 11 FA 76 85 98 8A F 97 2D 80 12 84 8 82 11 F1 21 A6 B0 F1 11 FA 76 85 98 8A F 97 2D 80 12 84 8 82 11 F1 21 A6 B0 F1 11 FA 76 85 98 8A F 97 2D 80 12 84 8 82 11 F1 21 A6 B0 F1 11 FA 76 85 98 8A F 97 2D Fastinit
Otpravil zapros Init
80 12 84 27 82 11 F1 21 A6 B0 F1 11 FA 76 85 98 8A F 97 0 84 34 81 11 F1 81 Otpravil zapros Init
81 11 F1 81 83 F1 11 C1 EF 8F C4 
Received message is OK! Checksum is correct!
     Initialization OK!!!!:  
82 11 F1 21 A6 B0 F1 11 FA 76 85 98 8A F 97 2D 80 12 84 8 82 11 F1 21 A6 B0 F1 11 FA 76 85 98 8A F 97 2D 80 12 84 8 82 11 F1 21 A6 B0 F1 11 FA 76 85 98 8A F 97 2D 80 12 84 8 82 11 F1 21 A6 B0 F1 11 FA 76 85 98 8A F 97 2D 80 12 84 8 82 11 F1 21 A6 B0 F1 11 FA 76 85 98 8A F 97 2D Fastinit
Otpravil zapros Init

Я так понимаю, проблема кроется в задержках? Но вот где какую крутить? Поигрался с byte waitbyte_RX = 1; ставил вплоть до 100. Но не помогло. Видать на Марсе жизни нет :)

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

Строка 290 попробуй задержку более 500

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

Также попробовать строка 125 после delay поставить 

K_LINE.read();

 

Targitai
Offline
Зарегистрирован: 05.10.2018

K_LINE.read помогло. Заработало!

только теперь на кнопку ее реагирует никак. Запросы не чтение и стирание ошибок не шлёт ))))

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

Это по тойже причине. Аналогично нужнг вставить клайн.Реад и в те requestы. Причина в том что шина к лайн эхо даёт и мы в приёмнике видим свои отправленные мессаги . клайн.Реад вычитывает мусорные эхо байты сразу после отправки и освобождает приемный буфер для приёма уже нужных байтов от оппонента. Вопрос почему на софтсериале работало

UPDATE. а вообще я нечаянно снёс опрос кнопки (вставить в первую строку цикла loop()  )

test.read();          // обновление состояния кнопок

 

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

можно еще так попробовать

#include <Button.h>
Button test;

#define BUTTON_PIN 4       // пин подключения тактовой кнопки
#define BUTTON 0           // программный номер кнопки

//#define ARDUINO_MEGA       // закоментировать эту строку если НЕ будем мегу использовать

#ifdef ARDUINO_MEGA
  #define K_LINE Serial3 
  #define TX 14
#else 
  #include <SoftwareSerial.h>
  #define RX 12
  #define TX 13
  SoftwareSerial K_LINE   (RX, TX); 
#endif
  
 byte TXmessage[][8] = {
 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},    // балласт
 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},    // балласт
 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},    // балласт
 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},    // балласт
 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},    // балласт
 {0x81,0x11,0xF1,0x81,0x04,0x00,0x00,0x00},    // запрос инициализации
 {0x82,0x11,0xF1,0x21,0x01,0xA6,0x00,0x00},    // запрос пид 2101
 {0x83,0x11,0xF1,0x14,0xFF,0x00,0x98,0x00},    // запрос стирания ошибок
 {0x84,0x11,0xF1,0x18,0x00,0xFF,0x00,0x9D}     // запрос ошибок
 
                       };  




 
 uint32_t curmillis =0;      // снимок текущего времени 
 
 uint32_t prevRequest = 0;   // таймер периодических запросов
 int RequestPeriod = 100;    // периодичность запросов , мс
 
 uint32_t prevRESETheader=0; // таймер сброса заголовка если в момент приёма заголовка данные оборвались
 bool RESETheader_timer;     // таймер сброса заголовка если в момент приёма заголовка данные оборвались
 
 uint32_t prev_NOanswer=0;   // таймер контроля неответов от ЭБУ после запросов
 bool NOanswer_timer = 0;    // таймер контроля неответов от ЭБУ после запросов
 byte noanswers = 0;         // количество подряд неответов от ЭБУ 
 
 uint32_t timerdelay = 0;    // таймер ожидания байт (для успевания появления данных в буфере UART)
 bool Delay = 0;             // таймер ожидания байт (для успевания появления данных в буфере UART)
 byte waitbyte_RX = 1;       // задержка, мс для успевания появления данных в буфере RX 
                             // (подрегулировать в зависимости от уровня жизнидеятельности на Марсе) 
 #define TIMER_DELAY Delay = 0; timerdelay = curmillis  // включение этого таймера
  
 byte delaybyte_TX  = 1;     // задержка между посылкой байт в запросе, мс

// возможные варианты запросов на ЭБУ: 
 
 #define INIT_bus 1
 #define INIT     5
 #define PID      6
 #define DTCREAD  8
 #define DTCERASE 7
 
  

byte request = INIT;      // переменная, показывающая какой запрос будем делать

byte header = 0;          // состояние заголовка
byte message_size = 0;    // размер тела сообщения
byte j = 3;               // инкремент
byte n = 3;               // количество старт байт
const byte bufsize = 100; // размер буфера принятого сообщения
byte buf [bufsize] = {0}; // буфер принятого сообщения
byte crc =0;              // байт контрольной суммы 

// переменные трип компьютера 

 float MAP = 0;            //13 байт   Датчик абсолютного давления
 float SysVolt = 0;        //14 байт   Напряжение в сети
 int TempAir = 0;          //16 байт   Температура воздуха в градусах
 int Temp = 0;             //18 байт   Температура охлаждающей жидкости в градусах
 int EngLoad = 0;          //20 байы   нагрузка на двигатель
 byte Throtle = 0;         //28 байт   Открытие дроссельной заслонки в процентах
 unsigned int RPM = 0;     //30 байт   Обороты двигателя
 unsigned int Speed = 0;   //29 байт   Скорость а/м
 float InjPulse = 0;       //31 байт   Время впрыска форсунок
 unsigned int IdleAir = 0; //32 байт   Клапан холостого хода, шаги
 unsigned int O2sens = 0;  //35 байт   Лямбда мВ
 unsigned int O2int = 0;   //36 байт   Интегратор лямда, шагов
 float FuelRatio = 0;      //41 байт   Соотношение воздуха/топлива
 int STFT = 0;             //          Краткосрочная коррекция топлива
 

void setup() {
  
  delay(3000);
 
 // ниже настройки кнопок 
test.NO();                          // кнопка нормально разомкнутая 
test.pullUp();                      // внутренняя подтяжка к питанию вкючена
test.duration_bounce       (  50);  // время антидребезга, мс
test.duration_click_Db     ( 250);  // время дабл клика,   мс
test.duration_inactivity_Up(5000);
test.duration_inactivity_Dn(1000);
test.duration_press        ( 500);  // время длительного нажатия, мс
test.button(BUTTON_PIN);            // подключенные кнопки (пишутся через запятую)  
   
   Serial.begin(115200);
   pinMode(TX, OUTPUT);
   fastinit();
             }

void loop() {

test.read();          // обновление состояния кнопок
curmillis = millis(); // снимок текущего времени

if (test.event_click_Dn (BUTTON))  {request = DTCREAD; RequestPeriod  = 1000;}   // если было короткое   нажатие на тактовую кнопку запросим DTC
if (test.event_press_long (BUTTON)){request = DTCERASE; RequestPeriod = 1000;}   // если было длительное нажатие на тактовую кнопку удалим   DTC

if (curmillis - prevRequest > RequestPeriod && header == 0) {
        
        NOanswer_timer = 1; prev_NOanswer = curmillis; //т.к. сейчас будем делать запрос, то запускаем таймер контроля неответов 

       if (request == INIT_bus) {K_LINE.end(); delay (450); fastinit();} 
     
     else {      for (byte i = 0; i<request; i++){K_LINE.write(TXmessage[request][i]); delay (delaybyte_TX); K_LINE.read(); }}
   TX_otladka();    
   prevRequest = curmillis;
                                                             }
  
   //разбор входящих сообщений      
    receive ();  
             }


//стартовая инициализация PCM на 7 пине ОБД (fast init - 25ms LOW 25ms HIGH)
 
 void fastinit() {
   digitalWrite (TX, HIGH);  // makes K-line high 3
   delay(360);             // wait for K-line to be clear 3
   digitalWrite (TX, LOW);  // makes K-line low  3
   delay(25);
   digitalWrite (TX, HIGH); // makes K-line high  3
   delay(25);               //last delay before first message
   K_LINE.begin(10400);  // baud rate of the OBD
   request = INIT; RequestPeriod = 500;
 }
 
 //получение данных от ЭБУ, разборка входящих сообщений
 
 void receive () {
 
 if (K_LINE.available() ){
    

 // первый старт байт
 if (header == 0 && Delay){TIMER_DELAY ; buf[0]=K_LINE.read();  
         if (buf[0]!=0xFF && bitRead (buf[0],7)){header = 1; RESETheader_timer =1; prevRESETheader = curmillis; 
         Serial.print (buf[0], HEX);  Serial.print (" "); }}                  

 // второй старт байт
 if (header == 1 && Delay){TIMER_DELAY ; buf[1]=K_LINE.read(); Serial.print (buf[1], HEX);  Serial.print (" ");if (buf[1]==0xF1){ header = 2;} else {header = 0; RESETheader_timer = 0;}} 

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

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

 // сообщение приняли, действуем
 if (header == 5) {TIMER_DELAY ;  
 Serial.println();  
 NOanswer_timer = 0; noanswers = 0;    // сбрасываем таймер контроля неответов 

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

 // если контрольная сумма верна: 
if ( crc == buf[message_size+n]) {Serial.println("Received message is OK! Checksum is correct!" );  // Если КС совпала, тут чёнибудь нужное делаем
    
    
      if (buf[n]==0xC1 && buf[n+1]==0xEF && buf[n+2]==0x8F) {request = PID; RequestPeriod = 100; Serial.println ("     Initialization OK!!!!:  "); }
 else if (buf[n]==0x58 && buf[n+1]==0x00) {Serial.println ("     NO DTC  ");      request = PID; RequestPeriod = 100;}
 else if (buf[n]==0x58 && buf[n+1] >0x00) {Serial.println ("     DTC is found!"); request = PID; RequestPeriod = 100;
 
 for (byte i=0; i<buf[n+1]; i++ ) {
    

     Serial.print("ERROR ");
     Serial.print (i+1);
     
  if (!bitRead(buf[n+2+(i*3)],6) && !bitRead(buf[n+2+(i*3)],7)) Serial.print(": P");
  if (bitRead(buf[n+2+(i*3)],6) && !bitRead(buf[n+2+(i*3)],7))  Serial.print(": C");
  if (!bitRead(buf[n+2+(i*3)],6) && bitRead(buf[n+2+(i*3)],7))  Serial.print(": B");
  if (bitRead(buf[n+2+(i*3)],6) && bitRead(buf[n+2+(i*3)],7))   Serial.print(": U");

  if (buf[n+2+(i*3)]<=0x0F) Serial.print("0"); 
  Serial.print (buf[n+2+(i*3)],HEX);
  if (buf[n+3+(i*3)]<=0x0F) Serial.print("0");
  Serial.print (buf[n+3+(i*3)],HEX);
    
  if (!bitRead(buf[n+4+(i*3)],6) && bitRead(buf[n+4+(i*3)],7)){
     Serial.print(" -Passive-");} 
  if (bitRead(buf[n+4+(i*3)],7) && bitRead(buf[n+4+(i*3)],6)) {
     Serial.print(" -Active-");} 
     
     Serial.println();
  

  }                                          } 
                  

  
 else if (buf[n]==0x54 && buf[n+1]==0xFF && buf[n+2]==0x00){ Serial.println ("     DTC CLEARED  "); request = PID; RequestPeriod = 100;}
 
 else if (buf[n]==0x61 && buf[n+1]==0x01) {               Serial.println ("     Receive DATA");
      
 MAP = ((uint16_t)buf[n+9]*1.04/255.0);                  //13 байт   Датчик абсолютного давления 102mbar
 SysVolt = ((float)buf[n+10]/10.00);                    //14 байт   Напряжение в сети 12.1v
 {double t , cel , drob ;
   t = (buf[n+12]*191ul/255.0)-40;                         //16 байт   Температура воздуха в градусах 50
   drob = modf(t, &cel); if (drob>=0.5) cel++;
 TempAir = cel;}
 {double t , cel , drob ;
 t = (buf[n+14]*191ul/255.0)-40;                           //18 байт   Температура охлаждающей жидкости в градусах104
 drob = modf(t, &cel); if (drob>=0.5) cel++;
 Temp = cel;}             
 EngLoad = ((uint16_t)buf[n+16]*100/255);               //20 байы   нагрузка на двигатель7%
 Throtle = ((uint16_t)buf[n+24]*100/255);               //28 байт   Открытие дроссельной заслонки в процентах 0
 RPM = ((uint32_t)buf[n+26]*6375ul/255ul);              //30 байт   Оборогты двигателя 0
 Speed = (buf[n+25]);                                   //29 байт   Скорость 0
 InjPulse = ((float)buf[n+27]*21.8/255.0);              //31 байт   Время впрыска форсунок 11.9
 IdleAir = (buf[n+28]);                                 //32 байт   Клапан холостого хода, шаги 38
 O2sens =(uint32_t) buf[n+31]*1127ul/255ul;             //35 байт   Лямбда мВ 380
 O2int = (buf[n+32]);                                   //36 байт   Интегратор лямда, шагов 128
 FuelRatio = ((float)buf[n+37]/10.00);                  //41 байт   Соотношение воздуха/топлива 12.3
 STFT = (((uint16_t)buf[n+32]-128)*100/128);        //          Краткосрочная коррекция топлива
 
  Serial.print(" MAP=");Serial.print(MAP);Serial.print(" Battery=");Serial.print(SysVolt);
  Serial.print(" Air=");Serial.print(TempAir);Serial.print(" Temp=");Serial.print(Temp);
  Serial.print(" EngLoad=");Serial.print(EngLoad);Serial.print(" Throtle=");Serial.print(Throtle);
  Serial.print(" RPM=");Serial.print(RPM); Serial.print(" Speed=");Serial.print(Speed);
  Serial.print(" Inj=");Serial.print(InjPulse);Serial.print(" IdleAir=");Serial.print(IdleAir);
  Serial.print(" O2sens=");Serial.print(O2sens);Serial.print(" O2int=");Serial.print(O2int);
  Serial.print(" FuelRatio=");Serial.print(FuelRatio);Serial.print(" STFT=");Serial.println(STFT);
   
   
   }
  
}   

// если контрольная сумма не совпала: 
else Serial.println("CRC fail!!!" );
message_size = 0; header=0; RESETheader_timer = 0; j=3; crc = 0;
}

// таймер ожидания байт (для успевания появления данных в буфере UART)
if (!Delay && curmillis - timerdelay > waitbyte_RX) Delay = 1; 

// таймер сброса заголовка если данные оборвались во время приёма заголовка
if (RESETheader_timer && curmillis - prevRESETheader > 500) {RESETheader_timer = 0; header = 0;}   
 
// если нет ответа после запроса: +1 к счетчику неответов. Если накопилось 6 и более: делаем реинит.  
if (NOanswer_timer && curmillis - prev_NOanswer > RequestPeriod - RequestPeriod/8) {NOanswer_timer = 0; noanswers++; 
     if (noanswers>=6) { noanswers = 0; request = INIT_bus;}         }
 
 }             


  void TX_otladka(){
    
      if (request == INIT_bus) Serial.println ("Bus_INIT"); 
 else if (request == INIT)     Serial.println ("Otpravil zapros Init");
 else if (request == DTCREAD)  Serial.println ("Otpravil zapros DTC read");
 else if (request == DTCERASE) Serial.println ("Otpravil zapros DTC clear");
                   }

 

Targitai
Offline
Зарегистрирован: 05.10.2018

Отлично работает 1316. Переподключается, все читает, все сбрасывает и даже определил активную ошибку.

Было: 

Otpravil zapros DTC read
85 F1 11 58 1 1 70 22 73 
Received message is OK! Checksum is correct!
     DTC is found!
ERROR 1: P0170

Снял реле топливного насоса, и стало:

Otpravil zapros DTC read
88 F1 11 58 2 1 70 22 2 30 E2 8B 
Received message is OK! Checksum is correct!
     DTC is found!
ERROR 1: P0170
ERROR 2: P0230 -Active-

Поставил реле назад:

Otpravil zapros DTC read
88 F1 11 58 2 1 70 22 2 30 22 CB 
Received message is OK! Checksum is correct!
     DTC is found!
ERROR 1: P0170
ERROR 2: P0230

Вот смотрю на код распознования ошибки и в упор не могу его понять. А хотелось бы для общего развития:

for (byte i=0; i<buf[n+1]; i++ ) {
    

     Serial.print("ERROR ");
     Serial.print (i+1);
     
  if (!bitRead(buf[n+2+(i*3)],6) && !bitRead(buf[n+2+(i*3)],7)) Serial.print(": P");
  if (bitRead(buf[n+2+(i*3)],6) && !bitRead(buf[n+2+(i*3)],7))  Serial.print(": C");
  if (!bitRead(buf[n+2+(i*3)],6) && bitRead(buf[n+2+(i*3)],7))  Serial.print(": B");
  if (bitRead(buf[n+2+(i*3)],6) && bitRead(buf[n+2+(i*3)],7))   Serial.print(": U");

  if (buf[n+2+(i*3)]<=0x0F) Serial.print("0"); 
  Serial.print (buf[n+2+(i*3)],HEX);
  if (buf[n+3+(i*3)]<=0x0F) Serial.print("0");
  Serial.print (buf[n+3+(i*3)],HEX);
    
  if (!bitRead(buf[n+4+(i*3)],6) && bitRead(buf[n+4+(i*3)],7)){
     Serial.print(" -Passive-");} 
  if (bitRead(buf[n+4+(i*3)],7) && bitRead(buf[n+4+(i*3)],6)) {
     Serial.print(" -Active-");}

Далее захотел все же добавить УОЗ, добавил так:

 int SparkAngel = 0;       //19 байт   УОЗ
 unsigned int Cyl1 =0;     //23 цил1 уменшение УОЗ для уменьшения детонации
 unsigned int Cyl2 =0;     //24 цил2 уменшение УОЗ для уменьшения детонации
 unsigned int Cyl3 =0;     //25 цил3 уменшение УОЗ для уменьшения детонации
 unsigned int Cyl4 =0;     //26 цил4 уменшение УОЗ для уменьшения детонации



SparkAngel = ((uint16_t)buf[n+15]*180/255-90);         //19 байт   УОЗ
 Cyl1 =((uint16_t)buf[n+19]*90/255);                    //23 цил1 уменшение УОЗ для уменьшения детонации
 Cyl2 =((uint16_t)buf[n+20]*90/255);                    //24 цил2 уменшение УОЗ для уменьшения детонации
 Cyl3 =((uint16_t)buf[n+21]*90/255);                    //25 цил3 уменшение УОЗ для уменьшения детонации
 Cyl4 =((uint16_t)buf[n+22]*90/255);                    //26 цил4 уменшение УОЗ для уменьшения детонации

SparkAngel показывает правильно, а по цилиндрам по нулям. Потому не уверен, может оно только на ходу будет видно?

И еще формула часового расхода, которая была найдена для программы Torque под двигатель z16xe, почему-то у меня показывает ноль:

float FuelHour =0;        //          Расход топлива литров в час

FuelHour =  (((InjPulse/1000ul)*(169ul/60000ul)*(RPM/120ul))*14400ul);  //          Расход топлива литров в час

Понятно, что с коэффициентами поиграться нужно будет и подобрать, но вот, например, при таких параметрах:

B0 F1 11 61 1 1 1 70 22 0 0 0 48 8B 72 52 66 AE 86 17 34 A 0 0 0 0 1E 0 0 22 26 19 5 44 AA 80 12 75 10 0 92 0 0 7 CC A 7 34 0 0 0 61 
Received message is OK! Checksum is correct!
     Receive DATA
 MAP=0.29 Battery=13.90 Air=21 Temp=90 EngLoad=9 Throtle=0 RPM=850 Speed=0 Inj=3.25 IdleAir=25 O2sens=751 O2int=128 FuelRatio=14.60 STFT=0 SparkAngel=4 Cyl1=0 Cyl2=0 Cyl3=0 Cyl4=0 FuelHour=0.00 FuelKm=0.00

FuelHour=(((3.25/1000)*(169/60000)*(850/120)*14400)= 0,933725 л/ч а у меня ноль. (((

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

Сначала все умножать, а потом делить

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

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

Targitai
Offline
Зарегистрирован: 05.10.2018

Работает! И вроде даже совпадает со штатным бортовиком, но это нужно смотреть уже с экрана, поставив два рядышком, а то в ноут отвлекаться в бегущие строчки не айс.

FuelHour =  (InjPulse*169*RPM*14400/1000/60000/120);   //          Расход топлива литров в час
FuelKm= (FuelHour/Speed*100);                          //          Мгновенный расход топлива на сотню
MAP=0.32 Battery=13.40 Air=17 Temp=90 EngLoad=9 Throtle=0 RPM=875 Speed=20 Inj=4.87 IdleAir=29 O2sens=738 O2int=178 FuelRatio=14.60 STFT=39 SparkAngel=8 Cyl1=0 Cyl2=0 Cyl3=0 Cyl4=0 FuelHour=1.44 FuelKm=7.21
B0 F1 11 61 1 1 1 70 22 0 0 0 50 86 81 4C 68 AD 8B 17 34 A 0 0 0 0 1E 0 13 23 39 1D 7 4C A6 B1 12 73 0 0 92 0 0 47 8C 8 7 34 0 0 0 C1
Received message is OK! Checksum is correct!
Receive DATA
MAP=0.33 Battery=13.40 Air=17 Temp=90 EngLoad=9 Throtle=0 RPM=875 Speed=19 Inj=4.87 IdleAir=29 O2sens=733 O2int=177 FuelRatio=14.60 STFT=38 SparkAngel=8 Cyl1=0 Cyl2=0 Cyl3=0 Cyl4=0 FuelHour=1.44 FuelKm=7.59
B0 F1 11 61 1 1 1 70 22 0 0 0 52 85 81 4C 68 AD 8C 17 34 A 0 0 0 0 1E 0 12 22 3A 1E 7 4C A6 B1 12 73 0 0 92 0 0 47 8C 8 7 34 0 0 0 C3
Received message is OK! Checksum is correct!
Receive DATA
MAP=0.33 Battery=13.30 Air=17 Temp=90 EngLoad=9 Throtle=0 RPM=850 Speed=18 Inj=4.96 IdleAir=30 O2sens=733 O2int=177 FuelRatio=14.60 STFT=38 SparkAngel=8 Cyl1=0 Cyl2=0 Cyl3=0 Cyl4=0 FuelHour=1.42 FuelKm=7.91
B0 F1 11 61 1 1 1 70 22 0 0 0 53 87 81 4C 68 AD 8C 17 34 A 0 0 0 0 1E 0 10 22 3A 1E 7 4C A6 B0 12 73 0 0 92 0 0 47 8C 8 7 34 0 0 0 C3
Received message is OK! Checksum is correct!
Receive DATA
MAP=0.34 Battery=13.50 Air=17 Temp=90 EngLoad=9 Throtle=0 RPM=850 Speed=16 Inj=4.96 IdleAir=30 O2sens=733 O2int=176 FuelRatio=14.60 STFT=37 SparkAngel=8 Cyl1=0 Cyl2=0 Cyl3=0 Cyl4=0 FuelHour=1.42 FuelKm=8.90
B0 F1 11 61 1 1 1 70 22 0 0 0 53 87 81 4C 69 AC 8C 17 34 A 0 0 0 0 1E 0 F 22 3A 1E 9 4C A5 B0 12 73 0 0 92 0 0 47 8C 8 7 34 0 0 0 C3
Received message is OK! Checksum is correct!
Receive DATA
MAP=0.34 Battery=13.50 Air=17 Temp=89 EngLoad=9 Throtle=0 RPM=850 Speed=15 Inj=4.96 IdleAir=30 O2sens=729 O2int=176 FuelRatio=14.60 STFT=37 SparkAngel=8 Cyl1=0 Cyl2=0 Cyl3=0 Cyl4=0 FuelHour=1.42 FuelKm=9.50
B0 F1 11 61 1 1 1 70 22 0 0 0 54 85 81 4C 69 AC 8A 17 34 A 0 0 0 0 1E 0 E 22 3A 1E 9 4B A4 AF 12 73 0 0 92 0 0 47 8C 8 7 34 0 0 0 BC
Received message is OK! Checksum is correct!
Receive DATA
MAP=0.34 Battery=13.30 Air=17 Temp=89 EngLoad=9 Throtle=0 RPM=850 Speed=14 Inj=4.96 IdleAir=30 O2sens=724 O2int=175 FuelRatio=14.60 STFT=36 SparkAngel=7 Cyl1=0 Cyl2=0 Cyl3=0 Cyl4=0 FuelHour=1.42 FuelKm=10.18
B0 F1 11 61 1 1 1 70 22 0 0 0 54 84 81 4C 69 AC 8A 17 34 A 0 0 0 0 1E 0 D 22 3A 1E 9 4B A4 AE 12 73 0 0 92 0 0 47 8C 8 7 34 0 0 0 B9
Received message is OK! Checksum is correct!
Receive DATA
MAP=0.34 Battery=13.20 Air=17 Temp=89 EngLoad=9 Throtle=0 RPM=850 Speed=13 Inj=4.96 IdleAir=30 O2sens=724 O2int=174 FuelRatio=14.60 STFT=35 SparkAngel=7 Cyl1=0 Cyl2=0 Cyl3=0 Cyl4=0 FuelHour=1.42 FuelKm=10.96
B0 F1 11 61 1 1 1 70 22 0 0 0 54 86 81 4C 69 AC 8A 17 34 A 0 0 0 0 1E 0 D 22 3A 1E 9 4B A4 AE 12 73 0 0 92 0 0 47 8C 8 7 34 0 0 0 BB
Received message is OK! Checksum is correct!
Receive DATA
MAP=0.34 Battery=13.40 Air=17 Temp=89 EngLoad=9 Throtle=0 RPM=850 Speed=13 Inj=4.96 IdleAir=30 O2sens=724 O2int=174 FuelRatio=14.60 STFT=35 SparkAngel=7 Cyl1=0 Cyl2=0 Cyl3=0 Cyl4=0 FuelHour=1.42 FuelKm=10.96
B0 F1 11 61 1 1 1 70 22 0 0 0 54 88 81 4C 69 AC 8A 17 34 A 0 0 0 0 1E 0 C 23 39 1E 9 4B A4 AD 12 73 0 0 92 0 0 47 8C 8 7 34 0 0 0 BB
Received message is OK! Checksum is correct!
Receive DATA
MAP=0.34 Battery=13.60 Air=17 Temp=89 EngLoad=9 Throtle=0 RPM=875 Speed=12 Inj=4.87 IdleAir=30 O2sens=724 O2int=173 FuelRatio=14.60 STFT=35 SparkAngel=7 Cyl1=0 Cyl2=0 Cyl3=0 Cyl4=0 FuelHour=1.44 FuelKm=12.01
B0 F1 11 61 1 1 1 70 22 0 0 0 60 87 81 4C 69 AC 8A 20 34 A 0 0 0 0 28 B C 22 42 23 9 4B A4 AB A 87 0 0 92 0 0 43 8C 8 7 34 0 0 0 F7
Received message is OK! Checksum is correct!
Receive DATA
MAP=0.39 Battery=13.50 Air=17 Temp=89 EngLoad=12 Throtle=4 RPM=850 Speed=12 Inj=5.64 IdleAir=35 O2sens=724 O2int=171 FuelRatio=14.60 STFT=33 SparkAngel=7 Cyl1=0 Cyl2=0 Cyl3=0 Cyl4=0 FuelHour=1.62 FuelKm=13.51
B0 F1 11 61 1 1 1 70 22 0 0 0 9B 87 81 4C 69 AC 8A 47 34 5 0 0 0 0 47 3A C 27 61 36 9 4B 94 A9 A 87 0 1E 92 0 0 43 8C 8 7 34 0 0 0 E5
Received message is OK! Checksum is correct!
Receive DATA
MAP=0.63 Battery=13.50 Air=17 Temp=89 EngLoad=27 Throtle=22 RPM=975 Speed=12 Inj=8.29 IdleAir=54 O2sens=654 O2int=169 FuelRatio=14.60 STFT=32 SparkAngel=7 Cyl1=0 Cyl2=0 Cyl3=0 Cyl4=0 FuelHour=2.73 FuelKm=22.77
B0 F1 11 61 1 1 1 70 22 0 0 0 BA 87 81 4C 69 AC 86 4C 34 5 2 0 14 0 4B 40 B 32 74 40 9 4A A8 A7 E 78 0 6D 92 0 0 47 8C 8 7 34 0 0 0 A5
Received message is OK! Checksum is correct!
Receive DATA
MAP=0.76 Battery=13.50 Air=17 Temp=89 EngLoad=29 Throtle=25 RPM=1250 Speed=11 Inj=9.92 IdleAir=64 O2sens=742 O2int=167 FuelRatio=14.60 STFT=30 SparkAngel=4 Cyl1=0 Cyl2=0 Cyl3=7 Cyl4=0 FuelHour=4.19 FuelKm=38.09
B0 F1 11 61 1 1 1 70 22 0 0 0 CB 87 81 4C 69 AC 82 4E 34 0 1 1 13 0 4D 43 B 2F 7D 40 9 4A A6 A4 E 78 0 84 92 0 0 47 8C 8 7 34 0 0 0 CB
Received message is OK! Checksum is correct!
Receive DATA
MAP=0.83 Battery=13.50 Air=17 Temp=89 EngLoad=30 Throtle=26 RPM=1175 Speed=11 Inj=10.69 IdleAir=64 O2sens=733 O2int=164 FuelRatio=14.60 STFT=28 SparkAngel=1 Cyl1=0 Cyl2=0 Cyl3=6 Cyl4=0 FuelHour=4.24 FuelKm=38.58
B0 F1 11 61 1 1 1 70 22 0 0 0 E3 87 81 4C 69 AC 7B 55 34 0 1 1 13 0 53 4B B 29 86 3F 9 4A A3 A2 E 78 0 90 92 0 0 47 8C 8 7 34 0 0 0 FA

Осталось только средний расход на сотню как-то сделать. Жаль, конечно, что одновременно с приборкой невозможна работа. Хотя от приборки всего то можно было бы сделать остаток пути на баке и напоминалку о замене масла...

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

да почему, можно и приборку добить. вот чуть правленый скетч, добавил passive DTC , и убрал балласт из массива TX сообщений 

#include <Button.h>
Button test;

#define BUTTON_PIN 4       // пин подключения тактовой кнопки
#define BUTTON 0           // программный номер кнопки

//#define ARDUINO_MEGA       // закоментировать эту строку если НЕ будем мегу использовать

#ifdef ARDUINO_MEGA
  #define K_LINE Serial3 
  #define TX 14
#else 
  #include <SoftwareSerial.h>
  #define RX 7
  #define TX 8
  SoftwareSerial K_LINE   (RX, TX); 
#endif


 // возможные варианты запросов на ЭБУ: 
 enum REQUEST {
 INIT,     
 PID,      
 DTCERASE, 
 DTCREAD,
 PRESENT,
 INIT_bus};
 
 
 //различные запросы на ЭБУ  
 byte TXmessage[][8] = {
 {0x81,0x11,0xF1,0x81,0x04,0x00,0x00,0x00},    // запрос инициализации
 {0x82,0x11,0xF1,0x21,0x01,0xA6,0x00,0x00},    // запрос пид 2101
 {0x83,0x11,0xF1,0x14,0xFF,0x00,0x98,0x00},    // запрос стирания ошибок
 {0x84,0x11,0xF1,0x18,0x00,0xFF,0x00,0x9D},    // запрос ошибок
 {0x81,0x11,0xF1,0x3E,0xC1,0x00,0x00,0x00}     // запрос поддержания связи
                       };  


 
 uint32_t curmillis =0;      // снимок текущего времени 
 
 uint32_t prevRequest = 0;   // таймер периодических запросов
 int RequestPeriod = 100;    // периодичность запросов , мс
 
 uint32_t prevRESETheader=0; // таймер сброса заголовка если в момент приёма заголовка данные оборвались
 bool RESETheader_timer;     // таймер сброса заголовка если в момент приёма заголовка данные оборвались
 
 uint32_t prev_NOanswer=0;   // таймер контроля неответов от ЭБУ после запросов
 bool NOanswer_timer = 0;    // таймер контроля неответов от ЭБУ после запросов
 byte noanswers = 0;         // количество подряд неответов от ЭБУ 
 
 uint32_t timerdelay = 0;    // таймер ожидания байт (для успевания появления данных в буфере UART)
 bool Delay = 0;             // таймер ожидания байт (для успевания появления данных в буфере UART)
 byte waitbyte_RX = 1;       // задержка, мс для успевания появления данных в буфере RX 
                             // (подрегулировать в зависимости от уровня жизнидеятельности на Марсе) 
 #define TIMER_DELAY Delay = 0; timerdelay = curmillis  // включение этого таймера
  
 byte delaybyte_TX  = 1;     // задержка между посылкой байт в запросе, мс


 
  

byte request = INIT;      // переменная, показывающая какой запрос будем делать

byte header = 0;          // состояние заголовка
byte message_size = 0;    // размер тела сообщения
byte j = 3;               // инкремент
byte n = 3;               // количество старт байт
const byte bufsize = 100; // размер буфера принятого сообщения
byte buf [bufsize] = {0}; // буфер принятого сообщения
byte crc =0;              // байт контрольной суммы 

// переменные трип компьютера 

 float MAP = 0;            //13 байт   Датчик абсолютного давления
 float SysVolt = 0;        //14 байт   Напряжение в сети
 int TempAir = 0;          //16 байт   Температура воздуха в градусах
 int Temp = 0;             //18 байт   Температура охлаждающей жидкости в градусах
 int EngLoad = 0;          //20 байы   нагрузка на двигатель
 byte Throtle = 0;         //28 байт   Открытие дроссельной заслонки в процентах
 unsigned int RPM = 0;     //30 байт   Обороты двигателя
 unsigned int Speed = 0;   //29 байт   Скорость а/м
 float InjPulse = 0;       //31 байт   Время впрыска форсунок
 unsigned int IdleAir = 0; //32 байт   Клапан холостого хода, шаги
 unsigned int O2sens = 0;  //35 байт   Лямбда мВ
 unsigned int O2int = 0;   //36 байт   Интегратор лямда, шагов
 float FuelRatio = 0;      //41 байт   Соотношение воздуха/топлива
 int STFT = 0;             //          Краткосрочная коррекция топлива
 

void setup() {
  
  delay(2000);
 
 // ниже настройки кнопок 
test.NO();                          // кнопка нормально разомкнутая 
test.pullUp();                      // внутренняя подтяжка к питанию вкючена
test.duration_bounce       (  50);  // время антидребезга, мс
test.duration_click_Db     ( 250);  // время дабл клика,   мс
test.duration_inactivity_Up(5000);
test.duration_inactivity_Dn(1000);
test.duration_press        ( 500);  // время длительного нажатия, мс
test.button(BUTTON_PIN);            // подключенные кнопки (пишутся через запятую)  
   
   Serial.begin(115200);
   pinMode(TX, OUTPUT);
   fastinit();
             }

void loop() {

test.read();          // обновление состояния кнопок
curmillis = millis(); // снимок текущего времени

if (test.event_click_Dn (BUTTON))  {request = DTCREAD; RequestPeriod  = 1000;}   // если было короткое   нажатие на тактовую кнопку запросим DTC
if (test.event_press_long (BUTTON)){request = DTCERASE; RequestPeriod = 1000;}   // если было длительное нажатие на тактовую кнопку удалим   DTC

if (curmillis - prevRequest > RequestPeriod && header == 0) {
        
        NOanswer_timer = 1; prev_NOanswer = curmillis; //т.к. сейчас будем делать запрос, то запускаем таймер контроля неответов 

       if (request == INIT_bus) {K_LINE.end(); delay (450); fastinit();} 

     else {      
          byte mesSize;   
          if (TXmessage[request][0] !=0x80) {mesSize=TXmessage[request][0];  bitWrite (mesSize, 7 , 0);mesSize+=4;}
          else mesSize=TXmessage[request][3]+5;
      for (byte i = 0; i<mesSize; i++){K_LINE.write(TXmessage[request][i]); delay (delaybyte_TX); K_LINE.read(); } // отправляем соответсвтующий запрос
          }
   TX_otladka();    
   prevRequest = curmillis;
                                                             }
  
   //разбор входящих сообщений      
    receive ();  
             }


//стартовая инициализация PCM на 7 пине ОБД (fast init - 25ms LOW 25ms HIGH)
 
 void fastinit() {
   digitalWrite (TX, HIGH);  // makes K-line high 3
   delay(360);             // wait for K-line to be clear 3
   digitalWrite (TX, LOW);  // makes K-line low  3
   delay(25);
   digitalWrite (TX, HIGH); // makes K-line high  3
   delay(25);               //last delay before first message
   K_LINE.begin(10400);  // baud rate of the OBD
   request = INIT; RequestPeriod = 500;
 }
 
 //получение данных от ЭБУ, разборка входящих сообщений
 
 void receive () {
 
 if (K_LINE.available() ){
    

 // первый старт байт
 if (header == 0 && Delay){TIMER_DELAY ; buf[0]=K_LINE.read();  
         if (buf[0]!=0xFF && bitRead (buf[0],7)){header = 1; RESETheader_timer =1; prevRESETheader = curmillis; 
         Serial.print (buf[0], HEX);  Serial.print (" "); }}                  

 // второй старт байт
 if (header == 1 && Delay){TIMER_DELAY ; buf[1]=K_LINE.read(); Serial.print (buf[1], HEX);  Serial.print (" ");if (buf[1]==0xF1){ header = 2;} else {header = 0; RESETheader_timer = 0;}} 

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

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

 // сообщение приняли, действуем
 if (header == 5) {TIMER_DELAY ;  
 Serial.println();  
 NOanswer_timer = 0; noanswers = 0;    // сбрасываем таймер контроля неответов 

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

 // если контрольная сумма верна: 
if ( crc == buf[message_size+n]) {Serial.println("Received message is OK! Checksum is correct!" );  // Если КС совпала, тут чёнибудь нужное делаем
    
    
      if (buf[n]==0xC1 && buf[n+1]==0xEF && buf[n+2]==0x8F) {request = PID; RequestPeriod = 100; Serial.println ("     Initialization OK!!!!:  "); }
 else if (buf[n]==0x58 && buf[n+1]==0x00) {Serial.println ("     NO DTC  ");      request = PID; RequestPeriod = 100;}
 else if (buf[n]==0x58 && buf[n+1] >0x00) {Serial.println ("     DTC is found!"); request = PID; RequestPeriod = 100;
 
 for (byte i=0; i<buf[n+1]; i++ ) {
    

     Serial.print("ERROR ");
     Serial.print (i+1);
     
  if (!bitRead(buf[n+2+(i*3)],6) && !bitRead(buf[n+2+(i*3)],7)) Serial.print(": P");
  if (bitRead(buf[n+2+(i*3)],6) && !bitRead(buf[n+2+(i*3)],7))  Serial.print(": C");
  if (!bitRead(buf[n+2+(i*3)],6) && bitRead(buf[n+2+(i*3)],7))  Serial.print(": B");
  if (bitRead(buf[n+2+(i*3)],6) && bitRead(buf[n+2+(i*3)],7))   Serial.print(": U");

  if (buf[n+2+(i*3)]<=0x0F) Serial.print("0"); 
  Serial.print (buf[n+2+(i*3)],HEX);
  if (buf[n+3+(i*3)]<=0x0F) Serial.print("0");
  Serial.print (buf[n+3+(i*3)],HEX);
    
  
  if (bitRead(buf[n+4+(i*3)],7) && bitRead(buf[n+4+(i*3)],6)) {
       Serial.print(" -Active-");} 
  else Serial.print(" -Passive-");
     Serial.println();
  

  }                                          } 
                  

  
 else if (buf[n]==0x54 && buf[n+1]==0xFF && buf[n+2]==0x00){ Serial.println ("     DTC CLEARED  "); request = PID; RequestPeriod = 100;}
 
 else if (buf[n]==0x61 && buf[n+1]==0x01) {               Serial.println ("     Receive DATA");
      
 MAP = ((uint16_t)buf[n+9]*1.04/255.0);                  //13 байт   Датчик абсолютного давления 102mbar
 SysVolt = ((float)buf[n+10]/10.00);                    //14 байт   Напряжение в сети 12.1v
 {double t , cel , drob ;
   t = (buf[n+12]*191ul/255.0)-40;                         //16 байт   Температура воздуха в градусах 50
   drob = modf(t, &cel); if (drob>=0.5) cel++;
 TempAir = cel;}
 {double t , cel , drob ;
 t = (buf[n+14]*191ul/255.0)-40;                           //18 байт   Температура охлаждающей жидкости в градусах104
 drob = modf(t, &cel); if (drob>=0.5) cel++;
 Temp = cel;}             
 EngLoad = ((uint16_t)buf[n+16]*100/255);               //20 байы   нагрузка на двигатель7%
 Throtle = ((uint16_t)buf[n+24]*100/255);               //28 байт   Открытие дроссельной заслонки в процентах 0
 RPM = ((uint32_t)buf[n+26]*6375ul/255ul);              //30 байт   Оборогты двигателя 0
 Speed = (buf[n+25]);                                   //29 байт   Скорость 0
 InjPulse = ((float)buf[n+27]*21.8/255.0);              //31 байт   Время впрыска форсунок 11.9
 IdleAir = (buf[n+28]);                                 //32 байт   Клапан холостого хода, шаги 38
 O2sens =(uint32_t) buf[n+31]*1127ul/255ul;             //35 байт   Лямбда мВ 380
 O2int = (buf[n+32]);                                   //36 байт   Интегратор лямда, шагов 128
 FuelRatio = ((float)buf[n+37]/10.00);                  //41 байт   Соотношение воздуха/топлива 12.3
 STFT = (((uint16_t)buf[n+32]-128)*100/128);        //          Краткосрочная коррекция топлива
 
  Serial.print(" MAP=");Serial.print(MAP);Serial.print(" Battery=");Serial.print(SysVolt);
  Serial.print(" Air=");Serial.print(TempAir);Serial.print(" Temp=");Serial.print(Temp);
  Serial.print(" EngLoad=");Serial.print(EngLoad);Serial.print(" Throtle=");Serial.print(Throtle);
  Serial.print(" RPM=");Serial.print(RPM); Serial.print(" Speed=");Serial.print(Speed);
  Serial.print(" Inj=");Serial.print(InjPulse);Serial.print(" IdleAir=");Serial.print(IdleAir);
  Serial.print(" O2sens=");Serial.print(O2sens);Serial.print(" O2int=");Serial.print(O2int);
  Serial.print(" FuelRatio=");Serial.print(FuelRatio);Serial.print(" STFT=");Serial.println(STFT);
   
   
   }
  
}   

// если контрольная сумма не совпала: 
else Serial.println("CRC fail!!!" );
message_size = 0; header=0; RESETheader_timer = 0; j=3; crc = 0;
}

// таймер ожидания байт (для успевания появления данных в буфере UART)
if (!Delay && curmillis - timerdelay > waitbyte_RX) Delay = 1; 

// таймер сброса заголовка если данные оборвались во время приёма заголовка
if (RESETheader_timer && curmillis - prevRESETheader > 500) {RESETheader_timer = 0; header = 0;}   
 
// если нет ответа после запроса: +1 к счетчику неответов. Если накопилось 6 и более: делаем реинит.  
if (NOanswer_timer && curmillis - prev_NOanswer > RequestPeriod - RequestPeriod/8) {NOanswer_timer = 0; noanswers++; 
     if (noanswers>=6) { noanswers = 0; request = INIT_bus;}         }
 
 }             


  void TX_otladka(){
    
      if (request == INIT_bus) Serial.println ("Bus_INIT"); 
 else if (request == INIT)     Serial.println ("Otpravil zapros Init");
 else if (request == DTCREAD)  Serial.println ("Otpravil zapros DTC read");
 else if (request == DTCERASE) Serial.println ("Otpravil zapros DTC clear");
                   }

Targitai пишет:

Осталось только средний расход на сотню как-то сделать.

Это просто. Правда это будет мгновенный расход на сотню 

L100 = (float)LHor*100.0/(float)Speed;
чтобы сделать средний расход нужна все же работа с приборкой - остаток топлива. 
Targitai
Offline
Зарегистрирован: 05.10.2018

Да мгновенный я то сделал, в логе есть. FuelKm=inf - когда стоим, А когда трогаемся, немного пугает :)))

MAP=0.42 Battery=13.60 Air=21 Temp=98 EngLoad=21 Throtle=14 RPM=1800 Speed=1 Inj=4.96 IdleAir=52 O2sens=4 O2int=135 FuelRatio=14.60 STFT=5 SparkAngel=24 Cyl1=1 Cyl2=0 Cyl3=7 Cyl4=2 FuelHour=3.02 FuelKm=301.67

На скорости 1 км/ч расход 301 литр :)

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

А с приборкой ж непонятка. Мало того, что последняя  версия скеча не работала, так еще и переделывать из-за hardware serial.