SoftwareSerial readBytesUntil unexplainable characters

Hi,

I'm reading from the serial output of a device.
The output format is in ASCII sent about once per second with 9600bps in the following pattern:

[Variable length decimal][CR][LF]

When I run the loop as a single program, the output is fine. (At least during the 30min I've tested it)
When I run the exactly same as a part of my program, randomly (first afer ~20-30 seconds, then every 16s) an extra number appears in the pattern

[Variable length decimal][Variable lenght decimal][CR][LF] (example on the bottom, CR LF visible when using readBytes instead of readBytesUntil)

I don't know where the second number comes from, because I only read until CR, and every number is sent followed by a CR.
I'm using the following code (with debug output -48 to show decimal value of ASCII character digit)
I don't use any variable outside of this (except cpm)

#include <SoftwareSerial.h>

SoftwareSerial mySerial(8,9); //RX, TX


unsigned int cpm;

void setup() {
 Serial.begin(115200);
 mySerial.begin(9600);
 mySerial.setTimeout(1500);

 
}

void loop() {

    char cpm_array[6]= {0,0,0,0,0,0};			// Make sure the array is 0 before starting
    if(mySerial.find(0x0A)){				// Start reading after 0x0A (LF)
    mySerial.readBytesUntil(0x0D,cpm_array,5);		// Until 0x0D (CR)

    char buffer[6];
    buffer[0] = cpm_array[0],
    buffer[1] = cpm_array[1],
    buffer[2] = cpm_array[2],
    buffer[3] = cpm_array[3],
    buffer[4] = cpm_array[4],
    buffer[5] = '\0';

    Serial.print("cpm_array: ");
          for(int i= 0; i<6; i++) {
      Serial.print(cpm_array[i]-48);
      Serial.print(" ");
          }
      Serial.println();

      cpm = atoi(buffer);

  }

  Serial.print("cpm = ");
  Serial.println(cpm);
 
}

An example of the output containing an unexpected number:

cpm_array: 3 6 -48 -48 -48 -48 
cpm = 36
cpm_array: 3 7 -48 -48 -48 -48 
cpm = 37
cpm_array: 3 7 3 8 -48 -48       //Why?!
cpm = 3738
cpm_array: 3 7 -48 -48 -48 -48 
cpm = 37
cpm_array: 3 8 -48 -48 -48 -48 
cpm = 38

How could anything outside of this code have an influence on cpm_array[]?

To me it looks like readBytes is omitting one CR,LF somehow, but I don't know why and how.

Serial.readBytesUntil() returns the number of characters read into the buffer, you might get a hint there if you check what ut returns.

==> I suggest you check it. I'm guessing that when you see weird numbers it's because your Serial.readBytesUntil timeOut and thus you did not fill your buffer, thus you print whatever is in the array that you just allocated on the stack.

You should never assume that Serial will get you all the data you need, you should loop until you have received all what you want and then do your action.

"Serial.readBytesUntil() reads characters from the serial buffer into an array. The function terminates if the terminator character is detected, the determined length has been read, or it times out"

The data is put out from the device like
2 0 CR LF [1s break] 2 1 CR LF [1s break] 2 2 CR LF [1s break] etc.

As far as I understand have I defined a start character LF and a termination character CR and everything in between is saved in cpm_array
(respectively max. 5 characters, or max 1500ms timeout; since data output is every 1s and doesn't contain more than 5 characters, the latter two conditions never happen).

What more should I do?

Have a look at the examples in Serial Input Basics - simple reliable ways to receive data without blocking.

...R

Ah that looks good. I will need some time to go through, thank you.

Just bump timeout to 5 seconds and see if that solves your problem

Also check if the number of bytes received is not what you expect and in which case wait again for the missing part

I've rewritten everything according to recommendations from @Robin2.
The code looks much cleaner now with everything moved in functions.

But unfortunately the problem still persists though the design is different, but I know under which circumstances it happens:

I'd like to print out the latest reading every 60 seconds, so I have this kind of loop:

  if ((millis()-starttime) >=60000)
     {
           //here i print the content of the variable from the function which reads the serial device
           starttime = millis();
     }

So I guess multiple readings overlap when they change while reading the variable.
But how do i print out the latest reading every 60 seconds in a clean way without delay()?

Use 60000UL juste to be on the safe side

I guess multiple readings overlap when they change while reading the variable.

What do you mean?

Ah i forgot to implement the condition to only print when there is new data:

    if (newData == true) {
        Serial.print("This just in ... ");
        Serial.println(receivedChars);
        newData = false;

5 Minutes now without overlap.
Problem solved, case closed. :slight_smile:

Good