My arduino (this is not an Arduino issue but a general C++ one) is connected to the PC and sends every 2 seconds a counting 3 digit number:
for (long i=100; i <= 999; i++){
Serial.println(i);
delay(2000);
}
Connecting via a terminal program to the com port shows that the code does what is intended.
In my C++ application (lets call it client) I am using following code - which runs in an own thread - to pickup the data from the serial connection:
void *MyThread::Entry() {
SerialPort arduino(port_name); // Init serial port
if (arduino.isConnected()){
wxLogMessage("Message: %s", "Connection Established");
}
else {
wxLogMessage("Message: %s", "ERROR, check port name");
}
while (arduino.isConnected()){
int read_result = arduino.readSerialPort(incomingData, MAX_DATA_LENGTH); // Read data
if (read_result > 2){ // Length of read data
wxLogMessage("incomingData: %s", incomingData);
}
}
}
However, this produces an output like the following:
09:02:14: Message: Connection Established
09:02:14: incomingData: 100
09:02:15: incomingData:
1
09:02:17: incomingData: 01
09:02:18: incomingData:
10
09:02:20: incomingData: 2
09:02:21: incomingData: 103
09:02:23: incomingData:
1
09:02:24: incomingData: 04
09:02:26: incomingData:
10
09:02:27: incomingData: 5
09:02:29: incomingData: 106
09:02:30: incomingData:
1
09:02:32: incomingData: 07
09:02:33: incomingData:
10
09:02:35: incomingData: 8
09:02:36: incomingData: 109
09:02:38: incomingData:
1
So I have always 4 lines with wrong values between two correct lines. I think it's a racing issue. The C++ code is polling the serial connection ways higher than the arduino sends data (every 2 seconds).
As incomingData is
char incomingData[255];
I can't just empty incomingData and test for 3 digits.
So how can I achieve that the client is just getting every full 3 digit value send by the arduino in a correct way? Do I need to implement an own messaging system like enclosing the value send by the arduino with a start and stop sign? Or is there another cheap way I don't see?
As a general rule, you can't "read exactly the length you want" (including newlines and whatever) when using serial commms. There is a possibility that characters go missing, or "noise" gets added.
It is a much better way to validate the data from the serial input, and using a larger buffer to read into a separate buffer, and return lines (or whatever "packets" you want to return), when they are complete, to the calling code. This will of course get a little more complicated, as you need a second buffer to track what you "haven't yet given to the caller".
Although, as my comment implies, I think the problem here is that you are reading exactly 3 bytes, and you receive 5 bytes. Your actual messages look like this:
100<CR><LF>
101<CR><LF>
102<CR><LF>
103<CR><LF>
So the first time, you read 100
, then second read gets <CR><LF>1
, and then 01<CR>
, next gets <LF>10
, then 2<CR><LF>
, and we're back in sync with 103
again.
Where <CR>
is character 13 (Control-M) and <LF>
is character 10 (Control-J)