Hardware Serial, how the data come to buffer?

So, inside the super loop, I am getting the data from the GPS (i used serial2 (uart2)), gps sensor sends it every 200 ms.
My question:
Does an arduino reads the data from buffer in parallel or not? I mean what if the arduino will be make another stuff when gps sends the data ? Will the these data be read or not? Sometimes I got trash or incomplete data, is the problem associate with timings ?

example of incomplete data

$GNGGA,114728.00,5018.06879,N,12730.70747,E,1,13,0.81,143.5,M,9.8,M,,*7A
Lat: 5018.06879N Long: 12730.70747E
$GNGGA,114729.00,5018.06933,N,12730.70688,E,1,13,0.81,143.7,M,9.8,M,,*74
Lat: 5018.06933N Long: 12730.70688E
$GNGGA,114729.00,5018.06933,N,12730.70688,E,1,13,0.81,143.7,M,9.8,M,,*74
Lat: 5018.06933N Long: 12730.70688E
$GNGGA,114729.00,5018.06933,N,12730.70688,E,1,13,0.81,143.7,M,9.8,M,,*74
Lat: 5018.06933N Long: 12730.70688E
18.07022,N,12730.70662,E,1,12,0.88,144.5,M,9.8,M,,*7C
Lat: Long:
18.07022,N,12730.70662,E,1,12,0.88,144.5,M,9.8,M,,*7C
Lat: Long:
$GNGGA,114732.00,5018.07070,N,12730.70651,E,1,12,0.88,144.5,M,9.8,M,,*78
Lat: 5018.07070N Long: 12730.70651E
$GNGGA,114732.00,5018.07070,N,12730.70651,E,1,12,0.88,144.5,M,9.8,M,,*78
Lat: 5018.07070N Long: 12730.70651E
$GNGGA,114733.00,5018.07096,N,12730.70637,E,1,12,0.88,143.9,M,9.8,M,,*7A
Lat: 5018.07096N Long: 12730.70637E

Example of code

void loop() {

static char buff_GGA[nmea_size];
static String GGA = "";
static size_t pos;
int counter;
static int bothStrings;

while (Serial2.available() && pos <= nmea_size) {
  char c = Serial2.read();
  if (c != '\n' && c != '\r') {
      buff_GGA[pos++] = c;
    }

  if (c == '\n') {
    buff_GGA[pos++] = '\0';
    GGA = buff_GGA;
    pos = 0;
  }
  if (pos >= nmea_size){ pos = 0;}
  
  
}


// $GNGGA,150550.00,5018.10764,N,12730.68759,E,1,05,7.62,150.9,M,9.8,M,,*76




if (millis() - timer >= 500) {

  Serial.println(S);
  coords = getCoordinates(S);
  Serial.println(coords[0]);
  Serial.println(coords[1]);

  file = SD.open("gps.txt", FILE_WRITE);
  if (file) {
    file.println(GGA);
    file.print("Lat: "); file.print(coords[0]); file.print('\t');
    file.print("Long: "); file.println(coords[1]);
    file.close();
  }


  timer = millis();
}

}

As long as interrupts are not disabled the data should come into the serial buffer. If the buffer is read often enough so that it does not fill up the data should be intact.

What other code is running. Some libraries, like for instance FastLED, disable interrupts during execution. Data that comes into the serial port while interrupts are disabled can be missed or corrupted.

We can't see your code so can't offer any less general advice.

That is the important part; the buffer is only 64 bytes. If that is full, you loose the data that follows.

@vipnoob, can you please post your complete code, not just loop(). It's e.g. not clear what the variable S is and how it is filled. How big is buff_GGA, can it hold the full message plus a terminating '\0'?

One possible issue that I see in your code is that you don't take into account that serial is slow. It's possible that the GPS is transfering a byte but it's not completely transfered yet and Serial2.available() will in that case return 0 and your while-loop will terminate.

whole code (github.com)

I'm not familiar with NMEA but would base my code on example 3 in Serial Input Basics - updated with correctly choosen startmarker ('$') and endmarker ('\n').

You're advised to post your code here, lots of people don't like going to another site? I've done it now for you.

#include <SPI.h>
#include <SD.h>


char UART_4800bps[] = "$CCCAS,1,0*50";
char UART_9600bps[] = "$CCCAS,1,1*51";
char UART_19200bps[] = "$CCCAS,1,2*52";
char UART_38400bps[] = "$CCCAS,1,3*53";
char UART_57600bps[] = "$CCCAS,1,4*54";
char UART_115200bps[] = "$CCCAS,1,5*55";
char UART_230400bps[] = "$CCCAS,1,6*56";


char resetSettings[] = "$CCDFT,0,*66";


char delay100ms[] = "$CCINV,100,*60";
char delay500ms[] = "$CCINV,500,*64";
char delay1s[] = "$CCINV,1000,*50";
char delay10s[] = "$CCINV,10000,*60";
char delay60s[] = "$CCINV,60000,*67";



char OpenRMC[] = "$CCMSG,RMC,1,1,*05";
char CloseRMC[] = "$CCMSG,RMC,1,0,*04";
char OpenGGA[] = "$CCMSG,GGA,1,1,*18";
char CloseGGA[] = "$CCMSG,GGA,1,0,*19";
char OpenGSA[] = "$CCMSG,GSA,1,1,*0C";
char CloseGSA[] = "$CCMSG,GSA,1,0,*0D";
char OpenGSV[] = "$CCMSG,GSV,1,1,*1B";
char CloseGSV[] = "$CCMSG,GSV,1,0,*1A";



char GPS_GLO_COLD[] = "$CCSIR,6,1*4F";
char GPS_GLO_WARM[] = "$CCSIR,6,2*4C";
char GPS_GLO_HOT[] = "$CCSIR,6,3*4D";



// MAX length of the sentence is 82 bits + 1 bit for \0
char RMC[82 + 1];




File file;
// CS пин для sd карты
const int sdPin = 53;
void setup() {
  Serial2.begin(9600);
  Serial.begin(9600);
  // println отправляем текст + \r\n!!!


  if (!SD.begin(sdPin)) {
    Serial.println(F("Sd card module hasn't been found!"));
    //while (1);
  }


  //Serial2.println(resetSettings);
  Serial2.println(delay1s);
  delay(200);

  Serial2.println(CloseGSA);
  delay(200);
  Serial2.println(CloseRMC);
  delay(200);
  Serial2.println(CloseGSV);
  delay(200);
}

unsigned long timer;

String S =  "$GNGGA,150559.00,5018.10716,N,12730.68913,E,1,05,7.62,150.8,M,9.8,M,,*7B";
String S1 = "$GNGGA,115806.00,,,,,0,00,99.9,,,,,,*4A";



String* getCoordinates(String& s) {
  int len = s.length();

  int num_commas = 0;
  static String coordinates[] = {"", ""};

  String lattitude = "";
  char lat_dir;
  String longtitude = "";
  char long_dir;

  bool wrong_dataFlag = false;
  coordinates[0] = "";
  coordinates[1] = "";
  
  int blanks = 0;
  

  if (s.substring(0,  7) == "$GNGGA," && s[len - 3] == '*') {
    for (int i = 0; i < len; i++) {
      if (wrong_dataFlag) { break; }
      if (s[i] == ',') { num_commas++; continue; }
      switch (num_commas){
        case 2:
          if (blanks < 1) {blanks++;}
          if ((s[i] >= '0' && s[i] <= '9') || (s[i] == '.')) {
            lattitude += s[i];
          }
          else{
            wrong_dataFlag = true;
          }
           break;
        case 3:
          if (blanks < 2) {blanks++;}
          if (s[i] == 'N' || s[i] == 'S') {
            lat_dir = s[i];
          }
          else{
            wrong_dataFlag = true;
          }
          break;
        case 4:
          if (blanks < 3) {blanks++;}
          if ((s[i] >= '0' && s[i] <= '9') || (s[i] == '.')) {
            longtitude += s[i];
          }
          else{
            wrong_dataFlag = true;
          }
          break;
        case 5:
          if (blanks < 4) {blanks++;}
          if (s[i] == 'E' || s[i] == 'W') {
            long_dir = s[i];
          }
          else{
            wrong_dataFlag = true;
          }
          break;
      }

    }
    if (wrong_dataFlag == false && blanks == 4){

      float latt = lattitude.toFloat();
      float longt = longtitude.toFloat();
 
      // 5018.10716
      latt = int(latt / 100) + ((int(latt) % 100) + (latt - int(latt))) / 60;
      // 12730.68913
      longt = int(longt / 100) + ((int(longt) % 100) + (longt - int(longt))) / 60;
      //Serial.println(latt, 6);
      //Serial.println(longt, 6);
      coordinates[0] = String(latt, 6) + lat_dir; coordinates[1] = String(longt, 6) + long_dir;


      
    }
    // Если есть пропуски или данные с мусором
    else{
      coordinates[0] = "-"; coordinates[1] = "-";
    }

    
  }
  else{
    coordinates[0] = "-"; coordinates[1] = "-";
  }
  return coordinates;
}
  String* coords;



#define nmea_size 82

void loop() {

    
    static char buff_GGA[nmea_size];
    static String GGA = "";
    static size_t pos;
    int counter;
    static int bothStrings;
    
    while (Serial2.available() && pos <= nmea_size) {
      char c = Serial2.read();
      if (c != '\n' && c != '\r') {
          buff_GGA[pos++] = c;
        }
   
      if (c == '\n') {
        buff_GGA[pos++] = '\0';
        GGA = buff_GGA;
        pos = 0;
      }
      if (pos >= nmea_size){ pos = 0;}
      
      
    }
    

    // $GNGGA,150550.00,5018.10764,N,12730.68759,E,1,05,7.62,150.9,M,9.8,M,,*76




    if (millis() - timer >= 500) {

      Serial.println(S);
      coords = getCoordinates(S);
      Serial.println(coords[0]);
      Serial.println(coords[1]);

      file = SD.open("gps.txt", FILE_WRITE);
      if (file) {
        file.println(GGA);
        file.print("Lat: "); file.print(coords[0]); file.print('\t');
        file.print("Long: "); file.println(coords[1]);
        file.close();
      }


      timer = millis();
    }
  }

Sorry for my faults and thank you for your advices :smiling_face:

I forgot to mention that you need to adjust the buffer size :wink:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.