Building a better clock (part 2)
In part 1 of this series, we discussed the hardware for getting the time and keeping it accurate – but even the most accurate of clocks is no fun if it has no way of telling you what the time is!
Across the local network and the internet, we can use the Network Time Protocol (NTP) to check the time (more on that in part 3). But I also wanted to have a human readable display – big and bright enough to read from across the room. Whilst looking into the various options, I remembered that it’s post-2015: the year that Marty McFly travelled to in “Back to the Future II”. So, I took a little inspiration from Doc Brown’s Delorian and decided to use 7-segment LED displays for the date and time.
A normal 7-segment display actually has eight LEDs – seven for the number, and an eight to drive either a colon or a period. So, displaying the date and time means operating an awful lot of separate lights. To make it easier, I’m using a backpack device which will allow me to control each group of 4 displays (32 LED channels) using the I2C interface.
The I2C interface operates off two pins (SDA and SCL) on the Raspberry Pi, and multiple devices can be daisy-chained to each other. Each device has a unique address between 1 and 255 (0x01 to 0xFF in hex) and there are software libraries available to easily read and write from the devices. The I2C bus provides data communications only, so we also need to provide power to the modules separately. As a matter of good design, it’s best to but an optical isolator between the Pi and the devices, to protect against voltage surges coming from faulty modules back through the I2C bus. but I haven’t bothered with this for now as the displays will all be powered from the 5V supply from the Pi itself so the risk is minimal.
Looking at the photo above, you may notice on the bottom module there are three connections on the far right of the board. These solder links allow us to set the I2C address of the board. The default is 0x70, and three jumpers allows us to select anywhere between 0x70 to 0x77.
For this project, I want to display the date (day, month and 4 digit year = 8 digits) and time (hours, minutes and seconds = 6 digits) so 14 digits in total. Since each module contains 4 digits, I’ll need four of them. Since that’s 16 digits, I can run the time display out to 1/100th of a second with my 4 LED displays, which I’ve addressed as 0x70 to 0x73) At this point, it doesn’t matter which display goes where as I can adjust which unit displays what in software later.
A note on calendars
The more perceptive of you may notice that since I’m only allowing 4 digits for the year, I’ve also introduced a Y10K bug into the project, but I’m hoping we’ll have switched to the Stardate system by then. 🙂 What’s of more practical concern is that the calculations above are based on using the Gregorian calendar. For the foreseeable service life of the calendar, four digits should be sufficient to display a Hebrew calender as well.
Additionally, because the digital display will always show the local time (as Linux sees it), it will auto-adjust for daylight savings, provided your system location and time zone data is up up to date.
For those following along, you may have noticed that the Chronodot timing crystal also sits on the I2C bus. This is quite OK because it sits at a different address than the displays, but it did lead to another problem. By displaying the time to 1/100th of a second, it means that I need to update LCD displays, well, one hundred times each second. The I2C bus isn’t fast enough to do this, so the update script (see next post) will only update the portions of the display it needs to. This may lead to a slight delay at exactly midnight on 1 January, but again – I’ll likely be doing something other watching the display at that precise second.
In section 3, we’ll put the system all together and see accurate it will be.