Go Down

Topic: GPS digital clock (Read 4984 times) previous topic - next topic

CrossRoads

Do you have a listing for those?
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.

#16
Jan 31, 2015, 02:52 pm Last Edit: Jan 31, 2015, 03:41 pm by adream608
I know it's an old thread but you never know :-)

I have built an uno based 8 digit clock like this one

different gps module but same sketch

it acquires the gps signal and displays it to the LED display but every few seconds it stops for a while and then picks up, about 5 second pauses

the serial output shows a steady stream of data from the gps module every second, but something in the code is preventing it from running entirely smoothly

any ideas ?

CrossRoads

No ideas without seeing your code and schematic.
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.

Code: [Select]
// GPS clock with digital read-out
// Author: Nick Gammon
// Date:   4 April 2013
//http://www.gammon.com.au/forum/?id=11991&page=999
// NB: Compile for Lilypad Arduino (8 MHz clock)

// Version 2. Fixes problem with detecting daylight-saving time on the change-over day.

#include <SoftwareSerial.h>
#include <Regexp.h>
#include <SPI.h>

// Adjust for your time zone. Hours + or - from UTC.
const int DST_TIME_OFFSET = -1;

// MAX7219 constants

const byte MAX7219_REG_NOOP        = 0x0;
// codes 1 to 8 are digit positions 1 to 8
const byte MAX7219_REG_DECODEMODE  = 0x9;
const byte MAX7219_REG_INTENSITY   = 0xA;
const byte MAX7219_REG_SCANLIMIT   = 0xB;
const byte MAX7219_REG_SHUTDOWN    = 0xC;
const byte MAX7219_REG_DISPLAYTEST = 0xF;

// For GPS input
SoftwareSerial GPSserial(2, 3); // RX, TX

// how much serial data we expect before a newline
const unsigned int MAX_INPUT = 100;

// send a digit or other data to the MAX7219
void sendByte (const byte reg, const byte data)
  {   
  digitalWrite (SS, LOW);
  SPI.transfer (reg);
  SPI.transfer (data);
  digitalWrite (SS, HIGH);
  }  // end of sendByte


void setup() 
  {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);

  // set the data rate for the SoftwareSerial port
  GPSserial.begin(9600);
 
  SPI.begin ();
  sendByte (MAX7219_REG_SCANLIMIT, 7);      // show 6 digits
  sendByte (MAX7219_REG_DECODEMODE, 0xFF);  // use digits (not bit patterns)
  sendByte (MAX7219_REG_DISPLAYTEST, 0);    // no display test
  sendByte (MAX7219_REG_INTENSITY, 10);      // character intensity: range: 0 to 15
  sendByte (MAX7219_REG_SHUTDOWN, 1);       // not in shutdown mode (ie. start it up)
 
  // send hyphens during start-up
  for (int digit = 0; digit < 8; digit++)
    sendByte (digit + 1, 0x0A);
  }  // end of setup

// http://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week
// Devised by Tomohiko Sakamoto in 1993, it is accurate for any Gregorian date.
// Returns 0 = Sunday, 1 = Monday, etc.

int dayOfWeek (int d, int m, int y)
   {
   static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
   y -= m < 3;
   return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
   }  // end of dayOfWeek
   
   
// DST = Daylight Savings Time
boolean isDaylightTime (int day, int month, int year, int hour)
  {
  int firstSundayInApril;
  int firstSundayInOctober;

  for (firstSundayInApril = 1; firstSundayInApril <= 31; firstSundayInApril++)
    if (dayOfWeek (firstSundayInApril, 4, year) == 0)
      break;

  for (firstSundayInOctober = 1; firstSundayInOctober <= 31; firstSundayInOctober++)
    if (dayOfWeek (firstSundayInOctober, 10, year) == 0)
      break;

  // May to September: not DST
  if (month >= 5 && month <= 9)
    return false;
 
  // January to March, and November to December: is DST
  if (month <= 3 || month >= 11)
    return true; 
   
  // In April, if not yet first Sunday, still DST
  if (month == 4 && day < firstSundayInApril)
    return true;

  // In April, on first Sunday, still DST before 2 am
  if (month == 4 && day == firstSundayInApril && hour < 2)
    return true;
   
  // In October, if after first Sunday, is DST
  if (month == 10 && day > firstSundayInOctober)
    return true;

  // In October, on first Sunday, is DST after 2 am
  if (month == 10 && day == firstSundayInOctober && hour >= 2)
    return true;
   
  // some date in April or October that did not pass the above tests
  return false;
  } // end of isDaylightTime 

// here to process incoming serial data after a terminator received
void process_data (char * data)
  {
  // for now just display it
  Serial.println (data);

  MatchState ms;
  ms.Target (data);   
 
  char hour [5];
  char mins [5]; 
  char secs [5];
  char valid [5];
  char day [5];
  char month [5];
  char year [5];

  char result = ms.Match ("^$GPRMC,(%d%d)(%d%d)(%d%d)%.%d+,(%a),.-,.-,.-,.-,.-,.-,(%d%d)(%d%d)(%d%d)");
//                                   HH    MM    SS    ms valid   lat  long spd crs  DD   MM    YY

  if (result != REGEXP_MATCHED)
    return;
   
   ms.GetCapture (hour, 0);
   ms.GetCapture (mins, 1);
   ms.GetCapture (secs, 2);
   ms.GetCapture (valid, 3);
   ms.GetCapture (day, 4);
   ms.GetCapture (month, 5);
   ms.GetCapture (year, 6);
   
   int iHour = atoi (hour);
   int iDay = atoi (day);
   
   // make time local
   iHour += DST_TIME_OFFSET;
   
   // if past midnight with time-zone offset adjust the day so the DST calculations are correct
   if (iHour >= 24)
     iDay++;
   else if (iHour < 0)
     iDay--;
   
   // allow for daylight savings
   if (isDaylightTime (iDay, atoi (month), atoi (year) + 2000, iHour))
     iHour++;
     
   // pull into range
   if (iHour >= 24)
     iHour -= 24;
   else
   if (iHour < 0)
     iHour += 24;
   
   // work out AM/PM
   boolean pm = false;
   if (iHour >= 12)
     pm = true;
     
   if (iHour > 12)
     iHour -= 12;
   
   char buf [8];
   sprintf (buf, "%02i%s%s", iHour, mins, secs);
   
   // send all 6 digits
   for (byte digit = 0; digit < 6; digit++)
     {
     byte c = buf [digit];
     if (c == '0' && digit == 0)
       c = 0xF;  // code for a blank
     else
       c -= '0';
     if (digit == 1 || digit == 3)
       c |= 0x80;  // decimal place
     sendByte (8 - digit, c); 
     }   
     
  sendByte (2, 0xF | ((valid [0] == 'A') ? 0x80 : 0));  // space, add dot if valid
 
  if (pm)
    sendByte (1, 0xE);  // P   
  else
    sendByte (1, 0xF);   
  }  // end of process_data
 

void loop()
{
static char input_line [MAX_INPUT];
static unsigned int input_pos = 0;

  if (GPSserial.available () > 0)
    {
    char inByte = GPSserial.read ();

    switch (inByte)
      {

      case '\n':   // end of text
        input_line [input_pos] = 0;  // terminating null byte
       
        // terminator reached! process input_line here ...
        process_data (input_line);
       
        // reset buffer for next time
        input_pos = 0; 
        break;
 
      case '\r':   // discard carriage return
        break;
 
      default:
        // keep adding if not full ... allow for terminating null byte
        if (input_pos < (MAX_INPUT - 1))
          input_line [input_pos++] = inByte;
        break;

      }  // end of switch

  }  // end of incoming data


}  // end of loop



the schematic is broadly similar to Nick Gammons, (thanks Nick), same pins on the arduino


Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy