The data of the two sensors in serial monitor are messy

I am using two IMU senors of GY-951 [(https://github.com/Razor-AHRS/razor-9dof-ahrs)] with Arduino Mega 2560 (connected serially with Mega at the same time) , But The data of the two sensors in serial monitor are messy. How can I solve this problem?

This is the code that I am using:

const byte BUFF_SIZE = 40;

char buffer[BUFF_SIZE]; // an array to store the received data

char buffer2[BUFF_SIZE]; // an array to store the received data

boolean newData = false;

void setup()

{

Serial.begin(57600);

Serial2.begin(57600);

Serial2.write("#osrt");

Serial3.begin(57600);

Serial3.write("#osrt");

}

void loop()

{

recvWithEndMarker();

// showNewData();

if (newData)

{

parseData();

}

//delay(5);

}

void recvWithEndMarker()

{

static byte ndx = 0;

char endMarker = '\n';

char rc;

char rc2;

while (Serial2.available() > 0 && newData == false)

while (Serial3.available() > 0 && newData == false)

{

rc = Serial2.read();

rc2 = Serial3.read();

if(rc == '\r' && rc2 == '\r' ) // ignore carruage return

{

return;

}

if (rc != endMarker && rc2 != endMarker)

{

buffer[ndx] = rc;

buffer2[ndx] = rc2;

ndx++;

if (ndx >= BUFF_SIZE)

{

ndx = BUFF_SIZE - 1;

}

}

else

{

buffer[ndx] = '\0'; // terminate the string

buffer2[ndx] = '\0'; // terminate the string

ndx = 0;

newData = true;

}

}

}

void showNewData()

{

if (newData == true)

{

Serial.print("data from input ... ");

Serial.println(buffer);

Serial.println(buffer2);

//newData = false;

}

}

void parseData()

{

if(strstr(buffer, "#A-R=") != 0 && strstr(buffer2, "#A-R=") != 0 ) // does the new line have the correct header?

{

Serial.print("Sensor1:\t");

Serial.println(buffer);

Serial.print("Sensor2:\t");

Serial.println(buffer2);

}

newData = false;



}

it should be shown as the following:

Sensor1:#A-R=233.00,-93.00,-34.00
Sensor2:#A-R=3.00,-98.00,-50.00
Sensor1:#A-R=100.00,-73.00,-34.00
.
.
.
But I got the following:

What do you mean "not synchronous"?

@red_car
Please check the photo in the question

it should be shown as the following:

Sensor1:#A-R=233.00,-93.00,-34.00
Sensor2:#A-R=3.00,-98.00,-50.00
Sensor1:#A-R=100.00,-73.00,-34.00
.
.
.

Can you show a picture of the serial monitor.

The way you are handling the incoming serial data is not very good at all. You are assuming that both sensors will always send exactly the same number of bytes... this will not always be the case.

If one sends 25 and one send 250... your reading routine will fail.

Don't update previous posts... it makes the thread impossible to read.

Did you read this? Do you understand the problem?

@red_car , yes, but I dont know how to solve the problem?
Do you have any suggestion please?

The way you are handling two serial streams is "messy". They are independent, and should not be handled at the same time.

What happens below if one stream receives an end marker but the other does not?

Start over, with separate procedures to handle each serial input.

@jremington , I separated as the following but still the same.

const byte BUFF_SIZE =500;

char buffer[BUFF_SIZE]; // an array to store the received data

char buffer2[BUFF_SIZE]; // an array to store the received data

boolean newData = false;

void setup()

{

Serial.begin(57600);

Serial2.begin(57600);

Serial2.write("#osrt");

Serial3.begin(57600);

Serial3.write("#osrt");

}

void loop()

{

recvWithEndMarker();

// showNewData();

if (newData)

{

parseData();

}

//delay(5);

}

void recvWithEndMarker()

{

static byte ndx = 0;

char endMarker = '\n';

char rc;

char rc2;

while (Serial2.available() > 0 && newData == false)

while (Serial3.available() > 0 && newData == false)

{

rc = Serial2.read();

rc2 = Serial3.read();

if(rc == '\r' ) // ignore carruage return

if (rc2 == '\r' )

{

return;

}

if (rc != endMarker )

if (rc2 != endMarker)

{

buffer[ndx] = rc;

buffer2[ndx] = rc2;

ndx++;

if (ndx >= BUFF_SIZE)

{

ndx = BUFF_SIZE - 1;

}

}

else

{

buffer[ndx] = '\0'; // terminate the string

buffer2[ndx] = '\0'; // terminate the string

ndx = 0;

newData = true;

}

}

}

void showNewData()

{

if (newData == true)

{

Serial.print("data from input ... ");

Serial.println(buffer);

Serial.println(buffer2);

//newData = false;

}

}

void parseData()

{

if(strstr(buffer, "#A-R=") != 0 ) // does the new line have the correct header?

if(strstr(buffer2, "#A-R=") != 0)

{

Serial.print("Sensor1:\t");

Serial.println(buffer);

Serial.print("Sensor2:\t");

Serial.println(buffer2);

}

newData = false;

delay(10);

}

That is exactly the same logic as your previous effort. Do not use while.

Start completely over, with something like this approach:

if (Serial2.available() > 0) {
get_serial2_character();
test_serial2_character_and_take_action();
}
if (Serial3.available() > 0) {
get_serial3_character();
test_serial3_character_and_take_action();
}

What did you mean of this line?

Get a character from Serial2.

Sorry, I thought that would be pretty obvious.

@jremington I tried to do the following, but I didnt get any data in the serial monitor:

const byte BUFF_SIZE =500;
char buffer[BUFF_SIZE]; // an array to store the received data
char buffer2[BUFF_SIZE]; // an array to store the received data
boolean newData = false;
void setup()
{
Serial.begin(57600);
Serial2.begin(57600);
Serial2.write("#osrt");
Serial3.begin(57600);
Serial3.write("#osrt");
}
void loop()
{
recvWithEndMarker();
// showNewData();
if (newData)
{
parseData();
}
//delay(5);
}
void recvWithEndMarker()
{
static byte ndx = 0;
char endMarker = '\n';
char rc;
char rc2;
//while (Serial2.available() > 0 && newData == false)
//while (Serial3.available() > 0 && newData == false)
if (Serial2.available() > 0) {
rc = Serial2.read();
if(rc == '\r' ) // ignore carruage return
if (rc != endMarker )

buffer[ndx] = rc;
ndx++;
if (ndx >= BUFF_SIZE)
{
ndx = BUFF_SIZE - 1;
}

else
{
buffer[ndx] = '\0'; // terminate the string

ndx = 0;
newData = true;
}
}

if (Serial3.available() > 0) {
rc2 = Serial3.read();
if (rc2 == '\r' )
if (rc2 != endMarker)
buffer2[ndx] = rc2;
ndx++;
if (ndx >= BUFF_SIZE)
{
ndx = BUFF_SIZE - 1;
}

else
{

buffer2[ndx] = '\0'; // terminate the string
ndx = 0;
newData = true;
}
}
}





void showNewData()
{
if (newData == true)
{
Serial.print("data from input ... ");
Serial.println(buffer);
Serial.println(buffer2);
//newData = false;
}
}
void parseData()
{
if(strstr(buffer, "#A-R=") != 0  ) // does the new line have the correct header?
if(strstr(buffer2, "#A-R=") != 0)
{
Serial.print("Sensor1:\t");  
Serial.println(buffer);
Serial.print("Sensor2:\t");  
Serial.println(buffer2);
}
newData = false;
delay(10);
}

You still haven't grasped the concept of separating these two data streams completely.

You need a separate "newData" variable for each stream (same for "ndx"), and print the "new data" for each individual stream, when it becomes available.

@jremington
I add (newData2) but Still I didnt see any data on the serial monitor:

const byte BUFF_SIZE =500;
char buffer[BUFF_SIZE]; // an array to store the received data
char buffer2[BUFF_SIZE]; // an array to store the received data
boolean newData = false;
boolean newData2 = false;
void setup()
{
Serial.begin(57600);
Serial2.begin(57600);
Serial2.write("#osrt");
Serial3.begin(57600);
Serial3.write("#osrt");
}
void loop()
{
recvWithEndMarker();
// showNewData();
if (newData)

{
parseData();
}
//delay(5);
}
void recvWithEndMarker()
{
static byte ndx = 0;
static byte ndx2 = 0;
char endMarker = '\n';
char rc;
char rc2;
//while (Serial2.available() > 0 && newData == false)
//while (Serial3.available() > 0 && newData == false)
if (Serial2.available() > 0) {
rc = Serial2.read();
if(rc == '\r' ) // ignore carruage return
if (rc != endMarker )

buffer[ndx] = rc;
ndx++;
if (ndx >= BUFF_SIZE)
{
ndx = BUFF_SIZE - 1;
}

else
{
buffer[ndx] = '\0'; // terminate the string

ndx = 0;
newData = true;
}
}

if (Serial3.available() > 0) {
rc2 = Serial3.read();
if (rc2 == '\r' )
if (rc2 != endMarker)
buffer2[ndx2] = rc2;
ndx2++;
if (ndx2 >= BUFF_SIZE)
{
ndx2 = BUFF_SIZE - 1;
}

else
{

buffer2[ndx2] = '\0'; // terminate the string
ndx2 = 0;
newData2 = true;
}
}
}





void showNewData()
{
if (newData == true)
{
Serial.print("data from input ... ");
Serial.println(buffer);
//newData = false;
}
if (newData2 == true)
{
Serial.print("data from input ... ");
Serial.println(buffer2);
//newData = false;
}
}
void parseData()
{
if(strstr(buffer, "#A-R=") != 0  ) // does the new line have the correct header?
if(strstr(buffer2, "#A-R=") != 0)
{
Serial.print("Sensor1:\t");  
Serial.println(buffer);
Serial.print("Sensor2:\t");  
Serial.println(buffer2);
}
newData = false;
newData2 = false;
delay(10);
}

Wrong!

This is the same as

if (newData && newData2)

Again: separate the two streams completely.

@jremington
I didnt know how to separate the newData and newData2 , Do you have any suggestions please?

Use braces, like this:

if (newData) {
do_first_thing();  // so whatever is required to handle the new data
do_final_thing();
newData = false; //ready for some new data from that stream
}
if(newData2) {
// likewise
newData2 = false;
}

At some point, you will need to learn the basics of C/C++ programming. Otherwise, expect endless frustration.

Try this (untested)...

const byte BUFF_SIZE = 128;

char buffer1[BUFF_SIZE];
char buffer2[BUFF_SIZE];

boolean newData1 = false;
boolean newData2 = false;

uint8_t ndx1 = 0;
uint8_t ndx2 = 0;


void setup()
{
  Serial.begin(57600);

  Serial2.begin(57600);
  Serial2.write("#osrt");

  Serial3.begin(57600);
  Serial3.write("#osrt");
}

void loop()
{
  if (!newData1)               // Have we finished getting buffer1 data?
    recvWithEndMarker1();      // Keep getting data

  if (!newData2)               // Have we finished getting buffer2 data?
    recvWithEndMarker2();      // Keeping getting data

  if (newData1 && newData2)    // Have we received both sets of data.
  {
    parseData();               // Display the data & clear the buffers.
  }
}


void recvWithEndMarker1()
{
  char c;

  if (Serial2.available() > 0) // Is there data ready to be read?
  {
    c = Serial2.read();        // Get a character.

    if (c == '\r' )            // Carriage return?
    {}                         // Do nothing
    else if (c == '\n')        // End of record?
    {
      buffer1[ndx1] = '\0';    // Terminate the string
      ndx1 = 0;                // Reset the buffer index
      newData1 = true;         // Set the found flag
      return;                  // Finish reading
    }
    else
    {
      buffer1[ndx1++] = c;      // Add to the buffer
    }


    if (ndx1 > BUFF_SIZE)       // Have we exceeded the buffer length?
    {
      Serial.println("Buffer 1 overflow");
      ndx1--;
      buffer1[ndx1] = '\0';
    }
  }
}


void recvWithEndMarker2()
{
  char c;

  if (Serial3.available() > 0) // Is there data ready to be read?
  {
    c = Serial3.read();        // Get a character.

    if (c == '\r' )            // Carriage return?
    {}                         // Do nothing
    else if (c == '\n')        // End of record?
    {
      buffer2[ndx2] = '\0';    // Terminate the string
      ndx2 = 0;                // Reset the buffer index
      newData2 = true;         // Set the found flag
      return;                  // Finish reading
    }
    else
    {
      buffer2[ndx2++] = c;     // Add to the buffer
    }


    if (ndx2 > BUFF_SIZE)      // Have we exceeded the buffer length?
    {
      Serial.println("Buffer 2 overflow");
      ndx2--;
      buffer2[ndx2] = '\0';
    }
  }
}


void parseData()
{
  Serial.print("Sensor1:\t");
  Serial.print(buffer1);
  if (strstr(buffer1, "#A-R=") != NULL)
    Serial.println();
  else
    Serial.println(" - Invalid header");

  Serial.print("Sensor2:\t");
  Serial.print(buffer2);
  if (strstr(buffer2, "#A-R=") != NULL)
    Serial.println();
  else
    Serial.println(" - Invalid header");

  newData1 = false;
  newData2 = false;
}

This assumes your serial data is arriving from both sources at the same frequency... so you may still run into trouble if it doesn't.

EDIT: corrected strstr response check to != NULL

1 Like

@jremington

separate the two streams completely.

Is the correct way to go.
In order to get there, write a sketch that ONLY processes one serial input.
Get that running so you only have output like
Sensor1:#A-R=233.00,-93.00,-34.00
Sensor1:#A-R=100.00,-73.00,-34.00
Then break the processing up into two methods the initialization part in setup() and the processing part in loop()
e.g.

void initSerial1() {
  Serial2.begin(57600);
  Serial2.write("#osrt");
}

and

void processSerial1() {
  recvSerial1WithEndMarker();
  if (newSerial1Data) {
      parseSerial1Data();  // print output here when data parsed
  }
}

Again these methods ONLY handle Serial1.
Once you have these working, write the Serial2 methods and test them by them selves.
Then write a sketch that contains both
e.g.

void setup() {
 // other setup stuff here
 initSerial1();
 initSerial2();
}

void loop() {
 processSerial1();
 processSerial2();
 // other loop stuff here
}

Note: It is important that loop() code does not block.
See Simple Multitasking Arduino and its links.

Finally, as noted by @red_car above, the data arriving at Serial1 and Serial2 are not in locked step. They come when they come. If the sender to Serial1 is delayed you may get two Serial2 outputs one after another.
But I suggest you just ignore that issue for now.

Thanks, but I got Invalid header beside every line is this, what does that mean?
Also, I didnt get this "This assumes your serial data is arriving from both sources at the same frequency" when this case will be happened?