Hi there, I need some help to stop using serial.readBytes() in my sketch, I understand it is a blocking function and therefore undesirable, and while it works for my project, I believe reading one byte at a time would work better.
I have created a circuit to interface with my car's ECU (early Nissan Consult protocol, OBDII does not apply). As far as communicating with the ECU, the circuit works.
I send a few bytes to the ecu (via Serial1 on a mega), it should reply (and does) and begins a stream of bytes at 9600 baud as below:
0xFF 0x04 data1 data2 data3 data4
This repeats continuously. The first byte is a generic response, the second byte is the number of bytes to follow. The data bytes are some engine parameters that keep the same position within the response and I know what they are.
I have read through Robin2's Serial Input Basics, however the problem using an example from there is that the data could possibly match the start/end markers.
Here is the code that allows me to display the values currently:
while (Serial1.available() > 0) {
Serial1.readBytes(consultReply,9);
for (int i = 0; i < 9; i++) {
Serial.print(consultReply[i]); //print to serial monitor for debugging
Serial.print(" ");
}
if (consultReply[0] == 0xFF && consultReply[1] == 0x04 && consultReply[6] == 0xFF && consultReply[7] == 0x04) { //check for start & end markers
waterTemp = consultReply[2] - 50;
tps = consultReply[3];
rpm = (((consultReply[4] * 256.0) + consultReply[5]) * 12.5);
Serial.print(" *** ");
Serial.print(millis() - timenow); //make a timestamp to check response time
timenow = millis();
}
Serial.println();
}
So this is what works, and I can output the variables to an LCD, however I think it could be better, and my output on the serial monitor with the millis timing the response times does end up with some gaps of ~200ms.
I check for 0xFF 0x04 at each end of the array to stop the data acting as start/end markers.
The consultReply array is deliberately longer than the data so it can 'line up' and match the start/end markers.
I'm using serial.Print for debugging and this is a snippet of my output:
4 83 24 0 0 255 4 83 24
4 83 24 0 0 255 4 83 24
4 83 24 0 0 255 4 83 24
255 4 83 24 0 0 255 4 83 *** 232
0 0 255 4 83 24 0 0 255
4 83 24 0 0 255 4 83 24
255 4 83 24 0 0 255 4 83 *** 92
0 0 255 4 83 24 0 0 255
4 83 24 0 0 255 4 83 24
255 4 83 24 0 0 255 4 83 *** 92
0 255 4 83 24 0 0 255 4
255 4 83 24 0 0 255 4 83 *** 66
83 24 0 0 255 4 83 24 0
255 4 83 24 0 0 255 4 83 *** 65
255 4 83 24 0 0 255 4 83 *** 38
255 4 83 24 0 0 255 4 83 *** 39
83 24 0 0 255 4 83 24 0
24 0 0 255 4 83 24 0 0
255 4 83 24 0 0 255 4 83 *** 91
255 4 83 24 0 0 255 4 83 *** 39
255 4 83 24 0 0 255 4 83 *** 38
255 4 83 24 0 0 255 4 83 *** 39
255 4 83 24 0 0 255 4 83 *** 39
255 4 83 24 0 0 255 4 83 *** 37
This recognises when a readable string arrives in consultReply and prints a timestamp since the last one arrived.
I do find it strange how the output doesn't "wrap around" i.e seems to skip numbers quite a lot.
I have attempted to use Serial1.read(), put the bytes into a buffer, check the buffer for the correct arrangement of the start/end markers, however when using Serial1.read() in any way the data is ok for a couple of seconds, then I seem to end up with many numbers repeating and I cannot extract any useable data - I will end up with lines like:
255 255 255 255 0 0 0 0
4 4 4 0 0 0 0 255 255 255
255 255 4 83 255 255 255
0 0 0 0 0 0 0 0
etc.
I don't understand why Serial1.readBytes() will consistently get the serial data in the correct order, but Serial1.read() into a buffer will read the same byte several times.
Any advice for me on this?
Happy to provide more info if required.
Cheers