The idea is to have three clocks, one MSF clock being received from the NPL on 60KHz, one DCF77 clock on 77.5 KHz and one GPS clock.
This is the first part of the clock, the GPS clock.
I'll be using the Ublox NEO receiver I've used before in the fast GPS-logger project here. The receiver is configured in exactly the same manner as described in that article, so pop along there and learn how to use u-center to configure your receiver.
I purchased some great MAX7219 display boards from eBay. There was a bit of a wait, as they came from China, but they were much less expensive than others, and the build quality is OK.
Note on some board the CS pin is marked up LOAD.
I'm not going to draw a schematic, as it really is simple. (Leave me a comment if you get stuck!)
The wiring is commented in the code below.
The code is also simple, we're not doing anything particularly clever. There's a bit in the code which writes "no GPS" on the display, and this is defined as a bitmap. The bitmap refers to the segments as follows:
Bit 1(LSB) is G
Bit 2 is F
Bit 3 is E
Bit 4 is D
Bit 5 is C
Bit 6 is B
Bit 7 is A
and finally, bit 8 is the decimal point.
Here's a quick video of the clock in action:
... and here's the code:-
/* 7-segment GPS clock Version 0.9 Written by Andy Doswell 2015 License: The MIT License (See full license at the bottom of this file) Schematic can be found at www.andydoz.blogspot.com/ You will need the LedControl library from http://playground.arduino.cc/Main/LedControl and the very excellent TinyGPS++ library from http://playground.arduino.cc/Main/LedControl pin 12 is connected to the DataIn pin 11 is connected to the CLK pin 10 is connected to CS pin 0 (RX) is connected to the GPS TX pin */ #include "LedControl.h" #include <TinyGPS++.h> LedControl lc=LedControl(12,11,10,1); //Tells LedControl where our hardware is connected. TinyGPSPlus gps; //TinyGPS++ class static const uint32_t GPSBaud = 57600; //Our GPS baudrate. int hourTen; //tens of hours int hourUnit; //units of hours int minTen; // you get the idea.. int minUnit; int secTen; int secUnit; int centTen; //centiseconds. int centUnit; unsigned long timer =0; void setup() { lc.shutdown(0,false); // Wake up the MAX 72xx controller lc.setIntensity(0,8); // Set the display brightness lc.clearDisplay(0); //Clear the display Serial.begin(GPSBaud); // start the comms with the GPS Rx } // This contains the bit patterns for the "no GPS" display. void displayNoGPS() { // displays "noGPS" if the GPS lock isn't valid lc.setRow(0,0,B00000000); lc.setRow(0,1,B00000000); lc.setRow(0,2,B01011011); lc.setRow(0,3,B01100111); lc.setRow(0,4,B01011110); lc.setRow(0,5,B00000000); lc.setRow(0,6,B00011101); lc.setRow(0,7,B00010101); } void displayNoSerial() { // Displays "noSeriAL" in the event of serial comms fail. lc.setRow(0,7,B00010101); lc.setRow(0,6,B00011101); lc.setRow(0,5,B01011011); lc.setRow(0,4,B01001111); lc.setRow(0,3,B00000101); lc.setRow(0,2,B00010000); lc.setChar(0,1,'a',false); lc.setRow(0,0,B00001110); } // Displays the time on our LEDs void displayTime() { if (gps.time.isValid()) { timer = millis(); // reset the serial comms timer hourUnit = (gps.time.hour()%10); hourTen = ((gps.time.hour()/10)%10); minUnit = (gps.time.minute()%10); minTen = ((gps.time.minute()/10)%10); secUnit = (gps.time.second()%10); secTen = ((gps.time.second()/10)%10); secUnit = (gps.time.second()%10); secTen = ((gps.time.second()/10)%10); centUnit = (gps.time.centisecond()%10); centTen = ((gps.time.centisecond()/10)%10); lc.setDigit (0,7,hourTen,false); lc.setDigit (0,6,hourUnit,false); lc.setDigit (0,5,minTen,false); lc.setDigit (0,4,minUnit,false); lc.setDigit (0,3,secTen,false); lc.setDigit (0,2,secUnit,false); lc.setDigit (0,1,centTen,false); lc.setDigit (0,0,centUnit,false); } else { displayNoGPS(); delay (2000); } } void loop() { // If the GPS data is OK, then display it. If not display "no GPS" while (Serial.available() > 0) if (gps.encode(Serial.read())){ displayTime(); } if (millis() > timer+1000 ) // detects if the serial comms has failed. { displayNoSerial(); } } /* * Copyright (c) 2015 Andrew Doswell * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHOR(S) OR COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */
Wow great project which I have recreated using the same components. However, I cannot get the milliseconds to show anything other than 00 whereas in your video they increment in 25ms chunks.
ReplyDeleteIs there any chance you would be able to add some code to show the milliseconds counting from 00 to 99?
Hi Ian,
ReplyDeleteThis is most likely a problem with the GPS receiver module, as the code simply reads the data as and when it's available. If you load up the uBlox uCenter software, click on the CFG drop down, as detailed in my post at http://andydoz.blogspot.com/2015/02/fast-arduino-gps-datalogger.html , and check the rate is set to 250mS (or as fast as your chipset allows). Don't forget to upload this CFG back up to the uBlox chipset afterwards, the dtails are in the GPS logger post.... Sadly you won't get 0-99(9?)mS... the uBlox chipset just won't go that fast. I suppose we could implement a counter using an interrupt to check the arduino millis timer, and adjust it every 250mS or so, but that's a job for another day! Let me know how you get on!
Hi Andy,
ReplyDeleteMany thanks for your response and especially the link to your datalogger project. Using the uBlox uCenter software my gps module was set to 1000ms measurement period and 9600 baud. I experimented with lower values down to 200ms and varying baud rates but all these resulted in data errors and satellite fix times of over an hour in some combinations so I have left things as per the default. I have ordered another gps module (at £7 it's worth a shot) in the hope that it is more forgiving of settings etc. Thanks again.
Hi Ian,
ReplyDeleteYou must retain the baud rate at 56700, otherwise you will need to change the GPSBaud variable in the sketch to suit. I chose I higher baud rate than 9600 just to ensure we've got enough time to process the data before the next 100mS. Although there's plenty of time in reality. It should also be noted that you cannot programme the arduino with the GPS receiver connected, as the hardware serial interface used is shared between the FTDI (or ATMEGA) USB interface on the Arduino itself, and , undoubtedly, you'll have bad luck because the GPS will attempt to transmit the instant your IDE tries to upload. I wonder if these are the sources of errors you are seeing?
£7 , what's not to like!
Hi Andy,
ReplyDeleteMy new gps module has arrived and it accepted a measurement period of 200ms and baud rate of 57600 1st time with fast fix and lock so it would appear my original gps module is a bit suspect.
Again many thanks for your superb project.
Hi!
ReplyDeleteHow to adjust time zone?
Now there's a question.... This isn't as straightforward as you'd think, especially if you are trying to use daylight saving time... See the timelord library I used in the pond pump controller... or "isBST" function in the Arduino analogue clock post.
DeleteI have tried to incorporate a +9:30 time offset into this wonderfully concise and effective code without spoiling it to display my local time. Even though the modifications compile,UTC continues to be displayed.Is there an effective way to add minor adjustments without denigrating your code?
ReplyDeleteThe gps. values are fixed by the library. You'll have to copy them into another bunch of hh,mm and ss variables and manipulate those, and deal with rolling over of the hours etc. I'm not sure how much of time.h is implemented in arduino (I've never relied on it) http://www.cplusplus.com/reference/ctime/ , but there is a UTC to localtime function listed. I'd start there.
DeleteHello DOZ, excellent work. I will do my first arduino project based on you post. Is it possible to post the diagram, if not then few images from top, so I can refer it, what to connect and where. Thanks!
ReplyDeleteThis was 8 years ago! The pins are shown at the top of the sketch in the comments
DeleteThanks!! it worked on the first go.... :-)
Deleteyea! Here's a more recent incarnation of a similar thing... https://youtu.be/2Sca76-mIhg I'll write it up here soon.
Delete