Problem getting date from gps

I try to use a gps module for a clock. I need the gps date for calculating the summer/winter time. I know it is not ideal, but I use the gps module inside. I get a time and coördinates without problem, but I always have problems getting the actual date. Most of the time the date is invalid (year 2000). I this a problem from reading the gps inside, or do I get better results with another gps module/library.

Board: Arduino nano
Gps module: Neo-6m (cheap Ebay module)
Gps library: TinyGps++

I bought a cheap module to see if this concept works. I have no problem getting a better module if this leads to better results.

Hi.

You can get good performance from low cost modules.

You should be looking at the raw NMEA sentences outputted from the board to see exactly what the GPS receiver is generating for the date field. Start troubleshooting from there.

John.

Sounds like a problem with your software.

things to know about GPS

  • the module does not need to be outside. the antenna needs to be outside
  • you need the ability to disconnect the antenna. you need a connector. I use nothing but SMA connectors. the common u.fl connector is pathetic.
  • I will not buy any module that does not have at least two mounting holes. one hole is a swivel, not a mount.

these:

the last time I bought a pot of GPS modules I asked the vendor to send modules with no connectors, and they did. my current project needs an SMA connector sticking straight out the back side, and the header has the same orientation. you won't find that over the counter

one of my modules puts out time but not location, so I don't play "that's not possible" when the question comes up.

Can you please post the raw output from your GPS module? Just read the characters from the GPS and send it directly to the Serial Monitor.

You should get something that looks like the sample file on the Wikipedia page.

simplest GPS checker, for a Mega. you have to add software serial for other boards

void setup()
                                 
{
  Serial.begin(9600); Serial.println("GPS Serial Test" );
  Serial3.begin(9600);
  while (Serial3.available())                           // look for data from GPS module
  {
     char c = Serial3.read();                           // read in all available chars   
     Serial.print(c);                               
     }
}

void loop() 
{
  // put your main code here, to run repeatedly:
}

I am sorry for my late reply. Thank you for all help. I think indeed there was a problem with my software. I updated and the GPS is working great now, even inside.

I am still a bit confused about this part:

   while (gpsSerial.available() > 0)
    if (gps.encode(gpsSerial.read()))

Apperantly the GPS data needs to be updated constantly to work properly.

This is my program now:

#include <TinyGPS++.h>
#include <SoftwareSerial.h>

static const int RXPin = A0, TXPin = A1;
static const uint32_t GPSBaud = 9600;
unsigned int time = 0;
bool changed = 0;
bool wintertime;
int wintermonths[] = {10,11,12,1,2,3};
byte mask =1; //our bitmask
int pins[] = {2,3,4,5};
int controlPins[] = {6,7,8,9,10,11};
// Create a TinyGPS++ object
TinyGPSPlus gps;

// Create a software serial port called "gpsSerial"
SoftwareSerial gpsSerial(RXPin, TXPin);


void setup() {
cli();//stop interrupts
//set timer1 interrupt at 1Hz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  // set compare match register for 1hz increments
  OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS12 and CS10 bits for 1024 prescaler
  TCCR1B |= (1 << CS12) | (1 << CS10);
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
  sei();//allow interrupts

for (int i=0; i < sizeof(pins)/sizeof(int);i++){ //lengte array is in
bytes, daarom delen door sizeof(int)
    pinMode(pins[i], OUTPUT);
    digitalWrite(pins[i], HIGH);
  }
for (int i=0; i < sizeof(controlPins)/sizeof(int);i++){ //lengte array
is in bytes, daarom delen door sizeof(int)
    pinMode(pins[i], OUTPUT);
    digitalWrite(pins[i], LOW);
  }
Serial.begin(115200);
// Start the software serial port at the GPS's default baud
  gpsSerial.begin(GPSBaud);
}

void loop() {
   while (gpsSerial.available() > 0)
    if (gps.encode(gpsSerial.read()))

  if (changed == true) {
    if (time >= 86400){
      time=0;
    }
      if (time%30==0){
        set_time();
      }
      display_time();
      changed=0;
  }
}

void set_time(){
  if (gps.date.isValid()&&gps.time.isValid())
  {
   int h = gps.time.hour();
   int m = gps.time.minute();
   int s = gps.time.second();
   int mo = gps.date.month();
   int d = gps.date.day();
   int y = gps.date.year();
   for (int i=0; i < sizeof(wintermonths)/sizeof(int);i++){
    if (wintermonths[i]== m){
      wintertime = 1;
    }
    else{
      wintertime = 0;
    }
   }
   //calculate end of wintertime
   if (mo == 3) {
    int winterend = (31 -((((5*y)/4)+4)%7));
    if (d>=winterend){
      wintertime=0;
    }
   }
   if (mo == 10) {
    int winterstart = (31 - ((((5*y)/4)+1)%7));
    if (d<=winterstart){
      wintertime=0;
    }
   }
   int tz;
   if (wintertime==0){
    tz=7200;
   }
   else {
    tz=3600;
   }
   time = (h*3600)+(m*60)+s+tz;
   if (time>=86400){
    time = time - 86400;
   }

  }
  else {
    Serial.print("date not available \n" );
  }
}
void display_time() {
  int h,rem,m,s;
  h = time/3600;
  rem = time%3600;
  m = rem/60;
  s = rem % 60;
  int timearray[]={(h/10)%10,h%10,(m/10)%10,m%10,(s/10)%10,s%10};
for (int i=0; i < sizeof(timearray)/sizeof(int);i++){
  digitalWrite(controlPins[i],HIGH);
  numbers(timearray[i]);
  digitalWrite(controlPins[i],LOW);
}
}

void numbers(int x){
    for (int i=0;i<4;i++) {
    if (~x & mask<<i){ // if bitwise AND resolves to true
      digitalWrite(pins[i],HIGH); // send 1
  //Serial.print(1);
    }
    else{ //if bitwise and resolves to false
      digitalWrite(pins[i],LOW); // send 0
   // Serial.print(0);
    }
   }

}

SIGNAL(TIMER1_COMPA_vect) {
time++;
changed=1;
}

hetoosten:
Apperantly the GPS data needs to be updated constantly to work properly.

The gps.encode function is the only input function into the GPS parser. Every time you receive a character from the serial port you give it to the parser. The parser then checks whether it has a complete and valid message and then computes all the values.

And because the GPS module does not know whether you want the data or not, sends it out in a continuous serial stream. Additionally most GPS module send the same data in multiple message formats.

hetoosten:
I am still a bit confused about this part:

Maybe this helps understanding what is going on

while (gpsSerial.available() > 0) // Are there any characters received from the UART peripheral
char c = gpsSerial.read(); // read a single character from the serial library buffer 
if (gps.encode(c)) // Copy the character to the GPS parser

If your code is written in a way that the loop function runs often enough you do not even need the while. You can use "if(gpsSerial.available())" instead

@Klaus_K thank you! That was very insighful.

Klaus_K:
The parser then checks whether it has a complete and valid message and then computes all the values.

That is true, but the parser can only 'compute' the values for the sentance it has just received.

TinyGPS++ in common with most GPS libraries needs to receive at least two different NMEA sentances to be fully updated.

Using the .encode method, on its own, to assume that you have fully updated, position, altitude, data, time etc is a mistake.