[SOLVED] strange bhavior Serial1, Serial2 mega2560

hello, im facing the following problem:
I want to get data from 2 GPSs. Use 2 same devices , garmin17, same configuration uploaded and checked thru garmin's program. Output is NMEA sentenses RMC, GLL, GGA. Both devices work fine when connected (one by one) to mentioned program.

Now, output of devices is connected to Serial1rx and the other to Serial2rx on mega2560.
I have the following code

String txtmsg = "";
char inchar = ' ';
int a = 0;
int b = 0;
byte valid = 0;

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

void loop() {
  
  txtmsg = "";
   CheckLeft();
  txtmsg = "";
  CheckRight();
 
 
}
void CheckLeft(void) {
  while (Serial1.available()) {
    if (Serial1.available()) {
      inchar = Serial1.read();
      Serial.write(inchar);
    }
    if (Serial1.available()) {}
    else delay(5);
    if (Serial1.available()) {}
    else  Serial.println();
  }
}

void CheckRight(void) {
   while (Serial2.available()) {
    if (Serial2.available()) {
      inchar = Serial2.read();
     Serial.write(inchar);
    }
    if (Serial2.available()) {}
    else delay(5);
    if (Serial2.available()) {}
    else  Serial.println();
  }
}

what i get on serialmonitor is strange (well, as i see it). (I ll use code tags for easier scrolling)

$GPRMC,155115,A,1234.2531,N,1234.3938,E,000.0,000.0,070899,003.2,E*75
$GPGGA,155115,1234.2531,N,1234.3938,E,2,09,0.9,78.4,M,35.4,M,,*75
$GPGLL,1234.2531,N,1234.3938,E,155115,A*27

$GPRMC,155115,A,1234.2534,N,1234.3926,E,000.0,000.0,070899,003

$GPRMC,155116,A,1234.2534,N,1234.3926,E,000.1,000.0,070899,003.2,E*7D
$GPGGA,155116,1234.2534,N,1234.3926,E,2,08,1.0,79.6,M,35.4,M,,*76
$GPGLL,1234.2534,N,1234.3926,E,155116,A*2E

$GPRMC,155116,A,1234.2530,N,1234.3936,E,000.0,000.0,070899,003116,A*2B



remove cable on Serial1, Serial2 works fine when alone


$GPRMC,155123,A,1234.2534,N,1234.3926,E,000.1,000.0,070899,003.2,E*7B
$GPGGA,155123,1234.2534,N,1234.3926,E,2,08,1.0,79.6,M,35.4,M,,*70
$GPGLL,1234.2534,N,1234.3926,E,155123,A*28

$GPRMC,155124,A,1234.2534,N,1234.3926,E,000.0,000.0,070899,003.2,E*7D
$GPGGA,155124,1234.2534,N,1234.3926,E,2,08,1.0,79.6,M,35.4,M,,*77
$GPGLL,1234.2534,N,1234.3926,E,155124,A*2F

$GPRMC,155125,A,1234.2534,N,1234.3926,E,000.1,000.0,070899,003.2,E*7D
$GPGGA,155125,1234.2534,N,1234.3926,E,2,08,1.0,79.6,M,35.4,M,,*76
$GPGLL,1234.2534,N,1234.3926,E,155125,A*2E

put cable Serial1 in place
remove cable Serial2, Serial1 works fine when alone

$GPRMC,155131,A,1234.2530,N,1234.3936,E,000.0,000.0,070899,003.2,E*7C
$GPGGA,155131,1234.2530,N,1234.3936,E,2,08,1.0,79.0,M,35.4,M,,*70
$GPGLL,1234.2530,N,1234.3936,E,155131,A*2E

$GPRMC,155132,A,1234.2530,N,1234.3936,E,000.0,000.0,070899,003.2,E*7F
$GPGGA,155132,1234.2530,N,1234.3936,E,2,08,1.0,79.0,M,35.4,M,,*73
$GPGLL,1234.2530,N,1234.3936,E,155132,A*2D

$GPRMC,155133,A,1234.2530,N,1234.3936,E,000.0,000.0,070899,003.2,E*7E
$GPGGA,155133,1234.2530,N,1234.3936,E,2,08,1.0,79.0,M,35.4,M,,*72
$GPGLL,1234.2530,N,1234.3936,E,155133,A*2C


exchange cables Serial1-Serial2, same problem

$GPRMC,155136,A,1234.2534,N,1234.3926,E,000.1,000.0,070899,003.2,E*7F
$GPGGA,155136,1234.2534,N,1234.3926,E,2,08,1.0,79.6,M,35.4,M,,*74
$GPGLL,1234.2534,N,1234.3926,E,155136,A*2C

$GPRMC,155136,A,1234.2530,N,1234.3936,E,000.0,000.0,070899,0039

$GPRMC,155137,A,1234.2534,N,1234.3926,E,000.1,000.0,070899,003.2,E*7E
$GPGGA,155137,1234.2534,N,1234.3926,E,2,08,1.0,79.6,M,35.4,M,,*75
$GPGLL,1234.2534,N,1234.3926,E,155137,A*2D

$GPRMC,155137,A,1234.2530,N,1234.3936,E,000.0,000.0,070899,003,155137,A*28

$GPRMC,155138,A,1234.2530,N,1234.3936,E,000.1,000.0,070899,003.2,E*74
$GPGGA,155138,1234.2530,N,1234.3936,E,2,08,1.0,79.0,M,35.4,M,,*79
$GPGLL,1234.2530,N,1234.3936,E,155138,A*27

$GPRMC,155138,A,1234.2534,N,1234.3926,E,000.1,000.0,070899,003,E,155138,A*22

$GPRMC,155139,A,1234.2530,N,1234.3936,E,000.0,000.0,070899,003.2,E*74
$GPGGA,155139,1234.2530,N,1234.3936,E,2,08,1.0,79.0,M,35.4,M,,*78
$GPGLL,1234.2530,N,1234.3936,E,155139,A*26

(integer part of LON, LAT is ok, but has been changed to 1234, for safety reasons. )
problem1 : why not all sentenses (3 + 3) appear , when both inputs are connected?
problem2 : why the faulty - alone RMC "stops" sometimes around byte 64 and other times is "mixed" with following messages?
any ideas?

You code seems a bit off when checking for new data. You have a while() loop and then check inside that with an 'if( Serial.available()' call again.

You also have to realized that the data coming in at 9600 is very slow compared to how fast the arduino is operating. It will only see a new character about every millisecond. A better approach may be to have a buffer for each GPS and then transfer incoming data into that buffer until you detect the message is complete and then print it out, all in one go. Otherwise, you could get GPS1 and GPS2 data intermixed.

I don't know if there is a way for you to detect the end of a message (CR, LF, other?)

@blh64
the second if inside while is exactly to "delay" ..some ms if there are more data not received yet.
the final if inside while is just to LF, if after delay buffer is still empty.
With 3 sentenses , about 200 chars, at 9600 as you said is ~200ms. two times that = 400ms. Messages arrive every 1000 (so i dont see any problem)

Now, i made a small change so to see from what serial is printed each line. The result :

serial1  
$GPRMC,165632,A,1234.2547,N,1234.3948,E,000.0,000.0,070899,003
serial2  
$GPRMC,165633,A,1234.2529,N,1234.3915,E,000.0,000.0,070899,003.2,E*73
$GPGGA,165633,1234.2529,N,1234.3915,E,2,08,0.9,80.2,M,35.4,M,,*73
$GPGLL,1234.2529,N,1234.3915,E,165633,A*21

serial1  
$GPRMC,165633,A,1234.2547,N,1234.3948,E,000.0,000.0,070899,003547,N,1234.3948,E,165633,A*21

serial1  
$GPRMC,165634,A,1234.2547,N,1234.3948,E,000.0,000.0,070899,003.2,E*74
$GPGGA,165634,1234.2547,N,1234.3948,E,2,08,0.9,82.7,M,35.4,M,,*73
$GPGLL,1234.2547,N,1234.3948,E,165634,A*26

serial2  
$GPRMC,165634,A,1234.2529,N,1234.3915,E,000.0,000.0,070899,003
serial1  
$GPRMC,165635,A,1234.2547,N,1234.3948,E,000.0,000.0,070899,003.2,E*75
$GPGGA,165635,1234.2547,N,1234.3948,E,2,08,0.9,82.7,M,35.4,M,,*72
$GPGLL,1234.2547,N,1234.3948,E,165635,A*27

serial2  
$GPRMC,165635,A,1234.2529,N,1234.3915,E,000.0,000.0,070899,003
serial2  
$GPRMC,165636,A,1234.2529,N,1234.3915,E,000.1,000.0,070899,003.2,E*77
$GPGGA,165636,1234.2529,N,1234.3915,E,2,08,0.9,80.2,M,35.4,M,,*76
$GPGLL,1234.2529,N,1234.3915,E,165636,A*24

serial1  
$GPRMC,165636,A,1234.2546,N,1234.3948,E,000.0,000.0,070899,003A*25

$GPRMC,165637,A,1234.2529,N,1234.3915,E,000.1,000.0,070899,003.2,E*76
$GPGGA,165637,1234.2529,N,1234.3915,E,2,08,0.9,80.2,M,35.4,M,,*77
$GPGLL,1234.2529,N,1234.3915,E,165637,A*25

serial1  
$GPRMC,165637,A,1234.2546,N,1234.3948,E,000.0,000.0,070899,003*24

serial2  
$GPRMC,165638,A,1234.2529,N,1234.3915,E,000.1,000.0,070899,003.2,E*79
$GPGGA,165638,1234.2529,N,1234.3915,E,2,08,0.9,80.2,M,35.4,M,,*78
$GPGLL,1234.2529,N,1234.3915,E,165638,A*2A

So now it seems that both inputs are "ok" but there is a mixup/or data loss
(?)

If the serial input buffer fills up before you go to read data, any characters received after that will be thrown away.

If you are going to use a GPS library to interpret the GPS data, just pass each character to the library as it arrives.

If you want to interpret the statements yourself, buffer each character as it arrives. Act on the buffer when you get the character that signals the end of the statement.

johnwasser:
If the serial input buffer fills up before you go to read data, any characters received after that will be thrown away.

On startup, since i expected ~ 200 chars, I "defined" in the hardwareserial.h the rxbuffer to 256chars. Isn't this enough?

ok, solved

many thanks for insisting at the obvious....

void CheckLeft(void) {
  if (Serial1.available()) {
    inchar = ' ';
    Serial.println("serial1  ");
    while ((inchar != 10)) {
      inchar = Serial1.read();
      Serial.write(inchar);
      if (Serial1.available()) ;
      else delay(5);
    }
  }
}

void CheckRight(void) {
  if (Serial2.available()) {
    inchar = ' ';
    Serial.println("serial2  ");
    while ((inchar != 10)) {
      inchar = Serial2.read();
      Serial.write(inchar);
      if (Serial2.available()) ;
      else delay(5);
    }
  }
}

I'm glad you solved your problem, but it would be much better to read in the chars and store them in a buffer. If the last char read is a LF, then act on it, if not then just return. The way you have your program structured, these functions block until the entire message is received. While GPS1 is blocking (being read), the buffer for GPS2 is filling up and you aren't doing anything with it. You would also not have to mess around with the hardware buffers.

const int BUFFER_SIZE = 256;

void CheckLeft(void) {
  static char buffer[BUFFER_SIZE];
  static int count = 0;
  while (Serial1.available()) {
    int inchar = Serial1.read();
    if ( count < BUFFER_SIZE ) {
      buffer[count++] = inchar;
    }
    if ( inchar == '\n' ) {
      // got a complete message
      // so print it out and reset for the next one
      buffer[count] = '\0';   // null terminate string
      Serial.print("serial1:");
      Serial.print(buffer);
      count = 0;  // reset pointer
    }
  }
}

void CheckRight(void) {
  static char buffer[BUFFER_SIZE];
  static int count = 0;
  while (Serial2.available()) {
    int inchar = Serial2.read();
    if ( count < BUFFER_SIZE ) {
      buffer[count++] = inchar;
    }
    if ( inchar == '\n' ) {
      // got a complete message
      // so print it out and reset for the next one
      buffer[count] = '\0';   // null terminate string
      Serial.print("serial1:");
      Serial.print(buffer);
      count = 0;  // reset pointer
    }
  }
}