Вопрос по ISO-14230-4
- Войдите на сайт для отправки комментариев
Втр, 04/12/2018 - 12:08
Добрый день. Есть автомобиль VW. Хочу считать данные по температуре с K-line. При запросе получил 55h 6Bh 8Fh. Как выполнить инициализацию?
http://arduino.ru/forum/apparatnye-voprosy/mc-33290-i-k-line-adapter-vop... вот с этим скетчем я получил ответ 55h 6Bh 8Fh.
В общем понял, что нужно в ответ отправить инвертированный 2й байт и получить в ответ инвертированный 33h.
верно мыслите. 55h это синхробайт 6Bh и 8Fh это keyword 1 и keyword 2. отправляете на эбу инвертированный 8Fh это 70h и инициализация будет закончена.
Спасибо 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();
}
незнаю как код вставить по нормальному.
А как мне теперь захватить данные?
https://www.drive2.ru/c/479335393737572613/
Вот здесь есть что то похожее, но я не уверен что для меня это подойдет.
для начала вставляем скетч правильно. Лучше использовать скетч Александра (немец вроде он). Там уже реализовано считываение ваговских блоков данных.
/* 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(); }Спасибо MaksVV. Вечером попробую. Отпишусь.
а скорость к-лайн у вас 10400 смотрю? это точно?
Я пробовал 4800, 9600, 10400. Синхро байт 55h получил на 10400. Предположил что протокол ISO14230-4.
/* 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(); }Вот здесь есть немного описание. https://ru.scribd.com/document/388728618/1278519259-K-line-Communication...
Не совсем уверен, что код от Александра подойдет.
у вас есть рабочая диагностика, которая подключается к ЭБУ? Типа VAGcom или подобная? Если да, то нужно просниффить диагностическую сессиию и всё станет понятно какой там протокол
К сожалению нет. Буду пытаться в слепую.
Вот еще нашел кое что https://www.instructables.com/id/Low-Cost-OBD2-Communications-on-K-line-ISO-9141-2-/
Там есть main. Принцип инициализации такой же.
В общем останавливается на
---KWPSend sz=3 blockCounter=0.
И заново
------ connect addr=1 baud=10400
179 строка.
ну так пробуем.
#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(); }в строке 11 нулевой байт массива можно попробовать также сделать 0xC1
первый вариант(самый первый)
строка 42 пробуем убрать delay (1). Также строку 38 пробуем сделать такую
if (inByte == 0x8F) {delay (10); mySerial.write(0x70);Если сделать 0xC1, тогда и контрольную сумму пересчитать?
Или ее здесь нет?
кстати байт FE это как раз удачный конец инициализации - эбу шлёт на диагностику (нам) свой инвертированный адрес. 01 в инверсии это FE
значит первый байт 81 сработал?
нет, сработал отправленный байт 0х70, это инверсия на keyword 2. После удачного инита запрос {0x81, 0x01, 0xF1, 0x81, 0xF4}; не сработал.
Что я примерно должен получить?
можно также попробовать строку 11 сделать такую
byte initMes[] = {0xC2, 0x01, 0xF1, 0x01, 0x00, 0xE7}какие-нибудь байты в ответ если прилетят то уже хорошо
КС в скетче сама подсчитывается, её исправлять в массиве сообщения не надо
Нет ничего. Только когда добавил delay(10); ответ стал:
delay (1) пробовал убирать?
Если смотреть 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) тоже пробовал. результат не изменился.пробуем поочереди такие строки 11?
byteinitMes[] = {0x68, 0x01, 0xF1, 0x81, 0xE7};byteinitMes[] = {0x68, 0x01, 0xF1, 0x01, 0x00, 0xE7};byteinitMes[] = {0x68, 0x6A, 0xF1, 0x01, 0x00, 0xE7};byteinitMes[] = {0x68, 0x6A, 0xF1, 0x81, 0xE7};byteinitMes[] = {0xC2, 0x33, 0xF1, 0x01, 0x00, 0xE7};byteinitMes[] = {0xC1, 0x33, 0xF1, 0x81, 0xE7};byteinitMes[] = {0xC2, 0x01, 0xF1, 0x01, 0x04, 0xE7};Хорошо завтра.
Чет не совсем понятно. в main идет инит 5 бод, а потом запрос параметров.
Сделал что то подобное как на 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); }Получил ответ:
синхробайт получаю 55h.
потом получаю E9h и 8Fh
Вот нашел немного информации про OBD. http://blog.perquin.com/blog/category/odbii/
пробуем такой скетч. вверху можно адрес ЭБУ попробовать 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 (" "); } }MaksVV, спасибо за отклик. В общем на твой скетч получил ответ.
#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(""); } */вот ответы
Все понятно. Все таки адрес у эбу 33h. Поэтому он отвечает инверсией на 33h байтом ССh а у меня в скетче проверка на FEh была, поэтому периодические запросы не посылались. Могу завтра поправить скетч. Также можно другие данные вытянуть по стандартным пидам
И сделать получше парсинг входящих сообщений с проверкой КС.
Да. Нужно 8Eh переворачивать. И слушать перевернутый 33h. Код нужно оптимизировать. Я не силен в программировании. По поводу параметров. Еще хотел скорость, чтоб зуммер пикал. И напряжение борт сети. Кстати если заметил. Там у меня дин. индикация. Только почему-то 2 й таймер, если я инициализирую. То ногодрыг Тх. Не работает.
С таймером разобрался. Все норм.
вот код опроса напряжения,температуры ДВС и скорости а/м . Можно подключить кнопку и считывать стирать 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;}}Добрый день MaksVV. Спасибо за скетч. У меня работает свой сейчас. Читаю параметры температуры, скорости и обороты двигателя. Но с напряжением по адресу 0x42h почему-то не получается. Возвращает 0x83 0xF1 0x10 0x7F 0x01 0x12 0x16.
Где 0x7F это ошибка. Я так понял, что ответ идет только на первые 20 PID. Или я не правильно запрашиваю напряжение 0xC2, 0x33, 0xF1, 0x01, 0x42, 0x29.
вот исправленный скетч, в том есть косяки . Видимо такой 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;}}нужно на эбу послать такой PID 01 00 ну т.е. С2 33 F1 01 00 E7 и тогда получишь ответ от ЭБУ - какие пиды он поддерживает
тынц
У меня работает свой сейчас. Читаю параметры температуры, скорости и обороты двигателя.
ну дак нужно сюда выложить. Тема ведь не только для вас , другие тоже читают. Глядишь и про косяки в скетче кто-нибудь чего скажет. Только код сворачиваем под кат, не нужно этих простыней тут. Внимательно читаем как это сделать .
на текущий момент рабочий вариант примерно такой.
А #45 работает?
Вариант бортового мк через терминал http://timothyshaffer.com/website/obdii.php