serial gps nmea sentences and other operations

Hello,
Let's say I have 2 hardware serials and I'm using a mt3339 (PA6H) GPS module.
I'm pretty sure that I'm missing something; please, someone may help me? Look at this simple code (that reproduces the problem).

The program sends some data to Serial, every 25ms, and gps nmea sentences also, as they came out from the mt3339, but every sec would be ok.
mt3339 has 9600 baud and the complete sentence is about 350-400 chars (RMCGGA or ALLDATA have the same problem). .

If I don't call the do_something function, the serial displays the right GPS data.
but when I add the timer, to display the other data (here millis() as example), the nmea sentences become garbage.

I understand that the data mixes because of the poor code, but I cannot find a code that works.
I tried to exchange the timer to the GPS, and other tricks, but no lucky.

Is there any chance to print right sequences to the serial?
Thanks

#define HWSERIAL Serial1
IntervalTimer myTimer;

void setup()
{
  Serial.begin(115200);
    HWSERIAL.begin(9600);
    myTimer.begin(do_something, 25000); 
}

void loop()
{    
    while (HWSERIAL.available())
    {
      char c = HWSERIAL.read();
       Serial.write(c);    
    }
}

void do_something () {
  Serial.println(millis());
}
1348429
1348454
1348479
1348504
1348529
1348554
1348579
$G1348604
PGGA,092423.084,,,,,0,01348629
,,,M,,M,,*4A
$GPGSA,A,11348654
,,,,,,,,,,,,,,,*1E
$GPG1348679
SV,1,1,00*79
$GPRMC,0921348704
423.084,V,,,,,0.00,0.001348729
,070715,,,N*4B
$GPVTG,01348754
.00,T,,M,0.00,N,0.00,K,N1348779
*32
1348804
1348829
1348854
1348879
1348904
1348929
1348954

maybe disable interrupts around read()?

First get rid of the pointless while loop!
use

    if (HWSERIAL.available()>0)
    {
      char c = HWSERIAL.read();
       Serial.write(c);    
    }

The Arduino runs s fast that there will only ever be 1 char in the serial buffer! so your do_somthing() is printing at any old place in the gps report.

This also means that turning off interrupts will not work!

Mark

prnet:
If I don't call the do_something function, the serial displays the right GPS data.
but when I add the timer, to display the other data (here millis() as example), the nmea sentences become garbage.

That's exactly what you want the program to do: You are mixing the received GPS chars with your millis printed.

$G1348604
PGGA,092423.084,,,,,0,01348629
,,,M,,M,,4A
$GPGSA,A,11348654
,,,,,,,,,,,,,,,1E
$GPG1348679
SV,1,1,00
79
$GPRMC,0921348704
423.084,V,,,,,0.00,0.001348729
,070715,,,N
4B
$GPVTG,01348754
.00,T,,M,0.00,N,0.00,K,N1348779
*32

So everything is mixed as you wanted it: Some received chars from the GPS are mixed with the milli() printed in between.

If this is not what you want: Why do you tell the program to do it?

What do you want? Please describe!

:grin:

you're right, I would had add the right data example.
my idea was:

$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
xxxxxx
$GPGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1*39
$GPGSV,2,1,08,01,40,083,46,02,17,308,41,12,07,344,39,14,22,228,45*75
xxxxxx
$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A
$GPGLL,4916.45,N,12311.12,W,225444,A,*1D
$GPVTG,054.7,T,034.4,M,005.5,N,010.2,K*48
xxxxxx
xxxxxx
xxxxxx
xxxxxx
xxxxxx
xxxxxx
$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
$GPGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1*39
$GPGSV,2,1,08,01,40,083,46,02,17,308,41,12,07,344,39,14,22,228,45*75
xxxxxx
xxxxxx
$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A
$GPGLL,4916.45,N,12311.12,W,225444,A,*1D
..........
..........

where xxxxxx is a value that I read from another sensor.
I don't mind the exact order, but I need to keep full gps sentences, not truncated. :wink:

I already tried to work with interrupts, but similar results.
I also tried also to cutoff the while, but, the data is still scrambled, imagine it as a piece, maybe shorter, but the pieces of gps and the other parameter can still mix.

do I really need to make a "serial" code? nothing to let them in "parallel" run?

prnet:
my idea was:

In that case I'd forget about the timer and do something like:

void loop()
{    
    while (HWSERIAL.available())
    {
      char c = HWSERIAL.read();
      Serial.write(c);    
      if (c=='\n') Serial.println(millis()); // After end-of-line print millis()
    }
}

Something like that?

mt3339 has 9600 baud and the complete sentence is about 350-400 chars (RMCGGA or ALLDATA have the same problem). .

This is part of your problem. It is sending you stuff faster than it can transmit.

Either choose to send less data, or increase the serial data rate.

Yes, I was conscious about the baud rate, but I used a buffer to solve (to say the true, I just received help with the code and it seems working good. Let me test, then I'll share the complete code.

Thanks guys.

The examples in serial input basics are simple reliable non-blocking ways to receive data.

Even if you don’t want to use any of them you will need code that does much the same thing.

…R

Turning off interrupts would likely interfere with your GPS reading, otherwise you could turn it off from the first GPS char read to the first ‘\n’ char returned by the GPS, to ensure your line is not garbled.

Plan B is to push your GPS chars into a string:

char buffer[64];
uint8_t pos = 0;

void loop() {
  char c = HWSERIAL.read();
  buffer[pos++] = c;
  if (c == '\n') {
    Serial.write(buffer);    
    pos =0;
  }
}

You could also ghave do_something() store milli() into a global variable that loop() writes to screen when it is non-zero at a convenient time (aka end of a GPS line), then clears it.

Except the GPS lines are longer than 64 char, so the previous example would be ok but you will have to make the char array bigger.

yes, sonyhome, your plan B is exactly what I was suggested, and it already works, and better with few improvements. A gps use nmea sentences of 80 chars so the array could be fixed at 80.