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

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. 

 

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

а когда стоим., расход на сотню вообще бесконечность . и это нормально.поэтому если скорость ниже 10, можно просто выводить 99 чтоб двузначное число было. 

Targitai пишет:

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

Улыбнуло про скорость и время. Это тебе не 7 класс школы. Твоя формула для постоянной скорости. автомобиль так не ездит. Есть ещё такое понятие как ускоение. 
С ускорением конечно тоже есть фомула, но тут ведь не лабораторная, где считается для движения прямолинейного равноукоренного. Автомобиль так тоже не ездит.  
Тут полный пипец, и ускорение изменяемое и движение криволинейное, при котором возникает ускорение Кориолиса и т.п. Полная жопа рассчитать. 
Проще приборку замучить 
 
Targitai
Offline
Зарегистрирован: 05.10.2018

Не не, просто делаем условие - при скорости меньше 10 км/ч показывает л/ч, при большей - л/100.

Ну у нас и не звездолет чтоб так все считать. Грубо говоря, раз в 5-10 секунд расчитываем пройденное расстояние и складируем в массив. Потом находим среднее из массива. Вопрос, правда, в ОЗУ. Для более точных значений нужен большой массив. С приборкой же тоже не все так гладко - полезли в нее, потеряли связь с ЭБУ. Есть, правда, вариант подключиться вторым k-line адаптером к самой приборке. Но вариант не очень, т.к. тогда ее от OBD разъема придется отключить и сторонние сканеры уже не увидят...

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

 

ЗыЖ.... кстати так же можно реализовать Long Term Fuel Trim. Было бы очень неплохо.

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

Проверил на всякий случай скетч 1321. Правда, ошибки забыл глянуть, ну да думаю будет работать. Добавил в него свои формулы по УОЗ и расходу. Кстати, обратил внимание, если STFT = (((uint16_t)buf[n+32]-128)*100/128); вот так, то формула работает неправильно. А если убрать (uint16_t), то все отлично.

В общем, получается финальный скетч (а то постоянно формулы прописываю :) ):

#include <Button.h>
Button test;

#define BUTTON_PIN 6       // пин подключения тактовой кнопки
#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;             //          Краткосрочная коррекция топлива
 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 уменшение УОЗ для уменьшения детонации
float  FuelHour =0;        //          Расход топлива литров в час
float FuelKm=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 = ((buf[n+32]-128)*100/128);                      //          Краткосрочная коррекция топлива
 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 уменшение УОЗ для уменьшения детонации
 FuelHour =  (InjPulse*169*RPM*14400/1000/60000/120);   //          Расход топлива литров в час
 FuelKm= (FuelHour/Speed*100ul);                        //          Мгновенный расход топлива на сотню
 
  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);
  Serial.print(" SparkAngel=");Serial.print(SparkAngel);Serial.print(" Cyl1=");Serial.print(Cyl1);
   Serial.print(" Cyl2=");Serial.print(Cyl2);Serial.print(" Cyl3=");Serial.print(Cyl3);
   Serial.print(" Cyl4=");Serial.print(Cyl4);
    Serial.print(" FuelHour=");Serial.print(FuelHour);Serial.print(" FuelKm=");Serial.println(FuelKm); 
   
   }
  
}   

// если контрольная сумма не совпала: 
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");
                   }

 

По поводу приборки. Последний рабочий скеч, который без периодического опроса, по софтсериалу переделал на хард так:



#define BAUD_200  0
#define BAUD_5    1

bool Protocol = BAUD_5;   // тут выбираем протокол 200 baud или 5 baud 
byte GAUGE_ADDRESS = 0xE0;  // тут выбираем адрес панели. Возможные варианты 0xE0, 0xE1, 0xB8, 0XB9, 0xBA

byte EndSession []= {0x02, 0xB2, 0x00, 0xB4};

int  bit_time = 0;

//#include <SoftwareSerial.h>

#define RX_gauge 15
#define TX_gauge 14
#define Gauge_K_line Serial3 // (RX_gauge, TX_gauge); 

bool InitGauge = 0;    // флаг инита панели

void setup() {
  Serial.begin (9600); //открываем соединение терминала для отладки

  pinMode  (TX_gauge, OUTPUT);
  digitalWrite  (TX_gauge, 1); // BUS idle
  delay (2000);

// далее посылаем на панель адрес на скорости 5 baud или 200 baud 
  
  Serial.print("Delayu zapros na panel. Adress: "); Serial.println(GAUGE_ADDRESS, HEX);

  if (Protocol) {bit_time = 200; Serial.println("5 baud Init"); }
  else {bit_time = 5;            Serial.println("200 baud Init"); }
  digitalWrite  (TX_gauge, 0); delay (bit_time); // старт бит
  for(byte i = 0; i<8; i++) {digitalWrite  (TX_gauge, bitRead(GAUGE_ADDRESS,i)); delay(bit_time);}
  digitalWrite  (TX_gauge, 1); delay (bit_time); // стоп бит
  
Gauge_K_line.begin(4800); // открываем к-лайн на приборку на 4800
}

byte head_count = 0;
byte head[4] = {0};


void loop() {
 while(!InitGauge){
   if (Gauge_K_line.available()) {
   byte inByte = Gauge_K_line.read();
   Serial.print(" ");
   Serial.print(inByte,HEX);
  if (inByte==0x80) {delay (10); Gauge_K_line.write (0x7F); }
  delay (10);
  if (inByte==0x78) {
  delay (10);
    Gauge_K_line.write (0x02);  delay (2);
    Gauge_K_line.write (0x11);  delay (2);
    Gauge_K_line.write (byte(0x00));  delay (2);
    Gauge_K_line.write (0x13);  delay (2); InitGauge=1; Serial.println("   Ura! Panel init proshla uspeshno!"); }}}
 
 
 if (InitGauge && Gauge_K_line.available()) {
  
  
  
  
  // ниже ищем шапку кадра 
     
     byte inbyte = Gauge_K_line.read();
     delay (7);
         if (inbyte == 0x21 && head_count == 0) {head_count = 1; head[0] = inbyte; } 
    else if (inbyte == 0xA1 && head_count == 1) {head_count = 2; head[1] = inbyte; } 
    else if (inbyte == 0x04 && head_count == 2) {head_count = 3; head[2] = inbyte; } 
    else {head_count = 0; for (byte i=0; i<sizeof(head); i++) head[i] = 0;} 

    // нашли шапку: 
  
  if (head_count == 3){
    
    head_count = 0; // очищаем переменную поиска шапки 
    
     byte Length = head[0];
     if (Length>100)Length=100;
    
    const byte sizeMes = Length+2;
    
    byte MessageRx [sizeMes] = {0};
    uint16_t crc = 0; 
    for (byte i=0; i<3; i++){MessageRx[i]= head[i]; crc += MessageRx[i]; head[i] = 0; Serial.print (MessageRx[i], HEX); Serial.print (" ");}  // очищаем переменные поиска шапки 
    
    bool CRC_OK = 0;

    // ниже пишем сообщение в буфер и считаем КС
    for (byte i = 3; i < sizeMes; i++) { MessageRx[i] = Gauge_K_line.read();  if (i<=sizeMes-3) crc += MessageRx[i]; delay (7); Serial.print (MessageRx[i], HEX); Serial.print (" "); }
//   Serial.println();
int CRC =  ( ( unsigned int )MessageRx [sizeMes-2] << 8 ) | MessageRx [sizeMes-1];
if (CRC==crc) CRC_OK = 1;

     if (CRC_OK){

Serial.println (" OK!!!");

uint32_t Odometer = ((uint32_t) MessageRx[26] << 16 ) | ((uint32_t) MessageRx[25] << 8 ) | MessageRx[24]; 
float FuelLevel    =  MessageRx[21]/2.0 ;

Serial. print ("Odometer: "); Serial. print (Odometer/10);  Serial. print (" km,  FuelLevel: "); Serial. print (FuelLevel);Serial.println (" l");

 for (byte i = 0; i < sizeof (EndSession); i++ ) { Gauge_K_line.write (EndSession [i]); delay (2);}
   } // конец ифа с правильной CRC  

   else  Serial.println("  CRC FAIL!!!");

  
  }   

}

}

И получил только так:

Delayu zapros na panel. Adress: E0
5 baud Init
 55 52 80 7F 20 A0 20 39 30 35 36 39 37 38 35 20 30 36 39 36 20 30 36 39 36 20 30 37 39 37 20 30 31 32 20 33 6 78   Ura! Panel init proshla uspeshno!

 

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

Targitai пишет:

С приборкой же тоже не все так гладко - полезли в нее, потеряли связь с ЭБУ. Есть, правда, вариант подключиться вторым k-line адаптером к самой приборке. Но вариант не очень, т.к. тогда ее от OBD разъема придется отключить и сторонние сканеры уже не увидят...

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

 

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

по приборке пока такой скетч 

#define BAUD_200  0
#define BAUD_5    1

bool Protocol = BAUD_5;   // тут выбираем протокол 200 baud или 5 baud 
byte GAUGE_ADDRESS = 0xE0;  // тут выбираем адрес панели. Возможные варианты 0xE0, 0xE1, 0xB8, 0XB9, 0xBA

byte EndSession []= {0x02, 0xB2, 0x00, 0xB4};
byte PIDGauge []=   {0x02, 0x11, 0x00, 0x13};
byte delaybyte_TX  = 1; //задержка между отправкой байт, мс

int  bit_time = 0;

//#include <SoftwareSerial.h>

#define RX_gauge 15
#define TX_gauge 14
#define Gauge_K_line Serial3 // (RX_gauge, TX_gauge); 

bool InitGauge = 0;    // флаг инита панели

void setup() {
  Serial.begin (9600); //открываем соединение терминала для отладки

  pinMode  (TX_gauge, OUTPUT);
  digitalWrite  (TX_gauge, 1); // BUS idle
  delay (2000);

// далее посылаем на панель адрес на скорости 5 baud или 200 baud 
  
  Serial.print("Delayu zapros na panel. Adress: "); Serial.println(GAUGE_ADDRESS, HEX);

  if (Protocol) {bit_time = 200; Serial.println("5 baud Init"); }
  else {bit_time = 5;            Serial.println("200 baud Init"); }
  digitalWrite  (TX_gauge, 0); delay (bit_time); // старт бит
  for(byte i = 0; i<8; i++) {digitalWrite  (TX_gauge, bitRead(GAUGE_ADDRESS,i)); delay(bit_time);}
  digitalWrite  (TX_gauge, 1); delay (bit_time); // стоп бит
  
Gauge_K_line.begin(4800); // открываем к-лайн на приборку на 4800
}

byte head_count = 0;
byte head[4] = {0};


void loop() {
 while(!InitGauge){
   if (Gauge_K_line.available()) {
   byte inByte = Gauge_K_line.read();
   Serial.print(" ");
   Serial.print(inByte,HEX);
  if (inByte==0x80) {delay (10); Gauge_K_line.write (0x7F); }
  if (inByte==0x78) {
  delay (10);
    for (byte i=0; i< sizeof(PIDGauge); i++) {Gauge_K_line.write (PIDGauge[i]);  delay (delaybyte_TX);}
    
    InitGauge=1; Serial.println("   Ura! Panel init proshla uspeshno!"); }}}
 
 
 if (InitGauge && Gauge_K_line.available()) {
  
  
  
  
  // ниже ищем шапку кадра 
     
     byte inbyte = Gauge_K_line.read();
     delay (7);
         if (inbyte == 0x21 && head_count == 0) {head_count = 1; head[0] = inbyte; } 
    else if (inbyte == 0xA1 && head_count == 1) {head_count = 2; head[1] = inbyte; } 
    else if (inbyte == 0x04 && head_count == 2) {head_count = 3; head[2] = inbyte; } 
    else {head_count = 0; for (byte i=0; i<sizeof(head); i++) head[i] = 0;} 

    // нашли шапку: 
  
  if (head_count == 3){
    
    head_count = 0; // очищаем переменную поиска шапки 
    
     byte Length = head[0];
     if (Length>100)Length=100;
    
    const byte sizeMes = Length+2;
    
    byte MessageRx [sizeMes] = {0};
    uint16_t crc = 0; 
    for (byte i=0; i<3; i++){MessageRx[i]= head[i]; crc += MessageRx[i]; head[i] = 0; Serial.print (MessageRx[i], HEX); Serial.print (" ");}  // очищаем переменные поиска шапки 
    
    bool CRC_OK = 0;

    // ниже пишем сообщение в буфер и считаем КС
    for (byte i = 3; i < sizeMes; i++) { MessageRx[i] = Gauge_K_line.read();  if (i<=sizeMes-3) crc += MessageRx[i]; delay (7); Serial.print (MessageRx[i], HEX); Serial.print (" "); }
//   Serial.println();
int CRC =  ( ( unsigned int )MessageRx [sizeMes-2] << 8 ) | MessageRx [sizeMes-1];
if (CRC==crc) CRC_OK = 1;

     if (CRC_OK){

Serial.println (" OK!!!");

uint32_t Odometer = ((uint32_t) MessageRx[26] << 16 ) | ((uint32_t) MessageRx[25] << 8 ) | MessageRx[24]; 
float FuelLevel    =  MessageRx[21]/2.0 ;

Serial. print ("Odometer: "); Serial. print (Odometer/10);  Serial. print (" km,  FuelLevel: "); Serial. print (FuelLevel);Serial.println (" l");

 for (byte i = 0; i < sizeof (EndSession); i++ ) { Gauge_K_line.write (EndSession [i]); delay (2);}
   } // конец ифа с правильной CRC  

   else  Serial.println("  CRC FAIL!!!");

  
  }   

}

}

если не заработает. пробовать регулировать задержки в строках 9 , 51, 53

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

Строка 9, наилучший результат при задержке 3 мс. Хватает 4 правильных результата. Но в любом случае, конектиться только со второго раза.

Лог:

Delayu zapros na panel. Adress: E0
5 baud Init
 55 52 80 7F 20 A0 20 39 30 35 36 39 37 38 35 20 30 36 39 36 20 30 36 39 36 20 30 37 39 37 20 30 31 32 20 33 6 78   Ura! Panel init proshla uspeshno!
21 A1 4 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 67 3A 3A A4 35 31 24 25 6F 7 AF C0 3F 1 5 1A  OK!!!
Odometer: 243409 km,  FuelLevel: 29.00 l
21 A1 4 0 0 0 0 0 0 0 0 0 0 0 1 2 36 FF 0 0 67 3A 3A A4 35 31 24 25 6F 7 AF C0 3F 1 5   CRC FAIL!!!
21 A1 4 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 67 3B 3B A3 34 31 24 25 6F 7 AF C0 3F 1 5 1A  OK!!!
Odometer: 243409 km,  FuelLevel: 29.50 l
21 A1 4 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 67 3A 3A A3 34 31 24 25 6F 7 AE C1 3F 1 5 18  OK!!!
Odometer: 243409 km,  FuelLevel: 29.00 l
21 A1 4 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 67 3A 3A A5 35 31 24 25 6F 7 AF BF 3F 1 5 1A  OK!!!
Odometer: 243409 km,  FuelLevel: 29.00 l
Delayu zapros na panel. Adress: E0
5 baud Init
Delayu zapros na panel. Adress: E0
5 baud Init
 55 52 80 7F 20 A0 20 39 30 35 36 39 37 38 35 20 30 36 39 36 20 30 36 39 36 20 30 37 39 37 20 30 31 32 20 33 6 78   Ura! Panel init proshla uspeshno!
21 A1 4 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 67 3A 3A A3 34 31 24 25 6F 7 AE C0 3F 1 5 17  OK!!!
Odometer: 243409 km,  FuelLevel: 29.00 l
21 A1 4 0 0 0 0 0 0 0 0 0 0 0 1 2 3 0 0 68 3A 3A A5 34 31 24 25 6F 7 AF C0 3F 1 5 1B   CRC FAIL!!!
21 A1 4 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 68 3A 3A A4 34 31 24 25 6F 7 AE C1 3F 1 5 1A  OK!!!
Odometer: 243409 km,  FuelLevel: 29.00 l
21 A1 4 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 68 3A 3A A5 34 31 24 25 6F 7 AF C0 3F 1 5 1B  OK!!!
Odometer: 243409 km,  FuelLevel: 29.00 l
21 A1 4 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 67 3B 3B A5 35 31 24 25 6F 7 AF C0 3F 1 5 1D  OK!!!
Odometer: 243409 km,  FuelLevel: 29.50 l

Скеч:

#define BAUD_200  0
#define BAUD_5    1

bool Protocol = BAUD_5;   // тут выбираем протокол 200 baud или 5 baud 
byte GAUGE_ADDRESS = 0xE0;  // тут выбираем адрес панели. Возможные варианты 0xE0, 0xE1, 0xB8, 0XB9, 0xBA

byte EndSession []= {0x02, 0xB2, 0x00, 0xB4};
byte PIDGauge []=   {0x02, 0x11, 0x00, 0x13};
byte delaybyte_TX  = 3;                                   //задержка между отправкой байт, мс

int  bit_time = 0;

//#include <SoftwareSerial.h>

#define RX_gauge 15
#define TX_gauge 14
#define Gauge_K_line Serial3 // (RX_gauge, TX_gauge); 

bool InitGauge = 0;    // флаг инита панели

void setup() {
  Serial.begin (9600); //открываем соединение терминала для отладки

  pinMode  (TX_gauge, OUTPUT);
  digitalWrite  (TX_gauge, 1); // BUS idle
  delay (2000);

// далее посылаем на панель адрес на скорости 5 baud или 200 baud 
  
  Serial.print("Delayu zapros na panel. Adress: "); Serial.println(GAUGE_ADDRESS, HEX);

  if (Protocol) {bit_time = 200; Serial.println("5 baud Init"); }
  else {bit_time = 5;            Serial.println("200 baud Init"); }
  digitalWrite  (TX_gauge, 0); delay (bit_time); // старт бит
  for(byte i = 0; i<8; i++) {digitalWrite  (TX_gauge, bitRead(GAUGE_ADDRESS,i)); delay(bit_time);}
  digitalWrite  (TX_gauge, 1); delay (bit_time); // стоп бит
  
Gauge_K_line.begin(4800); // открываем к-лайн на приборку на 4800
}

byte head_count = 0;
byte head[4] = {0};


void loop() {
 while(!InitGauge){
   if (Gauge_K_line.available()) {
   byte inByte = Gauge_K_line.read();
   Serial.print(" ");
   Serial.print(inByte,HEX);
  if (inByte==0x80) {delay (10); Gauge_K_line.write (0x7F); }                                                   //тут играемся задержкой
  if (inByte==0x78) {
  delay (10);                                                                                                   //и тут еще
    for (byte i=0; i< sizeof(PIDGauge); i++) {Gauge_K_line.write (PIDGauge[i]);  delay (delaybyte_TX);}
    
    InitGauge=1; Serial.println("   Ura! Panel init proshla uspeshno!"); }}}
 
 
 if (InitGauge && Gauge_K_line.available()) {
  
  
  
  
  // ниже ищем шапку кадра 
     
     byte inbyte = Gauge_K_line.read();
     delay (7);
         if (inbyte == 0x21 && head_count == 0) {head_count = 1; head[0] = inbyte; } 
    else if (inbyte == 0xA1 && head_count == 1) {head_count = 2; head[1] = inbyte; } 
    else if (inbyte == 0x04 && head_count == 2) {head_count = 3; head[2] = inbyte; } 
    else {head_count = 0; for (byte i=0; i<sizeof(head); i++) head[i] = 0;} 

    // нашли шапку: 
  
  if (head_count == 3){
    
    head_count = 0; // очищаем переменную поиска шапки 
    
     byte Length = head[0];
     if (Length>100)Length=100;
    
    const byte sizeMes = Length+2;
    
    byte MessageRx [sizeMes] = {0};
    uint16_t crc = 0; 
    for (byte i=0; i<3; i++){MessageRx[i]= head[i]; crc += MessageRx[i]; head[i] = 0; Serial.print (MessageRx[i], HEX); Serial.print (" ");}  // очищаем переменные поиска шапки 
    
    bool CRC_OK = 0;

    // ниже пишем сообщение в буфер и считаем КС
    for (byte i = 3; i < sizeMes; i++) { MessageRx[i] = Gauge_K_line.read();  if (i<=sizeMes-3) crc += MessageRx[i]; delay (7); Serial.print (MessageRx[i], HEX); Serial.print (" "); }
//   Serial.println();
int CRC =  ( ( unsigned int )MessageRx [sizeMes-2] << 8 ) | MessageRx [sizeMes-1];
if (CRC==crc) CRC_OK = 1;

     if (CRC_OK){

Serial.println (" OK!!!");

uint32_t Odometer = ((uint32_t) MessageRx[26] << 16 ) | ((uint32_t) MessageRx[25] << 8 ) | MessageRx[24]; 
float FuelLevel    =  MessageRx[21]/2.0 ;

Serial. print ("Odometer: "); Serial. print (Odometer/10);  Serial. print (" km,  FuelLevel: "); Serial. print (FuelLevel);Serial.println (" l");

 for (byte i = 0; i < sizeof (EndSession); i++ ) { Gauge_K_line.write (EndSession [i]); delay (2);}
   } // конец ифа с правильной CRC  

   else  Serial.println("  CRC FAIL!!!");

  
  }   

}

}

 

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

Ну шо, я такой себе радостный, что ECU отвечает адекватно. Запилил вывод на экран... И тут опять облом. Вечный инит. Опять где-то задержки крутить? Вот такой скеч:

#include <logo.h>           //логотип Опель
#include <shema.h>          //Разлинейка экрана
#include <font4x6.h>
#include <font6x8.h>
#include <font8x8.h>
#include <font8x8ext.h>
#include <fontALL.h>
#include <TVout.h>
#include <video_gen.h>
TVout TV;

#include <DS3231.h>        // библиотека часов
DS3231  rtc(SDA, SCL);


#include <Button.h>
Button test;

#define BUTTON_PIN 6       // пин подключения тактовой кнопки
#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 = 0;       // задержка, мс для успевания появления данных в буфере RX 
                             // (подрегулировать в зависимости от уровня жизнидеятельности на Марсе) 
 #define TIMER_DELAY Delay = 0; timerdelay = curmillis  // включение этого таймера
  
 byte delaybyte_TX  = 0;     // задержка между посылкой байт в запросе, мс

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;             //          Краткосрочная коррекция топлива
 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 уменшение УОЗ для уменьшения детонации
float  FuelHour =0;        //          Расход топлива литров в час
float FuelKm=0;            //          Мгновенный расход топлива на сотню

//Состояние дисплея

bool scr_clear=false;        //Очищать ли экран
int scr_mode=1;             //Номер отображаемого экрана
 

void setup() {

  TV.begin(NTSC, 136, 72);            // режим вывода на ТВ
  TV.select_font(font8x8ext);         // выбор шрифта
  TV.bitmap(0, 0, logo);              // вывод логотипа Опель
  TV.delay(3000);                     // задержка 3 секунд
  TV.clear_screen();                  // очистить экран
  TV.bitmap(0, 0, shema);
  rtc.begin();                        // Инициализация часов
  
 
 // ниже настройки кнопок 
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))  {
    if (scr_mode >=5){
      scr_mode=1;
      scr_clear=true;
    }
    else {
      scr_mode++;
      scr_clear=true;
    }
    
}


if (scr_mode == 1){func_main_display();}
if (scr_mode == 2){func_Diag1();}
if (scr_mode == 3){func_Diag2();}
if (scr_mode == 4){func_Diag3();}
if (scr_mode == 5){func_DTC();}

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

       if (request == INIT_bus) {K_LINE.end(); delay (450); fastinit();Serial.println ("Bus_INIT");} 

     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 = ((buf[n+32]-128)*100/128);                      //          Краткосрочная коррекция топлива
 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 уменшение УОЗ для уменьшения детонации
 FuelHour =  (InjPulse*169*RPM*14400/1000/60000/120);   //          Расход топлива литров в час
 FuelKm= (FuelHour/Speed*100ul);                        //          Мгновенный расход топлива на сотню
 
  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);
  Serial.print(" SparkAngel=");Serial.print(SparkAngel);Serial.print(" Cyl1=");Serial.print(Cyl1);
   Serial.print(" Cyl2=");Serial.print(Cyl2);Serial.print(" Cyl3=");Serial.print(Cyl3);
   Serial.print(" Cyl4=");Serial.print(Cyl4);
    Serial.print(" FuelHour=");Serial.print(FuelHour);Serial.print(" FuelKm=");Serial.println(FuelKm); 
   
   }
  
}   

// если контрольная сумма не совпала: 
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");
                   }

 void func_main_display()
 {
  //if ((millis() % 2000) == 0)
  //{
  if (scr_clear==true){
    TV.clear_screen();                  
    scr_clear=false;
   TV.bitmap(0, 0, shema);  
  }
  
    TV.select_font(font8x8ext);
    TV.set_cursor(20, 5);                      
    TV.print(TempAir);                           //температура с наружнего датчика          
    
    TV.set_cursor(52, 5);                        
    TV.print(rtc.getTimeStr(FORMAT_SHORT));      // выодим время в формате чч:мм
    
    TV.set_cursor(116, 5);                       
    TV.print(int(rtc.getTemp()));                //температура внутри с датчика часов
    
    TV.set_cursor(20, 62);                       
    TV.print(Temp);                              // температура двигла
    
    TV.set_cursor(49, 62);                       // ставим курсор
    TV.select_font(font6x8);
    TV.print(rtc.getDateStr(FORMAT_SHORT));      // выводим дату
    
    TV.set_cursor(118, 62);                       
    TV.print(SysVolt);                            // выводим Вольтаж
    
if (Speed >= 10){                                 //Если скороть больше 10 км/ч
    TV.set_cursor(1, 23);                       
    TV.print("INT.CONSUM.:");
    TV.print(FuelKm);                             //Выводим мгновенный расход на сотню
    TV.print(" l/100");}
    else{
    TV.set_cursor(1, 23);                      
    TV.print("INT.CONSUM.:");
    TV.print(FuelHour);                           //Иначе часовой расход
    TV.print(" l/h");}
    
    TV.set_cursor(1, 33);                      
    TV.print("STFT       :");
    TV.print(STFT);                               //кратоскрочная коррекция
    TV.print(" %");
    
    TV.set_cursor(1, 43);                       
    TV.print("ENGINE LOAD:");
    TV.print(EngLoad);                            //нагрузка на двигатель
    TV.print(" %");
  //}
 }

 void func_Diag1()
{
   if (scr_clear==true){
    TV.clear_screen();                  
    scr_clear=false;
  }
    TV.select_font(font6x8);
    TV.set_cursor(20, 0);                       
    TV.print("DIAGNOSTIC MODE 1");                           
       
    TV.set_cursor(0, 10);                      
    TV.print("AIR TEMP   : ");
    TV.print(TempAir);                
    
    TV.set_cursor(0, 20);                      
    TV.print("ENGINE TEMP: ");
    TV.print(Temp);                              
    
    TV.set_cursor(0, 30);                       
    TV.print("ENGINE LOAD: ");
    TV.print(EngLoad);     
    
    TV.set_cursor(0, 40);                      
    TV.print("THROTLE    : ");
    TV.print(Throtle);                           

    TV.set_cursor(0, 50);                         
    TV.print("RPM        : ");
    TV.print(RPM);                           

    TV.set_cursor(0, 60);
    TV.print("SPEED      : ");
    TV.print(Speed);

}
void func_Diag2()
{
   if (scr_clear==true){
    TV.clear_screen();                  
    scr_clear=false;
  }
    TV.select_font(font6x8);
    TV.set_cursor(20, 0);                       
    TV.print("DIAGNOSTIC MODE 2");                           
       
    TV.set_cursor(0, 10);                      
    TV.print("MAP          : ");
    TV.print(MAP);                
    
    TV.set_cursor(0, 20);                      
    TV.print("INJ. PULSE   : ");
    TV.print(InjPulse);                              
      
    TV.set_cursor(0, 30);                      
    TV.print("O2 SENSOR    : ");
    TV.print(O2sens);                           

    TV.set_cursor(0, 40);                         
    TV.print("O2 INTEGRATOR: ");
    TV.print(O2int);                           

    TV.set_cursor(0, 50);
    TV.print("FUEL RATIO   : ");
    TV.print(FuelRatio);
    
    TV.set_cursor(0, 60);                       
    TV.print("IDLE AIR     : ");
    TV.print(IdleAir); 
}
void func_Diag3()
{
   if (scr_clear==true){
    TV.clear_screen();                  
    scr_clear=false;
  }
    TV.select_font(font6x8);
    TV.set_cursor(20, 0);                       
    TV.print("DIAGNOSTIC MODE 3");                           
       
    TV.set_cursor(0, 10);                      
    TV.print("SPARK ANGEL     : ");
    TV.print(SparkAngel);                
    
    TV.set_cursor(0, 20);                      
    TV.print("DETONATION CYL 1: ");
    TV.print(Cyl1);                              
      
    TV.set_cursor(0, 30);                      
    TV.print("DETONATION CYL 2: ");
    TV.print(Cyl2);                           

    TV.set_cursor(0, 40);                         
    TV.print("DETONATION CYL 3: ");
    TV.print(Cyl3);                           

    TV.set_cursor(0, 50);
    TV.print("DETONATION CYL 4: ");
    TV.print(Cyl4);
    
 
}
void func_DTC(){
 {
   if (scr_clear==true){
    TV.clear_screen();                  
    scr_clear=false;
  }
    TV.select_font(font6x8);
    TV.set_cursor(40, 0);                       
    TV.print("DTC MODE"); 

}}

Не разобрался как вывести на экран ошибки  DTC. Кнопку повесил на перебор экранов, но вообще их нужно 4-ре. Две для установки часов, две для управления экаранами и стирания ошибок/сброса трипа/сервиса. Мучал и так и эдак, что-то у меня с этой библиотекой не срастается.

И еще вопрос, строка 113, где инициализируем серийник. Он что, софтварный разве? Это ж хардварный серийник в который мы с компа глядим. Если он включен, то экран дергается постоянно. Еслим закоментить, то нормально. После отладки его ж можно будет убрать?

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

Targitai пишет:

Ну шо, я такой себе радостный, что ECU отвечает адекватно. Запилил вывод на экран... И тут опять облом. Вечный инит. Опять где-то задержки крутить? 

нужно проще сначала делать. Просто сначала добавь чисто библу ТВ, смотри будет ли работать. Если да, то усложняй потихоньку (например просто вывод какой-либо фразы на экран), каждый раз проверяя работает ли, чтобы потом понять на каком этапе перестало работать. 

Targitai пишет:

Не разобрался как вывести на экран ошибки  DTC. Кнопку повесил на перебор экранов, но вообще их нужно 4-ре. Две для установки часов, две для управления экаранами и стирания ошибок/сброса трипа/сервиса. Мучал и так и эдак, что-то у меня с этой библиотекой не срастается.

потом покажу когда заработает. 

Targitai пишет:

И еще вопрос, строка 113, где инициализируем серийник. Он что, софтварный разве? Это ж хардварный серийник в который мы с компа глядим. Если он включен, то экран дергается постоянно. Еслим закоментить, то нормально. После отладки его ж можно будет убрать?

Не вижу в строке 113 инита Сериала. Попробуй в свой рабочий скетч с ТВ аут вставить только инит Serial. Если перестанет работать, стало быть ТВ аут не совместим и с хард сериалом, поэтому у тебя рабочий скетч с PCM перестал работать. 

 

 

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

Targitai пишет:
Мучал и так и эдак, что-то у меня с этой библиотекой не срастается.

пины кнопок настраиваются так, покажу на примере, где подключены 3 кнопки :

#include <Button.h>
Button test;

#define StartButtonpin  7     // пин старт кнопки 7
#define LEFTButtonpin   8     // пин кнопки лево  8
#define RIGHTButtonpin  9     // пин кнопки право 9

#define StartButton 0
#define LEFTButton  1
#define RIGHTButton 2

void setup() {

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);

// ниже через запятую пишутся пины кнопок, соответственно в скетче программные номера у этих кнопок будут 0, 1 , 2 и т.д. и обращение к ним далее уже будет по программым номера, поэтому выше рядом с дефайнами пинов сделаны дефайны программных номеров: 
test.button(StartButtonpin, LEFTButtonpin, RIGHTButtonpin);
}
void loop (){ 
test.read(); 
if (test.event_click_Dn (StartButton)){ если нажата старт}; 
if (test.event_click_Dn (LEFTButton)){ если нажата лево}; 
if (test.event_click_Dn (RIGHTButton)){ если нажата право}; 
}

 

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

Чет нумерация строк отличается, смотрел в IDE. Я имел ввиду вот этот серийник: serial.begin(115200), это ж тот в который мы смотрим с компа и он будет не нужен в финале, так?

Ок, буду постепенно добавлять и смотреть шо будет.

А с кнопками я смотрел примеры по ссылке, что ты дал.

#include <Button.h>

Button test;

void setup() {
test.NO(); // N.O. Normal Open
// test.NC(); // N.C. Normal Closed
test.pullUp();
// test.pullDn();
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( 5, 4, 9, 7, 8); // arduino pins connected to button
// test.button();
}

void loop() {
test.read();
if (test.state_button       (0) == 1) {}
if (test.state_inactivity_Up(0) == 1) {}
if (test.state_inactivity_Dn(0) == 1) {}
if (test.event_click_Up     (0) == 1) {}
if (test.event_click_Dn     (0) == 1) {}
if (test.event_click_Db     (0) == 1) {}
if (test.event_inactivity_Up(0) == 1) {}
if (test.event_inactivity_Dn(0) == 1) {}
if (test.event_press_short  (0) == 1) {}
if (test.event_press_long   (0) == 1) {}
//  test....................(*) == 1) {}
if (test.state_button       (4) == 1) {}
if (test.state_inactivity_Up(4) == 1) {}
if (test.state_inactivity_Dn(4) == 1) {}
if (test.event_click_Up     (4) == 1) {}
if (test.event_click_Dn     (4) == 1) {}
if (test.event_click_Db     (4) == 1) {}
if (test.event_inactivity_Up(4) == 1) {}
if (test.event_inactivity_Dn(4) == 1) {}
if (test.event_press_short  (4) == 1) {}
if (test.event_press_long   (4) == 1) {}

if (test.state_button       ()  == 1) {}
if (test.state_inactivity_Up()  == 1) {}
if (test.state_inactivity_Dn()  == 1) {}
if (test.event_click_Up     ()  == 1) {}
if (test.event_click_Dn     ()  == 1) {}
if (test.event_click_Db     ()  == 1) {}
if (test.event_inactivity_Up()  == 1) {}
if (test.event_inactivity_Dn()  == 1) {}
if (test.event_press_short  ()  == 1) {}
if (test.event_press_long   ()  == 1) {}

}

И так же пытался сделать. И одна кнопка на перебор экрана работала, а вторая, по которой по длинному нажатию я хотел заходить в настройку часов - никак. Не могут же define'ы так влиять, это ж чисто для своего удобства мы кнопки обзываем. Хотя подтяжка включилась. Попробую переписать свой старый скеч с часами на эту библиотеку....

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

да это для отладки серийник, потом не нужен будет. Просто если с ним косяки, то и с Serial1 Serial2 Serial3, наверное, тоже самое будет. 

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

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

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

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

На крайняк уже смирился со второй Дуней для вывода изображения.

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

только как ей данные передавать?  по сериал? ))))

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

есть ещё SPI и i2С . Надеюсь их твой ТВ аут не глушит.  но моя не уметь этим пользоваться

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

"только как ей данные передавать?  по сериал? ))))"

Таки да, почти. даже с этого сайта: http://arduino.ru/forum/programmirovanie/peredacha-dannykh-po-uart-pri-aktivnom-tvout

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

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

дак смотри в той теме, в последнем посту объяснили, что блокирует UART звуковые функции библиотеки и выложили другую либу, где эти функции вырезаны и теперь типа уарт должен задышать. 

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

ато ТВ-аут не дышит в последних IDE.... Хоть с вырезанными звуковыми функциями. Я еще раз попытаюсь найти тему, где редактируют эту либу. Там вместо макросов заменяют что-то типа /nop /nop и вот тогда IDE ее хавает. Я ночью сидел ковырял и так точно не понял что я сделал :) Но либа заработала на последнем IDE. Хопошо хотть сохранил. 

Да и к тому же, там получилось передать по серийнику данные с одной Дуни на другую и вывести на экран, что и будет нужно, если что....

Ага, вот, отсюда я начал: https://github.com/sheaivey/rx5808-pro-diversity/issues/89

Но либа от BoRKeLSNoRKeL не заработала и я начал в ней ковыряться, сравнивая. Нашел несовпадение в какой-то строке и изменил, после чего все заработало. Вот где нашел разницу - увы, не вспомню. Могу выложить ту либу, что работает под последним IDE и сравнить ее с порезанной на звук, если поможет.

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

Таки все же ТВ аут виноват. Если уменьшить разрешение экрана до 128*96, то можно вывести аж целую одну цифру на экран. Начинаешь еще что-то добавлять - и все.

Попробовал сделать через pollserial. Экран мерцает даже с отключенным монитором порта (serial0) (на машине не пробовал). На тему про pollserial натукнулся тут: https://forum.arduino.cc/index.php?topic=412718.msg2842942#msg2842942     Там же поправленная библиотека, чтобы его на Мега можно было назначить на любой serial

Сейчас поковырялся в либе, которая без звука. Завтра испытаю на машине.

Но такой вопрос - а на столе то должно работать? Если в Уно загрузить скетч эмулятора нашего ECU, ну и соединить все через k-line адаптеры? Т.е. чтоб Мега сейчас выступала в роли OP-COM K-Line? А то что-то у меня так не фурычит...

PS... заказал Нано на всякий случай. Но пока можно будет попробовать в качестве видеодрайвера Уно. Как бы скетч дописать для отправки пакета с одной на другую и разбором сообщений....

PPS... А кстати, если получится с двумя Ардуинами, то выйдет даже неплохо. Тогда можно две Нано будет использовать. И места меньше занимают, и дешевле. Итоговый скеч для приема данных от ЭБУ машины вполне вмещается в Уно (Нано же столько же памяти имеет). 

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

Targitai пишет:

Но такой вопрос - а на столе то должно работать? Если в Уно загрузить скетч эмулятора нашего ECU, ну и соединить все через k-line адаптеры? Т.е. чтоб Мега сейчас выступала в роли OP-COM K-Line? А то что-то у меня так не фурычит...

да так должно работать. Может 12В забыл подать на к-лайн адаптеры? 

Targitai пишет:

PS... заказал Нано на всякий случай. Но пока можно будет попробовать в качестве видеодрайвера Уно. Как бы скетч дописать для отправки пакета с одной на другую и разбором сообщений....

дак по какой шине данные то передавать? по Serial? получается от чего ушли к тому и пришли. ТВ то блокирует Serial. По SPI нужно пробовать будет ли она работать с ТВ аут

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

MaksVV пишет:

да так должно работать. Может 12В забыл подать на к-лайн адаптеры? 

Аднака на хочет, чтоб его! Напряжение подавал, ессно. Я эту схему скоро по среди ночи с закрытими глазами уже собирать буду....

MaksVV пишет:

дак по какой шине данные то передавать? по Serial? получается от чего ушли к тому и пришли. ТВ то блокирует Serial. По SPI нужно пробовать будет ли она работать с ТВ аут

Ну так вот в той теме то получилось по Сериал передать. Используя библиотеку pollserial. И тут ведь у меня хотя б одну цифру передать получилось, значит все же не совсем блокирует, просто своими прерываниями влияет на наши. А их в скетче слишком много. Если же Ардуина будет без лишних задержек принимать и просто выводить на экран данные, то, думаю, может и получится. Можно же на столе проверить. Мега в качестве эмулятора работы, Уно в качестве видеодрайвера.

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

Targitai пишет:

Аднака на хочет, чтоб его! Напряжение подавал, ессно. Я эту схему скоро по среди ночи с закрытими глазами уже собирать буду....

могу только предположить, что на меге к-лайн повесил на софтсериал 7,8 (софтсериал на 7,8 на меге не пашет). А если на меге Сериал3 у меня всё работает. скетч диаг #1325 и эмуль #1205