-
Notifications
You must be signed in to change notification settings - Fork 72
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
Mode 0x03: Request trouble codes. #9
Comments
I would like to see in your library modes 0x03, 0x07, 0x04 |
you can probably use the 0x01 mode, 0x01 PID, which tells us how many errors we'll have when we query in 0x03 mode |
Hi @produmann , thanks for the extensive post. I'll try to take a look at your code for the diagnostic codes (mode 03) over the weekend. It could be that the offset you were required to make was to account for the list encapsulation described on wikipedia, but I'm a bit skeptical that that is also used for 9141-2. In regards to mode |
Hey, Ok, took a look at your debug logs, very helpful! Thanks so much for posting the raw data it makes it so much easier to help out 👍 Regarding the following:
You are indeed correct! The Regarding the checksums... I think you're on the right track. We should use mode
If we run the checksum method on the first 10 bytes of that, we actually obtain the uint8_t result[] = {72, 107, 1, 67, 1, 19, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
Serial.print("Checksum: ");
Serial.println(OBD9141::checksum(result, 10)); // this will print 11.. One thing I'm not sure of is how many bytes are actually returned, it appears the response header is 4 bytes again, then follow the
Certainly, I don't have access to an Arduino or OBD9141 hardware at the moment, so can't really test anything. But I would do something along the lines of (based on explanation on wikipedia): // This code is incorrect, scroll down further!
/**
* Decodes the two bytes at input_bytes into the diagnostic troublecode, written
* in printable format to output_string.
*/
void decodeDTC(void* input_bytes, char* output_string) {
const uint8_t A = reinterpret_cast<uint8_t*>(input_bytes)[0];
const uint8_t B = reinterpret_cast<uint8_t*>(input_bytes)[1];
const static char type_lookup[4] = {'P', 'C', 'B', 'U'};
const static char digit_lookup[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
output_string[0] = type_lookup[A >> 6];
output_string[1] = digit_lookup[(A >> 4) & 0b11];
output_string[2] = digit_lookup[B >> 4];
output_string[3] = digit_lookup[B & 0b1111];
} Use like: uint8_t errorcodes[] = {0x48, 0x6B, 0x1, 0x43, 0x1, 0x13, 0x0, 0x0, 0x0, 0x0};
char buffer[5] = {0}; // just a buffer to hold the formatted string, zero terminated for testing on pc
decodeDTC(&(errorcodes[4]), buffer); // interpretets the 0x1, 0x13 bytes as an error code
// buffer now holds a null terminated string that can be printed...
// std::cout << " dtc: " << buffer << std::endl; // dtc: P013
Serial.print("dtc: ");
Serial.write(buffer, 4); // write the first four bytes from buffer to the serial port If you place this method inside the class it can obviously directly access the internal Moving forward, if we really want support for mode |
Ok, I understand, I will check your code in my home, but according to your method, the error code is not defined correctly, it should not be P013, it should be P0113 - Intake Air Temperature Circuit High Input |
I read Wikipedia, but I still did not understand the principle of determining the first letter in the error code, namely 'P', 'C', 'B', 'U' |
about the checksum, I selected it in the range 1-15 and neither gave the correct result, maybe it is more, although it's vryatli, it can not be checked at that time, but simply erase all the data from the serial buffer to make room for the request PID, because when too small ret_len is specified, the old data interferes with the next request |
maybe I do not understand something :) |
Hah, you are completely right, I didn't read the page carefully enough and forgot the third character from the first byte. Updated code below.
This is given by the two most significant bits of the first byte. If these two bytes are
Hmm, interesting. The request does indeed only read up to the Fixed code for parsing the error code: /**
* Decodes the two bytes at input_bytes into the diagnostic troublecode, written
* in printable format to output_string.
*/
void decodeDTC(void* input_bytes, char* output_string) {
const uint8_t A = reinterpret_cast<uint8_t*>(input_bytes)[0];
const uint8_t B = reinterpret_cast<uint8_t*>(input_bytes)[1];
const static char type_lookup[4] = {'P', 'C', 'B', 'U'};
const static char digit_lookup[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
// A7-A6 is first dtc character, error type:
output_string[0] = type_lookup[A >> 6];
// A5-A4 is second dtc character
output_string[1] = digit_lookup[(A >> 4) & 0b11];
// A3-A0 is third dtc character.
output_string[2] = digit_lookup[A & 0b1111];
// B7-B4 is fourth dtc character
output_string[3] = digit_lookup[B >> 4];
// B3-B0 is fifth dtc character
output_string[4] = digit_lookup[B & 0b1111];
}
// use like:
uint8_t errorcodes[] = {0x48, 0x6B, 0x1, 0x43, 0x1, 0x13, 0x0, 0x0, 0x0, 0x0};
char buffer[6] = {0}; // just a buffer to hold the formatted string, zero terminated for testing on pc
decodeDTC(&(errorcodes[4]), buffer); // interprets the 0x1, 0x13 bytes as an error code
// buffer now holds a null terminated string that can be printed...
// std::cout << " dtc: " << buffer << std::endl; // dtc: P0113
Serial.print("dtc: ");
Serial.write(buffer, 4); // write the first four bytes from buffer to the serial port |
Oh, and regarding clearing the troublecodes. As part of the #8 issue I mentioned the method to clear the trouble codes is available obd.clearTroubleCodes(), it would be awesome if you could check if that works as it should. |
thanks, I will definitely check this code and clear errors, as there will be free time, I'm a very busy person :) You are the first to learn about this.
I'm using iso9141-2
this is suitable only for 0x03 mode, for 0x07 mode this possible method will not work, it's easier to write a function to erase all data from the serial buffer for correct work with subsequent requests, how to implement it correctly? |
correction, Serial.write(buffer, 5); that's right |
excellent, this method correctly identifies 3 error codes |
Hmm, you are right. I didn't know I guess we finally need a method that can deal with a response of a variable number of bytes, as I proposed two years ago under issue #1... Easiest is probably to use loop on |
at the moment I'm doing just like this: res = obd.getPID (0, 0x03, 6); |
tell me please on an example how to return to me the buffer of the answer in an external variable "buffer" that I could process the answer here: |
Okay... I wrote some code without being able to test any of it. So I need your help in testing it! In 3833cd2 I've implemented the following:
Please take a look at the mentioned commit and checkout branch Please get back to me with your findings and be thorough in logging, I really want to get these changes tested and merged into the master branch, but I can't do it without your help in testing them. |
ok, I'll check everything and write you the results and, if possible, with the logs |
hello, it's time to check this code, all in order:
Next is my modified work code:
here is the log of my code:
the log of your code |
Hey, are you sure you ran it with the debug flag enabled when you tested the new Because I would really expect atleast the request to be printed. I don't really see how it could be completely empty. If you have the chance, could you check if you tested with the debug flag? I'm likely to build the hardware that allows me to test it myself, I ordered some parts already, but it'll probably be a few more months before I get around to it. |
Hi, I used your code |
Ah yes... That may not work with the official Arduino IDE; if the libraries are build separately from the sketches that doesn't work. |
Hi, OBD9141_DEBUG does not work, I had to edit the library OBD9141.cpp, for example:
error code:
here is the log of your code, the query does not work:
nothing happens next...... Here's a working log, with a query via obd.getPID (0, 0x03, 6); :
|
Hey, Thanks for testing again! I've fixed the typo and set
That last byte should be the same, the last byte is the checksum byte. This shows that the value sent on the bus and then read as echo are different... This is a great find! I had a mistake and forgot to sent the checksum byte. I've fixed this!
Interesting... I'm surprised it pauses after that, I've added printing the length of the response from the ECU. To provide some more information, even with our malformed request it shouldn't block on that line, there could've been an out of bounds read on the array, I've fixed that as well. Please see the changes. We definitely fixed a bug in this iteration, thanks so much for testing. If you have time, can you please test again with latest version from the dtc_support branch? |
of course, the results will tell |
hi, the query is working, but
I assign the value res = 1 manually and everything works:
|
Hey, I'm super grateful that you are taking the time to test this and help bring this feature to the library! 👍 We're almost there! I've fixed the bug that caused the checksum to be calculated incorrectly in 1283b9c, I made an off-by-one error on reading the checksum byte. I've fixed it, please try the latest version on the branch. If it works, and you have any way to get the ECU to return more than one trouble code, could you try that as well? Then we know if the number of trouble codes is correctly calculated by the display code. |
hello, I checked it works, but
please indicate me in the participating in the development |
Hmm... the return of the function does really need to work, otherwise others can't use this new functionality. In the log you show, did you set
Yes, definitely! I'll write a section in the main readme on the trouble codes, how they work and are supposed to be used. I'll add a word of thanks in that paragraph. Before we do that though, I want the example to work without modification. |
no, I did not touch anything, ran the code as it is, |
all the same res = 3:
I would write such an algorithm of actions: read the response buffer to the first zero byte and calculate how many bytes were read Or knowing that |
You can also manually insert the response buffer |
Hey,
Oh that is great! That means everything is working now! 🎉
Yeah, I get what you mean. However, the ECU has returned a trouble code that is I've also updated the readme to reflect your help in this and added a section on the trouble codes. Besides this I've updated the comments here and there, please see the latest changes. Can you give it a final test and revise the changes? Then I'll merge this into |
okay, I'll check it out |
Everything works great
The only thing I would correct that the symbol "-" instead of P0000 is better not to print at all, the user does not need to know this, he will be interested in specific trouble codes and |
this is not a valid definition of res, since res takes a value of 3 even if the number of errors is zero, the ECU will simply return these bytes
|
I see your point, but disagree. Thing is, if the ECU returns:
The ECU really returned 6 This is the reason I switched the internal data representation to Additionally, by keeping this |
Hi, I added the 0x07 method. Show pending Diagnostic Trouble Codes can be added to the main library and I think issues will be closed |
hello, your code does not have a bug-viewing mode, that's how I implemented it
cutting from my program code:
I had to tweak the library OBD9141.cpp a bit for this:
buffer[4 + index] instead buffer[5 + index]
Only I can not determine the checksum for the response
when there are no engine errors, the checksum = 5
when there are errors, the checksum from 1 to 15 is not suitable, maybe you need another method?
Can you suggest your method of displaying errors?
My method works well, but without a checksum ...
here are my debug logs:
The text was updated successfully, but these errors were encountered: