gps synced led clock

Hi
I need to build a signboard showing the time of day, plus 3 rows of " days elapsed since whatever " and the date of the previous events.
I have built the display pcbs with 5x7 leds driven by MAX7219s in 5 rows of 7 chips ( with lc0-5 cs pins from the arduino ProMini using 1.8.9 ide using pins 14,15,x,7 ) )

That hook-up is working using LedControl for the Max chips and the SoftwareSerial.
The TinyGps library and a ublox6 are fine on their own showing showing the date/time etc.( pins 4&5 )

The board is going to be outdoors, and the time from the gps module on my bench is rock steady even when it sees 6 satellites.
I have checked around and found examples of this type of project using a gps and an RTC module, which appears overkill, but I dont want it showing a blantantly wrong time.

I though of just a simple clock using the Arduinos clock, and updating it to gps time every minute or so, but the TinyGps ( and other libraries ) start with " while ( SerialGPS.available () ) … which will just hang up everything if the signal is lost.

Possibly I can just parse the date and time from the raw data, as the gps is just pouring that out all the time independent of the loop.

I havnt got code written yet, just test snippets, like trying " if ( SerialGPS.available () ) " but that didnt work.
I think I can make the days elapsed and previous dates routines using Unix time and the Time library, but I just need a bit of advice on the gps/display side please.

I’ve been using a NEO-6M GPS in a speedometer for some years and when the GPS has wormed up the time has never played me any tricks. Why not use it all the time?
Comparing 2 different "clocks"looks likemeasy but how to decide which one is right and which one is wrong in case they show different time?

Thanks I was hoping someone had tried relying on a stable output.

Are you parsing the speed from the raw data, or using a library ?

I display the speed on an LCD. It’s all a portable, standalone device in a plastic casing.
I’ll give You the code so You can check things up.

//boolean debug = false;

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

#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>

//#define BACKLIGHT_PIN     13

hd44780_I2Cexp mylcd; // declare lcd object: auto locate & config exapander chip

// LCD geometry
#define LCD_COLS 20
#define LCD_ROWS 4

// The TinyGPS++ object
TinyGPSPlus gps;
TinyGPSCustom vdop(gps, "GPGSA", 17);//Pick upVdop

//Create GPS channel using digital i/o
#define RX 2
#define TX 3
SoftwareSerial mySerial(RX, TX);  // pick any 2 unused digital pins (not pins 0 or 1)

#define arr_size 20

int time_adj; // adjust: +1 for winter time, +2 for summer time
int act_cnt = 0;
char activity[] = "<><>";
unsigned long next_act_print, Start_Up_Time = millis();
//unsigned int speed_age, hdop_age, alt_age, dir_age, sat_age;
unsigned long speed_age, hdop_age, vdop_age, alt_age, dir_age, sat_age;

unsigned long speed_print, dir_print, alt_print, time_print, date_print, sat_print, hdop_print = 0L;
unsigned long vdop_print, next_menue_print, avg_print = 0L;
unsigned long speed_warning_end, alt_warning_end;
int last_alt, last_speed, last_dir, prev_speed;
unsigned long avg_alt, avg_ant;
boolean average_alt_inc_flag;
int avg_arr[arr_size + 1], inp_index;
long unsigned avg_sum;

/*
  boolean ok_test(int, int, int, int);

  boolean ok_test(int(a), int(b), int(val), int(norm))
  {
  if (norm == 0) norm = val;
  return ( (val >= ((norm * a) / 100)) && (norm <= ((val * b) / 100) ) );
  }
*/
boolean lim_test(int, int, int, int);

boolean lim_test(int(a), int(val), int(norm))
{
  if (norm == 0) norm = val;
  return (abs(val - norm) <= a );
}

void setup()
{
  int status;

  status = mylcd.begin(LCD_COLS, LCD_ROWS);
  if (status) // non zero status means it was unsuccesful
  {
    status = -status; // convert negative status value to positive number

    // begin() failed so blink error code using the onboard LED if possible
    hd44780::fatalError(status); // does not return
  }
  mylcd.clear();
  // initalization was successful, the backlight should be on now

  mySerial.begin(9600);  // 9600 is the default baud rate for my Neo6m units
  Serial.begin(9600);// For PC, serial monitor

  // Print start message to the LCD
  mylcd.print("Started");
  // Print start message to the PC
  Serial.println("Starting up");//sent to PC

  //initialize age and print flags
  next_act_print, Start_Up_Time, avg_print = millis();
  speed_age, hdop_age, alt_age, dir_age, sat_age = 999;
  speed_print, dir_print, alt_print, time_print, date_print, sat_print, hdop_print, vdop_print = millis();

  last_alt, last_speed, prev_speed, last_dir = -1;
  average_alt_inc_flag = false;
  avg_alt = 0L;
  avg_ant = 0;
  for ( inp_index = 0; inp_index < arr_size; inp_index++)
    avg_arr[inp_index] = 0;
  inp_index = 0;
  avg_sum = 0L;
//  time_adj = 2;// Will be set for winter or summer time, +1 for winter time, +2 for summer time, april t o m october
}

void loop()
{
//Serial.println(gps.location.lat(), 6); // Latitude in degrees (double)
//Serial.println(gps.location.lng(), 6); // Longitude in degrees (double)
//Serial.print(gps.location.rawLat().negative ? "-" : "+");
//Serial.println(gps.loc2ation.rawLat().deg); // Raw latitude in whole degrees
//Serial.println(gps.location.rawLat().billionths);// ... and billionths (u16/u32)
//Serial.print(gps.location.rawLng().negative ? "-" : "+");
//Serial.println(gps.location.rawLng().deg); // Raw longitude in whole degrees
//Serial.println(gps.location.rawLng().billionths);// ... and billionths (u16/u32)
//Serial.println(gps.date.value()); // Raw date in DDMMYY format (u32)
//Serial.println(gps.date.year()); // Year (2000+) (u16)
//Serial.println(gps.date.month()); // Month (1-12) (u8)
//Serial.println(gps.date.day()); // Day (1-31) (u8)
//Serial.println(gps.time.value()); // Raw time in HHMMSSCC format (u32)
//Serial.println(gps.time.hour()); // Hour (0-23) (u8)
//Serial.println(gps.time.minute()); // Minute (0-59) (u8)
//Serial.println(gps.time.second()); // Second (0-59) (u8)
//Serial.println(gps.time.centisecond()); // 100ths of a second (0-99) (u8)
//Serial.println(gps.speed.value()); // Raw speed in 100ths of a knot (i32)
//Serial.println(gps.speed.knots()); // Speed in knots (double)
//Serial.println(gps.speed.mph()); // Speed in miles per hour (double)
//Serial.println(gps.speed.mps()); // Speed in meters per second (double)
//Serial.println(gps.speed.kmph()); // Speed in kilometers per hour (double)
//Serial.println(gps.course.value()); // Raw course in 100ths of a degree (i32)
//Serial.println(gps.course.deg()); // Course in degrees (double)
//Serial.println(gps.altitude.value()); // Raw altitude in centimeters (i32)
//Serial.println(gps.altitude.meters()); // Altitude in meters (double)
//Serial.println(gps.altitude.miles()); // Altitude in miles (double)
//Serial.println(gps.altitude.kilometers()); // Altitude in kilometers (double)
//Serial.println(gps.altitude.feet()); // Altitude in feet (double)
//Serial.println(gps.satellites.value()); // Number of satellites in use (u32)
//Serial.println(gps.hdop.value()); // Horizontal Dim. of Precision (100ths-i32)

Too big. I had to drop the contents of loop. Check for libraries and look at the end, the out commented Seril.prints showing what the library provides.

Railroader:
Comparing 2 different "clocks" looks likemeasy but how to decide which one is right and which one is wrong in case they show different time?

Like the old saying: "A person with a watch always knows what time it is. A person with two watches is never sure."

I did a similar project a while back. I had both GPS and an RTC to get the time. From the GPS, I parsed the time and the valid fix flag (no library used). It use the GPS time if the fix was valid and the RTC time if the fix not valid.

That was an option but I have run out of time ( while everyone else has been bored stiff at home ! )

Another hassle is that I dont know how to feed each of the 5 rows of 7 Max7219s with an array ( each row needs lc1 lc2 etc, ) but I tried sending each line with the same patterns, but I ran low on memory.

I tried to work out how Nick Gammon was doing it with a Progman array, but it seems beyond me I am afraid.

I had a look at a Youtube showing how to use Parola, but I couldn't see how or what he called up to select the chiptype in " header "

I think my 72 yo brain is still in lockdown :frowning:

Does anyone know of a simple example of a non scrolling 7 char display using Max7219s ( I already built that part ! )

If you run out of memory and are baffled by Progmem, there are lots of new boards with tons more memory available than the Uno. There is no "simpler" version of Progmem if that is what you are hoping for.

Also, earlier you complained about how a GPS library " starts with ' while ( SerialGPS.available () ) .."
That is not how it "starts". It is one of many ways that you can use the functions that are provided there. If you want to make code to handle a condition where that test finds nothing available, you are perfectly free to test for and handle it in your custom code. Not just that library, but almost any library as well...

Almost all my projects have been clocks, so I know this drill. The most reliable ones have multi-tiered time sync. A GPS or NTP syncs an RTC, which then syncs a CPU based timer (provided by either the Time library or native time.h. So if GPS or NTP fails, RTC keeps going, if RTC fails, timer keeps going until power down.

My first attempt at GPS decoding was done with my self written code. Since then I've been using various libraries. If your brain is addled by Progmem, I doubt that you will have much luck writing your own. If there is no internet connection, you should have at least an RTC because it will keep on ticking no matter what.