A project to create a simple digital clock using a GPS receiver as the source for the time. The point of the project was mainly to find a use for a very old GPS receiver and one of several TFT touch screens that were originally sourced for other projects.
UNO. Standard format, but the exact variant doesn't matter. However
some are easier to use than others - see comments below.
TFT Touch Screen 320x240. This is the type that has a row of pre-printed button icons in an additional strip across the bottom (or down the side, as used in this project).
GPS receiver with 5v serial output. This project uses a SiRF-Star III because it was available. It is a 'puck' style on a long lead which enables it to be placed conveniently for a good view of the satellites.
The UNO supports a single serial port on D0, D1. However this port is used for programming and is driven though the USB interface, and is inconvenient to use for other devices. So the project uses a software serial port for the GPS interface. The problem is that the TFT touch screen is a shield that connects to all the UNO pins, even though it doesn't use them all - D2, D3 are available for a serial device, but making a connection to them can be difficult.
The UNO chosen for this project provides a row of solder points for pins or wires alongside both strips of headers, as well as a small prototyping area. This makes attachment of other devices in addition to the TFT shield very simple. The GPS receiver is wired to the pads for D2, D3, 5v and Gnd.
The alternative is to wire to the bottom of the UNO board, which is tricky, or to use a breakout board inserted between the UNO and the TFT shield.
Note: If the breakout is used it is important to check whether the shield uses the ISP header on the UNO. The reason that the shield might use this header, even though it only duplicates pins already available elsewhere, is to make it compatible with the MEGA 2560, which uses different pins for ISP. If the shield uses the header then it must be provided on the breakout. It is not necessary to use a long-tail header - a simple 2x3 header can be used if it is wired across the bottom of the breakout to the appropriate pins for a UNO.
A simple 3D-printed case is used to house the clock. For this project the base was built up only to the underside of the UNO PCB, and the lid extends down to the bottom of the base. The lid is secured by three small screws through the side, into the pads that support the UNO. A nice addition to the case would be a holder for the stylus. The case interior can be lined with black vinyl tape to suppress the light from the module LEDs that otherwise bleeds through the plastic.
The GPS must be set up for the messages (only RMC is used), the message interval (1s) and the baud rate (4800 in this case). Some example GPS initialisation code is included. As this is a very old GPS receiver it was simplest to select the update rate and baud rate that the device defaulted to. A faster baud rate (up to about 19200) would be preferable, and initialisation code to support a specific GPS receiver could be used (an example is included). At a rate of 4800Bd and only receiving RMC messages once per second the display can nearly keep up with the time - a second is skipped about once every couple of minutes.
The software is more complex than might be imagined, mainly because of the need to keep screen updating to a minimum. This is achieved by only updating what has changed - seconds every second, minutes every minute and so on. When updating the hour the date is also updated in case it also changed. (Note that the date needs to be checked every hour because the GPS day could change at any hour, depending on the UTC offset.).
The other complexity is the date calculation. Because the time and date data from the GPS is UTC, it is possible that a day needs to be added to or subtracted from the GPS data to get the local date. If this adjustment occurs at the first or last day of the month then it is possible that the month has to be changed, if February is involved then then it needs to be checked for leap year, and if the month then becomes 1 or 12 then the year may have to change.
The software footprint is about 25000 bytes or a bit less than 80% of program storage space - about the practical limit for a UNO.
The touch pads at the right of the screen are used to open the user menu and then provide options to reboot, select 12- or 24-hour format, increment UTC offset, and decrement UTC offset. The home symbol is used to open and close the user menu. Time format and UTC offset are stored in EEPROM. UTC Offset is only supported for 1-hour increments - changing this to 1/2-hour would require very little additional code, but would make selection slower for most users.
The seconds update is not regular and updates are sometimes missed. This is because the UNO cannot quite keep up with all the things that need to happen when the GPS message is received, especially at 4800bd. Each message is first checked to be sure it is a RMC, then the CRC is checked and finally it is parsed to extract the time and date values. If any time value is changed then the changed values are updated, and in the case of an hour change the date is also recalculated and displayed.
The user menu is accessed with the 'Home' icon in the lower right corner and the options use the other icons. The button facility of the GFX library is not used, and the button locations are hard-coded. Note that for this procedure to work correctly the screen calibration data must be entered. If this is not available from a calibration routine it can be worked out by removing the mapping function in the Touch_getXY function and displaying the raw touch data on the console. Note that the names used for the mapping variables do not make sense for a landscape orientation - they have been left like this in order to be consistent with the way they are reported in the TFT touch screen calibration example sketch used for these displays.
The temperature is displayed whenever it changes. Note that this is never correct because the sensor is buried in the middle of the two modules and gets significant warming from the devices, especially the display lighting. A small heatsink connected to a metal pad on the base of the case would improve the temperature reading somewhat but would be difficult to arrange.
The code uses a custom font for the time and temperature display, because the default font looks awful when expanded to the required size. The UNO memory is not sufficient to support a complete font at this size, so it is restricted to 0 to 9, A, C, M, P full stop and degree symbol. Note that all libraries (including the dependent GFX library) are referenced from a subfolder 'src\' in the sketch folder.