0

I am getting multiple messages from a GPS device at different frequencies. After getting strings I have to save this data on the SD card. It works well when we have the same frequencies messages but if the frequencies are not same the saved data gets some blank spaces.I am using the split strings method.

    CR1A = String1.indexOf(13);  //finds location of first    String1A = String1.substring(0, CR1A + 2 );   //captures first data String    CR1B = String1.indexOf(13, CR1A + 2 ); //finds location of second ,    String1B = String1.substring(CR1A , CR1B + 2 ); //captures second data String    CR1C = String1.indexOf(13, CR1B + 2 );    String1C = String1.substring(CR1B , CR1C + 2 );    CR1D = String1.indexOf(13, CR1C + 2 );    String1D = String1.substring(CR1C , CR1D + 2 );    CR1E = String1.indexOf(13, CR1D + 2 );    String1E = String1.substring(CR1D , CR1E + 2 );    CR1F = String1.indexOf(13, CR1E + 2 );    String1F = String1.substring(CR1E , CR1F + 2 );    strID = (String1A.substring(0, 2));    if (strID == "$G") {      File dataFile = SD.open("GPS1.txt", FILE_WRITE);      // if the file is available, write to it:      strID = (String1A.substring(0, 5));      if (strID == "$GPGG") {        dataFile.print(dt);        dataFile.print(" ");        dataFile.print(tm);        dataFile.print(msec);        dataFile.print(",");        dataFile.print(String1A);        String1A = "";      }      strID = (String1D.substring(4, 6));      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {        dataFile.print(String1B);        String1B = "";      }      strID = (String1C.substring(4, 6));      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {        dataFile.print(String1C);        String1C = "";      }      strID = (String1D.substring(4, 6));      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {        dataFile.print(String1D);        String1D = "";      }      strID = (String1E.substring(4, 6));      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {        dataFile.print(String1E);        String1E = "";      }      strID = (String1F.substring(4, 6));      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {        dataFile.print(String1F);        String1F = "";      }      dataFile.close();    }

EDIT:

This is the code now I am using. I have turned off all the commands which extract strings from my available data received at the serial port. I am just using an interrupt timer for it.. and it is working perfectly. But I didn't like this simple method and I don't know it's a good way to get strings like this or not as I am not a good programmer.

#include <TimerOne.h>#define RxTimeOut 5/*  ** MEGA MINI **  ** MOSI - pin 51  ** MISO - pin 50  ** CLK - pin 52  ** CS - pin 53 (for MKRZero SD: SDCARD_SS_PIN)  ** SDA - pin 20  ** SCL - pin 21*/#include <Wire.h>#include <Adafruit_GFX.h>#include <Adafruit_SSD1306.h>#include <EEPROM.h>#include "math.h"#include <SPI.h>#include <SD.h>#include "RTClib.h"#define DS1307_CTRL_ID 0x68unsigned long int ticks = 0;RTC_DS1307 rtc;bool flag = false;String GPSmessage = "";const int chipSelect = 53;String dataString = "";//String dataString1 = "";//String dataString2 = "";//String dataString3 = "";bool stringComplete = false;bool string1Complete = false;bool string2Complete = false;bool string3Complete = false;String strID = "";unsigned long msec;const long interval = 500;#define SCREEN_WIDTH 128 // OLED display width, in pixels#define SCREEN_HEIGHT 64 // OLED display height, in pixels#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);unsigned long CurrentBaudRate = 9600;unsigned long x = 0;int Up = 3;int Dn = 4;int Mnu = 5;String String1;String inputString1 = "";         // a String to hold incoming databoolean NewDataFlag1 = 0;unsigned int Serial1TimeOut = 0;String String2;String inputString2 = "";         // a String to hold incoming databoolean NewDataFlag2 = 0;unsigned int Serial2TimeOut = 0;String String3;String inputString3 = "";         // a String to hold incoming databoolean NewDataFlag3 = 0;unsigned int Serial3TimeOut = 0;void timerIsr(){  serial1Event();  serial2Event();  serial3Event();  if (Serial1TimeOut > 0)Serial1TimeOut--;  if (Serial1TimeOut == 0 && NewDataFlag1 == 1)  {    String1 = inputString1;    inputString1 = "";    NewDataFlag1 = 0;  }  if (Serial2TimeOut > 0)Serial2TimeOut--;  if (Serial2TimeOut == 0 && NewDataFlag2 == 1)  {    String2 = inputString2;    inputString2 = "";    NewDataFlag2 = 0;  }  if (Serial3TimeOut > 0)Serial3TimeOut--;  if (Serial3TimeOut == 0 && NewDataFlag3 == 1)  {    String3 = inputString3;    inputString3 = "";    NewDataFlag3 = 0;  }}void setup() {  Timer1.initialize(5000); // Timer event time  Timer1.attachInterrupt( timerIsr );  Serial.println("Sonay di nathli");  //========================================= SD Card =======================================================//  //  Serial.println("Initializing SD card...");  // see if the card is not present:  if (!SD.begin(chipSelect)) {    //    Serial.println("Card failed, or not present");    //     don't do anything more:    return;  }  //  Serial.println("SD card Ready");  //====================================================== RTC =============================================//  if (!rtc.begin())  {    //    Serial.println("Couldn't find RTC");    Serial.flush();    abort();  }  if (!rtc.isrunning()) {    //    Serial.println("RTC is NOT running, let's set the time!");    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));  }  //================================================ OLED Baudrate selection ====================================================//  pinMode(Up, INPUT_PULLUP);  pinMode(Dn, INPUT_PULLUP);  pinMode(Mnu, INPUT_PULLUP);  unsigned char bdindx = EEPROM.read(0);  if (bdindx > 3) bdindx = 0;  if (bdindx == 0) CurrentBaudRate = 4800;  if (bdindx == 1) CurrentBaudRate = 9600;  if (bdindx == 2) CurrentBaudRate = 19200;  if (bdindx == 3) CurrentBaudRate = 115200;  delay (500);  while (!Serial) { }// wait for serial port to connect  pinMode(LED_BUILTIN, OUTPUT);  Serial.begin(CurrentBaudRate);  Serial1.begin(CurrentBaudRate);  Serial2.begin(CurrentBaudRate);  Serial3.begin(CurrentBaudRate);  Serial.println(CurrentBaudRate);  delay (1000);  display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);  display.clearDisplay();  display.setTextSize(1);             // Normal 1:1 pixel scale  display.setTextColor(SSD1306_WHITE);        // Draw white text  display.display();}String String1A, String1B, String1C, String1D, String1E, String1F;String String2A, String2B, String2C, String2D, String2E, String2F;String String3A, String3B, String3C, String3D, String3E, String3F;int CR1A, CR1B, CR1C, CR1D, CR1E, CR1F;int CR2A, CR2B, CR2C, CR2D, CR2E, CR2F;int CR3A, CR3B, CR3C, CR3D, CR3E, CR3F;// ============================================ Showing baud rate on screen (position) ===========================================//void DrawBaudRate(unsigned long BdRt){  unsigned char Xoffset = 0;  if (BdRt >= 0 && BdRt < 10000) Xoffset = 37;  if (BdRt >= 10000 && BdRt < 100000) Xoffset = 30;  if (BdRt >= 100000 ) Xoffset = 25;  //  display.drawRect(0,0,128,64,SSD1306_WHITE);  //  display.setTextSize(2);  //  display.setCursor(15,10);  //  display.println("Baudrate");  //  display.setTextSize(2);  //  display.setCursor(15,10);  //  display.println(tm);  //  display.setCursor(Xoffset,37);// 6 digit  //  display.println(BdRt);  //  display.display();  //  delay(10);}// ================================================== Selection of Baud Rate ========================================================//unsigned long SelectBaudRate(unsigned long BdRt){  unsigned char BdRtIndx = 0;  unsigned int FlashCnt = 0;  if (BdRt == 4800) BdRtIndx = 0;  if (BdRt == 9600) BdRtIndx = 1;  if (BdRt == 19200) BdRtIndx = 2;  if (BdRt == 115200) BdRtIndx = 3;  unsigned char Xoffset = 0;  if (BdRt >= 0 && BdRt < 10000) Xoffset = 37;  if (BdRt >= 10000 && BdRt < 100000) Xoffset = 30;  if (BdRt >= 100000 ) Xoffset = 25;  display.drawRect(0, 0, 128, 64, SSD1306_WHITE);  display.setTextSize(1);  display.setCursor(15, 10); display.println("Select Baudrate");  display.setCursor(15, 20); display.println("by Up/Dn Buttons");  display.setTextSize(2);  display.setCursor(Xoffset, 37); // 6 digit  display.println(BdRt);  display.display();  delay(10);  while (digitalRead(Mnu) == 0) delay(10);  delay(100);  while (digitalRead(Mnu) == 1)  {    delay(10);    FlashCnt++;    if (digitalRead(Up) == 0)    {      if (BdRtIndx < 3) BdRtIndx++;    }    if (digitalRead(Dn) == 0)    {      if (BdRtIndx > 0) BdRtIndx--;    }    if (BdRtIndx == 0) BdRt = 4800;    if (BdRtIndx == 1) BdRt = 9600;    if (BdRtIndx == 2) BdRt = 19200;    if (BdRtIndx == 3) BdRt = 115200;    if (BdRt >= 0 && BdRt < 10000) Xoffset = 37;    if (BdRt >= 10000 && BdRt < 100000) Xoffset = 30;    if (BdRt >= 100000 ) Xoffset = 25;    display.clearDisplay();    display.drawRect(0, 0, 128, 64, SSD1306_WHITE);    display.setTextSize(1);    display.setCursor(15, 10); display.println("Select Baudrate");    display.setCursor(15, 20); display.println("by Up/Dn Buttons");    display.setTextSize(2);    display.setCursor(Xoffset, 37); // 6 digit    if (FlashCnt > 1) display.println(BdRt);    if (FlashCnt > 2) FlashCnt = 0;    display.display();    delay(250);    //while(digitalRead(Up)==0 || digitalRead(Dn)==0) delay(10);  }  while (digitalRead(Mnu) == 0) delay(10);  display.clearDisplay();  display.drawRect(0, 0, 128, 64, SSD1306_WHITE);  display.setTextSize(2);  display.setCursor(20, 10); display.println("Saving");  display.setCursor(20, 35); display.println("Changes");  display.display();  delay(2000);  EEPROM.write(0, BdRtIndx);  return (BdRt);}//=================================================== OLED showing time ===============================================//char Time[]     = "  :  :  ";byte i, second, minute, hour;void DS3231_display() {  // Convert BCD to decimal  second = (second >> 4) * 10 + (second & 0x0F);  minute = (minute >> 4) * 10 + (minute & 0x0F);  hour   = (hour >> 4)   * 10 + (hour & 0x0F);  // End conversion  Time[7]     = second % 10 + 48;  Time[6]     = second / 10 + 48;  Time[4]     = minute % 10 + 48;  Time[3]     = minute / 10 + 48;  Time[1]     = hour   % 10 + 48;  Time[0]     = hour   / 10 + 48;  display.drawRect(0, 0, 128, 64, SSD1306_WHITE);  draw_text(16, 25, Time, 2);                         // Display the time}void blink_parameter() {  byte j = 1;  while (j < 10 && digitalRead(Up) && digitalRead(Dn)) {    j++;    delay(25);  }}byte edit(byte x_pos, byte y_pos, byte parameter) {  char text[3];  sprintf(text, "%02u", parameter);  while (!digitalRead(Up));                     // Wait until button B1 released  while (true) {    while (!digitalRead(Dn)) {                  // If button B2 is pressed      display.clearDisplay();      parameter++;      if (i == 0 && parameter > 23)                  // If hours > 23 ==> hours = 0        parameter = 0;      if (i == 1 && parameter > 59)                  // If minutes > 59 ==> minutes = 0        parameter = 0;      sprintf(text, "%02u", parameter);      draw_text(x_pos, y_pos, text, 2);      delay(200);                                    // Wait 200ms    }    display.drawRect(0, 0, 128, 64, SSD1306_WHITE);    draw_text(x_pos, y_pos, "  ", 2);    blink_parameter();    draw_text(x_pos, y_pos, text, 2);    blink_parameter();    if (!digitalRead(Up)) {                     // If button B1 is pressed      i++;                                           // Increament 'i' for the next parameter      //      display.clearDisplay();      return parameter;                              // Return parameter value and exit    }  }}void draw_text(byte x_pos, byte y_pos, char *text, byte text_size) {  display.setCursor(x_pos, y_pos);  display.setTextSize(text_size);  display.print(text);  display.display();}//---------------------------------------------void loop() {  // ========================================= Editing time and displaying on OLED ============================================//  if (!digitalRead(Up)) {                       // If button B1 is pressed    i = 0;    while (!digitalRead(Up));                   // Wait for button B1 release    hour   = edit(16, 25, hour);                     // Edit hours    minute = edit(52, 25, minute);                   // Edit minutes    // Convert decimal to BCD    minute = ((minute / 10) << 4) + (minute % 10);    hour = ((hour / 10) << 4) + (hour % 10);    // End conversion    // Write data to DS3231 RTC    Wire.beginTransmission(0x68);               // Start I2C protocol with DS3231 address    Wire.write(0);                              // Send register address    Wire.write(0);                              // Reset sesonds and start oscillator    Wire.write(minute);                         // Write minute    Wire.write(hour);                           // Write hour    Wire.endTransmission();                     // Stop transmission and release the I2C bus    delay(200);                                 // Wait 200ms  }  Wire.beginTransmission(0x68);                 // Start I2C protocol with DS3231 address  Wire.write(0);                                // Send register address  Wire.endTransmission(false);                  // I2C restart  Wire.requestFrom(0x68, 7);                    // Request 7 bytes from DS3231 and release I2C bus at end of reading  second = Wire.read();                         // Read seconds from register 0  minute = Wire.read();                         // Read minutes from register 1  hour   = Wire.read();                         // Read hour from register 2  Wire.beginTransmission(0x68);                 // Start I2C protocol with DS3231 address  Wire.write(0x11);                             // Send register address  Wire.endTransmission(false);                  // I2C restart  Wire.requestFrom(0x68, 2);                    // Request 2 bytes from DS3231 and release I2C bus at end of reading  DS3231_display();                             // Diaplay time & calendar  delay(50);                                    // Wait 50ms  { display.clearDisplay();    if (digitalRead(Mnu) == 0) CurrentBaudRate = SelectBaudRate(CurrentBaudRate);    //  DrawBaudRate(CurrentBaudRate);    delay(10);    x++;    if (x > 123456) x = 0;  }  // ======================================= Reading Date and Time from RTC =============================================//  DateTime now = rtc.now();  char dt[16];  char tm[16];  char buffer [16];  uint8_t thisSec, thisMin, thisHour;  thisSec = now.second();  thisMin = now.minute();  thisHour = now.hour();  sprintf(dt, "%02d-%02d-%02d", now.year(), now.month(), now.day());  sprintf(tm, "%02d%02d%02d", now.hour(), now.minute(), now.second());  sprintf (buffer, "%02d:%02d:%02d", thisHour, thisMin, thisSec);  msec = millis() % 1000; //TO USE LAST 3 DIGITS OF MILLIS OF ARDUINO  //SERIAL_PORT_1//  if (string1Complete)  { Serial.print (String1);//    CR1A = String1.indexOf(13);  //finds location of first//    String1A = String1.substring(0, CR1A + 2 );   //captures first data String//    CR1B = String1.indexOf(13, CR1A + 2 ); //finds location of second ,//    String1B = String1.substring(CR1A , CR1B + 2 ); //captures second data String//    CR1C = String1.indexOf(13, CR1B + 2 );//    String1C = String1.substring(CR1B , CR1C + 2 );//    CR1D = String1.indexOf(13, CR1C + 2 );//    String1D = String1.substring(CR1C , CR1D + 2 );//    CR1E = String1.indexOf(13, CR1D + 2 );//    String1E = String1.substring(CR1D , CR1E + 2 );//    CR1F = String1.indexOf(13, CR1E + 2 );//    String1F = String1.substring(CR1E , CR1F + 2 );////    strID = (String1A.substring(0, 5));//    if (strID == "$GPGG") {//      Serial.println(String1);//    }//    strID = (String1B.substring(0, 5));//    if (strID == "$GPVT") {//      Serial.println(String1B);//    }//    strID = (String1C.substring(0, 5));//    if (strID == "$GPZD") {//      Serial.println(String1C);//    }//    strID = (String1D.substring(0, 5));//    if (strID == "$GPGL") {//      Serial.println(String1D);//    }//    strID = (String1E.substring(0, 5));//    if (strID == "$GPGN") {//      Serial.println(String1E);//    }//    strID = (String1F.substring(0, 5));//    if (strID == "$GPGR") {//      Serial.println(String1F);//    }//    strID = (String1.substring(0, 2));//    if (strID == "$") {      File dataFile = SD.open("GPS1.txt", FILE_WRITE);      // if the file is available, write to it:      strID = (String1A.substring(0, 5));      if (strID == "$GPGG") {        dataFile.print(dt);        dataFile.print(" ");        dataFile.print(tm);        dataFile.print(msec);        dataFile.print(",");        dataFile.print(String1);        Serial.print (String1);        String1 = "";        Serial.print (String1);        dataFile.close();      }//    }//      strID = (String1D.substring(4, 6));//      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {//        dataFile.print(String1B);//        String1B = "";//      }//      strID = (String1C.substring(4, 6));//      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {//        dataFile.print(String1C);//        String1C = "";//      }//      strID = (String1D.substring(4, 6));//      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {//        dataFile.print(String1D);//        String1D = "";//      }//      strID = (String1E.substring(4, 6));//      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {//        dataFile.print(String1E);//        String1E = "";//      }//      strID = (String1F.substring(4, 6));//      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {//        dataFile.print(String1F);//        String1F = "";//      }      //    }    else {      File dataFile = SD.open("ES2.txt", FILE_WRITE);      if (dataFile) {        dataFile.print(dt);        dataFile.print(" ");        dataFile.print(tm);        dataFile.print(msec);        dataFile.print(",");        dataFile.println(String1);        Serial.print (String1);//        dataFile.println(String1B);        String1A = "";        String1B = "";        dataFile.close();      }    }//  }  string1Complete = false;  }  }//-----------------------------------------------------------------------------------------------------------------void serial1Event() {  while (Serial1.available()) {    char inChar1 = (char)Serial1.read();    inputString1 += inChar1;    Serial1TimeOut = RxTimeOut;    NewDataFlag1 = 1;    if (NewDataFlag1 == 1) {      string1Complete = true;    }  }}
Juraj's user avatar
Juraj
18.3k4 gold badges32 silver badges50 bronze badges
askedOct 9, 2021 at 11:42
Omar Rai's user avatar
6
  • 2
    You never check thatindexOf() does find the'\r'. Why do you try to process five messages at a time instead of processing them one by one?CommentedOct 9, 2021 at 12:50
  • 1
    Please provide a more detailed description of what message data you have in that string, what errornous output you get and where in the code that happens.CommentedOct 9, 2021 at 14:51
  • 4
    If (strID == "TG" || "DA" || "LL" || "NS" ... that is nonsenseCommentedOct 9, 2021 at 15:41
  • I will provide you my complete program. Actually there is no delay between sentences so when the processor writes one sentence to sd card 2nd message arrives and most of the time it saves glitch in sd card.CommentedOct 10, 2021 at 13:06
  • 1
    If you're curious,"DA","LL", and"NS" are alltruthy in C++. So, the above mentioned nonsense is functionally equivalent toif (true).CommentedOct 10, 2021 at 13:25

1 Answer1

1

I do not know what the “frequencies” have to do with your problem, but Iwould bet that you would get more reliable results if you handle oneNMEA sentence at a time, instead of trying to handle six of them atonce, and hoping to get the right ones.

Below is a function that processes one complete sentence at a time. Itrecords the sentence to the SD file if its type belongs to a list of“interesting” types you want to monitor:

// Sentence types that are to be recorded.const char monitoredTypes[6][4] = {    "GGA", "VTG", "ZDA", "GLL", "GNS", "GRS"};// Process a complete, CRLF-terminated NMEA sentence.void processSentence(String &sentence) {    // Sanity check.    if (sentence.substring(0, 3) != "$GP") {        Serial.print("WARNING: invalid sentence: ");        Serial.print(sentence);        return;    }    // Record the sentence if it has an interesting type.    String type = sentence.substring(3, 6);    for (int i = 0; i < 6; i++) {        if (type == monitoredTypes[i]) {            File dataFile = SD.open("GPS1.txt", FILE_WRITE);            if (type == "GGA") {  // this type seems to be special                dataFile.print(dt);                dataFile.print(" ");                dataFile.print(tm);                dataFile.print(msec);                dataFile.print(",");            }            dataFile.print(sentence);            dataFile.close();        }    }}

The way to use it is to buffer the incoming characters until you get acomplete sentence (identified by the final LF), then submit that bufferto this function:

String buffer;void loop() {    while (Serial.available() > 0) {        char c = Serial.read();        buffer += c;        // On end of sentence, process and clear the buffer.        if (c == '\n') {            processSentence(buffer);            buffer = "";        }    }}

Note that it wouldn't take too much work to get rid of theStringclass and use plain C strings instead. Plain strings are way more memoryfriendly.

answeredOct 9, 2021 at 21:11
Edgar Bonet's user avatar
0

Your Answer

Sign up orlog in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

By clicking “Post Your Answer”, you agree to ourterms of service and acknowledge you have read ourprivacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.