Go Down

Topic: GPS clock almost working right (Read 2172 times) previous topic - next topic


I have built a GPS clock plus temperature display, using the UP501D gps module.

I have the display seperate to the gps unit, and send the numbers to be displayed via a cable using VirtualWire ( running slowly to avoid cable capacitance problems )  The waveform at the display end is identical to the gps unit end so thats fine.

At switch on, no data is sent to the display until the first valid sentance is received.

To avoid the occaisional spurious data from the gps being displayed, I read the minutes and hours every second, and every time the minute changes, I add a minute to make " nextminute" and " nexthour" to compare with the following minutes data.

If they match, the freerunning clock is updated, and its millis timing reset to zero.

Initially I lose an extra minute at switch on, but it takes a while for the gps to lock on anyway at power on.

If the GPS loses lock, the free running clock carries on updating the display every minute using its 16 MHz xtal ( its accurate to within a few seconds a day, so I havn't bothered with a RTC , the gps stays locked on virtually all the time )

At the display end, I have a micro receiving the VW data, and sending it serially to the display digits which are latched.

To avoid showing the wrong time all day if the data stops, I have a timer that blanks the display after 130 seconds of no data received.

My only problem is that once in a blue moon, the display blanks , which shows a lack of data.

The LED stays on ( not flashing ) which shows a valid sentance is being received...  and if it did lose lock, the freerun clock should be transmitting every minute anyway..

Unfortunately both times it has happened, I didnt leave it on to see if it would come back on after a minute, and it hasn't happened in the last day or two.  I am waiting with the scope ready, but a watched pot never boils ....

Can anyone see in my code below, if I have any stupid mistakes, or situations that could make it hang ?

Code: [Select]
    #include <NewSoftSerial.h>
    #include <TinyGPS.h>
    #include <VirtualWire.h>
    #define ledPin 8  //  flashes LED
    int sensorPin = 3; //  analog pin 0 reads tmp35 output
    unsigned long clockmillis = 0;
    unsigned long rxmillis = 0;
    unsigned long interval = 60000;
    unsigned long currentMillis;
    unsigned long currentclockMillis;
    int clockmins;
    int clockhours;
    #define RXPIN 14 //   
    #define TXPIN 15 //
    #define GPSBAUD 9600 // baud rate of our UP501D GPS module. Change for your GPS module if different
    char msg [6];
    TinyGPS gps;
    NewSoftSerial uart_gps(RXPIN, TXPIN);
    void getgps(TinyGPS &gps);
    int temptens;
    int tempunits;
    int hourtens;
    int hourunits;
    int mintens;
    int minunits;
    int rxhours;
    int rxmins;
    int ledState = LOW;
    long previousMillis = 0;
    long flashinterval = 1200;
    int searching;
    // ************************************* SET UP ***********************************************
    void setup()    {
      uart_gps.begin(GPSBAUD); // setup sketch for data output speed of GPS module
      // Serial.begin(115200);
      interval = 60000;
      pinMode  (ledPin, OUTPUT );
      digitalWrite(ledPin, LOW);
      searching = HIGH;
      vw_set_tx_pin(16);    //  Tx module connections and speed
      vw_set_ptt_pin(10);   // powers Tx and LED not used this project
    }   //   end of setup
    //  ===================================GET GPS==========================
    void getgps(TinyGPS &gps)    // The getgps function will get the values we want.
      int year,a,t;
      byte month, day, hour, minute, second, hundredths;
      hour=hour+2; // my zone is GMT +2
      if (hour>23) {
        hour = hour - 24;     
      int nexthour = rxhours;
      int nextmins = (rxmins + 1) ;
      if (nextmins > 59 ){
        nextmins = 0;
        (  nexthour + 1 );
        if ( nexthour > 23 ){
          nexthour = 0;
      rxhours = ( int ) hour;
      rxmins = (int) minute;
      if ( rxmins == nextmins ){
        if (rxhours == nexthour) { //  IF TIME IS AS EXPECTED FROM PREV READ
          searching = LOW;
          clockmins = rxmins; 
          clockhours = rxhours;   
          clockmillis = millis () ;                    // reset freerun clock counter millis
          showtime ();
    }   //   end of get gps
    void loop()
        //******************************* flashing the led *************************************************                               
      currentMillis = millis();   //  flash the led til GPS aquires
      if(currentMillis - previousMillis > flashinterval) {
        previousMillis = currentMillis;   
        if (ledState == LOW)
          ledState = HIGH;
          ledState = LOW;
      digitalWrite ( ledPin, ledState );
      //********************************NOW CHECK THE GPS RECEIVER  ************************************************
      if(uart_gps.available())     // While there is data on the RX pin...
        int c = uart_gps.read();    // load the data into a variable...
        if(gps.encode(c))      // if there is a new valid sentence...
          ledState = HIGH;  //  LEAVES THE LED ON when valid sentance aquired by resetting the ledflash timer
          previousMillis = currentMillis;
          getgps(gps);         // then grab the data,
        }// end if GPS encode
      } // end if uuart avail
      //  ------------------------------------------------   FREE RUNNING BACKUP CLOCK  ------------------
      currentclockMillis = millis();     
      if(currentclockMillis - clockmillis > interval) {  // if new minute
        clockmillis = currentclockMillis;
        clockmins ++;       
        if ( clockmins >59 ) {
          clockmins = 0;
          clockhours ++;
          if (clockhours >23 ) {
            clockhours = 0 ;
        if ( searching == LOW ){
          showtime (); 
      }// end of if new minute   
    }  // end of loop
    //*********************************GEN DISPLAY NUMBERS AND SEND TO DISPLAY UNIT ****************************************
    void showtime ()  { 
      checktemp ();
      int t,a;
      byte hour, minute;
      if (clockhours<10)
        hourtens = 0;
        hourunits = clockhours; // Serial.print("less than ten hours  == "); Serial.println(hourunits);
      if (clockhours>=10)  {
        hourtens = a;   // Serial.print(" hourstens  =  "); Serial.println(hourtens);
        hourunits = t;    // Serial.print("  hoursunits  == "); Serial.println(hourunits);       
      if (clockmins<10)
        mintens = 0;
        minunits = clockmins;  // Serial.print("less than ten mins  == "); Serial.println(minunits); 
      if (clockmins>=10)
        mintens = a;    //Serial.print(" mintens >10  ="); Serial.println(mintens);
        minunits = t;    //  Serial.print("  minunits>10  == "); Serial.println(minunits);       
      msg [0]  = hourtens;
      msg [1]  = hourunits;
      msg [2]  = mintens;
      msg [3]  = minunits;
      msg [4] = temptens;
      msg [5] = tempunits;
      vw_send((uint8_t *)msg, 6);     // send the character out
      vw_wait_tx();                             // Wait until the whole message is gone
    //================================================CHECKING TEMPERATURE=======================
    void  checktemp ()  {
      int reading = analogRead(sensorPin); 
      float voltage = reading * 5.0;
      voltage /= 1024.0;
      int temperatureC = (voltage ) * 100 ;                                             
      int x,y;
      if (temperatureC<10)
        temptens = 0;
        tempunits = temperatureC;
      if (temperatureC>=10)  {
        temptens = y;   //
        tempunits = x;    //
    }  // end checktemp
    // =================================================================================


Ah !  I have just noticed that I defined

long previousMillis = 0; 

instead of the normal unsigned long, so perhaps this was overrunning when the unit had been on a long time ( it gets set to millis () at one point )    ??


Even so, that would take 1/2 of 49+ days.

If that's not it tho, it's too subtle for me.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.



I will change it anyway, and perhaps I will let the clock wait for 5 minutes before blanking,  or even put another free running clock in the display micro to take over if nothing is coming in...not ideal as it might show the wrong time if the gps unit  one hangs up for a week :-(


I imagine a lot of local commerce would make a lot of noise if GPS was to go down for a week in your area.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.


LOL,    I meant if my gps receiving box hung up !


Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.


Well I managed to catch it while in the fault condition, and saw that the VW data was going out OK, but when I scoped the input pin on the display micro, it came back on.  Could be poor connection on the IC socket ?
I cleaned the socket with some switch cleaner and also doubled the baud rate both ends ( up from 1000 to 2000 )

Switched on ( on Friday 13th ) and nothing !  I left it a couple of minutes to verify the minute, but smelled burning :-(  the 5v regulator and the Atmega burnt my fingers.

I had plugged the micro in one pin offset, and it is my last chip !

Being the optimist, when it had cooled down enough to touch, I plugged in the chip correctly, and voila ! its working,  what a lovely chip , no wonder the Arduino is so succesful.

I often plug the chips in backwards in the middle of the night, and they can take it without damage.

So now I must wait to see if the intermittent fault shows up again.  It might have been a clash with the data rate too low ??

I will see.  I have also corrected the unsigned long  millis declaration........


Being 180 degrees off is not bad, GND pin goes to GND pin, VCC goes to AREF, AREF goes to VCC.
One pin off - could be bad news, with GND pin on VCC.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.


I havn't even checked to see what was connected where , with pin 1 plugged into 2 on the socket etc, perhaps I have blown some ports that I am not using, but its still running , the 5v reg has a thermal limiter that probably limited the damage, but I couldn't touch the chip for about a minute !

I have done the lotto tonight just in case, Friday the 13th might stay lucky for me !


I made a GPS clock, well with only a simple LCD display, that keeps track of the drift of the Uno clock.
With some calibrating and stable temperatures you can get 1ppm...
If you fall... I'll be there for you!

Skype Brighteyes3333
(262) 696-9619


I think I heard about your clock, I tried to monitor the clock drift and vary the interval to compensate, but I am not experienced enough and it all went pear shaped :-)

So I checked the gps receiver for drop out ( I have an LED showing valid sentance received ) and it never flashes, so my freerunning clock I just let run if  the gps were to drop out.
I tested it by lifting the battery supply to the gps, the LED flashed to show no data received , and 6 hours later, the clock was within a second of the computer clock.

I am not expecting more than a minute of gps signal loss, and when it comes back it resets the freerunning clock time and millis clock anyway, so it is perfectly in sync again.

The signal through the cable is perfect ( its the 3rd wire of a 5 metre core mains cable that carries the 12v for the LEDs etc ) at the faster 2000 rate, so I am going to take it much faster, I dont know what governs the choice of baud rate  if the waveforms are good, and I am only sending 6 bytes once a minute  ????


virtualwire has an upper limit tho, due to being intended for wireless and adding start & stop bytes for syncing & manchester encoding etc.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.


True Bob,   I am going to leave this running to see if the tweaks have solved it, its just such a simple sketch that I can't believe it has a bug :-)

I really dont need more than 2000 for any reason.  The VW library is so stable in all my other sketches, I am sure its not the problem.

Runaway Pancake

I often plug the chips in backwards in the middle of the night, and they can take it without damage.

Yours is a charmed life.

"You gotta fight - for your right - to party!"
Don't react - Read.
"Who is like unto the beast? who is able to make war with him?"
It's "bipolar transistor" or "junction transistor" - "BJT" is just stupid.
When all else fails, check your wiring!

Go Up