Serial + Software Serial Erratic Behavior without Delay

Hello!

I would like to get some clarity on the exact reason(s) why the following solutions work.

I am using am using an Arduino Uno to receive (via Software Serial) a short message sent by another device. The serial message is comprised of short semicolon-separated values (for now just two) with start and end markers as follows:

<D;3000>

When none of the solutions are implemented, the Serial.print(tempMessage); prints just the incomplete end marker like this:

Whole Message: >

And when either a certain length (68 ascii characters) of Serial.print() commands are made, or when a small delay (7ms) is set, as shown in the commented-out code, Serial.print(tempMessage); prints the value perfectly. Since these don't seem at first appearances to be related, I am at a pause..

I noticed this issue while removing a bunch of consecutive Serial.print lines from my original code which I had been using to keep an eye on values. Put eyes on the values and --poof-- the problem vanishes! Take them away and it reappears. Pretty frustrating.

Anyways, I had originally suspected some memory register was getting trampled all over by some rogue array, but adding and manipulating very long char arrays in the same location doesn't seem to affect anything. Now I am leaning more towards something related to the time it takes for the Serial Buffer and/or Software Serial buffer to be populated.

It seems to be a not-uncommon issue. I would love to know exactly what is going on here. Any ideas?

#include <SoftwareSerial.h>

SoftwareSerial portOne(11, 12); // RX = digital pin 11, TX = digital pin 12

bool inProgress; //whether receiving messages over serial is in progress
const int maxLength = 28; //max length of command component

void setup() {  
  Serial.begin(9600);
  portOne.begin(9600);
}

void recvQuery() {

  //The following commented code has confirmed that complete 
  //& correct serial data is being delivered to the Arduino

  // while (portOne.available() > 0) {
  //   char inByte = portOne.read();
  //   if (inByte == '>') {
  //     Serial.println(inByte);
  //   } else {
  //     Serial.print(inByte);
  //   }
  // }
  
  uint8_t pos = 0; //position for reading serial into in tempMessage
  char tempMessage[maxLength]; //char array to hold incoming message
  
  while (portOne.available() > 0) {
    char inByte = portOne.read();

    
    //start marker
    if (inByte == '<') {

      // TESTED SOLUTIONS:
      // delay(10); // current solution: delay of 10
      // delay(7); // minimal effective delay: delay of 7
      // Serial.print("11111111111111111111111111111111111111111111111111111111111111111111"); // effective Serial.print solution: any 68 ascii characters

      inProgress = true;
      memset(tempMessage, 0, sizeof tempMessage); // clear tempMessage memory
      pos = 0; // reset position index
      tempMessage[pos] = inByte;
      pos++;
    } 
    //data
    else if (inProgress == true && inByte != '>'){
      tempMessage[pos] = inByte;
      pos++;
    }
    //end marker
    else if (inProgress == true && inByte == '>'){
      tempMessage[pos] = inByte;
      tempMessage[pos+1] = '\0';
      inProgress = false;

      // readout to serial monitor
      Serial.print(" Whole Message: ");
      Serial.println(tempMessage);

    }
  }
}

void loop() {
  
  recvQuery();

}

Welcome

Your loop while (portOne.available() > 0) will stop as soon as the condition is false. This can happen after only one character has arrived in the Serial input buffer, because Serial is very slow. Your delay workaround allowed time for more characters to be stored in the Serial input buffer, thus your loop condition stayed true and didn't exit prematurely.

One possible solution is to make variables pos and tempMessage static or global, so they are not recreated everytime recvQuery is called.

1 Like

Thanks!

1 Like

And you should add a protection so that pos never exceed maxLength - 2, to avoid a buffer overflow if the received message is too long to be properly stored in tempMessage :).

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.