Open tistructor opened 2 years ago
I did it ;-) The protocol is KWP2000 slow. With the initKWP function, initialization was unsuccessful. So I modified it this way :
bool OBD9141::initKWP(){
use_kwp_ = true;
// this function performs the ISO9141 5-baud 'slow' init.
this->set_port(false); // disable the port.
this->kline(true);
delay(OBD9141_INIT_IDLE_BUS_BEFORE); // no traffic on bus for 3 seconds.
OBD9141println("Before magic 5 baud.");
// next, send the startup 5 baud init..
this->kline(false); //digitalWrite(7,LOW);
delay(200); // start
this->kline(true); //digitalWrite(7,HIGH);
delay(400); // first two bits
this->kline(false); //digitalWrite(7,LOW);
delay(400); // second pair
this->kline(true); //digitalWrite(7,HIGH);
delay(400); // third pair
this->kline(false); //digitalWrite(7,LOW);
delay(400); // last pair
this->kline(true); //digitalWrite(7,HIGH);
delay(200); // stop bit
// this last 200 ms delay could also be put in the setTimeout below.
// But the spec says we have a stop bit.
// done, from now on it the bus can be treated ad a 10400 baud serial port.
OBD9141println("Before setting port.");
this->set_port(true);
OBD9141println("After setting port.");
uint8_t mess[1];
this->serial->setTimeout(300+200);
// wait should be between 20 and 300 ms long
// read first value into buffer, should be 0x55
if (this->serial->readBytes(mess, 1)){
OBD9141print("First read is: "); OBD9141println(mess[0]);
if (mess[0] != 0x55){
return false;
}
} else {
OBD9141println("Timeout on read 0x55.");
return false;
}
// we get here after we have passed receiving the first 0x55 from ecu.
this->serial->setTimeout(20); // w2 and w3 are pauses between 5 and 20 ms
uint8_t v1=0, v2=0; // sent by car: (either 0x08 or 0x94)
// read v1
if (!this->serial->readBytes(mess, 1)){
OBD9141println("Timeout on read v1.");
return false;
} else {
v1 = mess[0];
OBD9141print("read v1: "); OBD9141println(v1);
}
// read v2
if (!this->serial->readBytes(mess, 1)){
OBD9141println("Timeout on read v2.");
return false;
} else {
v2 = mess[0];
OBD9141print("read v2: "); OBD9141println(v2);
}
OBD9141print("v1: "); OBD9141println(v1);
OBD9141print("v2: "); OBD9141println(v2);
// these two should be identical according to the spec.
//if (v1 != v2){
// return false;
//}
// we obtained w1 and w2, now invert and send it back.
// tester waits w4 between 25 and 50 ms:
delay(30);
this->write(~v2);
this->serial->setTimeout(50); // w5 is same as w4... max 50 ms
// finally, attempt to read 0xCC from the ECU, indicating succesful init.
if (!this->serial->readBytes(mess, 1)){
OBD9141println("Timeout on 0xCC read.");
return false;
} else {
OBD9141print("read 0xCC?: "); OBD9141println(mess[0]);
if ((mess[0] == 0xCC)){
delay(OBD9141_INIT_POST_INIT_DELAY);
// this delay is not in the spec, but prevents requests immediately
// after the finishing of the init sequency.
} else {
return false;
}
}
this->serial->setTimeout(300+200);
// wait should be between 20 and 300 ms long
// startCommunicationRequest message:
uint8_t message[4] = {0xC1, 0x33, 0xF1, 0x81};
// checksum (0x66) is calculated by request method.
// Send this request and read the response
if (this->requestKWP(&message, 4) == 6) {
// check positive response service ID, should be 0x7F.
OBD9141print("read 0x7F?: "); OBD9141println(buffer[3]);
if (this->buffer[3] == 0x7F) {
// Not necessary to do anything with this data?
return true;
} else {
return false;
}
}
return false;
}
The readKWP.ino file modified for arduino one :
#include "Arduino.h"
#include "AltSoftSerial.h"
#include "OBD9141.h"
#define TXL_PIN 7 // connect to transceiver TxL
#define RX_PIN 8
#define TX_PIN 9
#define EN_PIN 2
AltSoftSerial altSerial;
OBD9141 obd;
void setup(){
Serial.begin(9600);
delay(2000);
pinMode(EN_PIN, OUTPUT);
digitalWrite(EN_PIN, HIGH);
obd.begin(altSerial, RX_PIN, TX_PIN);
}
void loop(){
Serial.println("Looping");
// only change from reader is the init method here.
uint8_t init_success = obd.initKWP();
Serial.print("init_success:");
Serial.println(init_success);
delay(50);
//init_success = true;
// Uncomment this line if you use the simulator to force the init to be
// interpreted as successful. With an actual ECU; be sure that the init is
// succesful before trying to request PID's.
if (init_success){
bool res;
while(1){
res = obd.getCurrentPID(0x11, 1);
if (res){
Serial.print("Result 0x11 (throttle): ");
Serial.println(obd.readUint8());
}
delay(50);
res = obd.getCurrentPID(0x0C, 2);
if (res){
Serial.print("Result 0x0C (RPM): ");
Serial.println(obd.readUint16()/4);
}
delay(50);
res = obd.getCurrentPID(0x0D, 1);
if (res){
Serial.print("Result 0x0D (speed): ");
Serial.println(obd.readUint8());
}
Serial.println();
delay(200);
}
delay(200);
}
delay(3000);
}
TXL didn't help me. In the hardware interface I also made the L-Line, but it is not needed with my car.
Serial Monitor:
Looping
Before magic 5 baud.
Before setting port.
After setting port.
First read is: 85
read v1: 233
read v2: 143
v1: 233
v2: 143
read 0xCC?: 204
Rem: 6
ret_len: 7
R: 131 241 16 127 129 17 149 0
calc cs: 149
buf cs: 149
ok
6
read 0x7F?: 127
init_success:1
With car on but stopped:
Result 0x11 (throttle): 63
Rem: 7
ret_len: 8
R: 132 241 16 65 12 22 108 84 0
calc cs: 84
buf cs: 84
ok
7
Result 0x0C (RPM): 1435
Rem: 6
ret_len: 7
R: 131 241 16 65 13 0 210 0
calc cs: 210
buf cs: 210
ok
6
Result 0x0D (speed): 0
Optoisolated interface scheme :
Hey,
Hmm, I've never seen v1
and v2
not being identical, I think the spec says they should be... The values you get (233 and 143) as not even bitwise inverts of each other or something that could perhaps make sense... What is good to see is that your updated initialization code still sends ~v2
and then we get the 0xCC
back from the ECU that confirms the initialization succeeded. So you still get the confirmation the ECU is turned on and responding to your requests.
I wonder if the slow part of your initKWP function is somehow just acting as a wakeup signal or something and the end of the KWP init still takes care of the actual initialization :thinking: Regardless, it is working, that's what matters!
I'm glad you got it working :) Thanks for reporting the problem you encountered and the resolution. (Edit; I changed the title of this issue to better capture the issue encountered, hopefully others can find your resolution this way!)
I read this information to initialize odb2 kwp2000 : https://m0agx.eu/2018/01/02/reading-obd2-data-without-elm327-part-2-k-line/
I never got back to this, nor did I read the link you sent. But when answering on #41, I realised that the 233 and 143 looked familiar and looked this issue back up.
I've just filed https://github.com/iwanders/OBD9141/pull/42 which implements the same discoveries we had in #41 as you had to make this work.
Hi, I was trying to communicate with ODB2 with my 206 1.1cc auto peugeot which should have the KWB2000 slow protocol. I built the optoisolated hardware interface and it works properly with perfect signal ascent and descent fronts. I started testing examples of read_softserial.ino library and modified readerKWP.ino for AltSoftSerial. The first example with debug enabled has this log : " Looping Before magic 5 baud. Before setting port. After setting port. First read is: 85 read v1: 233 read v2: 143 v1: 233 v2: 143 init_success: 0 " The problem is that the numbers V1 and V2 are different and initialization fails.
With the second example it fails without log.
I don't understand why V1 values other than V2.
Some suggestions?