byte value "disappears"

I don't know what I am doing wrong, but a byte value seems to disappear.

I have the following code that reads the Serial for GPS data.
I then parse this data.
I use a if...else if...else statement to check if the GPS data is Valid.
If it is Valid, I will then write the time and date to the RTC.

The below log shows that I parse the data correctly.
However, as soon as I try to print the data within the if...else if...else statement, I loose the first "Hours Byte:"

code:

void GetGPS(){
  // MANAGES THE CHARACTERS RECEIVED BY GPS
  while (serGPS.available()) {
    GPS_info_char=serGPS.read();
    
    if (GPS_info_char == '

Log:

GNRMC,134008.000,A,2545.7844,S,02813.1639,E,1.23,357.00,270218,,,A,VV
Time String: 134008.000
Hours Byte: 13
Minutes Byte: 40
Seconds Byte: 8
Day Byte: 27
Month Byte: 2
Year Byte: 18

GOT VALID
Hours Byte: 0
Minutes Byte: 40
Seconds Byte: 8
Day Byte: 27
Month Byte: 2
Year Byte: 18

){ // start of message
      message_started=true;
      received_char=0;
    }else if (GPS_info_char == '*'){ // end of message

for (i=0; i<received_char; i++){
       
//  Serial.write(GPS_info_buffer[i]); // writes the message once it has been completely received

// GNRMC,064509.000,A,2545.7696,S,02813.1923,E,0.28,149.40,230218,,,A,V
// GPRMC,064602.000,V,,,,,0.00,149.40,230218,,,N,V

strcpy(tempGPS, GPS_info_buffer);
Serial.println(tempGPS);

char * strtokIndx; // this is used by strtok() as an index
    strtokIndx = strtok(tempGPS,",");      // get the first part - the string
    strcpy(GPSHeader, strtokIndx); // copy it to GPSHeader

strtokIndx = strtok(NULL, ",");
    strcpy(GPSTime, strtokIndx); // copy to GPSTime
    String GPSNowTime(GPSTime);
    Serial.print("Time String: ");
    Serial.println(GPSNowTime);

hours = GPSNowTime.substring(0,2).toInt();
            Serial.print("Hours Byte: ");
            Serial.println(hours);

minutes = GPSNowTime.substring(2, 4).toInt();
            Serial.print("Minutes Byte: ");
            Serial.println(minutes);

seconds = GPSNowTime.substring(4, 6).toInt();
            Serial.print("Seconds Byte: ");
            Serial.println(seconds);

strtokIndx = strtok(NULL, ",");
    strcpy(GPSValid, strtokIndx); // copy to GPSValid
    String Valid(GPSValid);

strtokIndx = strtok(NULL, ",");
    strcpy(GPSLat, strtokIndx); // copy to GPSLat
//    Serial.println(GPSLat);

strtokIndx = strtok(NULL, ",");
    strcpy(GPSNS, strtokIndx); // copy to GPSNS
//    Serial.println(GPSNS);
   
    strtokIndx = strtok(NULL, ",");
    strcpy(GPSLon, strtokIndx); // copy to GPSLon
//    Serial.println(GPSLon);

strtokIndx = strtok(NULL, ",");
    strcpy(GPSEW, strtokIndx); // copy it to GPSEW
//    Serial.println(GPSEW);

strtokIndx = strtok(NULL, ",");
    strcpy(GPSSpeed, strtokIndx); // copy to GPSSpeed
//    Serial.println(GPSSpeed);

strtokIndx = strtok(NULL, ",");
    strcpy(GPSTrack, strtokIndx); // copy to GPSTrack
//    Serial.println(GPSTrack);

strtokIndx = strtok(NULL, ",");
    strcpy(GPSDate, strtokIndx); // copy to GPSDate
//    Serial.println(GPSDate);
    String GPSNowDate(GPSDate);

day = GPSNowDate.substring(0, 2).toInt();
            Serial.print("Day Byte: ");
            Serial.println(day);

month = GPSNowDate.substring(2, 4).toInt();
            Serial.print("Month Byte: ");
            Serial.println(month);

year = GPSNowDate.substring(4, 6).toInt();
            Serial.print("Year Byte: ");
            Serial.println(year);
//      }

if (Valid == "A")
        {
          Serial.println();
          Serial.println("GOT VALID");
         
            Serial.print("Hours Byte: ");
            Serial.println(hours);

Serial.print("Minutes Byte: ");
            Serial.println(minutes);

Serial.print("Seconds Byte: ");
            Serial.println(seconds);

Serial.print("Day Byte: ");
            Serial.println(day);

Serial.print("Month Byte: ");
            Serial.println(month);

Serial.print("Year Byte: ");
            Serial.println(year);

Serial.println();
           
        }
        else if (Valid == "V")
        {
          Serial.println();
          Serial.println("NOT VALID");
          Serial.println();
        }
        else
        {
          // Do Nothing
        }

}
      Serial.println();
      message_started=false; // ready for the new message
    }
    else if (message_started==true){ // the message has already started and I got a new character
      if (received_char<=GPS_INFO_BUFFER_SIZE){ // to avoid buffer overflow
        GPS_info_buffer[received_char]=GPS_info_char;
        received_char++;
      }else{ // resets everything (overflow happened)
        message_started=false;
        received_char=0;
      }
    }
  }
}


Log:

§DISCOURSE_HOISTED_CODE_1§

    strcpy(GPSTime, strtokIndx); // copy to GPSTime
    String GPSNowTime(GPSTime);
    Serial.print("Time String: ");
    Serial.println(GPSNowTime);

Do you think that the print() method can't print a string? Do you think it can then somehow unwrap the string that the String instance wraps and then print it?

Quit pissing away resources on the String class, uselessly.

When variables unpredictably loose their values, it is almost always because you have a buffer overflow issue. Somewhere, you are writing more data into an array than it can hold.

You need to post ALL of your code, so we can see how big the arrays are vs. how much data you are writing to them.

The formatting of the code is horrible.... What is the purpose of this for loop?

if (GPS_info_char == '*'){ // end of message

  for (i=0; i<received_char; i++) {

Does this loop not cause the received message to be parsed "received_char" times instead of only once?

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. Just use cstrings - char arrays terminated with 0.

...R

Many thanks all.
I am using a MKRFOX1200 board.

My complete code:

#include <RTCZero.h>
#include <SigFox.h>
#include <ArduinoLowPower.h>
#include <Arduino.h>                              // required before wiring_private.h
#include <wiring_private.h>
#include <SparkFunLSM6DS3.h>



// GPSSerial (Serial3) pin and pad definitions (in Arduino files Variant.h & Variant.cpp)
#define PIN_SERIAL3_RX       (5ul)                // Pin description number for PIO_SERCOM on D5
#define PIN_SERIAL3_TX       (4ul)                // Pin description number for PIO_SERCOM on D4
#define PAD_SERIAL3_TX       (UART_TX_PAD_2)      // SERCOM pad 2 TX
#define PAD_SERIAL3_RX       (SERCOM_RX_PAD_3)    // SERCOM pad 3 RX

// Instantiate the extra Serial classes
Uart serGPS(&sercom4, PIN_SERIAL3_RX, PIN_SERIAL3_TX, PAD_SERIAL3_RX, PAD_SERIAL3_TX);

#define GPS_INFO_BUFFER_SIZE 128
char GPS_info_char;
char GPS_info_buffer[GPS_INFO_BUFFER_SIZE];
unsigned int received_char;

int i; // counter
bool message_started;
//unsigned long time_1=0;
//unsigned long time_2=0;


char tempGPS[256]; 
char GPSHeader[5] = {0};
char GPSTime[10];
char GPSValid[1];
char GPSLat[9];
char GPSNS[1];
char GPSLon[10];
char GPSEW[1];
char GPSSpeed[4];
char GPSTrack[6];
char GPSDate[6];


RTCZero rtc;

/* Change these values to set the current initial time */
byte seconds = 00;
byte minutes = 00;
byte hours = 00;
/* Change these values to set the current initial date */
byte day = 00;
byte month = 00;
byte year = 00;

byte valid;




void setup() {

  rtc.begin();
  rtc.attachInterrupt(alarmMatch);
//  rtc.standbyMode();
  
  pinPeripheral(4, PIO_SERCOM_ALT);   // Assign pins 4 & 5 SERCOM functionality
  pinPeripheral(5, PIO_SERCOM_ALT);
  serGPS.begin(9600);               // Begin Serial GPS
  
  Serial.begin(9600);

// Setup L96 NMEA messages to $GNRMC ONLY
serGPS.println("$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29");
Serial.println("GPS SET");

  
  while (!Serial) {};

// Setup Interrupt INT_BUTTON
  pinMode(A1, INPUT_PULLUP);
  attachInterrupt(A1, INT_BUTTON, FALLING);

  // Uncomment this line and comment begin() if you are working with a custom board
//  if (!SigFox.begin(SPI1, 30, 31, 33, 28, LED_BUILTIN)) {
  if (!SigFox.begin()) {
    Serial.println("Shield error or not present!");
    return;
  }
  // Enable debug led and disable automatic deep sleep
  // Comment this line when shipping your project :)
  SigFox.debug();

  String version = SigFox.SigVersion();
  String ID = SigFox.ID();
  String PAC = SigFox.PAC();

  // Display module informations
  Serial.println("MKRFox1200 Sigfox first configuration");
  Serial.println("SigFox FW version " + version);
  Serial.println("ID  = " + ID);
  Serial.println("PAC = " + PAC);

  Serial.println("");

  Serial.print("Module temperature: ");
  Serial.println(SigFox.internalTemperature());

//  Serial.println("Register your board on https://backend.sigfox.com/activate with provided ID and PAC");

  delay(100);

  // Send the module to the deepest sleep
  SigFox.end();

}

void loop()
{
  GetGPS();
}// End Loop



void GetGPS(){
  // MANAGES THE CHARACTERS RECEIVED BY GPS
  while (serGPS.available()) {
    GPS_info_char=serGPS.read();
    
    if (GPS_info_char == '

){ // start of message
     message_started=true;
     received_char=0;
   }else if (GPS_info_char == '*'){ // end of message

for (i=0; i<received_char; i++){
       
   strcpy(tempGPS, GPS_info_buffer);
   Serial.println(tempGPS);

char * strtokIndx; // this is used by strtok() as an index
   strtokIndx = strtok(tempGPS,",");      // get the first part - the string
   strcpy(GPSHeader, strtokIndx); // copy it to GPSHeader

strtokIndx = strtok(NULL, ",");
   strcpy(GPSTime, strtokIndx); // copy to GPSTime
   String GPSNowTime(GPSTime);
   Serial.print("Time String: ");
   Serial.println(GPSNowTime);

hours = GPSNowTime.substring(0,2).toInt();
           Serial.print("Hours Byte: ");
           Serial.println(hours);

minutes = GPSNowTime.substring(2, 4).toInt();
           Serial.print("Minutes Byte: ");
           Serial.println(minutes);

seconds = GPSNowTime.substring(4, 6).toInt();
           Serial.print("Seconds Byte: ");
           Serial.println(seconds);

strtokIndx = strtok(NULL, ",");
   strcpy(GPSValid, strtokIndx); // copy to GPSValid
   String Valid(GPSValid);

strtokIndx = strtok(NULL, ",");
   strcpy(GPSLat, strtokIndx); // copy to GPSLat
//    Serial.println(GPSLat);

strtokIndx = strtok(NULL, ",");
   strcpy(GPSNS, strtokIndx); // copy to GPSNS
//    Serial.println(GPSNS);
   
   strtokIndx = strtok(NULL, ",");
   strcpy(GPSLon, strtokIndx); // copy to GPSLon
//    Serial.println(GPSLon);

strtokIndx = strtok(NULL, ",");
   strcpy(GPSEW, strtokIndx); // copy it to GPSEW
//    Serial.println(GPSEW);

strtokIndx = strtok(NULL, ",");
   strcpy(GPSSpeed, strtokIndx); // copy to GPSSpeed
//    Serial.println(GPSSpeed);

strtokIndx = strtok(NULL, ",");
   strcpy(GPSTrack, strtokIndx); // copy to GPSTrack
//    Serial.println(GPSTrack);

strtokIndx = strtok(NULL, ",");
   strcpy(GPSDate, strtokIndx); // copy to GPSDate
//    Serial.println(GPSDate);
   String GPSNowDate(GPSDate);

day = GPSNowDate.substring(0, 2).toInt();
           Serial.print("Day Byte: ");
           Serial.println(day);

month = GPSNowDate.substring(2, 4).toInt();
           Serial.print("Month Byte: ");
           Serial.println(month);

year = GPSNowDate.substring(4, 6).toInt();
           Serial.print("Year Byte: ");
           Serial.println(year);
//      }

if (Valid == "A")
       {
         Serial.println();
         Serial.println("GOT VALID");
         
           Serial.print("Hours Byte: ");
           Serial.println(hours);

Serial.print("Minutes Byte: ");
           Serial.println(minutes);

Serial.print("Seconds Byte: ");
           Serial.println(seconds);

Serial.print("Day Byte: ");
           Serial.println(day);

Serial.print("Month Byte: ");
           Serial.println(month);

Serial.print("Year Byte: ");
           Serial.println(year);

Serial.println();
           
       }
       else if (Valid == "V")
       {
         Serial.println();
         Serial.println("NOT VALID");
         Serial.println();
       }
       else
       {
         // Do Nothing
       }

}
     Serial.println();
     message_started=false; // ready for the new message
   }
   else if (message_started==true){ // the message has already started and I got a new character
     if (received_char<=GPS_INFO_BUFFER_SIZE){ // to avoid buffer overflow
       GPS_info_buffer[received_char]=GPS_info_char;
       received_char++;
     }else{ // resets everything (overflow happened)
       message_started=false;
       received_char=0;
     }
   }
 }
}

void SetRTC()
{
 rtc.setTime(hours, minutes, seconds);
 rtc.setDate(day, month, year);
}

void SetAlarm()
{
 rtc.setAlarmTime(17, 00, 10);
 rtc.enableAlarm(rtc.MATCH_HHMMSS);
}

void alarmMatch()
{
 Serial.println("Got Alarm End");
}

void SERCOM4_Handler()    // Interrupt handler for SERCOM4
{
 serGPS.IrqHandler();
}

void sendSigFox(String str) {
 // Start the module
 SigFox.begin();
 // Wait at least 30mS after first configuration (100mS before)
 delay(100);
 // Clears all pending interrupts
 SigFox.status();
 delay(1);

SigFox.beginPacket();
 SigFox.print(str);

int ret = SigFox.endPacket();  // send buffer to SIGFOX network
 if (ret > 0) {
   Serial.println("No transmission");
 } else {
   Serial.println("Transmission ok");
 }

Serial.println(SigFox.status(SIGFOX));
 Serial.println(SigFox.status(ATMEL));
 SigFox.end();
}

void INT_BUTTON() {
 Serial.println("Pressed: INT_BUTTON");
}

Try changing this

byte seconds = 00;
byte minutes = 00;
byte hours = 00;

to

byte hours = 00;
byte seconds = 00;
byte minutes = 00;

and see if the problem moves to the variable called minutes. If it does it suggests memory is being corrupted.

...R

#define PIN_SERIAL3_RX       (5ul)                // Pin description number for PIO_SERCOM on D5
#define PIN_SERIAL3_TX       (4ul)                // Pin description number for PIO_SERCOM on D4

Why in the hell is the pin number an unsigned long? Do you REALLY have more than 65535 pins on your Arduino?

Your indenting sucks. There is NO excuse for that, when there is a dirt-simple-to-use item, Auto Format, on the Tools menu. Use it!

char GPSHeader[5] = {0};
    strcpy(GPSHeader, strtokIndx); // copy it to GPSHeader

GNRMC,134008.000,A,2545.7844,S,02813.1639,E,1.23,357.00,270218,,,A,VV

You want to explain how 'G', 'N', 'R', 'M', 'C', and a NULL are going to fit in a 5 element array?

THERE is where you shit on memory you don't own.

There may be other places. I'll leave it to you to learn to use strncpy(), instead of strcpy(), since you can't count.

I have changed to:

char tempGPS[256];
char GPSHeader[6] = {0};
char GPSTime[11]= {0};
char GPSValid[2]= {0};
char GPSLat[10]= {0};
char GPSNS[2]= {0};
char GPSLon[11]= {0};
char GPSEW[2]= {0};
char GPSSpeed[5]= {0};
char GPSTrack[7]= {0};
char GPSDate[7]= {0};

I now seem to be getting the correct data.
Log:

GOT VALID
Hours Byte: 16
Minutes Byte: 39
Seconds Byte: 0
Day Byte: 28
Month Byte: 2
Year Byte: 18
Latitude Byte: 2551.3675
N or S Byte: S
Longitude Byte: 02810.7626

RTC SET

How can I EXIT the routine once I have set the RTC?

How can I EXIT the routine once I have set the RTC?

Exit what routine?

If you return from GetGPS(), loop() ends, and gets called again, which calls GetGPS() again.

Yes, you are correct.
I am calling GetGPS(); from setup.
Then I read the values from RTC with:

void readRTC()
{
    // Print date...
  print2digits(rtc.getDay());
  Serial.print("/");
  print2digits(rtc.getMonth());
  Serial.print("/");
  print2digits(rtc.getYear());
  Serial.print(" ");

  // ...and time
  print2digits(rtc.getHours());
  Serial.print(":");
  print2digits(rtc.getMinutes());
  Serial.print(":");
  print2digits(rtc.getSeconds());

  Serial.println();
}

all seems ok, Log:

MKRFox1200 Sigfox first configuration
SigFox FW version 2.3
ID  = 001D1930
PAC = 657EB2682D2F4206

Module temperature: 25.00
28/02/18 18:29:00
28/02/18 18:29:05
28/02/18 18:29:10

How can I run GetGPS until all Valid GPS data has been received and RTC has been set?
I will also need to write the Latitude and Longitude to memory for later retrieval.

You did not answer my previous question about the for loop that causes the GPS message to be parsed "received_char" times (once for each character in the message)? Is this not a resource consuming bug?

How can I run GetGPS until all Valid GPS data has been received

As long as the GPS is functioning, it will send valid data. You will never have received all of the data.