Variable arrives as "nan" when sent over serial between Arduinos

I'm exchanging data between an Arduino Uno and a Mega via serial, which has worked well, being able to send int and float variables seamlessly. The protocol I use starts and ends a stream with "<" and ">" respectively, separating values with a ",". I'm using a library to separate the values.

Now I connected a MPU6050 accelerometer to the Arduino Uno and need to send the data to the Mega, nonetheless, the ang_x and ang_y variables (containing the tilt angles) always arrive as "nan".

When reading the Serial output of the Uno from the PC, the stream is correct:

<-9.39,6.82,9.99>

But when the stream is sent over to the Mega it is finally printed as:

X: nan  Y: nan Float test: 9.99

I checked reading the incoming stream directly and added a float variables with known value to debug the problem. But no luck.

This is the "sending" code on the Arduino Uno:

#include "I2Cdev.h"
#include "MPU6050.h"
#include "Wire.h"
MPU6050 sensor;

int ax, ay, az;
int gx, gy, gz;

long tiempo_prev;
float dt;
float ang_x, ang_y;
float ang_x_prev, ang_y_prev;
float float_test = 9.99;

int num;

void setup() {
  Serial.begin(38400);
  Wire.begin();            
  sensor.initialize();

}

void loop() { 

//**** Calculates tilt of the accelerometer
  sensor.getAcceleration(&ax, &ay, &az);
  sensor.getRotation(&gx, &gy, &gz);
  
  float accel_ang_x=atan(ay/sqrt(pow(ax,2) + pow(az,2)))*(180.0/3.14);
  float accel_ang_y=atan(-ax/sqrt(pow(ay,2) + pow(az,2)))*(180.0/3.14);
   
  ang_x = 0.98*(ang_x_prev+(gx/131)*dt) + 0.02*accel_ang_x;
  ang_y = 0.98*(ang_y_prev+(gy/131)*dt) + 0.02*accel_ang_y;
  
  ang_x_prev=ang_x;
  ang_y_prev=ang_y;

//**** Sends result via serial, including start/end markers

  Serial.write("<");
  Serial.print(ang_x); 
  Serial.write(",");
  Serial.print(ang_y);
  Serial.write(",");
  Serial.print(float_test);
  Serial.write(">");

  delay(10);

}

And this is the "receiving code on the Mega:

#include <Separador.h>
Separador s;
/*
String str;
byte receivedByte;
*/
const byte numChars = 32;
char receivedChars[numChars];
String str;
String str_x;
String str_y;
String test;
boolean newData = false;
char rc;

void setup() {
  Serial.begin(38400);
  Serial1.begin(38400);

}

void loop() {
/*
if (Serial1.available() > 0) {
   receivedByte = Serial1.read();
   Serial.println(receivedByte);
}
*/
recvBTData();
processRcvdBTData();
}


// **** Searches for start/end markers in the serial stream and stores characters
void recvBTData() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;
 
    while (Serial1.available() > 0 && newData == false) {
        rc = Serial1.read();

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

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

//**** Takes characters identified by recvBTData() and reconstructs original data into Strings

void processRcvdBTData() {

      if (newData == true) {
        String str(receivedChars);
        String str_x = s.separa(str, ',', 0);
        String str_y = s.separa(str, ',', 1);
        String test = s.separa(str, ',', 2);

//**** Prints out original variables (but can be replaced with whatever operation is needed)

        newData = false;
        
        Serial.write("X: ");
        Serial.print(str_x);
        Serial.write("  Y: ");
        Serial.print(str_y);
        Serial.write(" Float test: ");
        Serial.println(test);

    }
}

Thanks for your help.

Best,
Marcel

Could you upload the Separador source code?

Looking at your code it seems that the problem should be in the separa method.

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. This can happen after the program has been running perfectly for some time. Just use cstrings - char arrays terminated with '\0' (NULL).

There is a parse example in Serial Input Basics

You don't seem to have anything in your program to print the received data before you try to parse it.

...R

  receivedChars[ndx] = '\0'; // terminate the string
  Serial.println(receivedChars); // <Please add this line

I think you will see that "nan,nan,9.99" is what you receive and, therefore, the problem is on the sending side. I don't know why the PC is sent a different result than the MEGA.

Thanks for all your replies.

@pacoandres: you can find the library at somosioticos.com - This website is for sale! - somosioticos Resources and Information.

Nonetheless, the error occurs before the separa method is called. Pulling serial data with the following line shows the same result (similar to what johnwasser suggests):

if (Serial1.available() > 0) {
  Serial.write(Serial1.read());
}

@Robin2: thanks, I have read about that. Will see if I can change it as to avoid the issue you point out.

@jhonwasser: indeed, you are right, the "nan" appears already when printing the received characters at that point.

Indeed, the problem originates somewhere in the "sending" side on the Uno. Will keep tinkering.

SOLVED

Ok, it looks like the problem was in the circuit voltage. For the sake of simplicity (I cant really offer any good reasoning to this point) , I connected the Mega to the PC and connected a breadboard to the Mega GND and 5V. The Uno and the MPU6050 drew energy from the breadboard. As soon as I separated both circuits, with the Mega and the Uno connected independently to the PC, thus both with their own power source (theoretically at least, since they were both connected to the same PC USB plug), the sketch starting to behave as expected.

Interesting phenomenon. Happy to hear any explanations on how voltage/current availability impacts sketch calculations in a way they return NAN.

Lesson learned.

Best regards,
Marcel

Quick follow-up. The above functioning setup worked as long as the Uno and the Mega were connected via serial cable AND shared a GND. As soon as the GND connection was removed it stoped. It didn't work either with the Uno being powered from completely different power source, such as a battery. I ended up changing the MPU6050 for a MPU6500 (same chip as the MPU6050 but with a Gyro) and now it does work in its final wiring setup.

Margoye:
The above functioning setup worked as long as the Uno and the Mega were connected via serial cable AND shared a GND. As soon as the GND connection was removed it stoped.

Does that surprise you? It shouldn't.