Reading two serial ports concurrently using a MEGA

Hello,

Is someone able to help me with the following please?

I need to collect data (Sentences) from two NMEA devices connected to serial ports 1 & 2 on a MEGA.

The incoming data streams are continuous and arrive every sec from both devices. If I read from just one port the first NMEA sentence invariably arrives mid-sentence but then from the second sentence onwards everything runs smoothly.

Then if I read from each port consecutively the data flow never synchronises and each Sentence is split into a number of parts.

The Sentences always start with '$' and end with a '/n'

I have two identical routines that are called consecutively by the main loop which then stores each returned Sentence in a separate file, one for each stream.

eg: (I've reduced the loop() to just a few lines for simplicity)

void loop(){
gpsEvent();
** dataFileGPS.print(inputStringGPS);**
depthEvent();
** dataFileDepth.print(inputStringDepth);**
}
//************
void gpsEvent()
//************
{
** while (Serial1.available())**
** { // is data avaiilable**
** char inChar = (char)Serial1.read(); // get the new byte**
** inputStringGPS += inChar; // and append it to the inputString**
** if (inChar == '\n') **
** { // if the incoming byte is a newline it signifies the end of an NMEA Sentence so**
** stringCompleteGPS = true; // set flag and return to main loop where 'inputStringGPS' is written to GPS datafile**
** }**
** }**
}
//*************
void depthEvent()
//*************
{
** while (Serial2.available())**
** { // is data avaiilable**
** char inChar = (char)Serial2.read(); // get the new byte**
** inputStringDEPTH += inChar; // and append it to the inputString**
** if (inChar == '\n')**
** { // if the incoming byte is a newline it signifies the end of an NMEA Sentence so**
** stringCompleteDEPTH = true; // return to main loop where 'inputStringDEPTH' is written to DEPTH datafile**
** }**
** }**
}[\b]

I think this is a case where you want some time to process each string together vs wating for 1 to complete and then the other to complete. Maybe more like this:

void loop(){
 
if (Serial1.available()>0) 
 { // a data byte is avaiilable
 char inChar = (char)Serial1.read(); // get the new byte 
 inputStringGPS += inChar; // and append it to the inputString 
    if (inChar == '\n') 
    { // if the incoming byte is a newline it signifies the end of an NMEA Sentence so
    stringCompleteGPS = true; // set flag and return to main loop where 'inputStringGPS' is written to GPS datafile
    }
}
if (Serial2.available()>0) 
 { // a data byte is avaiilable
 char inChar = (char)Serial2.read(); // get the new byte 
 inputStringDEPTH += inChar; // and append it to the inputString 
    if (inChar == '\n') 
    { // if the incoming byte is a newline it signifies the end of an NMEA Sentence so
    stringCompleteDEPTH = true; // return to main loop where 'inputStringDEPTH' is written to DEPTH datafile
    }
 }
if (stringCompleteGPS == true){
stringCompleteGPS = false; // clear for next sentence
// do whatever
}
if (stringCompleteDEPTH == true){
stringCompleteDEPTH = false; // clear for next sentence
 // do whatever
}
 
 } // end loop

I would approach that using two copies (one for each serial port) of the function recvWithEndMarker() from the second example in Serial Input Basics.

If your code in loop() is something like

void loop() {
  recv1WithEndMarker();
  recv2WithEndMarker();
  // other stuff
}

the two streams of data will be received in parallel for all intents and purposes

...R

If the problem is capturing an incomplete data string, then you might check the captured sting for the presence of the $. if the $ is in the string, then the string should be complete and ready for processing. If the $ is not present, then clear what was captured and continue with the main capture looping.

Robin2:
the two streams of data will be received in parallel for all intents and purposes

This requires the data received fits in the 128 byte UART buffer right?

Many thanks for all your suggestions, I will try them and report back with my results.

Without this Forum I and probably many others would be pulling our hair out everyday.

Cheers.

You can send what is captured to the serial monitor to see how the capture is working.

DuaneDegn:
This requires the data received fits in the 128 byte UART buffer right?

If your sentence is longer than that (64, actually), you will lose the rest, especially when you are doing something else while the buffer overflows. You can, however, increase this buffer by modifying the value here:

arduino-1.6.5-r5\hardware\arduino\avr\cores\arduino\HardwareSerial.h
Line 48:

#define SERIAL_RX_BUFFER_SIZE 64

Change the value to a larger number.
If you are not sending long commands to these devices, decrease TX buffer to offset the memory cost of increasing RX buffer.
I would use C-string instead of String class. If you insist using String class, learn String.reserve().

DuaneDegn:
This requires the data received fits in the 128 byte UART buffer right?

The UART buffer is only 2 bytes. The Serial Input buffer is 64 bytes. Neither is a limitation if you use the code in Serial Input Basics

…R

If there aren’t any intentional delays in the code, the arduino can usually empty the serial input much faster than it can be filled.

The while loop would be intentional delay :slight_smile:

The while loop would be intentional delay :slight_smile:

Actually i would think the while loop would run as fast as the arduino allows. 8)

Robin2:
The UART buffer is only 2 bytes. The Serial Input buffer is 64 bytes. Neither is a limitation if you use the code in Serial Input Basics

...R

Thanks for the clarification. I know even less about this stuff than I thought.

DuaneDegn:
Thanks for the clarification. I know even less about this stuff than I thought.

In another Thread I have just proved that the Serial Input Basics code can receive 500+ bytes after the variable ndx is changed from byte to int.

...R

I'd like to thanks all the people who offered help with this part of my project, I am now collecting Data from my NMEA devices perfectly!

I have posted another question now and would appreciate any help. I'm trying to upload a text file containing my NMEA Data to an FTP site from my Mega which is equipped with a SparqEE Cell+Shield.

Here is the link if you can help.

Many thanks.