Serial output displaying values in twice in unexpected location

Hi, new to the forum here, sorry if I format wrong or posted in the wrong place.

I'm trying to get an Arduino UNO to send speed and wheel rotation count to another Arduino Mega in the form:

<speed,rotationCount,>

I can successfully send and receive it, but when I try to output the parsed data to the serial monitor from the Mega, it seems to be repeating one of the variables at the end of the line, and I can't figure out why it would be doing that.

What I am expecting is:
07:21:30.157 -> Data: 15,472, counter: 472 speed: 15
07:21:30.157 -> Data: 15,473, counter: 473 speed: 15
07:21:30.157 -> Data: 15,474, counter: 474 speed: 15

but what I actually get is:
07:21:30.157 -> Data: 15,472, counter: 472 speed: 15472
07:21:30.157 -> Data: 15,473, counter: 473 speed: 15473
07:21:30.157 -> Data: 15,474, counter: 474 speed: 15474

If I comment out the Serial.print(receivedChars) line, I get:
07:22:10.878 -> Data: counter: 479 speed: 16479
07:22:10.878 -> Data: counter: 480 speed: 16480
07:22:10.878 -> Data: counter: 481 speed: 16481

When I comment out the Serial.print(rotationCounter) line, I get:
07:24:18.405 -> Data: 16,487, counter: speed: 1616,487,
07:24:18.405 -> Data: 16,488, counter: speed: 1616,488,
07:24:18.405 -> Data: 16,489, counter: speed: 1616,489,

And if I comment out both, I get:
08:04:59.356 -> Data: counter: speed: 16)
08:04:59.529 -> Data: counter: speed: 16⸮
08:04:59.704 -> Data: counter: speed: 16{
08:04:59.878 -> Data: counter: speed: 16$
08:05:00.017 -> Data: counter: speed: 16⸮
08:05:00.225 -> Data: counter: speed: 16v
08:05:00.395 -> Data: counter: speed: 16#

My knowledge of C++ and serial communication isn't much, so I'm hoping someone here can help me understand whats going on.

receivingSerialData_Test.ino (2.81 KB)

Please post your code.
In code tags

Have a look at the examples in Serial Input Basics - simple reliable non-blocking ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.

The technique in the 3rd example will be the most reliable. It is what I use for Arduino to Arduino and Arduino to PC communication.

You can send data in a compatible format with code like this (or the equivalent in any other programming language)

Serial.print('<'); // start marker
Serial.print(value1);
Serial.print(','); // comma separator
Serial.print(value2);
Serial.println('>'); // end marker

...R

I'm able to send the code from the UNO, receive it on the Mega, and parse it correctly, but when I output it to the serial monitor, there are some extra characters that get output at the end of the line that depends on which variables I output. Based on everything I understand and have experienced outputting things to the serial monitor so far, I have no idea why its doing what its doing.

I attached the code in my first post, but here it is again:

const byte numChars = 15;
char receivedChars[numChars];
char speed_mph[2];
char rotationCounter[5];
char dataDelim = ',';

boolean newData = false;
boolean speedComplete = false;
boolean rotationCounterComplete = false;

void setup() {
    Serial.begin(9600);
 //   Serial.println("GO");
}

void loop() {
    recvWithStartEndMarkers();
    separateData();
    showNewData();
}

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte index = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;
 
 
    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[index] = rc;
                index++;
                if (index >= numChars) {
                    index = numChars - 1;
                }
            }
            else {
                receivedChars[index] = '\0'; // terminate the string
                recvInProgress = false;
                index = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}
void separateData() {
  rotationCounterComplete = false;
  speedComplete = false;
  int indexA = 0;
  int indexB = 0;
  if (newData == true) {
    while (rotationCounterComplete == false) {
      //get the speed:
      if (receivedChars[indexA] != dataDelim && speedComplete == false){
        speed_mph[indexB] = receivedChars[indexA];  
        indexA++;
        indexB++;
      }
      // skip the comma, reset indexB to use for rotationCounter:
      else if (receivedChars[indexA] == dataDelim && speedComplete == false && rotationCounterComplete == false) {
          speedComplete = true; 
          indexA++;
          indexB = 0;
      }
      // get the rotation count
      else if (receivedChars[indexA] != dataDelim && speedComplete == true && rotationCounterComplete == false) {
        rotationCounter[indexB] = receivedChars[indexA]; 
        indexA++;
        indexB++;
      }
      // end the loop at the second comma
      else if (receivedChars[indexA] == dataDelim && speedComplete == true && rotationCounterComplete == false) {
          rotationCounterComplete = true; 
      }
    }
  }

}
void showNewData() {
    if (newData == true) {
        Serial.print("Data:  ");
        Serial.print(receivedChars);

        Serial.print("   counter: ");
        Serial.print(rotationCounter);
        
        Serial.print("  speed: ");
        Serial.println(speed_mph);

        newData = false;
    }
}

I presume the program in Reply #3 is the Mega program.

How are you connecting the Uno to the Mega?

It seems surprising to me that you are not receiving the data on Serial1 on the Mega (i.e. on pins 19 and 18) so as to leave Serial (pins 0 and 1) free for communication with the PC and for uploading programs.

...R

Yes, the program in reply 3 is the Mega.

The UNO sends the data through the TX pin (pin 1), and initially I was sending it to the RX (pin 0) of the Mega, but I just changed it to send it to Serial2, RX2 (pin 17 -- I'm using Serial1 for another component), but I still get the unwanted repetition of some characters on the serial monitor.

So I just tried switching the order in which the speed and counter are output to the serial monitor (see showNewData() function in code), and the output I got was:

16:24:00.779 -> Data: 17,723, speed: 1717,723, counter: 723
16:24:00.954 -> Data: 16,724, speed: 1616,724, counter: 724
16:24:01.161 -> Data: 15,725, speed: 1515,725, counter: 725
16:24:01.342 -> Data: 14,726, speed: 1414,726, counter: 726
16:24:01.557 -> Data: 13,727, speed: 1313,727, counter: 727
|--------|--> why is this here?

This makes no sense because the variable holding speed is an array of 2 characters, so there is no way it can be storing 9 characters, and there is no code in between printing the speed and printing the counter.

const byte numChars = 15;
char receivedChars[numChars];
char speed_mph[2];
char rotationCounter[5];
char dataDelim = ',';

boolean newData = false;
boolean speedComplete = false;
boolean rotationCounterComplete = false;

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

void loop() {
    recvWithStartEndMarkers();
    separateData();
    showNewData();
}

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte index = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;
 
 
    while (Serial2.available() > 0 && newData == false) {
        rc = Serial2.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[index] = rc;
                index++;
                if (index >= numChars) {
                    index = numChars - 1;
                }
            }
            else {
                receivedChars[index] = '\0'; // terminate the string
                recvInProgress = false;
                index = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}
void separateData() {
  rotationCounterComplete = false;
  speedComplete = false;
  int indexA = 0;
  int indexB = 0;
  if (newData == true) {
    while (rotationCounterComplete == false) {
      //get the speed:
      if (receivedChars[indexA] != dataDelim && speedComplete == false){
        speed_mph[indexB] = receivedChars[indexA];  
        indexA++;
        indexB++;
      }
      // skip the comma, reset indexB to use for rotationCounter:
      else if (receivedChars[indexA] == dataDelim && speedComplete == false && rotationCounterComplete == false) {
          speedComplete = true; 
          indexA++;
          indexB = 0;
      }
      // get the rotation count
      else if (receivedChars[indexA] != dataDelim && speedComplete == true && rotationCounterComplete == false) {
        rotationCounter[indexB] = receivedChars[indexA]; 
        indexA++;
        indexB++;
      }
      // end the loop at the second comma
      else if (receivedChars[indexA] == dataDelim && speedComplete == true && rotationCounterComplete == false) {
          rotationCounterComplete = true; 
      }
    }
  }

}
void showNewData() {
    if (newData == true) {
        char emptyVariable = Serial.println("");
        Serial.print("Data:  ");
        Serial.print(receivedChars);


        Serial.print("  speed: ");
        Serial.print(speed_mph);
        
        Serial.print("   counter: ");
        Serial.print(rotationCounter);
        


        newData = false;
    }
}

You never add a null character to the end of speed_mph, so it keeps walking through memory until it finds one, when you print. Just so happens that receivedChars is the next thing in memory. Expand speed_mph to 3 elements, and null terminate it.

That did it! Thank you! I taught myself to code in LISP, and arrays in LISP don't need null terminators. Now I know, thanks again!

christov:
That did it! Thank you! I taught myself to code in LISP, and arrays in LISP don't need null terminators. Now I know, thanks again!

In general arrays in C++ do not need a null terminator. It is char arrays that are to be treated as cstrings that need the null terminator.

...R