Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to make it work.... #41

Closed
SteveTinkers opened this issue Sep 30, 2022 · 20 comments
Closed

How to make it work.... #41

SteveTinkers opened this issue Sep 30, 2022 · 20 comments

Comments

@SteveTinkers
Copy link

SteveTinkers commented Sep 30, 2022

Hey there.

I've been trying to connect to my VW EDC16 ECU with an arduino.

I have the 33290. It looks like this chip but labeled ZAUO instead of XAIK. I put pin 1 at the square, wasn't 100% sure.

image
I connected it like this... I also swapped TX and RX pins just in case they were backwards.
image
I keep getting init_success: 0. How can this be debugged?

If I connect with my ELM327 over COM port with putty, it works. So it's something in the Arduino or chip part of my configuration.
ATSP4 = ISO 14230-4 KWP (5 baud init, 10.4 kbaud). The documentation here mentions 14230-2, could that be the problem?
ELM327-Connects.png

@iwanders
Copy link
Owner

I put pin 1 at the square, wasn't 100% sure.

I'd do the same, sounds reasonable.

Start with setting the define here to enable debug mode, you should get more info.

@SteveTinkers
Copy link
Author

SteveTinkers commented Oct 1, 2022

Apparently, pin 1 and the first 5 pins are on the bottom beveled edge. So I fixed that. In case I smoked the IC by hooking it up backwards, I have 5...ha ha.

I enabled debugging. I'm not sure what all this means. I searched the OBD9141.h, Arduino.h, and AltSoftSerial.h for the words "magic" and "read" but didn't find a clue as to what it might be doing. Any idea what that means?

During that test, I sniffed what was happening with the ELM327. It prints a line of "55 E9 8F" at every loop, and the ELM seems to think its an error. The ELM considers this a header packet because they dont show up in H0 (headers off) mode. I switched between modes just in case it would change the sniff reading, it didn't. Finally, I connected with the ELM327 and it connects just fine. The ECU side hardware and connection seems ok.

My next step might be to rig up a voltage divider and another Arduino as a 12V scope to see what is happening on the K line and series RX/TX? What do you think? Any advice?

I wonder if we can put the 33290 into monitor mode??

Arduino-Debug

@iwanders
Copy link
Owner

iwanders commented Oct 1, 2022

Please always upload images to github instead of linking to a third party, just drag them into the edit window, that way they never expire. And ideally, no screenshots of text, I can't copy paste from that.


I enabled debugging. I'm not sure what all this means. I searched the OBD9141.h, Arduino.h, and AltSoftSerial.h for the words "magic" and "read" but didn't find a clue as to what it might be doing. Any idea what that means?

Certainly, we are now seeing the prints from the init function, so we get more information about what we get from the ECU and what we expect.

During that test, I sniffed what was happening with the ELM327. It prints a line of "55 E9 8F" at every loop, and the ELM seems to think its an error. I switched between modes just in case it would change the sniff reading, it didn't. Finally, I connected with the ELM327 and it connects just fine. The ECU side hardware and connection seems ok.

I'm not sure if the ELM can sniff this correctly without interfering with the handshake. So what happens during the handshake is that we send a very slow 5 baud init, then the reader reads the first byte; 0x55 from here sent from the ECU to the reader. After that, two more bytes should follow, v1 and v2, both of which should be identical according to the spec. Then, the reader should send back ~v2, after which 0xCC should be sent from the ECU to the reader to finish the handshake.

So I'm a bit confused with the screenshot, is the screenshot's left side part is just the output from this library and without the ELM interfering? If so we're failing this check.

You can try to remove the check on line 421 and just send back the inverted value of 143. Basically skipping the v1 == v2 check.

I wonder if we can put the 33290 into monitor mode??

It's always in monitor mode! These chips don't have state, so just latch EN high, attach a serial port to the Rx pin at 10400 baud and you should be able to sniff the ELM (not the slow 5 baud init though, but the rest should show up).

My next step might be to rig up a voltage divider and another Arduino as a 12V scope to see what is happening on the K line and series RX/TX? What do you think? Any advice?

It's an option, first I'd try to attach just your 33290 with arduino, in debug mode and see what happens.

@SteveTinkers
Copy link
Author

SteveTinkers commented Oct 1, 2022

Oh the cpp file! I forgot about that one. Learning lots today about OBD, GitHub, Electronics.. Thank you! Much easier to post images directly here.

I was messing around and noticed the ELM327 thinks the 55 E9 8F is a header, because it doesn't show up if in H0 (headers off) mode.

Unplugged the 327 and my splitter cable. K line is straight to the ECU...
I set line 422 to return true...

17:49:53.211 -> init_success:1
17:49:53.284 -> Timeout on reading bytes.
17:49:53.402 -> Timeout on reading bytes.
17:49:53.479 -> Timeout on reading bytes.
17:49:53.522 -> 
17:49:53.773 -> Timeout on reading bytes.
17:49:53.906 -> Timeout on reading bytes.
17:49:53.982 -> Timeout on reading bytes.
17:49:54.025 ->

Forever... it never exits the loop to a new loop. Not in a minute anyway.

I got my old school needle multimeter out and I've got constant power on Pin 1 and Pin 5 (K-Line) shows activity and bouncing voltages.

@iwanders
Copy link
Owner

iwanders commented Oct 1, 2022

Unplugged the 327 and my splitter cable. K line is straight to the ECU...
I set line 422 to return true...

I don't think that will work, because we still need to read the 0xCC from the ECU first, if anything, disable the check on 421, or comment out 422. Can you copy the full output during the initialisation (So the section above init_success?) I wonder if we ever get v1 and v2 and what their values are.

@SteveTinkers
Copy link
Author

SteveTinkers commented Oct 1, 2022

image

Here is the full log...

04:58:36.783 -> Looping
04:58:39.781 -> Before magic 5 baud.
04:58:41.750 -> Before setting port.
04:58:41.781 -> After setting port.
04:58:41.858 -> First read is: 85
04:58:41.858 -> read v1: 233
04:58:41.891 -> read v2: 143
04:58:41.891 -> v1: 233
04:58:41.891 -> v2: 143
04:58:41.934 -> init_success:1
04:58:41.966 -> Timeout on reading bytes.
04:58:42.043 -> Timeout on reading bytes.
04:58:42.165 -> Timeout on reading bytes.
04:58:42.210 -> 
04:58:42.485 -> Timeout on reading bytes.
04:58:42.552 -> Timeout on reading bytes.
04:58:42.662 -> Timeout on reading bytes.
04:58:42.707 -> 

Bonus round, FYI, might be relevant. I spent a bunch of time sniffing and messing around.
If I use the Y Cable and have the ELM327 do the init, I can ask for the vin and pids with the arduino using this sketch
The init and being able to find headers and frames/packets in the stream of bytes is way beyond me! Might mess with it though. I can manually decode them and see my VIN though...
It's at least got me come confidence that the hardware is ok. I didn't burn a chip up or anything.

#include <AltSoftSerial.h>

AltSoftSerial altser;
const int OBDbaud = 10400;
byte getVIN[6] = { 0xC2, 0x33, 0xF1, 0x09, 0x02, 0xF1 };
byte getPid[6] = { 0xC2, 0x33, 0xF1, 0x01, 0x00, 0xE7 };

void setup() {
  delay(200);
  altser.begin(OBDbaud);

  Serial.begin(9600);
  while (!Serial) ;  // wait for Arduino Serial Monitor
  Serial.println("OBD Testing!");
  Serial.println("Asking for VIN");
  //Serial.println(getVIN);
  altser.write(getPid, 6);
  Serial.println("Asked for VIN");
  Serial.println("Streaming Bytes...");
}

void loop() {
  if (altser.available() > 0) {
    byte b = altser.read();
    Serial.println(b, HEX);
  }
}

At one point in time I tried using two 33290 chips, hooking their serial together...didn't work, and I wonder why?
K line from ELM327<---> 33290 <---> Serial RX/TX <---> 33290 <---> K line to ECU.

@iwanders
Copy link
Owner

iwanders commented Oct 1, 2022

Bonus round, FYI, might be relevant. I spent a bunch of time sniffing and messing around.
It's at least got me come confidence that the hardware is ok. I didn't burn a chip up or anything.

Yup, looking good, glad you got confirmation the hardware is working, these are good discoveries.

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

Ooh, but that looks like a KWP request! So 9141-2 should be 0x86, 0x6a, 0xf1, 0x01, 0x0d, but this starts with 0xc2, which is hex((0b11 << 6) | 2) = 0xc2. For KWP, we swap the header bytes here, but only if we are in kwp mode. We also see the 0x33 byte, which is always the second byte of a KWP request.

So that does change things, can you try readerKWP? That may just work out of the box. It's pretty weird that we do get the 0x55 from the normal initialisation procedure, but the request you showed here is clearly a KWP request.

At one point in time I tried using two 33290 chips, hooking their serial together...didn't work, and I wonder why?
K line from ELM327<---> 33290 <---> Serial RX/TX <---> 33290 <---> K line to ECU.

You'll probably need to cross Rx and Tx between the two 33290s (so connect the left 33290's Rx to the right 33290s Tx), and you can only connect the arduino's Rx line to one of the communication directions, if you connect the tx line to anything it'll just pull that line high or low since the arduino would drive the tx line.

@SteveTinkers
Copy link
Author

SteveTinkers commented Oct 1, 2022

YAY! KWP worked out of the box! I saw that as an option but it wasn't clear to me, I knew I wanted software serial so all I did was change init to initKWP! I put the check back in and disabled debug mode and it still works!

11:01:28.237 -> Looping
11:01:31.236 -> Before 25 ms / 25 ms startup.
11:01:31.282 -> Enable port.
11:01:31.314 -> Rem: 6
11:01:31.314 -> ret_len: 7
11:01:31.346 -> R: 131 241 16 193 233 143 189 0 
11:01:31.378 -> calc cs: 189
11:01:31.378 -> buf cs: 189
11:01:31.410 -> init_success:1
11:01:31.410 -> Rem: 6
11:01:31.441 -> ret_len: 7
11:01:31.441 -> R: 131 241 16 65 17 240 198 0 
11:01:31.474 -> calc cs: 198
11:01:31.474 -> buf cs: 198
11:01:31.506 -> Result 0x11 (throttle): 240
11:01:31.538 -> Rem: 7
11:01:31.538 -> ret_len: 8
11:01:31.538 -> R: 132 241 16 65 12 0 0 210 0 
11:01:31.602 -> calc cs: 210
11:01:31.602 -> buf cs: 210
11:01:31.602 -> Result 0x0C (RPM): 0

Why it thinks I have throttle 240 when there is no pedal, I dont know. Is this 0-255?

I'm working on debugging and getting another windows ECU tool to connect to my ECU. We're noticing if you set the headers to the Functional ECU address 33 (broadcast) C1 33 F1 it works. If you send the Physical ECU address 82 10 F1 it doesn't listen. Not to mention somehow its communicating the number of data bytes in the header (3?). It's SOOO detailed and hard to understand. I'm barely wrapping my head around it. Kind of fun. I've also seen it respond to C1, C2... doesn't seem to matter.

I hate the new Arduino IDE serial monitor. I cant copy paste many lines with it. It stays connecting and I have to kill it to do an upload..ugh. What serial program do you use in Windows/Linux when messing with things? Putty is to old-ish too.

At one point in time I tried using two 33290 chips, hooking their serial together...didn't work, and I wonder why?
K line from ELM327<---> 33290 <---> Serial RX/TX <---> 33290 <---> K line to ECU.

I tried crossing the Rx and Tx lines. I had no arduino in the mix. I thinking maybe I need to connect the arduino to set the speed an initialize the serial communication, even if Rx only. I'll try that next. Next Next, mess with your simulator :D :D.

@iwanders
Copy link
Owner

iwanders commented Oct 1, 2022

YAY! KWP worked out of the box!

Hah, very nice, that makes things a lot easier :D Glad we got it working.

Why it thinks I have throttle 240 when there is no pedal, I dont know. Is this 0-255?

Hmm, I think this is supposed to be 0-100, so in percent? Maybe it's 240-255 for this car? To indicate there's only 16 levels? (I'm 100% guessing here, I have no idea :D)

We're noticing if you set the headers to the Functional ECU address 33 (broadcast) C1 33 F1 it works. If you send the Physical ECU address 82 10 F1 it doesn't listen.

Yeah... I always feel different cars have their own idiosyncrasies.

Not to mention somehow its communicating the number of data bytes in the header (3?).

Yes, with kwp the number of length in the request is encoded in the first byte, I'd be surprised if the ECU ignores that field, because then the checksum should also be invalid.

I hate the new Arduino IDE serial monitor. I cant copy paste many lines with it. It stays connecting and I have to kill it to do an upload..ugh. What serial program do you use in Windows/Linux when messing with things? Putty is to old-ish too.

😮 I almost always use Linux, I usually use miniterm.py, which probably also works on windows as it ships with pyserial. On windows you can get a bash shell by installing git for windows. I expect a combination of these both will work for you.

Next Next, mess with your simulator :D :D.

Heh, the simulator's handshake simulation is flakey, which is why that part is disabled by default. The simulator without the handshake should be fine. Just make sure you force your reader to assume it initialised correctly. I mainly built this to allow me to develop this display without having to test it on my car all the time.

@SteveTinkers
Copy link
Author

SteveTinkers commented Oct 1, 2022

Big Thank you for your help!!!!!! What does your display look like in real life?

I messed with the serial to serial connection, Arduino in RX only mode.
image

Completely Disconnect RX and TX from both modules, the only pins I read data on is 33289 #1 RX (6) and 33289 #2 RX (6). Never TX.
If I hook the two RXs together (6 and 6) I can read data and the connection works.
Same with the two TXs together (5 and 5). They are always empty/dead/no activity.
The moment I cross TX and RX between them (as pictured) the connection breaks. Something changed.
Disconnect the green K line between the two 33289s and it doesn't connect.
Quite interesting...

Yes, with kwp the number of length in the request is encoded in the first byte, I'd be surprised if the ECU ignores that field, because then the checksum should also be invalid.

Huh, it definitely listens to that. I swear I've seen C1s. I tried C1-C3 and only C2 works VIN and everything that is a two byte request (01 01, 09 02... most things are two bytes. What is a 3 or 1 or 5? I'll do some poking around.

Heh, the simulator's handshake simulation is flakey, which is why that part is disabled by default. The simulator without the handshake should be fine.

Hmm I wonder how the 5 baud init can work. Or if I can pass though the init from the connection requester to the connection receiver (ECU here), kind of a MITM approach. This is an engine swap into a MK1 VW. I'm trying to make some gauges, which is a read only operation. However the ECU also freaks out when half the modules it's used to talking to isn't there so I was going to fake their responses in the Arduino.

Big thank you!!! Fun too. I can close this but might poke around with more questions.

@SteveTinkers
Copy link
Author

SteveTinkers commented Oct 1, 2022

Oh man, looks like I lied. initKWP did not work by itself. I had an ELM327 connected and it was maintaining the connection.

15:35:03.296 -> Looping
15:35:06.307 -> Before 25 ms / 25 ms startup.
15:35:06.353 -> Enable port.
15:35:06.431 -> init_success:0
15:35:09.424 -> Looping
15:35:12.408 -> Before 25 ms / 25 ms startup.
15:35:12.440 -> Enable port.
15:35:12.516 -> init_success:0
15:35:15.520 -> Looping
15:35:18.512 -> Before 25 ms / 25 ms startup.
15:35:18.604 -> Enable port.
15:35:18.682 -> init_success:0
15:35:21.642 -> Looping
15:35:24.639 -> Before 25 ms / 25 ms startup.
15:35:24.731 -> Enable port.
15:35:24.763 -> Rem: 6
15:35:24.763 -> ret_len: 7
15:35:24.763 -> R: 131 241 16 193 233 143 189 0 
15:35:24.794 -> calc cs: 189
15:35:24.827 -> buf cs: 189
15:35:24.827 -> init_success:1
15:35:24.858 -> Rem: 6
15:35:24.858 -> ret_len: 7
15:35:24.858 -> R: 131 241 16 65 17 240 198 0 
15:35:24.891 -> calc cs: 198
15:35:24.922 -> buf cs: 198
15:35:24.922 -> Result 0x11 (throttle): 240
15:35:24.955 -> Rem: 7
15:35:24.986 -> ret_len: 8
15:35:24.986 -> R: 132 241 16 65 12 0 0 210 0 
15:35:25.019 -> calc cs: 210
15:35:25.019 -> buf cs: 210
15:35:25.052 -> Result 0x0C (RPM): 0

I unplugged everything and power cycled the arduino and ECU.
I started the arduino and watched "init_success:0" a couple of times.
I then connected the ELM327, set it to mode 4 and asked for 01 01.
BOOM connects right up.
I unplugged the ELM327 (and all other USB except the arduino) and it keeps going.
I unplugged the Arduino for a bit and plugged it in and the serial monitor starts and keeps going.
Restart the ECU....it never connects again.


Just for grins I did the same thing with init instead of initKWP.

15:53:46.301 -> Before magic 5 baud.
15:53:48.292 -> Before setting port.
15:53:48.292 -> After setting port.
15:53:48.370 -> First read is: 85
15:53:48.370 -> read v1: 233
15:53:48.402 -> read v2: 143
15:53:48.402 -> v1: 233
15:53:48.446 -> v2: 143
15:53:48.446 -> init_success:0
15:53:51.374 -> Looping
15:53:54.368 -> Before magic 5 baud.
15:53:56.382 -> Before setting port.
15:53:56.427 -> After setting port.
15:53:56.864 -> Timeout on read 0x55.
15:53:56.895 -> init_success:0
15:53:59.888 -> Looping
15:54:02.868 -> Before magic 5 baud.
15:54:04.890 -> Before setting port.
15:54:04.890 -> After setting port.
15:54:05.376 -> Timeout on read 0x55.
15:54:05.421 -> init_success:0

How would I get my VIN?
Something like "obd.getPID(0x02, 0x09, 4);"?

@iwanders
Copy link
Owner

iwanders commented Oct 1, 2022

I unplugged the ELM327 (and all other USB except the arduino) and it keeps going.

Hmm... can you try to build

ECU --- + ---- K Line 33290 Rx ----- arduino Rx (serial port at 10400 baud)
        |
        ELM

To capture what the ELM is sending during the handshake? Just put a minimal sketch on the arduino that just dumps everything from the Rx pin of the 33290 to the usb serial port? A lot of things are working, we're just failing at the handshake it seems? You could also try to just skip the init, and just force your reader to assume init has worked... maybe the ECU doesn't care about the initialization and just responds.

Just for grins I did the same thing with init instead of initKWP.

Yeah, I think that 233 & 143 for v1 and v2 is some kind of KWP error response.

How would I get my VIN?
Something like "obd.getPID(0x02, 0x09, 4);"?

You said it was:

byte getVIN[6] = { 0xC2, 0x33, 0xF1, 0x09, 0x02, 0xF1 };

We can decode this using this line and this for the first two, mode would be 0x09 indeed, pid would be 0x02. The 4` I'm not sure of, that's the length, I don't know how long the VIN PID is. You can also look at wikipedia here, looks like it will be whopping 17 byte return O_o Which means you may actually need to increase the internal buffer size. After that you can use this method to read your bytes.

@SteveTinkers
Copy link
Author

SteveTinkers commented Oct 2, 2022

A lot of things are working, we're just failing at the handshake it seems? You could also try to just skip the init, and just force your reader to assume init has worked... maybe the ECU doesn't care about the initialization and just responds.

Yes, seems like things are working just need massage out the handshake. I tried to skip the init, it never responded.
I wonder if it's possible to put the arduino in between the ELM and the ECU and have the arduino forward whatever is recieves to the ECU. I wonder if the arduino's loop would destroy any protocol timing? Then I can ask for whatever I want to see, and the init is handled.

17:35:29.937 -> OBD Testing!
17:35:29.937 -> Streaming Bytes...
17:35:36.946 -> 0
17:35:37.568 -> 0
17:35:38.336 -> 0
17:35:39.017 -> 55
17:35:39.056 -> E9
17:35:39.056 -> 8F
17:35:39.092 -> 70
17:35:39.092 -> CC

17:35:39.171 -> C2
17:35:39.171 -> 33
17:35:39.171 -> F1
17:35:39.171 -> 9
17:35:39.171 -> 2
17:35:39.204 -> F1

17:35:39.204 -> 87
17:35:39.204 -> F1
17:35:39.235 -> 10
17:35:39.235 -> 49
17:35:39.235 -> 2
17:35:39.235 -> 1
17:35:39.235 -> 0
17:35:39.235 -> 0
17:35:39.235 -> 0
17:35:39.235 -> 57
17:35:39.235 -> 2B

17:35:39.268 -> 87
17:35:39.268 -> F1
17:35:39.268 -> 10
17:35:39.268 -> 49
17:35:39.268 -> 2
17:35:39.268 -> 2
17:35:39.268 -> 56
17:35:39.268 -> 57
17:35:39.300 -> 41
17:35:39.300 -> 45
17:35:39.300 -> 8

The first part pre 39.171 should be whatever magic is happening with the handshake.
At about 39.235 the three 0s and the 57 2B starts my vin. I've been using vin because it's easy to find in the stream.


Here is what the Chinese ELM outputs. I noticed I can just ATZ 09 02. I dont have to specify anything. They sure handled a BUNCH of logic obfuscated from the user.
image


This is the sketch I used... How you group up the stream is currently beyond me. You also specify how long it is. I'm studying that....

#include <AltSoftSerial.h>

AltSoftSerial altser;
const int OBDbaud = 10400;
byte getVIN[6] = { 0xC2, 0x33, 0xF1, 0x09, 0x02, 0xF2 };
byte getPid[6] = { 0xC2, 0x33, 0xF1, 0x01, 0x00, 0xE7 };

void setup() {
  delay(200);
  altser.begin(OBDbaud);

  Serial.begin(9600);
  while (!Serial) ;  // wait for Arduino Serial Monitor
  Serial.println("OBD Testing!");
  //Serial.println("Asking for VIN");
  //Serial.println(getVIN);
  //altser.write(getVIN, 6);
  //Serial.println("Asked for VIN");
  Serial.println("Streaming Bytes...");
}

void loop() {
  if (altser.available() > 0) {
    byte b = altser.read();
    Serial.println(b, HEX);
  }
}

I had an idea to try it with the ELM establishing and the OBDLink monitoring.
I also tried it the other way around with ELM monitoring and OBDLink establishing, the only difference is the Chinese ELM doesn't show the three 00 lines, or the 70 and CC lines, just 55 E9 8F at timestamp 19.884.
I wouldn't have guessed it would treat that as one line...
image

@iwanders
Copy link
Owner

iwanders commented Oct 2, 2022

I wonder if it's possible to put the arduino in between the ELM and the ECU and have the arduino forward whatever is recieves to the ECU. I wonder if the arduino's loop would destroy any protocol timing?

Yeah, you can... but the problem is the 5 baud init, that will cause problems since that's not a proper serial port procedure at 10400 baud. So you'd have to first do either a very tight loop to just reflect the Rx state with polling, or pass that 5 baud init through with some interrupts, then only after that start the serial port.

The first part pre 39.171 should be whatever magic is happening with the handshake.

Yes, you are correct.

17:35:29.937 -> OBD Testing!
17:35:29.937 -> Streaming Bytes...
17:35:36.946 -> 0
17:35:37.568 -> 0
17:35:38.336 -> 0
17:35:39.017 -> 55
17:35:39.056 -> E9
17:35:39.056 -> 8F
17:35:39.092 -> 70
17:35:39.092 -> CC

So interestingly enough, this is not a kwp init... it appears to be closer to a standard 9141-2 handshake. The kwp init is this sequence with a start pulse, basically.

What you got here is

 0x55 0xe9 0x8f 0x70 0xcc

Which corresponds to the v1 and v2 numbers we already had before... 0xe9=233 and 0x8f=143.

So the handshake is;

  1. 5 baud init, the 3 zero bytes in your capture.
  2. Receive 0x55 with this line
  3. Read v1 = 0xe9 and v2 = 0x8f using this.
  4. Ignore the check that compares v1 and v2 here.
  5. Write the bit-inverted v2, ~v2=~0x8f=~0b10001111=0b01110000=0x70 with this line.
  6. Read 0xcc from the ECU to finalize; this line.

What is super odd... is that the timestamps group the bytes as:

  • 17:35:39.017 -> 55 should come from the ECU
  • 17:35:39.056 -> E9 8F both should come from the ECU
  • 17:35:39.092 -> 70 CC Reader should send the 70, CC should come from the ECU.

But the 70 and CC byte are on the same timestamp, almost as if the reader sent the 0xCC?? But this could just be a serial port buffering fluke or something... Unless we're timestamping on the arduino I don't trust these timestamps.

Either way... in this comment we had success doing the initialisation with init() with the v1==v2 check disabled, but reading PIDs failed because we weren't using KWP requests?

So I think next step to try is:

  1. Disable that v1==v2 check again.
  2. Perform handshake with init() to do a normal 9141-2 init.
  3. Perform requests with requestKWP to check if retrieving data works. requestKWP takes a buffer that's already formatted for the KWP retrieval, so from this, it should be the first 5 bytes for speed, the last one is the checksum, but requestKWP will compute that, so something like:
uint8_t message[5] = {0xc2, 0x33, 0xf1, 0x01, 0x0d};
uint8_t received_length = obd.requestKWP(message, 5);

I think at least... obviously can't try this.

To make that more elegant / less error prone, it's probably easier to:

  • add a method to manually flip this boolean
  • Initialise using init()
  • Flip the boolean using the new method.
  • Use the normal .getPID() method.

@SteveTinkers
Copy link
Author

SteveTinkers commented Oct 2, 2022

YAY!! I think we got it. I tried it several times to make sure.
Unplugged all my devices, and turned the ECU on.

09:32:57.458 -> Looping
09:33:00.438 -> Before magic 5 baud.
09:33:02.431 -> Before setting port.
09:33:02.463 -> After setting port.
09:33:02.939 -> Timeout on read 0x55.
09:33:02.985 -> init_success:0
09:33:05.968 -> Looping
09:33:08.934 -> Before magic 5 baud.
09:33:10.922 -> Before setting port.
09:33:10.953 -> After setting port.
09:33:11.024 -> First read is: 85
09:33:11.056 -> read v1: 233
09:33:11.056 -> read v2: 143
09:33:11.056 -> v1: 233
09:33:11.102 -> v2: 143
09:33:11.172 -> init_success:1
09:33:11.204 -> Rem: 6
09:33:11.204 -> ret_len: 7
09:33:11.236 -> R: 131 241 16 65 17 240 198 0 
09:33:11.269 -> calc cs: 198
09:33:11.269 -> buf cs: 198
09:33:11.300 -> Result 0x11 (throttle): 240

So, this is one strange ECU. I wonder how all the OBD2 software and scanners are connecting. It only kind-of adheres to the protocols.

That throttle of 240 is interesting. Maybe I have to pull it to ground or something. I'll worry about it later. I think it's valid because other OBD software shows throttle open 92%.


I need more experience with object orientated. I wasn't sure how to add the method to flip the bit, or track the bit. I tried...

I saw the use_kwp_ bit was set in the first line of OBD9141::init() Here
So I changed it here
image

I'm glad you explain concepts so well. I'm going to mess with it more and probably come back to this 12 times to learn more.
I actually watched it replace the 68 6A header with C2 33. Did I understand it right, that's what we did? 9141 Init but replacing with KWP bytes. I think is is physical vs functional addressing, like a broadcast address. How does anything connect to this ecu..ha.

this->write(~v2);
The comments reference w1, w2....and w4?
image

I noticed the readBuffer method does not contain the header in any position. How can we make it contain the header?
I want to use the header to find the length of the data so I dont have to worry about specifying a getPID with a 1 2 or 3 return_length.
image

Would adding a SoftwareSerial on pins 4 and 5 cause problems on a nano?
I can have a working system but as soon as I plug in the pins (or comment in SoftwareSerial.begin) it will no longer obd.init.


Once the arduino is connected and initialized I can read and write straight serial and look for key bits (ex "C2").
You've found them by actually specifying how long something should be based on the standard.

I'm trying to identify outgoing data so I can process it and send it to my gauges.
I am able to sniff out "C2" to find requests from the data stream, which is bit 0.
Then I know the next 5 bytes are request, and the request itself is bites 3 and 4.
So byte 6 is a response header and that byte - 80 is the response. I can then calculate the end too.

C2 33 F1 ( 01 01 ) E8
86 F1 10 ( 41 01 00 07 E0 00 ) B0

This logic will mess up if C2 is ever in the data or a checksum....

VIN is weird because there are 4 lines in the response
byte getVIN[6] = { 0xC2, 0x33, 0xF1, 0x09, 0x02, 0xF1 };
vs something like "obd.getPID(0x09, 0x02, 15)"? I can't read anything in mode 9... Not that I really need it.

I just made up 4, I don't know how long it is. Vin is the only PID I've seen that gets returned in multiple chunks...

Should I brew this up from scratch?

What is the difference between 8 16 and 32?
image


I'm going to close this now. I'm going to try and not pester you, I would love to ask questions as I mess around!
BIG THANK YOU! You've been awesome.

@iwanders
Copy link
Owner

iwanders commented Oct 3, 2022

It only kind-of adheres to the protocols.

I think the main problem is that there's a bunch of protocols, and they are all different. None of the specs are publicly available :( I built this from information on the internet and used it on my first car, a Kia, and currently on my Nissan.

That throttle of 240 is interesting. Maybe I have to pull it to ground or something. I'll worry about it later. I think it's valid because other OBD software shows throttle open 92%.

Could be a stuck sensor yeah, or signalling issue.

I saw the use_kwp_ bit was set in the first line of OBD9141::init() Here
So I changed it here

Yeah, that's fine. The problem is that the init method for your ECU is so custom it's not even easy to make a new init method

I finally remembered that I saw these numbers before in #34. So this is not a special init, this is a relatively standard / common one. I've filed #42 to add support for this initialisation procedure to the library, and added an example to use this init. If you could help test that example that'd be appreciated.

The comments reference w1, w2....and w4?

Should be v1, v2 and w4 for wait four... probably from some timing diagram I found somewhere.

I can have a working system but as soon as I plug in the pins (or comment in SoftwareSerial.begin) it will no longer obd.init.

You can only use these pins with AltSoftSerial, they need a timer's comparison, so it's limited to a number of pins.

I noticed the readBuffer method does not contain the header in any position. How can we make it contain the header?

readBuffer allows access to all received bytes? I think it should be there?

I just made up 4, I don't know how long it is. Vin is the only PID I've seen that gets returned in multiple chunks...

See my last sentence in this comment

What is the difference between 8 16 and 32?

See the implementation when in doubt :) Since there's no zero's in front of the bytes, we can't just always cast it to a uint32.

@SteveTinkers
Copy link
Author

SlowKWP works great! Thank you.

Would adding a SoftwareSerial on pins 4 and 5 cause problems on a nano?
I can have a working system but as soon as I plug in the pins (or comment in SoftwareSerial.begin) it will no longer obd.init.
You can only use these pins with AltSoftSerial, they need a timer's comparison, so it's limited to a number of pins.

Not quite what I mean. I have a working AltSoftSerial. As soon as I add another SoftSerial (for communicating with another module) the whole thing breaks.

readBuffer allows access to all received bytes? I think it should be there?

In the grey log there is a loop that reads out the contents of the readbuffer. I went to a max of 11, just because and indexed it at 0, also just because. In the white box I have an output of the command. The header is missing from the readbuffer...

image

@iwanders
Copy link
Owner

iwanders commented Oct 4, 2022

Not quite what I mean. I have a working AltSoftSerial. As soon as I add another SoftSerial (for communicating with another module) the whole thing breaks.

Yeah, they both probably use the same hardware timer and end up breaking functionality. On microcontrollers the number of timers is limited and to guarantee functionality a library needs exclusive access to the hardware timer. Two libraries usually can't share a timer. AltSoftSerial uses one of these timers. A timer is a dedicated piece of hardware in the microcontroller with various registers that allow you to configure how it is used.

I'd consider switching away from the atmega328 based arduino's and switch to something newer with more functionality. I've used Teensy 3.2's for years, they're performant, convenient and are really compatible with arduino sketches. Related to my comment on your PR, they have Serial for the serial to the computer, then Serial1, Serial2 and Serial3 still available as real hardware UARTS on various pins.

Another option are the stm32 series microcontrollers, they're available cheaply from various suppliers and can also run Rust. I used an stm32f103 for my displaylight firmware.

In the grey log there is a loop that reads out the contents of the readbuffer. I went to a max of 11, just because and indexed it at 0, also just because. In the white box I have an output of the command. The header is missing from the readbuffer...

Ehh, do you mean the whole request? The blue text? Because, no that's not in the buffer. I never thought that would be relevant, so we don't store it lives here on the stack, if you want to keep that around you'll have to store it in a second buffer.

The first byte though is present;

readBuffer 0: 131 F1

Weird is that F1... that should not be F1, 131 in hex is 0x83? Which matches the first byte of the green text.

@SteveTinkers
Copy link
Author

SteveTinkers commented Oct 4, 2022

Ehh, do you mean the whole request? The blue text? Because, no that's not in the buffer. I never thought that would be relevant, so we don't store it lives here on the stack, if you want to keep that around you'll have to store it in a second buffer.

Nope I mean the green 83.

Yeah, they both probably use the same hardware timer and end up breaking functionality.

Would that still be true if I can use SoftwareSerial and AltSoftSerial together in schetches that do not use OBD9141? Wonder if 9141 is using some timers or something...

I'd love to see the screen in your car, if you're willing to share.

I found the official documents for 9141 and 14230. I just dont have the skills to interpret them. You want em?
I'm learning lots. I found more on CAN bus than I did these, suprisingly.

@iwanders
Copy link
Owner

iwanders commented Oct 4, 2022

Nope I mean the green 83.

Hmm, but it's there, just something with printing looked off, from here;

The first byte though is present;

readBuffer 0: 131 F1

Weird is that F1... that should not be F1, 131 in hex is 0x83? Which matches the first byte of the green text.

Somehow the hexadecimal printout is wrong, but the 131 is the green 83 in hex.

Would that still be true if I can use SoftwareSerial and AltSoftSerial together in schetches that do not use OBD9141? Wonder if 9141 is using some timers or something...

The only thing that OBD9141 uses is a serial port. It needs exclusive access over that serial port, but it does not matter the serial port is made (or what timers that uses). But yes, the two serials likely both use a timer (or even the same timer).

I'd love to see the screen in your car, if you're willing to share.

I actually don't have any photos of my current screen and it's dark outside, but here's a photo from 2016 with the screen in my Kia;

obd_screen

That car didn't have an RPM gauge, so this screen provided that. This one had a PCB behind the screen with transceiver IC and voltage regulator. Plug at the bottom right is just gnd, 12v from accessory connection and the K-line. Very self-contained and modular, mounted on an aluminum bracket on the center console.
My current version has the pcb mounted in a storage compartment and has the screen mounted flush on the dashboard with a 3d printed bracket. This looks better, but it's harder to take apart to debug it, which is why the first version was more modular. It's worked for the past 4 years without any problems though, the current version. Both used a standard ILI9341 screen and a Teensy 3.x.

I found the official documents for 9141 and 14230. I just dont have the skills to interpret them. You want em?

Sure, not like I'll be doing any more work on this library, I consider it pretty much done / life support. I answer the occasional issue, but mostly don't touch it. It's been working well enough and I consider it pretty much complete. But having the official docs never hurts, you can find my email from any commit in this repo.

I'm learning lots. I found more on CAN bus than I did these, suprisingly.

Yeah, I feel these K-line obd ports are less standardized and mostly from the 90s early 00s. The CAN busses are more standardized and have more features I think.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants