Вопрос по ISO-14230-4

Aku
Offline
Зарегистрирован: 04.12.2018

Добрый день. Есть автомобиль VW. Хочу считать данные по температуре с K-line. При запросе получил 55h 6Bh 8Fh. Как выполнить инициализацию?

Aku
Offline
Зарегистрирован: 04.12.2018

http://arduino.ru/forum/apparatnye-voprosy/mc-33290-i-k-line-adapter-vop... вот с этим скетчем я получил ответ 55h 6Bh 8Fh.

Aku
Offline
Зарегистрирован: 04.12.2018

В общем понял, что нужно в ответ отправить инвертированный 2й байт и  получить в ответ инвертированный 33h.

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

верно мыслите. 55h это синхробайт  6Bh и 8Fh это keyword 1 и keyword 2. отправляете на эбу инвертированный 8Fh это 70h и инициализация будет закончена. 

Aku
Offline
Зарегистрирован: 04.12.2018

Спасибо MaksVV. От Вас и хотел услышать ответ. На базе вашего третьего скетча http://arduino.ru/forum/apparatnye-voprosy/mc-33290-i-k-line-adapter-vop... сделал свой.

#include <SoftwareSerial.h>

SoftwareSerial mySerial(2, 3); //Rx,Tx
#define TX 3

unsigned long prevTimedelay = 0;
int Delay = 0;

byte ECUaddress = 0x01;   // адрес блока двигателя, можно попробовать с другими адресами

void setup() {
  Serial.begin (115200);
  Serial.println(F("---KWP 5 baud init"));
  delay (500);
  pinMode (TX, OUTPUT);
  digitalWrite (TX, HIGH); // BUS IDLE
  delay (500);
 
  send5baud(ECUaddress); // функция отправки адреса блоку
  mySerial.begin (10400);
}

void loop() {

  if (mySerial.available()) {
    delay (20) // W2(51)
    unsigned long curTimedelay = millis ();
    Delay = curTimedelay-prevTimedelay;
    Serial.println ("");
    Serial.print(Delay);
    Serial.println ("ms");
    prevTimedelay = millis();  
    while(mySerial.available()) {
        byte inByte = mySerial.read();
        if (inByte == 0x8F) mySerial.write(0x70); // если получили 8F, то отправили инверсию
        Serial.print(" ");
        Serial.print(inByte,HEX);
    }      
  }
}

//ниже отправка блоку байта адреса на 5бод  1 стартбит, 7бит данных, 1 бит проверки четности odd, 1 стоп бит

void send5baud(uint8_t data){              
  // // 1 start bit, 7 data bits, 1 parity, 1 stop bit
  #define bitcount 10
  byte bits[bitcount];
  byte even=1;
  byte bit;
  for (int i=0; i < bitcount; i++) {
    bit=0;
    if (i == 0)  bit = 0;
      else if (i == 8) bit = even; // computes parity bit
      else if (i == 9) bit = 1;
      else {
        bit = (byte) ((data & (1 << (i-1))) != 0);
        even = even ^ bit;
      }
    Serial.print(F("bit"));      
    Serial.print(i);          
    Serial.print(F("="));              
    Serial.print(bit);
    if (i == 0) Serial.print(F(" startbit"));
      else if (i == 8) Serial.print(F(" parity"));    
      else if (i == 9) Serial.print(F(" stopbit"));              
    Serial.println();      
    bits[i]=bit;
  }
  // now send bit stream    
  for (int i=0; i < bitcount+1; i++) {
    if (i != 0) {
      delay(200);// wait 200 ms (=5 baud), adjusted by latency correction
      if (i == bitcount) break;
    }
    if (bits[i] == 1) { // high    
      digitalWrite(TX, HIGH);
    } else { // low    
      digitalWrite(TX, LOW);
    }
  }
  mySerial.flush();
}

незнаю как код вставить по нормальному.
 

Aku
Offline
Зарегистрирован: 04.12.2018

А как мне теперь захватить данные?

Aku
Offline
Зарегистрирован: 04.12.2018

https://www.drive2.ru/c/479335393737572613/

Вот здесь есть что то похожее, но я не уверен что для меня это подойдет.

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

для начала вставляем скетч правильно. Лучше использовать скетч Александра (немец вроде он). Там уже реализовано считываение ваговских блоков данных. 

/*
Arduino Nano OBD reader (OBD protocol KW1281,  Audi A4 B5 etc.)

wiring:
D2 --- OBD level shifter input (RX) (e.g. LM339)
D3 --- OBD level shifter output (TX) (e.g. LM339)
A5 --- Arduino 20x4 LCD display SCL
A4 --- Arduino 20x4 LCD display SDA

NOTE: For the level shifting, I used a 'AutoDia K409 Profi USB adapter', disassembled it,
      and connected the Arduino to the level shifter chip (LM339) - the original FTDI chip TX line
      was removed (so it does not influence the communication)                                                                                              
*/

#include <Wire.h>
#include "LiquidCrystal_I2C.h"
#include "NewSoftwareSerial.h"

#define pinKLineRX 2
#define pinKLineTX 3
#define pinLED 13
#define pinBuzzer 9
#define pinButton 5


// <a href="https://www.blafusel.de/obd/obd2_kw1281.html" rel="nofollow">https://www.blafusel.de/obd/obd2_kw1281.html</a>

#define ADR_Engine 0x01
#define ADR_Gears  0x02
#define ADR_ABS_Brakes 0x03
#define ADR_Airbag 0x15
#define ADR_Dashboard 0x17
#define ADR_Immobilizer 0x25
#define ADR_Central_locking 0x35

//#define DEBUG 1

LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x20 for a 16 chars and 2 line display
NewSoftwareSerial obd(pinKLineRX, pinKLineTX, false); // RX, TX, inverse logic

uint8_t currAddr = 0;
uint8_t blockCounter = 0;
uint8_t errorTimeout = 0;
uint8_t errorData = 0;
bool connected = false;
int sensorCounter = 0;
int pageUpdateCounter = 0;
int alarmCounter = 0;

uint8_t currPage = 2;


int8_t coolantTemp = 0;
int8_t oilTemp = 0;
int8_t intakeAirTemp = 0;
int8_t oilPressure = 0;
float engineLoad = 0;
int   engineSpeed = 0;
float throttleValve = 0;
float supplyVoltage = 0;
uint8_t vehicleSpeed = 0;
uint8_t fuelConsumption = 0;
uint8_t fuelLevel = 0;
unsigned long odometer = 0;

// наши параметры
int TurboPressure = 0;
int TurboPressure_target = 0;
uint8_t Turbocharger_valve = 0;
uint8_t EGR_duty = 0;
int EGR_Consumption = 0;
int EGR_Consumption_target = 0;



String floatToString(float v){
  String res; 
  char buf[16];      
  dtostrf(v,4, 2, buf); 
  res=String(buf);
  return res;
}

void disconnect(){
  connected = false;
  currAddr = 0;
}

void lcdPrint(int x, int y, String s, int width = 0){
  lcd.setCursor(x,y);
  while (s.length() < width) s += " ";
  lcd.print(s);
}

void obdWrite(uint8_t data){
#ifdef DEBUG
  Serial.print("uC:");
  Serial.println(data, HEX);
#endif
  obd.write(data);
}

uint8_t obdRead(){
  unsigned long timeout = millis() + 1000;  
  while (!obd.available()){
    if (millis() >= timeout) {
      Serial.println(F("ERROR: obdRead timeout"));
      disconnect();      
      errorTimeout++;
      return 0;
    }
  }
  uint8_t data = obd.read();
#ifdef DEBUG  
  Serial.print("ECU:");
  Serial.println(data, HEX);
#endif  
  return data;
}

// 5Bd, 7O1
void send5baud(uint8_t data){
  // // 1 start bit, 7 data bits, 1 parity, 1 stop bit
  #define bitcount 10
  byte bits[bitcount];
  byte even=1;
  byte bit;
  for (int i=0; i < bitcount; i++){
    bit=0;
    if (i == 0)  bit = 0;
      else if (i == 8) bit = even; // computes parity bit
      else if (i == 9) bit = 1;
      else {
        bit = (byte) ((data & (1 << (i-1))) != 0);
        even = even ^ bit;
      }
    Serial.print(F("bit"));      
    Serial.print(i);          
    Serial.print(F("="));              
    Serial.print(bit);
    if (i == 0) Serial.print(F(" startbit"));
      else if (i == 8) Serial.print(F(" parity"));    
      else if (i == 9) Serial.print(F(" stopbit"));              
    Serial.println();      
    bits[i]=bit;
  }
  // now send bit stream    
  for (int i=0; i < bitcount+1; i++){
    if (i != 0){
      // wait 200 ms (=5 baud), adjusted by latency correction
      delay(200);
      if (i == bitcount) break;
    }
    if (bits[i] == 1){ 
      // high
      digitalWrite(pinKLineTX, HIGH);
    } else {
      // low
      digitalWrite(pinKLineTX, LOW);
    }
  }
  obd.flush();
}


bool KWP5BaudInit(uint8_t addr){
  Serial.println(F("---KWP 5 baud init"));
  //delay(3000);
  send5baud(addr);
  return true;
}


bool KWPSendBlock(char *s, int size){
  Serial.print(F("---KWPSend sz="));
  Serial.print(size);
  Serial.print(F(" blockCounter="));
  Serial.println(blockCounter);    
  // show data
  Serial.print(F("OUT:"));
  for (int i=0; i < size; i++){    
    uint8_t data = s[i];
    Serial.print(data, HEX);
    Serial.print(" ");    
  }  
  Serial.println();
  for (int i=0; i < size; i++){
    uint8_t data = s[i];    
    obdWrite(data);
    /*uint8_t echo = obdRead();  
    if (data != echo){
      Serial.println(F("ERROR: invalid echo"));
      disconnect();
      errorData++;
      return false;
    }*/
    if (i < size-1){
      uint8_t complement = obdRead();        
      if (complement != (data ^ 0xFF)){
        Serial.println(F("ERROR: invalid complement"));
        disconnect();
        errorData++;
        return false;
      }
    }
  }
  blockCounter++;
  return true;
}

// count: if zero given, first received byte contains block length
// 4800, 9600 oder 10400 Baud, 8N1
bool KWPReceiveBlock(char s[], int maxsize, int &size){  
  bool ackeachbyte = false;
  uint8_t data = 0;
  int recvcount = 0;
  if (size == 0) ackeachbyte = true;
  Serial.print(F("---KWPReceive sz="));
  Serial.print(size);
  Serial.print(F(" blockCounter="));
  Serial.println(blockCounter);
  if (size > maxsize) {
    Serial.println("ERROR: invalid maxsize");
    return false;
  }  
  unsigned long timeout = millis() + 1000;  
  while ((recvcount == 0) || (recvcount != size)) {
    while (obd.available()){      
      data = obdRead();
      s[recvcount] = data;    
      recvcount++;      
      if ((size == 0) && (recvcount == 1)) {
        size = data + 1;
        if (size > maxsize) {
          Serial.println("ERROR: invalid maxsize");
          return false;
        }  
      }
      if ((ackeachbyte) && (recvcount == 2)) {
        if (data != blockCounter){
          Serial.println(F("ERROR: invalid blockCounter"));
          disconnect();
          errorData++;
          return false;
        }
      }
      if ( ((!ackeachbyte) && (recvcount == size)) ||  ((ackeachbyte) && (recvcount < size)) ){
        obdWrite(data ^ 0xFF);  // send complement ack        
        /*uint8_t echo = obdRead();        
        if (echo != (data ^ 0xFF)){
          Serial.print(F("ERROR: invalid echo "));
          Serial.println(echo, HEX);
          disconnect();
          errorData++;
          return false;
        }*/
      }
      timeout = millis() + 1000;        
    } 
    if (millis() >= timeout){
      Serial.println(F("ERROR: timeout"));
      disconnect();
      errorTimeout++;
      return false;
    }
  }
  // show data
  Serial.print(F("IN: sz="));  
  Serial.print(size);  
  Serial.print(F(" data="));  
  for (int i=0; i < size; i++){
    uint8_t data = s[i];
    Serial.print(data, HEX);
    Serial.print(F(" "));    
  }  
  Serial.println();
  blockCounter++;
  return true;
}

bool KWPSendAckBlock(){
  Serial.print(F("---KWPSendAckBlock blockCounter="));
  Serial.println(blockCounter);  
  char buf[32];  
  sprintf(buf, "\x03%c\x09\x03", blockCounter);  
  return (KWPSendBlock(buf, 4));
}

bool connect(uint8_t addr, int baudrate){  
  Serial.print(F("------connect addr="));
  Serial.print(addr);
  Serial.print(F(" baud="));  
  Serial.println(baudrate);  
  tone(pinBuzzer, 1200);    
  delay(100);
  noTone(pinBuzzer);            
  //lcd.clear();
  lcdPrint(0,0, F("KW1281 wakeup"), 20);
  lcdPrint(0,1, "", 20);
  lcdPrint(0,2, "", 20);  
  blockCounter = 0;  
  currAddr = 0;
  obd.begin(baudrate);       
  KWP5BaudInit(addr);
  // answer: 0x55, 0x01, 0x8A          
  char s[3];
  lcdPrint(0,0, F("KW1281 recv"), 20);
  int size = 3;
  if (!KWPReceiveBlock(s, 3, size)) return false;
  if (    (((uint8_t)s[0]) != 0x55) 
     ||   (((uint8_t)s[1]) != 0x6B) 
     ||   (((uint8_t)s[2]) != 0x8F)   ){
    Serial.println(F("ERROR: invalid magic"));
    disconnect();
    errorData++;
    return false;
  }
  currAddr = addr;
  connected = true;  
  if (!readConnectBlocks()) return false;
  return true;
}
  
bool readConnectBlocks(){  
  // read connect blocks
  Serial.println(F("------readconnectblocks"));
  lcdPrint(0,0, F("KW1281 label"), 20);
  String info;  
  while (true){
    int size = 0;
    char s[64];
    if (!(KWPReceiveBlock(s, 64, size))) return false;
    if (size == 0) return false;
    if (s[2] == '\x09') break; 
    if (s[2] != '\xF6') {
      Serial.println(F("ERROR: unexpected answer"));
      disconnect();
      errorData++;
      return false;
    }
    String text = String(s);
    info += text.substring(3, size-2);
    if (!KWPSendAckBlock()) return false;
  }
  Serial.print("label=");
  Serial.println(info);
  //lcd.setCursor(0, 1);
  //lcd.print(info);      
  return true;
}

bool readSensors(int group){
  Serial.print(F("------readSensors "));
  Serial.println(group);
  lcdPrint(0,0, F("KW1281 sensor"), 20);  
  char s[64];
  sprintf(s, "\x04%c\x29%c\x03", blockCounter, group);
  if (!KWPSendBlock(s, 5)) return false;
  int size = 0;
  KWPReceiveBlock(s, 64, size);
  if (s[2] != '\xe7') {
    Serial.println(F("ERROR: invalid answer"));
    disconnect();
    errorData++;
    return false;
  }
  int count = (size-4) / 3;
  Serial.print(F("count="));
  Serial.println(count);
  for (int idx=0; idx < count; idx++){
    byte k=s[3 + idx*3];
    byte a=s[3 + idx*3+1];
    byte b=s[3 + idx*3+2];
    String n;
    float v = 0;
    Serial.print(F("type="));
    Serial.print(k);
    Serial.print(F("  a="));
    Serial.print(a);
    Serial.print(F("  b="));
    Serial.print(b);
    Serial.print(F("  text="));
    String t = "";
    String units = "";
    char buf[32];    
    switch (k){
      case 0x01:  v=0.2*a*b;             units=F("rpm"); break;
      case 0x02:  v=a*0.002*b;           units=F("%%"); break;
      case 0x03:  v=0.002*a*b;           units=F("Deg"); break;
      case 0x04:  v=abs(b-127)*0.01*a;   units=F("ATDC"); break;
      case 0x05:  v=a*(b-100)*0.1;       units=F("°C");break;
      case 0x06:  v=0.001*a*b;           units=F("V");break;
      case 0x07:  v=0.01*a*b;            units=F("km/h");break;
      case 0x08:  v=0.1*a*b;             units=F(" ");break;
      case 0x09:  v=(b-127)*0.02*a;      units=F("Deg");break;
      case 0x0A: if (b == 0) t=F("COLD"); else t=F("WARM");break;
      case 0x0B: v=0.0001*a*(b-128)+1;  units = F(" ");break;
      case 0x0C: v=0.001*a*b;           units =F("Ohm");break;
      case 0x0D: v=(b-127)*0.001*a;     units =F("mm");break;
      case 0x0E: v=0.005*a*b;           units=F("bar");break;
      case 0x0F: v=0.01*a*b;            units=F("ms");break;
      case 0x12: v=0.04*a*b;            units=F("mbar");break;
      case 0x13: v=a*b*0.01;            units=F("l");break;
      case 0x14: v=a*(b-128)/128;       units=F("%%");break;
      case 0x15: v=0.001*a*b;           units=F("V");break;
      case 0x16: v=0.001*a*b;           units=F("ms");break;
      case 0x17: v=(b*a)/256;             units=F("%%");break;
      case 0x18: v=0.001*a*b;           units=F("A");break;
      case 0x19: v=(b*1.421)+(a/182);   units=F("g/s");break;
      case 0x1A: v=float(b-a);          units=F("C");break;
      case 0x1B: v=abs(b-128)*0.01*a;   units=F("°");break;
      case 0x1C: v=float(b-a);          units=F(" ");break;
      case 0x1E: v=b/12*a;              units=F("Deg k/w");break;
      case 0x1F: v=b/2560*a;            units=F("°C");break;
      case 0x21: v=100*b/a;             units=F("%%");break;
      case 0x22: v=(b-128)*0.01*a;      units=F("kW");break;
      case 0x23: v=0.01*a*b;            units=F("l/h");break;
      case 0x24: v=((unsigned long)a)*2560+((unsigned long)b)*10;  units=F("km");break;
      case 0x25: v=b; break; // oil pressure ?!
      // ADP: FIXME!
      /*case 37: switch(b){
             case 0: sprintf(buf, F("ADP OK (%d,%d)"), a,b); t=String(buf); break;
             case 1: sprintf(buf, F("ADP RUN (%d,%d)"), a,b); t=String(buf); break;
             case 0x10: sprintf(buf, F("ADP ERR (%d,%d)"), a,b); t=String(buf); break;
             default: sprintf(buf, F("ADP (%d,%d)"), a,b); t=String(buf); break;
          }*/
      case 0x26: v=(b-128)*0.001*a;        units=F("Deg k/w"); break;
      case 0x27: v=b/256*a;                units=F("mg/h"); break;
      case 0x28: v=b*0.1+(25.5*a)-400;     units=F("A"); break;
      case 0x29: v=b+a*255;                units=F("Ah"); break;
      case 0x2A: v=b*0.1+(25.5*a)-400;     units=F("Kw"); break;
      case 0x2B: v=b*0.1+(25.5*a);         units=F("V"); break;
      case 0x2C: sprintf(buf, "%2d:%2d", a,b); t=String(buf); break;
      case 0x2D: v=0.1*a*b/100;            units=F(" "); break;
      case 0x2E: v=(a*b-3200)*0.0027;      units=F("Deg k/w"); break;
      case 0x2F: v=(b-128)*a;              units=F("ms"); break;
      case 0x30: v=b+a*255;                units=F(" "); break;
      case 0x31: v=(b/4)*a*0.1;            units=F("mg/h"); break;
      case 0x32: v=(b-128)/(0.01*a);       units=F("mbar"); break;
      case 0x33: v=((b-128)/255)*a;        units=F("mg/h"); break;
      case 0x34: v=b*0.02*a-a;             units=F("Nm"); break;
      case 0x35: v=(b-128)*1.4222+0.006*a;  units=F("g/s"); break;
      case 0x36: v=a*256+b;                units=F("count"); break;
      case 0x37: v=a*b/200;                units=F("s"); break;
      case 0x38: v=a*256+b;                units=F("WSC"); break;
      case 0x39: v=a*256+b+65536;          units=F("WSC"); break;
     
      case 0x3B: v=(a*256+b)/32768;        units=F("g/s"); break;
      case 0x3C: v=(a*256+b)*0.01;         units=F("sec"); break;
      case 0x3E: v=0.256*a*b;              units=F("S"); break;
      case 0x40: v=float(a+b);             units=F("Ohm"); break;
      case 0x41: v=0.01*a*(b-127);         units=F("mm"); break;
      case 0x42: v=(a*b)/511.12;          units=F("V"); break;
      case 0x43: v=(640*a)+b*2.5;         units=F("Deg"); break;
      case 0x44: v=(256*a+b)/7.365;       units=F("deg/s");break;
      case 0x45: v=(256*a +b)*0.3254;     units=F("Bar");break;
      case 0x46: v=(256*a +b)*0.192;      units=F("m/s^2");break;
      default: sprintf(buf, "%2x, %2x      ", a, b); break;
    }
    
    switch (currAddr){
      case ADR_Engine: 
        switch(group){
          case 3: 
            switch (idx){
              case 0: engineSpeed = v; break;
              case 1: EGR_Consumption_target =v; break;
              case 2: EGR_Consumption=v; break;
              case 3: EGR_duty=v; break;
            }              
            break;
          case 11: 
            switch (idx){
              case 0: engineSpeed = v; break;
              case 1: TurboPressure_target =v; break;
              case 2: TurboPressure =v; break;
              case 3: Turbocharger_valve=v; break;
            }              
            break;
        }
        break;
      case ADR_Dashboard: 
        switch (group){ 
          case 1:  
            switch (idx){
              case 0: vehicleSpeed = v; break;
              case 1: engineSpeed = v; break;
              case 2: oilPressure = v; break;
            }
            break;
          case 2:
            switch (idx){
              case 0: odometer = v; break;
              case 1: fuelLevel = v; break;         
            }
            break;
          case 50:
            switch (idx){
              case 1: engineSpeed = v; break;
              case 2: oilTemp = v; break;
              case 3: coolantTemp = v; break;
            }
            break;
        }
        break;
    }
    if (units.length() != 0){
      dtostrf(v,4, 2, buf); 
      t=String(buf) + " " + units;
    }          
    Serial.println(t);
    
    //lcd.setCursor(0, idx);      
    //while (t.length() < 20) t += " ";
    //lcd.print(t);      
  }
  sensorCounter++;
  return true;
}

void alarm(){
  if (alarmCounter > 10) return;
  tone(pinBuzzer, 1200);    
  delay(100);
  noTone(pinBuzzer);   
  alarmCounter++;
}

void updateDisplay(){
  if (!connected){
    if ( (errorTimeout != 0) || (errorData != 0) ){
      lcdPrint(0,3, F("err to="));      
      lcdPrint(7,3, String(errorTimeout), 3);
      lcdPrint(10,3, F(" da="));      
      lcdPrint(14,3, String(errorData), 6);
    }
  } else {
    switch (currPage){
      case 1:      
        if (coolantTemp > 99){
          lcdPrint(0,1, F("COOL"));          
          alarm();          
        } else lcdPrint(0,1, F("cool"));
        lcdPrint(6,1,String(coolantTemp),3);                
        if ( (oilTemp > 99) || ((oilPressure != 30) && (oilPressure != 31)) ){          
          lcdPrint(10,1,F("OIL "));
          alarm();
        } else lcdPrint(10,1,F("oil "));        
        lcdPrint(14,1,String(oilPressure),3);        
        lcdPrint(0,2, F("rpm "));
        lcdPrint(4,2, String(engineSpeed),4);        
        lcdPrint(10,2, F("km/h "));
        lcdPrint(15,2, String(vehicleSpeed, 3));        
        lcdPrint(0,3, F("fuel "));
        lcdPrint(5,3, String(fuelLevel),3);        
        lcdPrint(10,3, F("odo "));
        lcdPrint(14,3, String(odometer),6);                        
        break;
      case 2:
        if (coolantTemp > 99){
          lcdPrint(0,1, F("COOL"));          
          alarm();          
        } else lcdPrint(0,1, F("cool"));
        lcdPrint(6,1,String(coolantTemp),3);                    
        lcdPrint(10,1, F("air "));          
        lcdPrint(14,1, String(intakeAirTemp), 3);                  
        lcdPrint(0,2, F("rpm "));
        lcdPrint(4,2, String(engineSpeed),4);        
        lcdPrint(10,2, F("km/h "));
        lcdPrint(15,2, String(vehicleSpeed, 3));                
        lcdPrint(0,3, F("fuel "));
        lcdPrint(5,3, String(fuelConsumption),3);                
        lcdPrint(10,3, F("volt "));
        lcdPrint(15,3, String(supplyVoltage),5);                                        
        break;
    }    
  }
  pageUpdateCounter++;
}

void setup(){      
  lcd.init();  
  lcd.backlight();      
  lcd.init();  
    
  pinMode(pinKLineTX, OUTPUT);  
  digitalWrite(pinKLineTX, HIGH);  
  
  pinMode(pinButton, INPUT);  
  pinMode(pinButton, INPUT_PULLUP);  
  
  pinMode(pinBuzzer, OUTPUT);
  /*tone(pinBuzzer, 1200);    
  delay(100);
  noTone(pinBuzzer);*/
  
  Serial.begin(19200);  
  Serial.println(F("SETUP"));            
        
  Serial.println(F("START"));       
}


void loop(){    
  
  if (digitalRead(pinButton) == LOW){    
    currPage++;
    if (currPage > 2) currPage = 1;
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(F("page "));    
    lcd.print(currPage);    
    errorTimeout = 0;
    errorData = 0;            
    while (digitalRead(pinButton) == LOW);        
  }

  switch (currPage){
    case 1:      
      if (currAddr != ADR_Dashboard){        
        connect(ADR_Dashboard, 9600);
      } else  {
        readSensors(1);
        readSensors(2);
        readSensors(50);        
      }      
      break;
    case 2:
      if (currAddr != ADR_Engine) {
        connect(ADR_Engine, 9600);
      } else {
        readSensors(3);
        readSensors(11);
      }    
      break;   
  }        
  
  updateDisplay(); 

Serial.println();
Serial.print ("engineSpeed:  "); Serial.println(engineSpeed);
Serial.print ("EGR valve :  "); Serial.println(EGR_duty);
Serial.print ("EGR rashod  "); Serial.println(EGR_Consumption);
Serial.print ("EGR rashod zadan:  "); Serial.println(EGR_Consumption_target);
Serial.print ("Pressure Turbo:  "); Serial.println(TurboPressure);
Serial.print ("Pressure Turbo zadan:  "); Serial.println(TurboPressure_target);
Serial.print ("Turbo Actuator:  "); Serial.println(Turbocharger_valve);
Serial.println();


 
       
}




 

Aku
Offline
Зарегистрирован: 04.12.2018

Спасибо MaksVV. Вечером попробую. Отпишусь.

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

а скорость к-лайн у вас 10400 смотрю? это точно? 

Aku
Offline
Зарегистрирован: 04.12.2018

Я пробовал 4800, 9600, 10400. Синхро байт 55h получил на 10400. Предположил что протокол ISO14230-4.

Aku
Offline
Зарегистрирован: 04.12.2018

​
/*
Arduino Nano OBD reader (OBD protocol KW1281,  Audi A4 B5 etc.)

wiring:
D2 --- OBD level shifter input (RX) (e.g. LM339)
D3 --- OBD level shifter output (TX) (e.g. LM339)
A5 --- Arduino 20x4 LCD display SCL
A4 --- Arduino 20x4 LCD display SDA

NOTE: For the level shifting, I used a 'AutoDia K409 Profi USB adapter', disassembled it,
      and connected the Arduino to the level shifter chip (LM339) - the original FTDI chip TX line
      was removed (so it does not influence the communication)                                                                                              
*/

///#include <Wire.h>
///#include "LiquidCrystal_I2C.h"
///#include "NewSoftwareSerial.h"
#include <SoftwareSerial.h>

#define pinKLineRX 2
#define pinKLineTX 3
// #define pinLED 13
// #define pinBuzzer 9
 #define pinButton 5

// <a href="<a href="https://www.blafusel.de/obd/obd2_kw1281.html" rel="nofollow">https://www.blafusel.de/obd/obd2_kw1281.html</a>" rel="nofollow"><a href="https://www.blafusel.de/obd/obd2_kw1281.html" rel="nofollow">https://www.blafusel.de/obd/obd2_kw1281.html</a></a>

#define ADR_Engine 0x01
/// #define ADR_Gears  0x02
/// #define ADR_ABS_Brakes 0x03
/// #define ADR_Airbag 0x15
#define ADR_Dashboard 0x17
/// #define ADR_Immobilizer 0x25
/// #define ADR_Central_locking 0x35

//#define DEBUG 1

///LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x20 for a 16 chars and 2 line display
///NewSoftwareSerial obd(pinKLineRX, pinKLineTX, false); // RX, TX, inverse logic
SoftwareSerial obd(pinKLineRX, pinKLineTX); // RX, TX

uint8_t currAddr = 0;
uint8_t blockCounter = 0;
uint8_t errorTimeout = 0;
uint8_t errorData = 0;
bool connected = false;
int sensorCounter = 0;
int pageUpdateCounter = 0;
int alarmCounter = 0;

uint8_t currPage = 2;

int8_t coolantTemp = 0;
int8_t oilTemp = 0;
int8_t intakeAirTemp = 0;
int8_t oilPressure = 0;
float engineLoad = 0;
int   engineSpeed = 0;
float throttleValve = 0;
float supplyVoltage = 0;
uint8_t vehicleSpeed = 0;
uint8_t fuelConsumption = 0;
uint8_t fuelLevel = 0;
unsigned long odometer = 0;

// наши параметры
/// int TurboPressure = 0;
/// int TurboPressure_target = 0;
/// uint8_t Turbocharger_valve = 0;
/// uint8_t EGR_duty = 0;
/// int EGR_Consumption = 0;
/// int EGR_Consumption_target = 0;

String floatToString(float v) {
  String res; 
  char buf[16];      
  dtostrf(v,4, 2, buf); 
  res=String(buf);
  return res;
}

void disconnect() {
  connected = false;
  currAddr = 0;
}

/*
void lcdPrint(int x, int y, String s, int width = 0){
  lcd.setCursor(x,y);
  while (s.length() < width) s += " ";
  lcd.print(s);
}
*/

void obdWrite(uint8_t data) {
#ifdef DEBUG
  Serial.print("uC:");
  Serial.println(data, HEX);
#endif
  obd.write(data);
}

uint8_t obdRead() {
  unsigned long timeout = millis() + 1000;  
  while (!obd.available()){
    if (millis() >= timeout) {
      Serial.println(F("ERROR: obdRead timeout"));
      disconnect();      
      errorTimeout++;
      return 0;
    }
  }
  uint8_t data = obd.read();
#ifdef DEBUG  
  Serial.print("ECU:");
  Serial.println(data, HEX);
#endif  
  return data;
}

// 5Bd, 7O1
void send5baud(uint8_t data) {
  // // 1 start bit, 7 data bits, 1 parity, 1 stop bit
  #define bitcount 10
  byte bits[bitcount];
  byte even=1;
  byte bit;
  for (int i=0; i < bitcount; i++){
    bit=0;
    if (i == 0)  bit = 0;
      else if (i == 8) bit = even; // computes parity bit
      else if (i == 9) bit = 1;
      else {
        bit = (byte) ((data & (1 << (i-1))) != 0);
        even = even ^ bit;
      }
    Serial.print(F("bit"));      
    Serial.print(i);          
    Serial.print(F("="));              
    Serial.print(bit);
    if (i == 0) Serial.print(F(" startbit"));
      else if (i == 8) Serial.print(F(" parity"));    
      else if (i == 9) Serial.print(F(" stopbit"));              
    Serial.println();      
    bits[i]=bit;
  }
  // now send bit stream    
  for (int i=0; i < bitcount+1; i++){
    if (i != 0){
      // wait 200 ms (=5 baud), adjusted by latency correction
      delay(200);
      if (i == bitcount) break;
    }
    if (bits[i] == 1){ 
      // high
      digitalWrite(pinKLineTX, HIGH);
    } else {
      // low
      digitalWrite(pinKLineTX, LOW);
    }
  }
  obd.flush();
}

bool KWP5BaudInit(uint8_t addr) {
  Serial.println(F("---KWP 5 baud init"));
  //delay(3000);
  send5baud(addr);
  return true;
}

bool KWPSendBlock(char *s, int size) {
  Serial.print(F("---KWPSend sz="));
  Serial.print(size);
  Serial.print(F(" blockCounter="));
  Serial.println(blockCounter);    
  // show data
  Serial.print(F("OUT:"));
  for (int i=0; i < size; i++){    
    uint8_t data = s[i];
    Serial.print(data, HEX);
    Serial.print(" ");    
  }  
  Serial.println();
  for (int i=0; i < size; i++){
    uint8_t data = s[i];    
    obdWrite(data);
    /*uint8_t echo = obdRead();  
    if (data != echo){
      Serial.println(F("ERROR: invalid echo"));
      disconnect();
      errorData++;
      return false;
    }*/
    if (i < size-1){
      uint8_t complement = obdRead();        
      if (complement != (data ^ 0xFF)){
        Serial.println(F("ERROR: invalid complement"));
        disconnect();
        errorData++;
        return false;
      }
    }
  }
  blockCounter++;
  return true;
}

// count: if zero given, first received byte contains block length
// 4800, 9600 oder 10400 Baud, 8N1
bool KWPReceiveBlock(char s[], int maxsize, int &size){  
  bool ackeachbyte = false;
  uint8_t data = 0;
  int recvcount = 0;
  if (size == 0) ackeachbyte = true;
  Serial.print(F("---KWPReceive sz="));
  Serial.print(size);
  Serial.print(F(" blockCounter="));
  Serial.println(blockCounter);
  if (size > maxsize) {
    Serial.println("ERROR: invalid maxsize");
    return false;
  }  
  unsigned long timeout = millis() + 1000;  
  while ((recvcount == 0) || (recvcount != size)) {
    while (obd.available()){      
      data = obdRead();
      s[recvcount] = data;    
      recvcount++;      
      if ((size == 0) && (recvcount == 1)) {
        size = data + 1;
        if (size > maxsize) {
          Serial.println("ERROR: invalid maxsize");
          return false;
        }  
      }
      if ((ackeachbyte) && (recvcount == 2)) {
        if (data != blockCounter){
          Serial.println(F("ERROR: invalid blockCounter"));
          disconnect();
          errorData++;
          return false;
        }
      }
      if ( ((!ackeachbyte) && (recvcount == size)) ||  ((ackeachbyte) && (recvcount < size)) ){
        obdWrite(data ^ 0xFF);  // send complement ack        
        /*uint8_t echo = obdRead();        
        if (echo != (data ^ 0xFF)){
          Serial.print(F("ERROR: invalid echo "));
          Serial.println(echo, HEX);
          disconnect();
          errorData++;
          return false;
        }*/
      }
      timeout = millis() + 1000;        
    } 
    if (millis() >= timeout){
      Serial.println(F("ERROR: timeout"));
      disconnect();
      errorTimeout++;
      return false;
    }
  }
  // show data
  Serial.print(F("IN: sz="));  
  Serial.print(size);  
  Serial.print(F(" data="));  
  for (int i=0; i < size; i++){
    uint8_t data = s[i];
    Serial.print(data, HEX);
    Serial.print(F(" "));    
  }  
  Serial.println();
  blockCounter++;
  return true;
}

bool KWPSendAckBlock() {
  Serial.print(F("---KWPSendAckBlock blockCounter="));
  Serial.println(blockCounter);  
  char buf[32];  
  sprintf(buf, "\x03%c\x09\x03", blockCounter);  
  return (KWPSendBlock(buf, 4));
}

bool connect(uint8_t addr, int baudrate) {  
  Serial.print(F("------connect addr="));
  Serial.print(addr);
  Serial.print(F(" baud="));  
  Serial.println(baudrate);  
  /// tone(pinBuzzer, 1200);    
  delay(100);
  /// noTone(pinBuzzer);            
  //lcd.clear();
  /// lcdPrint(0,0, F("KW1281 wakeup"), 20);
  /// lcdPrint(0,1, "", 20);
  /// lcdPrint(0,2, "", 20);  
  blockCounter = 0;  
  currAddr = 0;
  obd.begin(baudrate);       
  KWP5BaudInit(addr);
  // answer: 0x55, 0x6B, 0x8F          
  char s[3];
  /// lcdPrint(0,0, F("KW1281 recv"), 20);
  int size = 3;
  if (!KWPReceiveBlock(s, 3, size)) return false;
  if (    (((uint8_t)s[0]) != 0x55) 
     ||   (((uint8_t)s[1]) != 0x6B) 
     ||   (((uint8_t)s[2]) != 0x8F)   ){
    Serial.println(F("ERROR: invalid magic"));
    disconnect();
    errorData++;
    return false;
  }
  currAddr = addr;
  connected = true;  
  if (!readConnectBlocks()) return false;
  return true;
}
  
bool readConnectBlocks() {  
  // read connect blocks
  Serial.println(F("------readconnectblocks"));
  /// lcdPrint(0,0, F("KW1281 label"), 20);
  String info;  
  while (true){
    int size = 0;
    char s[64];
    if (!(KWPReceiveBlock(s, 64, size))) return false;
    if (size == 0) return false;
    if (s[2] == '\x09') break; 
    if (s[2] != '\xF6') {
      Serial.println(F("ERROR: unexpected answer"));
      disconnect();
      errorData++;
      return false;
    }
    String text = String(s);
    info += text.substring(3, size-2);
    if (!KWPSendAckBlock()) return false;
  }
  Serial.print("label=");
  Serial.println(info);
  //lcd.setCursor(0, 1);
  //lcd.print(info);      
  return true;
}

bool readSensors(int group) {
  Serial.print(F("------readSensors "));
  Serial.println(group);
  /// lcdPrint(0,0, F("KW1281 sensor"), 20);  
  char s[64];
  sprintf(s, "\x04%c\x29%c\x03", blockCounter, group);
  if (!KWPSendBlock(s, 5)) return false;
  int size = 0;
  KWPReceiveBlock(s, 64, size);
  if (s[2] != '\xe7') {
    Serial.println(F("ERROR: invalid answer"));
    disconnect();
    errorData++;
    return false;
  }
  int count = (size-4) / 3;
  Serial.print(F("count="));
  Serial.println(count);
  for (int idx=0; idx < count; idx++){
    byte k=s[3 + idx*3];
    byte a=s[3 + idx*3+1];
    byte b=s[3 + idx*3+2];
    String n;
    float v = 0;
    Serial.print(F("type="));
    Serial.print(k);
    Serial.print(F("  a="));
    Serial.print(a);
    Serial.print(F("  b="));
    Serial.print(b);
    Serial.print(F("  text="));
    String t = "";
    String units = "";
    char buf[32];    
    switch (k){
      case 0x01:  v=0.2*a*b;             units=F("rpm"); break;
      case 0x02:  v=a*0.002*b;           units=F("%%"); break;
      case 0x03:  v=0.002*a*b;           units=F("Deg"); break;
      case 0x04:  v=abs(b-127)*0.01*a;   units=F("ATDC"); break;
      case 0x05:  v=a*(b-100)*0.1;       units=F("°C");break;
      case 0x06:  v=0.001*a*b;           units=F("V");break;
      case 0x07:  v=0.01*a*b;            units=F("km/h");break;
      case 0x08:  v=0.1*a*b;             units=F(" ");break;
      case 0x09:  v=(b-127)*0.02*a;      units=F("Deg");break;
      case 0x0A: if (b == 0) t=F("COLD"); else t=F("WARM");break;
      case 0x0B: v=0.0001*a*(b-128)+1;  units = F(" ");break;
      case 0x0C: v=0.001*a*b;           units =F("Ohm");break;
      case 0x0D: v=(b-127)*0.001*a;     units =F("mm");break;
      case 0x0E: v=0.005*a*b;           units=F("bar");break;
      case 0x0F: v=0.01*a*b;            units=F("ms");break;
      case 0x12: v=0.04*a*b;            units=F("mbar");break;
      case 0x13: v=a*b*0.01;            units=F("l");break;
      case 0x14: v=a*(b-128)/128;       units=F("%%");break;
      case 0x15: v=0.001*a*b;           units=F("V");break;
      case 0x16: v=0.001*a*b;           units=F("ms");break;
      case 0x17: v=(b*a)/256;             units=F("%%");break;
      case 0x18: v=0.001*a*b;           units=F("A");break;
      case 0x19: v=(b*1.421)+(a/182);   units=F("g/s");break;
      case 0x1A: v=float(b-a);          units=F("C");break;
      case 0x1B: v=abs(b-128)*0.01*a;   units=F("°");break;
      case 0x1C: v=float(b-a);          units=F(" ");break;
      case 0x1E: v=b/12*a;              units=F("Deg k/w");break;
      case 0x1F: v=b/2560*a;            units=F("°C");break;
      case 0x21: v=100*b/a;             units=F("%%");break;
      case 0x22: v=(b-128)*0.01*a;      units=F("kW");break;
      case 0x23: v=0.01*a*b;            units=F("l/h");break;
      case 0x24: v=((unsigned long)a)*2560+((unsigned long)b)*10;  units=F("km");break;
      case 0x25: v=b; break; // oil pressure ?!
      // ADP: FIXME!
      /*case 37: switch(b){
             case 0: sprintf(buf, F("ADP OK (%d,%d)"), a,b); t=String(buf); break;
             case 1: sprintf(buf, F("ADP RUN (%d,%d)"), a,b); t=String(buf); break;
             case 0x10: sprintf(buf, F("ADP ERR (%d,%d)"), a,b); t=String(buf); break;
             default: sprintf(buf, F("ADP (%d,%d)"), a,b); t=String(buf); break;
          }*/
      case 0x26: v=(b-128)*0.001*a;        units=F("Deg k/w"); break;
      case 0x27: v=b/256*a;                units=F("mg/h"); break;
      case 0x28: v=b*0.1+(25.5*a)-400;     units=F("A"); break;
      case 0x29: v=b+a*255;                units=F("Ah"); break;
      case 0x2A: v=b*0.1+(25.5*a)-400;     units=F("Kw"); break;
      case 0x2B: v=b*0.1+(25.5*a);         units=F("V"); break;
      case 0x2C: sprintf(buf, "%2d:%2d", a,b); t=String(buf); break;
      case 0x2D: v=0.1*a*b/100;            units=F(" "); break;
      case 0x2E: v=(a*b-3200)*0.0027;      units=F("Deg k/w"); break;
      case 0x2F: v=(b-128)*a;              units=F("ms"); break;
      case 0x30: v=b+a*255;                units=F(" "); break;
      case 0x31: v=(b/4)*a*0.1;            units=F("mg/h"); break;
      case 0x32: v=(b-128)/(0.01*a);       units=F("mbar"); break;
      case 0x33: v=((b-128)/255)*a;        units=F("mg/h"); break;
      case 0x34: v=b*0.02*a-a;             units=F("Nm"); break;
      case 0x35: v=(b-128)*1.4222+0.006*a;  units=F("g/s"); break;
      case 0x36: v=a*256+b;                units=F("count"); break;
      case 0x37: v=a*b/200;                units=F("s"); break;
      case 0x38: v=a*256+b;                units=F("WSC"); break;
      case 0x39: v=a*256+b+65536;          units=F("WSC"); break;
     
      case 0x3B: v=(a*256+b)/32768;        units=F("g/s"); break;
      case 0x3C: v=(a*256+b)*0.01;         units=F("sec"); break;
      case 0x3E: v=0.256*a*b;              units=F("S"); break;
      case 0x40: v=float(a+b);             units=F("Ohm"); break;
      case 0x41: v=0.01*a*(b-127);         units=F("mm"); break;
      case 0x42: v=(a*b)/511.12;          units=F("V"); break;
      case 0x43: v=(640*a)+b*2.5;         units=F("Deg"); break;
      case 0x44: v=(256*a+b)/7.365;       units=F("deg/s");break;
      case 0x45: v=(256*a +b)*0.3254;     units=F("Bar");break;
      case 0x46: v=(256*a +b)*0.192;      units=F("m/s^2");break;
      default: sprintf(buf, "%2x, %2x      ", a, b); break;
    }
    
    switch (currAddr){
      case ADR_Engine: 
        switch(group){
          case 3: 
            switch (idx){
              case 0: engineSpeed = v; break;
              /// case 1: EGR_Consumption_target =v; break;
              /// case 2: EGR_Consumption=v; break;
              /// case 3: EGR_duty=v; break;
            }              
            break;
          case 11: 
            switch (idx){
              case 0: engineSpeed = v; break;
              /// case 1: TurboPressure_target =v; break;
              /// case 2: TurboPressure =v; break;
              /// case 3: Turbocharger_valve=v; break;
            }              
            break;
        }
        break;
      case ADR_Dashboard: 
        switch (group){ 
          case 1:  
            switch (idx){
              case 0: vehicleSpeed = v; break;
              case 1: engineSpeed = v; break;
              case 2: oilPressure = v; break;
            }
            break;
          case 2:
            switch (idx){
              case 0: odometer = v; break;
              case 1: fuelLevel = v; break;         
            }
            break;
          case 50:
            switch (idx){
              case 1: engineSpeed = v; break;
              case 2: oilTemp = v; break;
              case 3: coolantTemp = v; break;
            }
            break;
        }
        break;
    }
    if (units.length() != 0){
      dtostrf(v,4, 2, buf); 
      t=String(buf) + " " + units;
    }          
    Serial.println(t);
    
    //lcd.setCursor(0, idx);      
    //while (t.length() < 20) t += " ";
    //lcd.print(t);      
  }
  sensorCounter++;
  return true;
}

/*
void alarm(){
  if (alarmCounter > 10) return;
  tone(pinBuzzer, 1200);    
  delay(100);
  noTone(pinBuzzer);   
  alarmCounter++;
}
*/
/*
void updateDisplay(){
  if (!connected){
    if ( (errorTimeout != 0) || (errorData != 0) ){
      lcdPrint(0,3, F("err to="));      
      lcdPrint(7,3, String(errorTimeout), 3);
      lcdPrint(10,3, F(" da="));      
      lcdPrint(14,3, String(errorData), 6);
    }
  } else {
    switch (currPage){
      case 1:      
        if (coolantTemp > 99){
          lcdPrint(0,1, F("COOL"));          
          alarm();          
        } else lcdPrint(0,1, F("cool"));
        lcdPrint(6,1,String(coolantTemp),3);                
        if ( (oilTemp > 99) || ((oilPressure != 30) && (oilPressure != 31)) ){          
          lcdPrint(10,1,F("OIL "));
          alarm();
        } else lcdPrint(10,1,F("oil "));        
        lcdPrint(14,1,String(oilPressure),3);        
        lcdPrint(0,2, F("rpm "));
        lcdPrint(4,2, String(engineSpeed),4);        
        lcdPrint(10,2, F("km/h "));
        lcdPrint(15,2, String(vehicleSpeed, 3));        
        lcdPrint(0,3, F("fuel "));
        lcdPrint(5,3, String(fuelLevel),3);        
        lcdPrint(10,3, F("odo "));
        lcdPrint(14,3, String(odometer),6);                        
        break;
      case 2:
        if (coolantTemp > 99){
          lcdPrint(0,1, F("COOL"));          
          alarm();          
        } else lcdPrint(0,1, F("cool"));
        lcdPrint(6,1,String(coolantTemp),3);                    
        lcdPrint(10,1, F("air "));          
        lcdPrint(14,1, String(intakeAirTemp), 3);                  
        lcdPrint(0,2, F("rpm "));
        lcdPrint(4,2, String(engineSpeed),4);        
        lcdPrint(10,2, F("km/h "));
        lcdPrint(15,2, String(vehicleSpeed, 3));                
        lcdPrint(0,3, F("fuel "));
        lcdPrint(5,3, String(fuelConsumption),3);                
        lcdPrint(10,3, F("volt "));
        lcdPrint(15,3, String(supplyVoltage),5);                                        
        break;
    }    
  }
  pageUpdateCounter++;
}
*/
void setup(){      
  /// lcd.init();  
  /// lcd.backlight();      
  /// lcd.init();  
    
  pinMode(pinKLineTX, OUTPUT);  
  digitalWrite(pinKLineTX, HIGH);  
  
  pinMode(pinButton, INPUT);  
  pinMode(pinButton, INPUT_PULLUP);  
  
 /// pinMode(pinBuzzer, OUTPUT);
  /*tone(pinBuzzer, 1200);    
  delay(100);
  noTone(pinBuzzer);*/
  
  Serial.begin(19200);  
  Serial.println(F("SETUP"));            
        
  Serial.println(F("START"));       
}


void loop(){    
  
  if (digitalRead(pinButton) == LOW) {    
    currPage++;
    if (currPage > 2) currPage = 1;
    /// lcd.clear();
    /// lcd.setCursor(0,0);
    /// lcd.print(F("page "));    
    /// lcd.print(currPage);    
    errorTimeout = 0;
    errorData = 0;            
    while (digitalRead(pinButton) == LOW);        
  }

  switch (currPage) {
    case 1:      
      if (currAddr != ADR_Dashboard){        
        connect(ADR_Dashboard, 10400);
      } else  {
        readSensors(1);
        readSensors(2);
        readSensors(50);        
      }      
      break;
    case 2:
      if (currAddr != ADR_Engine) {
        connect(ADR_Engine, 10400);
      } else {
        readSensors(3);
        readSensors(11);
      }    
      break;   
}        
  
/// updateDisplay(); 

Serial.println();
Serial.print ("engineSpeed:  "); Serial.println(engineSpeed);
/*
Serial.print ("EGR valve :  "); Serial.println(EGR_duty);
Serial.print ("EGR rashod  "); Serial.println(EGR_Consumption);
Serial.print ("EGR rashod zadan:  "); Serial.println(EGR_Consumption_target);
Serial.print ("Pressure Turbo:  "); Serial.println(TurboPressure);
Serial.print ("Pressure Turbo zadan:  "); Serial.println(TurboPressure_target);
Serial.print ("Turbo Actuator:  "); Serial.println(Turbocharger_valve);
*/
Serial.println();      
}





Aku
Offline
Зарегистрирован: 04.12.2018

Вот здесь есть немного описание. https://ru.scribd.com/document/388728618/1278519259-K-line-Communication...

Не совсем уверен, что код от Александра подойдет.

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

у вас есть рабочая диагностика, которая подключается к ЭБУ? Типа VAGcom или подобная? Если да, то нужно просниффить диагностическую сессиию и всё станет понятно какой там протокол

Aku
Offline
Зарегистрирован: 04.12.2018

К сожалению нет. Буду пытаться в слепую.

Вот еще нашел кое что https://www.instructables.com/id/Low-Cost-OBD2-Communications-on-K-line-ISO-9141-2-/

Там есть main. Принцип инициализации такой же.

Aku
Offline
Зарегистрирован: 04.12.2018

В общем останавливается на 

---KWPSend sz=3 blockCounter=0.

И заново

------ connect addr=1 baud=10400

179 строка.

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

ну так пробуем. 

#include <SoftwareSerial.h>

SoftwareSerial mySerial(2, 3); //Rx,Tx
#define TX 3

unsigned long prevTimedelay = 0;
int Delay = 0;

byte ECUaddress = 0x01;   // адрес блока двигателя, можно попробовать с другими адресами

byte initMes[] = {0x81, ECUaddress, 0xF1, 0x81, 0xF4};


void setup() {
  Serial.begin (115200);
  Serial.println(F("---KWP 5 baud init"));
  delay (500);
  pinMode (TX, OUTPUT);
  digitalWrite (TX, HIGH); // BUS IDLE
  delay (500);
 
  send5baud(ECUaddress); // функция отправки адреса блоку
  mySerial.begin (10400);
}

void loop() {

  if (mySerial.available()) {
    delay (20); // W2(51)
    unsigned long curTimedelay = millis ();
    Delay = curTimedelay-prevTimedelay;
    Serial.println ("");
    Serial.print(Delay);
    Serial.println ("ms");
    prevTimedelay = millis();  
    while(mySerial.available()) {
        byte inByte = mySerial.read();
        if (inByte == 0x8F) {mySerial.write(0x70); // если получили 8F, то отправили инверсию
        delay (20); 
         byte Checksum = 0;
        for (byte i = 0 ; i<sizeof(initMes); i++){ if (i!=sizeof(initMes)-1) Checksum+=initMes[i];
    else initMes[i] = Checksum;    mySerial.write (initMes[i]); delay (1);}
        
        }
        Serial.print(" ");
        Serial.print(inByte,HEX);
    }      
  }


  
}

//ниже отправка блоку байта адреса на 5бод  1 стартбит, 7бит данных, 1 бит проверки четности odd, 1 стоп бит

void send5baud(uint8_t data){              
  // // 1 start bit, 7 data bits, 1 parity, 1 stop bit
  #define bitcount 10
  byte bits[bitcount];
  byte even=1;
  byte bit;
  for (int i=0; i < bitcount; i++) {
    bit=0;
    if (i == 0)  bit = 0;
      else if (i == 8) bit = even; // computes parity bit
      else if (i == 9) bit = 1;
      else {
        bit = (byte) ((data & (1 << (i-1))) != 0);
        even = even ^ bit;
      }
    Serial.print(F("bit"));      
    Serial.print(i);          
    Serial.print(F("="));              
    Serial.print(bit);
    if (i == 0) Serial.print(F(" startbit"));
      else if (i == 8) Serial.print(F(" parity"));    
      else if (i == 9) Serial.print(F(" stopbit"));              
    Serial.println();      
    bits[i]=bit;
  }
  // now send bit stream    
  for (int i=0; i < bitcount+1; i++) {
    if (i != 0) {
      delay(200);// wait 200 ms (=5 baud), adjusted by latency correction
      if (i == bitcount) break;
    }
    if (bits[i] == 1) { // high    
      digitalWrite(TX, HIGH);
    } else { // low    
      digitalWrite(TX, LOW);
    }
  }
  mySerial.flush();
}

 

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

в строке 11 нулевой байт массива можно попробовать также сделать 0xC1

Aku
Offline
Зарегистрирован: 04.12.2018

первый вариант(самый первый)

 

---KWP 5 baud init
bit0=0 startbit
bit1=1
bit2=0
bit3=0
bit4=0
bit5=0
bit6=0
bit7=0
bit8=0 parity
bit9=1 stopbit
 
3137ms
 55 6B 8F FE
MaksVV
Offline
Зарегистрирован: 06.08.2015

строка 42 пробуем убрать delay (1). Также  строку 38 пробуем сделать такую 

 if (inByte == 0x8F) {delay (10); mySerial.write(0x70);

 

Aku
Offline
Зарегистрирован: 04.12.2018

Если сделать 0xC1, тогда и контрольную сумму пересчитать? 

Или ее здесь нет?

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

кстати байт FE это как раз удачный конец инициализации - эбу шлёт на диагностику (нам) свой инвертированный адрес. 01 в инверсии это FE

Aku
Offline
Зарегистрирован: 04.12.2018

значит первый байт 81 сработал?

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

нет, сработал отправленный байт 0х70, это инверсия на keyword 2. После удачного инита запрос {0x81, 0x01, 0xF1, 0x81, 0xF4}; не сработал. 

 

Aku
Offline
Зарегистрирован: 04.12.2018

Что я примерно должен получить?

 

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

можно также попробовать строку 11 сделать такую 

byte initMes[] = {0xC2, 0x01, 0xF1, 0x01, 0x00, 0xE7}

 

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

какие-нибудь байты в ответ если прилетят  то уже хорошо

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

КС в скетче сама подсчитывается, её исправлять в массиве сообщения не надо

Aku
Offline
Зарегистрирован: 04.12.2018

 

 

Нет ничего. Только когда добавил delay(10); ответ стал:

3137ms
 55 6B 8F
64ms
 FE

 

 

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

delay (1) пробовал убирать? 

Aku
Offline
Зарегистрирован: 04.12.2018
Если смотреть main который на PICе.

/*
 * File:   main.c
 * Author: RichardvdK
 *
 * Created on 5th of May 2016, 17:07
 */


#include <xc.h>
#include <stdio.h>
#define	_XTAL_FREQ 8000000
#include "delays.h"
#include "xlcd.h"



// CONFIG1
#pragma config FOSC = INTRC_NOCLKOUT// Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // RE3/MCLR pin function select bit (RE3/MCLR pin function is digital input, MCLR internally tied to VDD)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = ON       // Brown Out Reset Selection bits (BOR enabled)
#pragma config IESO = ON        // Internal External Switchover bit (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)
#pragma config LVP = OFF        // Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming)

// CONFIG2
#pragma config BOR4V = BOR40V   // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
#pragma config WRT = OFF        // Flash Program Memory Self Write Enable bits (Write protection off)


void tx(char *array, unsigned int size);

void main(void) {

    OSCCONbits.IRCF = 0b111;
    ANSEL = 0;
    ANSELH = 0;

    TRISC = 0b10000000;
    PORTC = 0b00000000;
    TRISB = 0b00000000;
    TRISA = 0b00000000;

    BAUDCTLbits.SCKP = 1;

    SYNC = 0;
    BRGH = 0;
    BRG16 = 0;
    SPBRG = 11;

    TXSTAbits.TXEN = 1;
    TXSTAbits.SYNC = 0;
    TXSTAbits.BRGH = 0;

    PIE1bits.RCIE = 1;
    INTCONbits.PEIE = 1;
    INTCONbits.GIE = 1;

    WDTCONbits.WDTPS = 0b0101;
    OPTION_REGbits.PSA = 1;


    __delay_ms(250);

    
    OpenXLCD(FOUR_BIT & LINES_5X7);
    while (BusyXLCD());
    WriteCmdXLCD(SHIFT_DISP_LEFT);
    while (BusyXLCD());
    putrsXLCD("start init");
    while (BusyXLCD());

    __delay_ms(2000);


    PORTCbits.RC6 = 1;
    __delay_ms(200);
    PORTCbits.RC6 = 0;
    __delay_ms(400);
    PORTCbits.RC6 = 1;
    __delay_ms(400);
    PORTCbits.RC6 = 0;
    __delay_ms(400);
    PORTCbits.RC6 = 1;
    __delay_ms(400);
    PORTCbits.RC6 = 0;



    RCSTAbits.SPEN = 1; //enable eusart
    RCSTAbits.CREN = 1; //receive enable


    WDTCONbits.SWDTEN = 1;

    int iso;
    while (RCIF == 0);
    char syncrr = RCREG;
    if (syncrr == 0x55) {
        while (RCIF == 0);
        char key1 = RCREG;
        while (RCIF == 0);
        char key2 = RCREG;
        __delay_ms(25);
        TXREG = ~key2;
        while (RCIF == 0);
        char clear = RCREG;
        while (RCIF == 0);
        char ready = RCREG;
        if (ready == 0xcc) {
            WriteCmdXLCD(0x01);
            while(BusyXLCD());
            __delay_ms(25);
            if (key1 == 0x08 && key2 == 0x08) {
                iso = 9141;
                putrsXLCD("ISO 9141-2");
                while (BusyXLCD());
                WriteCmdXLCD(0xC0);
                while(BusyXLCD());
                putrsXLCD("5-baud init OK");
                while (BusyXLCD());
            }
            if (key2 == 0x8f) {
                iso = 14230;
                putrsXLCD("ISO 14230-4 KWP");
                while (BusyXLCD());
                WriteCmdXLCD(0xC0);
                while(BusyXLCD());
                putrsXLCD("5-baud init OK");
                while (BusyXLCD());
            }
        }
    } else {
        WriteCmdXLCD(0x01);
        while(BusyXLCD());
        putrsXLCD("init failed");
        while(BusyXLCD());
    }

    WDTCONbits.SWDTEN = 0;




    __delay_ms(4000);

    
    WriteCmdXLCD(0x01);
    while(BusyXLCD());
    putrsXLCD("init failed");
    while(BusyXLCD());
    
    unsigned int counter = 0;


    PR2 = 0xff;

    CCP2CON = 0b00001100;

    CCPR2L = 0x00;
    CCPR2H = 0x00;

    TMR2IF = 0x00;

    PIR1 = 0x00;


    T2CONbits.T2CKPS = 0b11;
    T2CONbits.TMR2ON = 1;

//    CCP2CONbits.DC2B0 = counter;
//    CCP2CONbits.DC2B1 = (counter >> 1);
//    CCPR2L = (counter >> 2);
    CCPR2L = counter;
    
    WriteCmdXLCD(0x01);
    while(BusyXLCD());
    
    OPTION_REGbits.nRBPU=0;
    WPUBbits.WPUB0=1;
    TRISBbits.TRISB0 = 1;
    
    

    while(1) {

        WDTCONbits.SWDTEN = 1;

        char byteline1[];
        char byteline2[];
        char rx_buffer[8];
        __delay_ms(5);
        
        
        WriteCmdXLCD(0x80);
        while(BusyXLCD());
        putrsXLCD("CEL  T Speed RPM");
        while(BusyXLCD());
        
        WriteCmdXLCD(0xC0);
        while(BusyXLCD());

        

        if (iso == 9141) {
            const char CalculatedEngineLoad[] = {0x68, 0x6a, 0xf1, 0x01, 0x04, 0xc8};
            tx(CalculatedEngineLoad, sizeof (CalculatedEngineLoad));
        }
        if (iso == 14230) {
            const char CalculatedEngineLoad[] = {0xc2, 0x33, 0xf1, 0x01, 0x04, 0xeb};
            tx(CalculatedEngineLoad, sizeof (CalculatedEngineLoad));
        }

        for (int i = 0; i < 7; i++) {
            while (RCIF == 0);
            char byte_in = RCREG;
            rx_buffer[i] = byte_in;
        }

        char cel = rx_buffer[5] * 100 / 255;


        if (rx_buffer[5] >= 35) {
            while (rx_buffer[5] - 35 > counter) {
                CCPR2L = counter;
                __delay_ms(2);
                counter++;
            }
            while (rx_buffer[5] - 35 < counter) {
                CCPR2L = counter;
                __delay_ms(2);
                counter--;
            }
        }







        __delay_ms(50);


        if (iso == 9141) {
            const char EngineCoolantTemperature[] = {0x68, 0x6a, 0xf1, 0x01, 0x05, 0xc9};
            tx(EngineCoolantTemperature, sizeof (EngineCoolantTemperature));
        }
        if (iso == 14230) {
            const char EngineCoolantTemperature[] = {0xc2, 0x33, 0xf1, 0x01, 0x05, 0xec};
            tx(EngineCoolantTemperature, sizeof (EngineCoolantTemperature));
        }

        for (int i = 0; i < 7; i++) {
            while (RCIF == 0);
            char byte_in = RCREG;
            rx_buffer[i] = byte_in;
        }

        char ect = rx_buffer[5] - 0x28;
        
        if (ect >= 93) {
            PORTBbits.RB7=1;
        }
        else {
            PORTBbits.RB7=0;
        }




        __delay_ms(50);


        if (iso == 9141) {
            const char VehicleSpeed[] = {0x68, 0x6a, 0xf1, 0x01, 0x0d, 0xd1};
            tx(VehicleSpeed, sizeof (VehicleSpeed));
        }
        if (iso == 14230) {
            const char VehicleSpeed[] = {0xc2, 0x33, 0xf1, 0x01, 0x0d, 0xf4};
            tx(VehicleSpeed, sizeof (VehicleSpeed));
        }

        for (int i = 0; i < 7; i++) {
            while (RCIF == 0);
            char byte_in = RCREG;
            rx_buffer[i] = byte_in;
        }

        char vs = rx_buffer[5];


        
        
        
        
        
        __delay_ms(50);

        
        if (iso == 9141) {
            const char CalculatedEngineLoad[] = {0x68, 0x6a, 0xf1, 0x01, 0x04, 0xc8};
            tx(CalculatedEngineLoad, sizeof (CalculatedEngineLoad));
        }
        if (iso == 14230) {
            const char CalculatedEngineLoad[] = {0xc2, 0x33, 0xf1, 0x01, 0x04, 0xeb};
            tx(CalculatedEngineLoad, sizeof (CalculatedEngineLoad));
        }

        for (int i = 0; i < 7; i++) {
            while (RCIF == 0);
            char byte_in = RCREG;
            rx_buffer[i] = byte_in;
        }

        cel = rx_buffer[5] * 100 / 255;


        if (rx_buffer[5] >= 35) {
            while (rx_buffer[5] - 35 > counter) {
                CCPR2L = counter;
                __delay_ms(2);
                counter++;
            }
            while (rx_buffer[5] - 35 < counter) {
                CCPR2L = counter;
                __delay_ms(2);
                counter--;
            }
        }

        
        
        
        
        

        __delay_ms(50);

        
        if (iso == 9141) {
            const char EngineRPM[] = {0x68, 0x6a, 0xf1, 0x01, 0x0c, 0xd0};
            tx(EngineRPM, sizeof (EngineRPM));
        }
        if (iso == 14230) {
            const char EngineRPM[] = {0xc2, 0x33, 0xf1, 0x01, 0x0c, 0xf3};
            tx(EngineRPM, sizeof (EngineRPM));
        }

        for (int i = 0; i < 8; i++) {
            while (RCIF == 0);
            char byte_in = RCREG;
            rx_buffer[i] = byte_in;
        }

        unsigned int rpm = ((rx_buffer[5] * 256) + rx_buffer[6]) / 4;

        sprintf(byteline2, "%3d %3d %3d %4d", cel, ect, vs, rpm);
        putrsXLCD(byteline2);
        while(BusyXLCD());



        __delay_ms(50);

        WDTCONbits.SWDTEN = 0;
        
        
        
        
        
        
        
        if (PORTBbits.RB0 == 0) {
            __delay_ms(1500);
            if (PORTBbits.RB0 == 0) {
                WriteCmdXLCD(0x01);
                while(BusyXLCD());
                putrsXLCD("Check for stored");
                while(BusyXLCD());
                WriteCmdXLCD(0xC0);
                while(BusyXLCD());
                putrsXLCD("trouble code 1");
                while (BusyXLCD());
                
                __delay_ms(2000);
                
                WDTCONbits.SWDTEN = 1;
                
                if (iso == 9141) {
                    const char trouble[] = {0x68, 0x6a, 0xf1, 0x03, 0xc6};
                    tx(trouble, sizeof (trouble));
                }
                if (iso == 14230) {
                    const char trouble[] = {0xc2, 0x33, 0xf1, 0x03, 0xe9};
                    tx(trouble, sizeof (trouble));
                }
                
                WDTCONbits.SWDTEN = 0;
                
                for (int i = 0; i < 8; i++) {
                    while (RCIF == 0);
                    char byte_in = RCREG;
                    rx_buffer[i] = byte_in;
                }
                
                char dtc1 = (rx_buffer[5] && 0x0c) >> 6;
                char dtc2 = (rx_buffer[5] && 0x30) >> 4;
                char dtc3 = rx_buffer[5] && 0x0f;
                char dtc4 = (rx_buffer[6] && 0xf0) >> 4;
                char dtc5 = rx_buffer[6] && 0x0f;
                
                char code = "";
                switch (dtc1) {
                    case 0b00 : code = "P";
                    break;
                    case 0b01 : code = "C";
                    break;
                    case 0b10 : code = "B";
                    break;
                    case 0b11 : code = "U";
                    break;
                }
                
                sprintf(byteline2, "%c%1d%1x%1x%1x", code, dtc2, dtc3, dtc4, dtc5);
                
                WriteCmdXLCD(0x01);
                while(BusyXLCD());
                putrsXLCD("Trouble code 1 =");
                while(BusyXLCD());
                WriteCmdXLCD(0xC0);
                while(BusyXLCD());
                putrsXLCD(byteline2);
                while (BusyXLCD());
                
                __delay_ms(10000);
                
                WriteCmdXLCD(0x01);
                while(BusyXLCD());
                putrsXLCD("Press button to");
                while(BusyXLCD());
                WriteCmdXLCD(0xC0);
                while(BusyXLCD());
                putrsXLCD("clear ECU");
                while (BusyXLCD());
                
                if (PORTBbits.RB0 == 0) {
                    __delay_ms(1000);
                    if (PORTBbits.RB0 == 0) {
                        WriteCmdXLCD(0x01);
                        while(BusyXLCD());
                        putrsXLCD("Clearing ECU");
                        while(BusyXLCD());
                
                        __delay_ms(4000);
                        
                        char byte_in = RCREG;
                        char byte_in = RCREG;
                        char byte_in = RCREG;
                        
                        WDTCONbits.SWDTEN = 1;
                
                        if (iso == 9141) {
                            const char trouble[] = {0x68, 0x6a, 0xf1, 0x04, 0xc7};
                            tx(trouble, sizeof (trouble));
                        }
                        if (iso == 14230) {
                            const char trouble[] = {0xc2, 0x33, 0xf1, 0x04, 0xea};
                            tx(trouble, sizeof (trouble));
                        }
                        WDTCONbits.SWDTEN = 0;
                    }
                }
            }
        }
    }
}



void tx(char * array, unsigned int size) {

    PIE1bits.TXIE = 1;
    for (int i = 0; i < size; i++) {
        while (TXIF == 0);
        TXREG = array[i];
        while (RCIF == 0);
        char clear = RCREG;
    }
    PIE1bits.TXIE = 0;
}




/*------------------------------------------------------------------------*/
void DelayFor18TCY(void) {
    __delay_us(18);

}

/*------------------------------------------------------------------------*/
void DelayPORXLCD(void) {
    __delay_ms(15);

}

/*------------------------------------------------------------------------*/
void DelayXLCD(void) {
    __delay_ms(5);

}
/*------------------------------------------------------------------------*/
то после инит 5 бод нужно отправить 

const char CalculatedEngineLoad[] = {0xc2, 0x33, 0xf1, 0x01, 0x04, 0xeb};
            tx(CalculatedEngineLoad, sizeof (CalculatedEngineLoad));

delay(1) тоже пробовал. результат не изменился.

 

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

пробуем поочереди  такие строки 11?

byte initMes[] = {0x68, 0x01, 0xF1, 0x81, 0xE7};

byte initMes[] = {0x68, 0x01, 0xF1, 0x01, 0x00, 0xE7};

byte initMes[] = {0x68, 0x6A, 0xF1, 0x01, 0x00, 0xE7};

byte initMes[] = {0x68, 0x6A, 0xF1, 0x81, 0xE7};

byte initMes[] = {0xC2, 0x33, 0xF1, 0x01, 0x00, 0xE7};

byte initMes[] = {0xC1, 0x33, 0xF1, 0x81, 0xE7};

byte initMes[] = {0xC2, 0x01, 0xF1, 0x01, 0x04, 0xE7};

 

 

Aku
Offline
Зарегистрирован: 04.12.2018

Хорошо завтра. 

Чет не совсем понятно. в main идет инит 5 бод, а потом запрос параметров.

Aku
Offline
Зарегистрирован: 04.12.2018

Сделал что то подобное как на PICe.

  mySerial.begin(10400);
  ///mySerial.begin(600);
  Serial.println("10400-baud");
  Serial.println("read byte");
char syncrr,key1,key2,Clear,Ready;
  while (!(mySerial.available()));
  syncrr = mySerial.read();
  if (syncrr == 0x55) {
    Serial.print("syncr ");
    Serial.println(syncrr,HEX);
    //while (!(mySerial.available()));
    if(mySerial.available()){
    delay (5);
    key1 = mySerial.read();
    Serial.print("keyword 1 ");
    Serial.println(key1,HEX);
    //}
    //while (!(mySerial.available()));
    key2 = mySerial.read();
    Serial.print("keyword 2 ");
    Serial.println(key2,HEX);
    }
    delay(25);
    mySerial.write(~key2);
    //while (!(mySerial.available()));
    if(mySerial.available()){
    Clear = mySerial.read();
    Serial.print("clear ");
    Serial.println(Clear,HEX);
    //while (!(mySerial.available()));
    Ready = mySerial.read();
    Serial.print("ready ");
    Serial.println(Ready,HEX);
    }
    if (Ready == 0xCC) {
    ///if (Ready == 0x55) {
      delay(25);
      if (key2 == 0x8F) {
       ///if (key2 == 0x55) {      
        Serial.println("5-baud init OK !!!");       
      } else {
          Serial.println("init failed keyword 2 !!!");
          //while (1);
        }
    } else {
        Serial.println("init failed ~ready !!!");
        //while (1);
      }
  } else {
      Serial.println("init failed syncrr !!!");
      //while (1);
    }
  delay(4000);  
}

Получил ответ:

5-baud init
10400-baud
read byte
syncr 55
clear FFFFFFE9
ready FFFFFF8F
init failed ~ready !!!
Aku
Offline
Зарегистрирован: 04.12.2018

синхробайт получаю 55h.

потом получаю E9h и 8Fh

 

Aku
Offline
Зарегистрирован: 04.12.2018

Вот нашел немного информации про OBD. http://blog.perquin.com/blog/category/odbii/

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

пробуем такой скетч. вверху можно адрес ЭБУ попробовать 0x01 и задержку между отправкой байт сделать 0 

#define BAUD_200  0
#define BAUD_5    1

bool Protocol = BAUD_5;   // тут выбираем протокол 200 baud или 5 baud 
byte ADDRESS = 0x33;      // тут выбираем адрес ЭБУ 


byte StartCommunication []=   {0xc1, ADDRESS, 0xf1, 0x81, 0x66};

byte delaybyte_TX  = 1; //задержка между отправкой байт, мс

int  bit_time = 0;
uint32_t prev = 0; 
#include <SoftwareSerial.h>

#define RX 2
#define TX 3
SoftwareSerial K_line(RX, TX); 

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

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

  pinMode  (TX, OUTPUT);
  digitalWrite  (TX, 1); // BUS idle
  delay (500);

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

  if (Protocol) {bit_time = 200; Serial.println("5 baud Init"); }
  else {bit_time = 5;            Serial.println("200 baud Init"); }
  digitalWrite  (TX, 0); delay (bit_time); // старт бит
  for(byte i = 0; i<8; i++) {digitalWrite  (TX, bitRead(ADDRESS,i)); delay(bit_time);}
  digitalWrite  (TX, 1); delay (bit_time); // стоп бит
  
K_line.begin(10400); //
}


void loop() {
 while(!InitGauge){
   if (K_line.available()) {
   byte inByte = K_line.read();
   Serial.print(" ");
   Serial.print(inByte,HEX);
  if (inByte==0x8F) {delay (10); K_line.write (0x70); }
  if (inByte==0xFE) {delay (10); InitGauge=1; Serial.println("   Ura! init proshol uspeshno!");}
  }}

if (millis()-prev>300) {
  byte Checksum = 0;
  for (byte i = 0; i< sizeof(StartCommunication); i++) {
       if (i!=sizeof(StartCommunication)-1) Checksum+=StartCommunication[i]; 
       else StartCommunication[i] = Checksum;
       K_line.write (StartCommunication[i]); 
       delay (delaybyte_TX);                           }
Serial.println ("Send StartCommunication");
prev = millis();       }
 
 if (K_line.available()) {
   Serial.print(K_line.read(), HEX);
   Serial.print (" ");

  
  }   



}

 

Aku
Offline
Зарегистрирован: 04.12.2018

MaksVV, спасибо за отклик. В общем на твой скетч получил ответ.

 Delayu zapros na PCM. Adress: 33
 5 baud Init
 55 E9 8F CC
Aku
Offline
Зарегистрирован: 04.12.2018


Но у меня получилось получить данные по температуре!!!
вот на этом скетче.

#define F_CPU 16000000UL

#include "din_ind.h"
#include <SoftwareSerial.h>

SoftwareSerial mySerial(2, 3); //Rx,Tx
#define TX 3

#define W1 200
#define W2 10
#define W3 5

byte StartCommunication[5] = {0xC1,0x33,0xF1,0x81,0x66};
byte TemperatureQuery[6] = {0xC2,0x33,0xF1,0x01,0x05,0xEC};

byte Syncro= 0;
byte Keyword1 = 0;
byte Keyword2 = 0;
byte Clear = 0;
byte Ready = 0;
byte BufSize = 0;

byte KeyBuf[4]; 

void setup() {
  
  delay(3000);  
  Serial.begin (115200);
  pinMode(TX,OUTPUT);
  digitalWrite(TX,HIGH);
  init_din_ind();  
  delay(500); 
  init_5_baud();
  //init_fast();
  
//get syncro 
  Serial.println("Wait Syncro ");
  while (!(mySerial.available()));
    Syncro = mySerial.read();
  if (Syncro == 0x55) {
    Serial.print("Syncro ");
    Serial.println(Syncro,HEX);
  }
  else {
    Serial.println("init failed syncrr !!!");
    while (1);
  }
  delay(W2); 
  

//get key  
  while (!(mySerial.available()));

      for (int i = 0; i < 4; i++) {    
        KeyBuf[i] = mySerial.read();
        Serial.print("Keyword ");
        Serial.print(i);
        Serial.print(" ");
        Serial.println(KeyBuf[i],HEX);
        Serial.print(" ");
        delay(5);
      }
 // }
  delay(W3);

//get key2   
  Keyword2 = KeyBuf[1];  
  if (Keyword2 == 0x8F) {  
    mySerial.write(~Keyword2);       
    Serial.println("send ~Keyword 2 ");       
  } 
  else {
    Serial.println("init failed keyword 2 !!!");
    while (1);
  }
  delay(W3);  
    
  while (!(mySerial.available()));
    Ready = mySerial.read();
    Serial.print("ready ");
    Serial.println(Ready,HEX);
  
  if (Ready == 0xCC) {
    Serial.print("ready OK ");
    Serial.println("5-baud init OK !!!");   
  } 
  else {
    Serial.println("init failed ~ready !!!");
    while (1);
  }

//end init    
  delay(1000);  
}

void loop() {
  
  byte rx_buffer[8];  
  tx(TemperatureQuery,sizeof(TemperatureQuery));
  
  Serial.print("byte_in -- ");
  while (!(mySerial.available()));
  //if (mySerial.available()>0) {
    for (int i = 0; i < 7; i++) {    
      byte byte_in = mySerial.read();
      rx_buffer[i] = byte_in;  
      Serial.print(rx_buffer[i],HEX);
      Serial.print(" ");
    }
  //}
  
  char ect = rx_buffer[5] - 0x28;
  Serial.println("");
  Serial.print("temp ");
  Serial.println(ect,DEC);
  
  signed char temper;
  temper = ect;
  unsigned char temper_module = temper >=0 ? temper : -temper;       
   if (temper < 0) digit[0] = 11;       // "прочерк" 
    else {
      if (((temper_module) % 1000/100) == 0) digit[0] = 10; // если 0 то пусто
      else digit[0] = (temper_module) % 1000/100; // Сотни 
    }        
  digit[1] = (temper_module) % 100/10;   // Десятки 
  digit[2] = (temper_module) % 10;       // Единицы 
  digit[3] = 12;                         // "градус"  

  refresh_din_ind();
    
  delay(250);
}

void tx(byte *array, unsigned int size) {
  for (int i = 0; i < size; i++) {
      delay(5);
      mySerial.write(array[i]); 
   }
}

void init_5_baud() {
  Serial.println("5-baud init");
  digitalWrite(TX,LOW); // start
  delay(200);
  digitalWrite(TX,HIGH); // 1,2
  delay(400);
  digitalWrite(TX,LOW); // 3,4
  delay(400);
  digitalWrite(TX,HIGH); // 5,6
  delay(400);
  digitalWrite(TX,LOW); // 7,8
  delay(400);
  digitalWrite(TX,HIGH); // stop
  delay(W1); //W1
  mySerial.begin(10400);
  Serial.println("10400-baud");
}

/*
void init_fast() {
  Serial.println("fast init");
  digitalWrite(TX,LOW);
  delay(25);
  digitalWrite(TX,HIGH); // 1,2
  delay(25);
  mySerial.begin(10400);
  Serial.println("10400-baud");
  
  for (int i = 0; i < 5; i++) {
    mySerial.write(StartCommunication[i]);
    Serial.print(StartCommunication[i],HEX);
    Serial.print("  ");
    delay(5);
  } 
  delay(55);
  Serial.println("");
}
*/


 

Aku
Offline
Зарегистрирован: 04.12.2018

вот ответы

5-baud init
10400-baud
Wait Syncro 
Syncro 55
Keyword 1 0 E9
 Keyword 1 1 8F
 Keyword 1 2 FF
 Keyword 1 3 FF
 send ~Keyword 2 
ready CC
ready OK 5-baud init OK !!!
byte_in -- 83 FF FF FF FF FF FF 
temp -41
byte_in -- F1 10 41 5 89 53 FF 
temp 43
byte_in -- 83 F1 10 41 5 89 53 
temp 97
byte_in -- 83 F1 10 41 5 89 53 
temp 97
byte_in -- 83 F1 10 41 5 89 53 
temp 97
byte_in -- 83 F1 10 41 5 89 53 
temp 97
byte_in -- 83 F1 10 41 5 89 53 
temp 97
byte_in -- 83 F1 10 41 5 89 53 
temp 97
byte_in -- 83 F1 10 41 5 89 53 
temp 97
byte_in -- 83 F1 10 41 5 89 53 
temp 97
byte_in -- 83 F1 10 41 5 89 53 
temp 97
byte_in -- 83 F1 10 41 5 89 53 
temp 97
byte_in -- 83 F1 10 41 5 89 53 
temp 97
MaksVV
Offline
Зарегистрирован: 06.08.2015

Все понятно. Все таки адрес у эбу 33h. Поэтому он отвечает инверсией на 33h байтом ССh а у меня в скетче проверка на FEh была, поэтому периодические запросы не посылались. Могу завтра поправить скетч. Также можно другие данные вытянуть по стандартным пидам

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

И сделать получше парсинг входящих сообщений с проверкой КС.

Aku
Offline
Зарегистрирован: 04.12.2018

Да. Нужно 8Eh переворачивать. И слушать перевернутый 33h. Код нужно оптимизировать. Я не силен в программировании. По поводу параметров. Еще хотел скорость, чтоб зуммер пикал. И напряжение борт сети. Кстати если заметил. Там у меня дин. индикация. Только почему-то 2 й таймер, если я инициализирую. То ногодрыг Тх. Не работает.

 

С таймером разобрался. Все норм.

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

вот код опроса напряжения,температуры ДВС и скорости а/м .  Можно подключить кнопку и считывать стирать DTC. (Расскоментировать в скетче для кнопки).

#define BAUD_200  0
#define BAUD_5    1
int  bit_time = 0;

//#include <Button.h>
//Button test;
//#define BUTTON_PIN 6       // пин подключения тактовой кнопки
//#define BUTTON 0           // программный номер кнопки

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


bool Protocol = BAUD_5;        // тут выбираем протокол инициализации 200 baud или 5 baud

const byte TX_ADDRESS = 0x33;  // тут выбираем адрес ЭБУ
const byte MY_ADDRESS = 0xF1;
 

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


 // возможные варианты запросов на ЭБУ (ПИДы): 
 enum REQUEST {DTCERASE,DTCREAD,PRESENT, STARTCOMMUNIC, PIDTEMP, PIDVOLT,PIDSPEED, ENDPID};

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


  //различные запросы на ЭБУ 
byte TXmessage[][6] = {
 {STARTCOMMUNIC, 0x01,0x81,0x00,0x00,0x00},    // запрос инициализации
 {PIDTEMP,       0x02,0x01,0x05,0x00,0x00},    // запрос температуры
 {PIDVOLT,       0x02,0x01,0x42,0x00,0x00},    // запрос напряжения борт сети
 {PIDSPEED,      0x02,0x01,0x0D,0x00,0x00},    // запрос скорости а/м
 {DTCERASE,      0x03,0x14,0xFF,0x00,0x00},    // запрос стирания ошибок
 {DTCREAD,       0x04,0x18,0x00,0xFF,0x00},    // запрос ошибок
 {PRESENT,       0x01,0x3E,0x00,0x00,0x00}     // запрос поддержания связи
                       };  


 uint32_t curmillis =0;      // снимок текущего времени 
 
 uint32_t prevRequest = 0;   // таймер периодических запросов
 int RequestPeriod = 2000;    // периодичность запросов , мс
 
 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 header = 0;          // состояние заголовка
byte message_size = 0;    // размер тела сообщения
byte j = 3;               // инкремент
byte n = 3;               // количество старт байт
const byte bufsize = 100; // размер буфера принятого сообщения
byte buf [bufsize] = {0}; // буфер принятого сообщения
byte crc =0;              // байт контрольной суммы 

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

 
 float SysVolt = 0;        //14 байт   Напряжение в сети
 int Temp = 0;             //18 байт   Температура охлаждающей жидкости в градусах
 unsigned int Speed = 0;   //29 байт   Скорость а/м
 
bool startsession = 0; 
bool Init = 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);
   initialisation();
             }

void loop() {

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

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

//ниже периодический запрос на ЭБУ
if (curmillis - prevRequest > RequestPeriod && header == 0) {
        
        NOanswer_timer = 1; prev_NOanswer = curmillis; //т.к. сейчас будем делать запрос, то запускаем таймер контроля неответов 
       if (!startsession) request = STARTCOMMUNIC;
       if (!Init) initialisation(); 
       else {SendMessage(); if (request>=STARTCOMMUNIC+1) request++; if  (request==ENDPID)request = STARTCOMMUNIC+1;}
          
   prevRequest = curmillis;                                 }
  
   //разбор входящих сообщений      
    receive ();  
             }

/*
//стартовая инициализация PCM на 7 пине ОБД (fast init - 25ms LOW 25ms HIGH)
 void initialisation() {
   K_LINE.end();
    Serial.println("Delayu FASTINIT na PCM");
   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;

   header = 0; RESETheader_timer =1; prevRESETheader = curmillis; 
 }
*/
 void initialisation() {
K_LINE.end();
digitalWrite  (TX, 1); // BUS idle
delay (400);
// далее посылаем на панель адрес на скорости 5 baud или 200 baud (SLOW INIT)
  Serial.print("Delayu SLOWINIT na PCM. Adress: "); Serial.println(TX_ADDRESS, HEX);
 if (Protocol) {bit_time = 200; Serial.println("5 baud Init"); }
 else {bit_time = 5;            Serial.println("200 baud Init"); }
 digitalWrite  (TX, 0); delay (bit_time); // старт бит
 for(byte i = 0; i<8; i++) {digitalWrite  (TX, bitRead(TX_ADDRESS,i)); delay(bit_time);}
 digitalWrite  (TX, 1); delay (bit_time); // стоп бит
 K_LINE.begin(10400); //
startsession = 0; 
RequestPeriod = 500;
 header = 0; RESETheader_timer =1; prevRESETheader = curmillis; 
}

 
 
 //получение данных от ЭБУ, разборка входящих сообщений
 
 void receive () {
 
 if (K_LINE.available() ){
if (!Init) {
if (header == 0 && Delay){TIMER_DELAY ; buf[0]=K_LINE.read(); Serial.print (buf[0], HEX);  Serial.print (" ");  
                          if (buf[0]==0x55) header = 1;}      

if (header == 1 && Delay){TIMER_DELAY ; buf[1]=K_LINE.read(); Serial.print (buf[1], HEX);  Serial.print (" ");
                          if (buf[1]==0xE9) 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]==0x8F) {header = 2; delay (10); K_LINE.write (0x70);} else {header = 0; RESETheader_timer = 0;}}

if (header == 3 && Delay){TIMER_DELAY ; buf[3]=K_LINE.read(); Serial.print (buf[3], HEX);  Serial.print (" ");
                          if (buf[3]==TX_ADDRESS^0xFF) {Init=1; RequestPeriod = 100; delay (10);} else {header = 0; RESETheader_timer = 0;}}
  }

    

 
else{
 // первый старт байт
 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]==0x10){ 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]==0xE9 && buf[n+2]==0x8F) {request =  STARTCOMMUNIC+1; RequestPeriod = 100; Serial.println ("     StartSession OK!!!!:  "); }
 else if (buf[n]==0x58 && buf[n+1]==0x00) {Serial.println ("     NO DTC  ");      request = STARTCOMMUNIC+1; RequestPeriod = 100;}
 else if (buf[n]==0x58 && buf[n+1] >0x00) {Serial.println ("     DTC is found!"); request = STARTCOMMUNIC+1; 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 = STARTCOMMUNIC+1; RequestPeriod = 100;}
 
 else if (buf[n]==0x41 && buf[n+1]==0x05) {Temp = buf[n+2]-40;      Serial.print ("     Receive Temperature: ");  Serial.print (Temp); Serial.println ( "*C");}
 else if (buf[n]==0x41 && buf[n+1]==0x0D) {Speed = buf[n+2];        Serial.print ("     Receive Speed: ");       Serial.print (Speed); Serial.println ( "km/h");}
 else if (buf[n]==0x41 && buf[n+1]==0x42) {SysVolt = buf[n+2]/10.0; Serial.print ("     Receive Voltage: ");   Serial.print (SysVolt); Serial.println ( " V");}
   
  
}   
 }

// если контрольная сумма не совпала: 
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 >1500) {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; Init=0; RequestPeriod = 2000;}         }
 
 }             


  void TX_otladka(){
    
       
      if (request == STARTCOMMUNIC) Serial.println ("Otpravil StartCommunication");
 else if (request == DTCREAD)       Serial.println ("Otpravil zapros DTC read");
 else if (request == DTCERASE)      Serial.println ("Otpravil zapros DTC clear");
 else if (request == PIDTEMP)       Serial.println ("Otpravil zapros Temperature");
 else if (request == PIDVOLT)       Serial.println ("Otpravil zapros Voltage");
 else if (request == PIDSPEED)      Serial.println ("Otpravil zapros Speed");
                   }


                   void SendMessage (){
 const byte sizeMess = SiZE();
 const byte Numb = numberMes();
 byte Checksum = 0;
 for(byte i = 0; i<sizeMess+4; i++){
     byte txbyte;
     if (i==0) txbyte=TXmessage[Numb][1]|0xC0;
     if (i==1) txbyte=TX_ADDRESS;
     if (i==2) txbyte=MY_ADDRESS;
     if (i==3) for (byte j = 0; j<sizeMess; j++) {
           txbyte = TXmessage[Numb][j+2]; Checksum+=txbyte; 
           K_LINE.write(txbyte); delay (delaybyte_TX); K_LINE.read(); i++;}

if (i!=sizeMess+3) Checksum+=txbyte;
else txbyte = Checksum; 
K_LINE.write(txbyte); delay (delaybyte_TX); K_LINE.read(); 
                                    }
TX_otladka();                                     
if (!startsession) {startsession = 1; request = STARTCOMMUNIC+1;} 
  }

byte SiZE()      {for (byte i = 0; i<sizeof(TXmessage)/2; i++) {if (TXmessage[i][0]==request) return TXmessage[i][1];}}
byte numberMes() {for (byte i = 0; i<sizeof(TXmessage)/2; i++) {if (TXmessage[i][0]==request) return i;}}

 

Aku
Offline
Зарегистрирован: 04.12.2018

Добрый день MaksVV. Спасибо за скетч. У меня работает свой сейчас. Читаю параметры температуры, скорости и обороты двигателя. Но с напряжением по адресу 0x42h почему-то не получается. Возвращает 0x83 0xF1 0x10 0x7F 0x01 0x12 0x16.

Где 0x7F это ошибка. Я так понял, что ответ идет только на первые 20 PID. Или  я не правильно запрашиваю  напряжение 0xC2, 0x33, 0xF1, 0x01, 0x42, 0x29.

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

вот исправленный скетч, в том есть косяки . Видимо такой PID 01 42   ЭБУ не поддерживает.

#define BAUD_200  0
#define BAUD_5    1
int  bit_time = 0;

//#include <Button.h>
//Button test;
//#define BUTTON_PIN 6       // пин подключения тактовой кнопки
//#define BUTTON 0           // программный номер кнопки

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


bool Protocol = BAUD_5;        // тут выбираем протокол инициализации 200 baud или 5 baud

const byte TX_ADDRESS = 0x33;  // тут выбираем адрес ЭБУ
const byte MY_ADDRESS = 0xF1;
 

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


 // возможные варианты запросов на ЭБУ (ПИДы): 
 enum REQUEST {DTCERASE,DTCREAD,PRESENT, STARTCOMMUNIC, PIDTEMP, PIDVOLT,PIDSPEED, ENDPID};

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


  //различные запросы на ЭБУ 
byte TXmessage[][6] = {
 {STARTCOMMUNIC, 0x01,0x81,0x00,0x00,0x00},    // запрос инициализации
 {PIDTEMP,       0x02,0x01,0x05,0x00,0x00},    // запрос температуры
 {PIDVOLT,       0x02,0x01,0x42,0x00,0x00},    // запрос напряжения борт сети
 {PIDSPEED,      0x02,0x01,0x0D,0x00,0x00},    // запрос скорости а/м
 {DTCERASE,      0x03,0x14,0xFF,0x00,0x00},    // запрос стирания ошибок
 {DTCREAD,       0x04,0x18,0x00,0xFF,0x00},    // запрос ошибок
 {PRESENT,       0x01,0x3E,0x00,0x00,0x00}     // запрос поддержания связи
                       };  


 uint32_t curmillis =0;      // снимок текущего времени 
 
 uint32_t prevRequest = 0;   // таймер периодических запросов
 int RequestPeriod = 2000;    // периодичность запросов , мс
 
 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 header = 0;          // состояние заголовка
byte message_size = 0;    // размер тела сообщения
byte j = 3;               // инкремент
byte n = 3;               // количество старт байт
const byte bufsize = 100; // размер буфера принятого сообщения
byte buf [bufsize] = {0}; // буфер принятого сообщения
byte crc =0;              // байт контрольной суммы 

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

 
 float SysVolt = 0;        //14 байт   Напряжение в сети
 int Temp = 0;             //18 байт   Температура охлаждающей жидкости в градусах
 unsigned int Speed = 0;   //29 байт   Скорость а/м
 
bool startsession = 0; 
bool Init = 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);
   initialisation();
   K_LINE.begin(10400);
             }

void loop() {

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

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

//ниже периодический запрос на ЭБУ
if (curmillis - prevRequest > RequestPeriod && header == 0) {
        
        NOanswer_timer = 1; prev_NOanswer = curmillis; //т.к. сейчас будем делать запрос, то запускаем таймер контроля неответов 
       if (!Init) initialisation(); 
       else {SendMessage(); if (request>=STARTCOMMUNIC+1) request++; if  (request==ENDPID)request = STARTCOMMUNIC+1;}
          
   prevRequest = curmillis;                                 }
  
   //разбор входящих сообщений      
    receive ();  
             }

/*
//стартовая инициализация PCM на 7 пине ОБД (fast init - 25ms LOW 25ms HIGH)
 void initialisation() {
   K_LINE.end();
    Serial.println("Delayu FASTINIT na PCM");
   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;

   header = 0; RESETheader_timer =1; prevRESETheader = curmillis; 
 }
*/
 void initialisation() {
K_LINE.end();
digitalWrite  (TX, 1); // BUS idle
delay (400);
// далее посылаем на панель адрес на скорости 5 baud или 200 baud (SLOW INIT)
  Serial.print("Delayu SLOWINIT na PCM. Adress: "); Serial.println(TX_ADDRESS, HEX);
 if (Protocol) {bit_time = 200; Serial.println("5 baud Init"); }
 else {bit_time = 5;            Serial.println("200 baud Init"); }
 digitalWrite  (TX, 0); delay (bit_time); // старт бит
 for(byte i = 0; i<8; i++) {digitalWrite  (TX, bitRead(TX_ADDRESS,i)); delay(bit_time);}
 digitalWrite  (TX, 1); delay (bit_time); // стоп бит
 K_LINE.begin(10400); //
request = STARTCOMMUNIC;
RequestPeriod = 3000;
 header = 0; RESETheader_timer =1; prevRESETheader = curmillis; 
}

 
 
 //получение данных от ЭБУ, разборка входящих сообщений
 
 void receive () {

if (K_LINE.available() && !Init) {
if (header == 0 && Delay){TIMER_DELAY ; buf[0]=K_LINE.read(); Serial.print ("header 0: ");  Serial.print (buf[0], HEX);  Serial.print (" ");  
                          if (buf[0]==0x55) header = 1;}      

if (header == 1 && Delay){TIMER_DELAY ; buf[1]=K_LINE.read(); Serial.print ("header 1: "); Serial.print (buf[1], HEX);  Serial.print (" ");
                          if (buf[1]==0xE9) header = 2; else {header = 2; RESETheader_timer = 0;}}

if (header == 2 && Delay){TIMER_DELAY ; buf[2]=K_LINE.read(); Serial.print ("header 2: "); Serial.print (buf[2], HEX);  Serial.print (" "); 
                          if (buf[2]==0x8F) {header = 3; delay (10); K_LINE.write (0x70);} else {header = 0; RESETheader_timer = 0;}}

if (header == 3 && Delay){TIMER_DELAY ; buf[3]=K_LINE.read(); Serial.print ("header 3: "); Serial.print (buf[3], HEX);  Serial.print (" ");
                          if (buf[3]==TX_ADDRESS^0xFF) {Init=1; Serial.print ("Init good!!!"); RequestPeriod = 100; request = STARTCOMMUNIC; noanswers = 0;header = 0;delay (10);} else {header = 0; RESETheader_timer = 0;}}
  }

 
 if (K_LINE.available() && Init ){

 // первый старт байт
 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]==0x10){ 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]==0xE9 && buf[n+2]==0x8F) {request =  STARTCOMMUNIC+1; RequestPeriod = 100; Serial.println ("     StartSession OK!!!!:  "); }
 else if (buf[n]==0x58 && buf[n+1]==0x00) {Serial.println ("     NO DTC  ");      request = STARTCOMMUNIC+1; RequestPeriod = 100;}
 else if (buf[n]==0x58 && buf[n+1] >0x00) {Serial.println ("     DTC is found!"); request = STARTCOMMUNIC+1; 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 = STARTCOMMUNIC+1; RequestPeriod = 100;}
 
 else if (buf[n]==0x41 && buf[n+1]==0x05) {Temp = buf[n+2]-40;      Serial.print ("     Receive Temperature: ");  Serial.print (Temp); Serial.println ( "*C");}
 else if (buf[n]==0x41 && buf[n+1]==0x0D) {Speed = buf[n+2];        Serial.print ("     Receive Speed: ");       Serial.print (Speed); Serial.println ( "km/h");}
 else if (buf[n]==0x41 && buf[n+1]==0x42) {SysVolt = buf[n+2]/10.0; Serial.print ("     Receive Voltage: ");   Serial.print (SysVolt); Serial.println ( " V");}
   
  
}   


// если контрольная сумма не совпала: 
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 >2000) {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; Serial.println ("no answ Init=0"); Init=0; RequestPeriod = 3000;}         }
 
 }             


  void TX_otladka(){
    
       
      if (request == STARTCOMMUNIC) Serial.println ("Otpravil StartCommunication");
 else if (request == DTCREAD)       Serial.println ("Otpravil zapros DTC read");
 else if (request == DTCERASE)      Serial.println ("Otpravil zapros DTC clear");
 else if (request == PIDTEMP)       Serial.println ("Otpravil zapros Temperature");
 else if (request == PIDVOLT)       Serial.println ("Otpravil zapros Voltage");
 else if (request == PIDSPEED)      Serial.println ("Otpravil zapros Speed");
                   }


                   void SendMessage (){
 const byte sizeMess = SiZE();
 const byte Numb = numberMes();
 byte Checksum = 0;
 for(byte i = 0; i<sizeMess+4; i++){
     byte txbyte;
     if (i==0) txbyte=TXmessage[Numb][1]|0xC0;
     if (i==1) txbyte=TX_ADDRESS;
     if (i==2) txbyte=MY_ADDRESS;
     if (i==3) for (byte j = 0; j<sizeMess; j++) {
           txbyte = TXmessage[Numb][j+2]; Checksum+=txbyte; 
           K_LINE.write(txbyte); delay (delaybyte_TX); K_LINE.read(); i++;}

if (i!=sizeMess+3) Checksum+=txbyte;
else txbyte = Checksum; 
K_LINE.write(txbyte); delay (delaybyte_TX); K_LINE.read(); 
                                    }
TX_otladka();                                     

  }

byte SiZE()      {for (byte i = 0; i<sizeof(TXmessage)/2; i++) {if (TXmessage[i][0]==request) return TXmessage[i][1];}}
byte numberMes() {for (byte i = 0; i<sizeof(TXmessage)/2; i++) {if (TXmessage[i][0]==request) return i;}}

 

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

нужно на эбу послать такой PID  01 00  ну т.е.   С2 33 F1 01 00 E7   и тогда получишь ответ от ЭБУ  - какие пиды он поддерживает

тынц

 

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

Aku пишет:

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

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

Aku
Offline
Зарегистрирован: 04.12.2018
//https://www.instructables.com/id/Low-Cost-OBD2-Communications-on-K-line-ISO-9141-2-/
//http://blog.perquin.com/blog/category/odbii/

#define F_CPU 16000000UL

#include "din_ind.h"
#include <SoftwareSerial.h>

SoftwareSerial mySerial(2,3); //Rx2,Tx3
#define TX 3 //3

#define speakerPin 13

//0-20 Синхронизация между байтами в ответе ECU
//25-50 Время между запросом на конец тестера и началом ответа ЭБУ или между ответами ECU
//25-5000 Расширенный режим для "rspPending"
//55-5000 Время между окончанием ответа ECU и началом нового запроса тестера или временем между тестом тестера запрос и начало нового запроса, если ECU не отвечает
//5-20 Время между байтами в запросе тестера

#define W1Syncro 25 // 20-300 Ожидание байта SYNC(300-timeOut)
#define W2byteOut 10 // 5-20 //10(20-timeOut)
#define W3byteIn 5   // 0-20
#define W4KeyTo 30// 25 мс <= W4 <= 50 мс (время между завершенным получением ключа 2 и началом отправки инвертированного ключа 2)
#define TxToRx 60    // от отправки до приема 55-5000

unsigned char StartCommunication[5] = {0xC1, 0x33, 0xF1, 0x81, 0x66};
unsigned char GetPids[6] =            {0xC2, 0x33, 0xF1, 0x01, 0x00, 0xE7};
unsigned char EngCoolTemp[6] =        {0xC2, 0x33, 0xF1, 0x01, 0x05, 0xEC};
unsigned char VehicleSpeed[6] =       {0xC2, 0x33, 0xF1, 0x01, 0x0D, 0xF4};
//unsigned char Voltage[6] =            {0xC2, 0x33, 0xF1, 0x01, 0x42, 0x29};
unsigned char EngineRPM[6] =          {0xC2, 0x33, 0xF1, 0x01, 0x0C, 0xF3};

unsigned char Syncro= 0;
unsigned char Key2 = 0;
unsigned char Clear = 0;
unsigned char Ready = 0;

unsigned char KeysBuf[4]; 

void setup() { 
  // Настраиваю таймер 2 для динамической индикации
  cli();// Глобально запрещаю прерывания
  TCCR2A = 0;
  TCCR2B = 0;
  TIMSK2 = 0; 
  TCCR2A |= (1<<COM2A0); // Toggle OC2A,No CTC
  //TCCR2B |= (1<<CS21)|(1<<CS20);              // Presc. = 32
  TCCR2B |= (1<<CS22);                      // Presc. = 64
  TIMSK2 |= (1<<TOIE2); // enable timer overflow interrupt
  sei();// Глобально разрешаю прерывания 
  
  Serial.begin (115200);
  init_din_ind();   
  pinMode(TX,OUTPUT);
  digitalWrite(TX,HIGH); 
  pinMode(speakerPin, OUTPUT);
  digitalWrite(speakerPin,LOW); 
  init_5_baud(); 
  //init_fast();  
  delay(TxToRx);  
}

void loop() {
  
  unsigned char rx_buffer[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
  signed char ect = 0;
  unsigned char temper_module = 0;
  unsigned char vs = 0;
  //unsigned short volts = 0;
  unsigned short rpm = 0;
   
//temper  
  txBuf(EngCoolTemp,sizeof(EngCoolTemp));
  delay(TxToRx);
  Serial.print("byte_in Temper -- ");
  if (mySerial.available()>0) {
    for (int i = 0; i < 7; i++) {    
      unsigned char byte_in = mySerial.read();
      rx_buffer[i] = byte_in;  
      Serial.print(rx_buffer[i],HEX);
      Serial.print(" ");
      delay(W3byteIn);
    }
  }
  
  if (rx_buffer[0]==0x83 && rx_buffer[1]==0xF1 && rx_buffer[2]==0x10 && rx_buffer[3]==0x41 && rx_buffer[4]==0x05) {
    ect = rx_buffer[5] - 0x28;
    Serial.println("");
    Serial.print("Temp ");
    Serial.println("");
    Serial.println(ect,DEC);
  }
  rx_buffer[5] = 0;
  
  temper_module = ect >=0 ? ect : - ect;       
   if (ect < 0) digit[0] = 11;       // "прочерк" 
    else {
      if (((temper_module)%1000/100) == 0) digit[0] = 10; // если 0 то пусто
      else digit[0] = (temper_module) % 1000/100; // Сотни 
    }        
  digit[1] = (temper_module) % 100/10;   // Десятки 
  digit[2] = (temper_module) % 10;       // Единицы 
  digit[3] = 12;                         // "градус"  
  DP1 = 0;   
  delayNoBeep();
  
//speed
  txBuf(VehicleSpeed,sizeof(VehicleSpeed));
  delay(TxToRx);
  Serial.print("byte_in Speed -- ");
  if (mySerial.available()>0) {
    for (byte i = 0; i < 7; i++) {    
      unsigned char byte_in = mySerial.read();
      rx_buffer[i] = byte_in;  
      Serial.print(rx_buffer[i],HEX);
      Serial.print(" ");
      delay(W3byteIn);
    }
  }
  
  if (rx_buffer[0]==0x83 && rx_buffer[1]==0xF1 && rx_buffer[2]==0x10 && rx_buffer[3]==0x41 && rx_buffer[4]==0x0D) {  
    vs = rx_buffer[5];
    rx_buffer[5] = 0; 
    Serial.println("");
    Serial.print("Speed ");
    Serial.println("");
    Serial.println(vs,DEC); 
  } 
   
  if (((vs) % 1000/100) == 0) digit[0] = 10; // если 0 то пусто
  else digit[0] = (vs)%1000/100;  // Сотни           
  digit[1] = (vs)%100/10;         // Десятки 
  digit[2] = (vs)%10;             // Единицы 
  digit[3] = 19;                  // "C" 
  DP1 = 0;   
  
  if ((vs >= 75)||(vs <= 80)) delayBeep();
  else delayNoBeep();
  
/*  
//volt
//42HEX 2BYTE Control module voltage  от 0 до 65.535 V  ==256*A+B/1000 
  txBuf(Voltage,sizeof(Voltage));
  delay(TxToRx);
  Serial.print("byte_in Voltage -- ");
  if (mySerial.available()>0) {
    for (byte i = 0; i < 8; i++) {    
      unsigned char byte_in = mySerial.read();
      rx_buffer[i] = byte_in;  
      Serial.print(rx_buffer[i],HEX);
      Serial.print(" ");
      delay(W3byteIn);
    }
  }  
  if (rx_buffer[0]==0x83 && rx_buffer[1]==0xF1 && rx_buffer[2]==0x10 && rx_buffer[3]==0x41 && rx_buffer[4]==0x42) {
    volts = (0x100*rx_buffer[5])+rx_buffer[6];
    volts = (256*rx_buffer[5])+rx_buffer[6];
    rx_buffer[5] = 0;
    rx_buffer[6] = 0;
    Serial.println("");
    Serial.print("Voltage ");
    Serial.println("");
    Serial.println(volts,DEC); 
  }
               
  digit[0] = (volts)%100000/10000;  // Десятки 
  digit[1] = (volts)%10000/1000;    // Единицы 
  digit[2] = (volts)%1000/100;      // 1/10 
  digit[3] = 17;                      //"U" 
  DP1 = 1;
  delayNoBeep();
 */  
//RPM 
  txBuf(EngineRPM,sizeof(EngineRPM));
  delay(TxToRx);
  Serial.print("byte_in EngineRPM -- ");
  //while (!(mySerial.available()));
  if (mySerial.available()>0) {
    for (byte i = 0; i < 8; i++) {    
      unsigned char byte_in = mySerial.read();
      rx_buffer[i] = byte_in;  
      Serial.print(rx_buffer[i],HEX);
      Serial.print(" ");
      delay(W3byteIn);
    }
  }  

  if (rx_buffer[0]==0x84 && rx_buffer[1]==0xF1 && rx_buffer[2]==0x10 && rx_buffer[3]==0x41 && rx_buffer[4]==0x0C) {
    //rpm = (0x100*rx_buffer[5]*0x100) + rx_buffer[6];  
    rpm = (256*rx_buffer[5]) + rx_buffer[6];  
    rx_buffer[5] = 0;
    rx_buffer[6] = 0;   
    rpm = rpm/4;
    Serial.println("");
    Serial.print("RPM ");
    Serial.println("");
    Serial.println(rpm,DEC); 
  }
   
  ///rpm = 3800;
  if (rpm % 10000/1000 == 0) digit[0] = 10; // "пусто" 
  else digit[0] = rpm % 10000/1000;         // тысячи
  digit[1] = rpm % 1000/100;                // сотни 
  digit[2] = rpm % 100/10;                  // десятки 
  digit[3] = rpm % 10/1;                    // 1 
  DP1 = 0;                       
  if (rpm >= 3800) delayBeep();
  else delayNoBeep();
   
} // конец loop

ISR(TIMER2_OVF_vect) { 
  refresh_din_ind();
}

void init_5_baud() {
  delay(2000); //ждем перед инициализацией
  Serial.println("5-baud init");
  digitalWrite(TX,LOW); // start
  delay(200);
  digitalWrite(TX,HIGH); // 1,2
  delay(400);
  digitalWrite(TX,LOW); // 3,4
  delay(400);
  digitalWrite(TX,HIGH); // 5,6
  delay(400);
  digitalWrite(TX,LOW); // 7,8
  delay(400);
  digitalWrite(TX,HIGH); // stop
  delay(200);
  //end 5-baud
  mySerial.begin(10400); //60ms min время настройки 10400
  Serial.println("10400-baud");
  delay(W1Syncro); // 100ms (300-timeOut) 
  //wait syncro 
  Serial.println("wait Syncro ");
  while (!(mySerial.available()));
    Syncro = mySerial.read();   
  if (Syncro == 0x55) {
    Serial.print("Syncro ");
    Serial.println(Syncro,HEX);
  }
  else {
    Serial.println("init failed Syncro !!!");
    while (1);
  }
  delay(W2byteOut); //10ms (20-timeOut) key1
  
//wait keys  
  while (!(mySerial.available()));
    for (byte i = 0; i < 4; i++) {    
      KeysBuf[i] = mySerial.read();
      Serial.print("Keys ");
      Serial.print(i);
      Serial.print(" ");
      Serial.println(KeysBuf[i],HEX);
      Serial.print(" ");
      delay(W3byteIn);
    }
  delay(W2byteOut); //10ms (20-timeOut) key2 0-24работает

//send key2   
  Key2 = KeysBuf[1];  
  if (Key2 == 0x8F) {  
    mySerial.write(~Key2);          
    Serial.println("send ~Key 2 ");       
  } 
  else {
    Serial.println("init failed Key 2 !!!");
    while (1);
  }
  // получаем эхо отправленного байта Keyword2, ждем 
  delay(W4KeyTo); //30 ms (50-timeOut) // ждем перед чтением read  
       
  while (!(mySerial.available()));
    Ready = mySerial.read();     
    Serial.print("Ready ");
    Serial.println(Ready,HEX);
  
  if (Ready == 0xCC) {
    Serial.print("Ready OK ");
    Serial.println("5-baud init OK !!!");   
  } 
  else {
    Serial.println("init failed ~Ready !!!");
    while (1);
  }
  delay(TxToRx);
}

void txBuf(unsigned char *array, unsigned int bufSizeTx) {
  for (int i = 0; i < bufSizeTx; i++) {     
      mySerial.write(array[i]); 
      delay(W2byteOut);
   }
}

void delayNoBeep() { 
  delay(1500);//1.5 сек без звук
  digitalWrite(speakerPin,LOW);
}

void delayBeep() { //1.5 сек звук
  digitalWrite(speakerPin,HIGH); 
  delay(50);
  digitalWrite(speakerPin,LOW);
  delay(100); 
  digitalWrite(speakerPin,HIGH); 
  delay(50);
  digitalWrite(speakerPin,LOW);
  delay(100);
  digitalWrite(speakerPin,HIGH); 
  delay(50);
  digitalWrite(speakerPin,LOW);
  delay(100); 
  digitalWrite(speakerPin,HIGH); 
  delay(50);
  digitalWrite(speakerPin,LOW);
  delay(100);  
  digitalWrite(speakerPin,HIGH); 
  delay(50);
  digitalWrite(speakerPin,LOW);
  delay(100);
  digitalWrite(speakerPin,HIGH); 
  delay(50);
  digitalWrite(speakerPin,LOW);
  delay(100);
  digitalWrite(speakerPin,HIGH); 
  delay(50);
  digitalWrite(speakerPin,LOW); 
  delay(100);
  digitalWrite(speakerPin,HIGH); 
  delay(50); //1100
  digitalWrite(speakerPin,LOW);
  delay(100);
  digitalWrite(speakerPin,HIGH); 
  delay(50); //1250
  digitalWrite(speakerPin,LOW);
  delay(100);
  digitalWrite(speakerPin,HIGH); 
  delay(50); //1400
  digitalWrite(speakerPin,LOW);
  delay(100); //1500
}
/*
Fastinit:
_________       _____        ____        ____
         \_____/     \/\/\/\/    \/\/\/\/
 300ms    25ms  25ms  packet     response 

1) Подождите 300 мс с высотой линии K.
2) Низкая линия K 25 +/- 1 мс
3) Пусть линия К поднимается высоко и ждет 25 мс
4) инициировать последовательное соединение с 10400 бод, 8N1, 1 = 0Volt 0 = 12Volt, младший значащий бит сначала
5) отправить пакет c1 33 f1 81 66 , 33 = dest, f1 = наш идентификатор тестера, 81 = начать комм.
6) ожидание ответа 83 f1 01 c1 e9 8f гдe 01 = физический адрес, c1 = ответ ok 
*/
/*
void init_fast() {
  delay(300); //ждем перед инициализацией
  Serial.println("fast init");
  digitalWrite(TX,LOW);
  delay(25);
  digitalWrite(TX,HIGH); 
  delay(25);
  mySerial.begin(10400);
  Serial.println("10400-baud");
  
  ///delay(60);
  
  txBuf(StartCommunication,sizeof(StartCommunication));
  delay(TxToRx);
  Serial.print("byte_in fast init -- ");
  //while (!(mySerial.available()));
  if (mySerial.available()>0) {
    for (byte i = 0; i < 7; i++) {    
      unsigned char byte_in = mySerial.read();
      rx_buffer[i] = byte_in;  
      Serial.print(rx_buffer[i],HEX);
      Serial.print(" ");
      delay(W3byteIn);
    }
  }
  if (rx_buffer[3]==0xC1) {
    rx_buffer[3] = 0;
    Serial.print("Ready OK ");
    Serial.println("5-baud init OK !!!");   
  } 
  else {
    Serial.println("init failed init !!!");
    while (1);
  }
  delay(TxToRx);
}

*/

на текущий момент рабочий вариант примерно такой.

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

А #45 работает?

Aku
Offline
Зарегистрирован: 04.12.2018

Вариант бортового мк через терминал http://timothyshaffer.com/website/obdii.php