CKRE150 Project Report
This document is a post-mortem of a Nixie clock incorporating a microcontroller, an FPGA, and a GPS module. This was created for the class CKRE150 at Toronto Metropolitan University.
GPS Nixie clock
The project is a 24-hour, 6-digit clock which retrieves the time via GPS, and displays it using nixie tubes. The use-case for such a clock is to provide maintenance-free accurate time, in an aesthetically pleasing package.
Component list
- 1 x SIM28 GPS module + antenna
-
For retrieving GPS information.
This differs from the proposal document, which anticipated using the effectively equivalent NEO6m module. - 1 x Arduino uno MCU board (ATmega328P)
-
For managing the stored time.
- 1 x Basys3 FPGA board (Artix 7)
-
For multiplexing the nixie tubes, in conjunction with a transistor array.
- 1 x 5V→180V power board
-
For powering the nixie tubes.
- 17 x 2N6517TA high voltage NPN transistors
- 6 x 2N6520TA high voltage PNP transistors
-
19 x 10 KΩ resistors 19 x 143 KΩ resistors For interfacing the low voltage FPGA signaling pins with the high voltage input pins of the nixie tubes.
This differs from the proposal document, which anticipated using only 2N6517TAs. - 6 x IN-12B nixie tubes
- 6 x IN-12 nixie tube socket
- 4 x Red LEDs
- 1 x Blue LED
-
Display indicators.
- 1 x SPST switch
- 2 x Momentary button
-
Input hardware.
Functionality
- Power
-
The clock is powered by an external 5V USB connection.
The proposal anticipated that the device would be powered from the Arduino’s 5 volt connection. However, the Arduino’s VRM can only handle relatively small current loads, which frequently caused issues during development.
- GPS Timekeeping
-
The clock relies on the SIM28 GPS module for timekeeping.
This module tracks the time and whether or not it has a GPS signal. Thus, it would be redundant to track the time on the Arduino. This would not be appropriate if it were intended for the user to be able to manually set the time.
It is undefined what time will be shown prior to first obtaining GPS lock after power on. In practice, the SIM28 starts counting at a time shortly before midnight.
The time zone is accounted for using a manual offset in half-hour increments. Time zones with a 15 minute multiple offset (such as NPT) are not supported.
- Inputs
-
The following inputs are provided:
-
Two (2) buttons which are used to increment and decrement the timezone in half-hour increments.
-
One (1) switch which toggles between the 12- and 24-hour modes.
-
- Display
-
The display uses six IN-12B nixie tubes, as described here: https://www.swissnixie.com/tubes/IN12B/.
In 12-hour mode, the decimal point on the most-significant hour digit is used to indicate PM.
When the hour value is a single digit, the leftmost nixie tube is disabled. The minutes and seconds are padded to 2 digits.
The display shall incorporate LEDs used for the following purposes:
-
Four (4) red LEDs in pairs, used to distinguish the hours:minutes:seconds.
-
One (1) blue LED which turns on if the GPS module does not report a valid GPS lock.
-
Design
The internal design is illustrated by the following diagram:
The general flow is as follows:
-
The GPS module is repsonsible for time tracking. It sends messages to the Arduino over the serial connection, at approximately 1 second intervals. These messages include the time in UTC, and the GPS signal status. + The GPS module continues to track the time using an internal clock, even if it does not currently have a GPS lock.
-
The Arduino is responsible for reading the time from the GPS module, handling user inputs, and applying the time zone to the UTC time from the GPS. + Note: The time is not sent to the FPGA immediately upon being received from the GPS module. See the Update Timing subsection of the Design in Detail section for more information.
-
Whenever the second rolls over, the arduino writes out the new time (one digit at a time) to the Basys3, which will store each digit in a register.
-
The Basys3 multiplexes the nixies by providing low-voltage signals to transistors which switch the 180V required by the nixie tubes. On each sweep, the current values stored in the registers are used.
The following image shows the complete prototype.
The following image shows the prototype circuit for Arduino, Basys3, GPS module, and HID controls.
Only the rightmost switch is used for timezone control. The leftmost switch is used to disable serial signals from the SIM28 while programming the Arduino. All other switches are unused. |
The following image shows the prototype circuit for transistor arrays which control the Nixie tubes.
Design in Detail
MCU to FPGA protocol
The protocol between the Arduino and the Basys3
uses double-pumped 4-bit parallel signaling,
led by the Arduino.
The Arduino produces one clock signal clk
and four binary signals D0→D3
.
On the clock’s rising edge the Arduino specifies which digit to control.
On the clock’s falling edge the Arduino specifies which value to set it to.
All numbers are specified in binary, with D3
being the most significant bit.
Digits are numbered as NXT0→NXT5
(NiXie Tube),
with NXT0
being the most significant digit of the hour.
The following example shows how the Arduino would perform the following sequence:
-
Start from all digits set to 0.
-
Set
NXT4
to 8. -
Set
NXT5
to 2. -
Set
NXT4
to 9.
Time accuracy
Because the clock retrieves the time from the GPS module every second, there is no risk of the time drifting. However, there are accuracy concerns regarding when the update occurs each second.
In an ideal scenario, the time displayed would be accurate to within 1 millisecond
(the resolution of time transmitted in teh $GPRMC
NMEA message).
For a display with a maximum resolution of 1 second,
this means that the display should update within 1 ms of the wall time
changing.
It should be noted that being millisecond accurate was not a requirement
specified in the original design document.
It is thus a "nice to have" feature.
While the GPS module provides NMEA messages with the accurate time at 1 Hz, it does not provide them exactly on the second. Thus, if the Arduino were to read an NMEA message and then immediately update the time, it would always miss the time change target by some significant amount.
For example, consider if the Arduino were to receive an NEMA message with the time 07:53:21.995
.
If the Arduino sets the time to 07:53:21
only upon receipt of that message,
that update would be with a latency of 995 ms, far from the ideal target of 1 ms.
The solution used in this project is to use the NMEA message as the source for the next time to be shown.
So in this case, the Arduino sleeps for 5 ms before showing the time 07:53:22
.
Assuming that the Arduino’s CPU clock does not gain or lose at least 1 ms in a single second,
the update should occur within the target window.
The final section of this document discusses further improvements that could be made to the millisecond accuracy of the clock.
Input handling
The toggle switch between 12- and 24-hour mode is read before displaying the time.
A timer overflow interrupt is used to check the time zone increment/decrement buttons every 16 ms. This is sufficient to debounce the buttons. The loop which checks this is short enough to not interfere with update accuracy.
Transistor arrays
Nixie tubes require ~180V voltage supply. In addition to 180V anode for each of the six tubes, each number requires its own cathode. Because we are multiplexing the display, this means having six independent anode control circuits and 11 cathode control circuits.
There are several options available for switching 180V using the 3.3v signals of the Basys3 (for example, the vintage SN74141 ICs that were traditionally used to control Nixie tubes). A transistor array was selected, primarily due to low cost.
It was originally planned to use only 2N6517TA NPN transistors for the character selector circuit. In practice, it was found that the NPN design leaked 1 amp when used to disable a tube; far more than was acceptable. It was also found that this circuit did not behave well when multiple were used in parallel, as required for multiplexing. The original circuit was as follows:
Instead, a circuit using a combination of NPN and PNP transistors was used. This circuit is based on an existing design (linked in the references section), which also mitigates a significant amount of ghosting between the characters of a given tube.
One alternative solution which may have worked would be to keep the original transistor arrangement, but adopt the additional 412k resistors of the revised design between the transistors. This would likely have been sufficient to resolve the excessive current draw. |
The high-side (the Nixie’s anode) requires two stages of transistors, an NPN and a PNP. The PNP transistor is the primary transistor responsible for switching 180V. The Basys 3 is not capable of creating the required negative current flow on the base, so it is connected to a second NPN transistor which provides a path to ground. When the Basys3 sets its signal high, the NPN transistor allows current to flow from the PNP transistor’s base to ground and thus current is allowed to flow to the Nixie tube. The high resistor value between VCC and the NPN transistor minimizes current draw by the control circuit.
The low-side (the per-character cathode) uses a simple control circuit, wherein an NPN transistor is used to enable or disable that character.
Within a nixie tube, it is possible for an unselected character to use the cathode of a selected character as a high-resistance path to ground. This can cause unselected digits to glow faintly, an effect known as "ghosting". In this design, a high-value resistor joining all cathodes allows the selected character to raise the low-side voltage level slightly. This reduces the apparent voltage for other characters, reducing the probability that those characters will glow.
Further developments
Simplified hardware
Using an FPGA and a microcontroller for this purposes is excessive; the same functionality could be achieved by either:
-
Using only the FPGA, moving the serial and control functionality on to it.
-
Using only the Arduino, in conjunction with specialized ICs that allow controlling high-voltage circuits with fewer GPIO pins.
This would make achieving timing targets more complicated, since the Arduino would need to manage the time while also multiplexing the Nixie tubes.
Most Nixie clock projects use a simple microcontroller in conjunction with specialized ICs.
Guaranteed millisecond accuracy
There are several possible methods for guaranteeing that we are millisecond accurate in rollover timing.
For example, one option would be to configure a timer on the Arduino to call an interrupt with a one second period. We could update the time within the interrupt. At some regular interval (for example every minute), we could reset the timer based on milliseconds provided by the GPS module, preventing clock drift from affecting the timing precision.
Another possibility would be to use the FPGA as a timing trigger. The FPGA could send a signal every second requesting that the time be incremented and sent. The Arduino could periodically reset that trigger by sending an accurate number of milliseconds.
In both cases, these solutions mitigate the problem that we may receive a time from the SIM28 after the rollover to the next second has already occurred. Both of these solutions use a local clock to maintain second-to-second accuracy, meaning that we will still keep correct time (in the short term) if we receive a message from the GPS module too late.
References
-
SIM28 datasheet: https://www.makerfabs.com/desfile/files/SIM28_Hardware%20Design_V1.06.pdf
-
NMEA sentence guide: https://www.rfwireless-world.com/Terminology/GPS-sentences-or-NMEA-sentences.html
-
Demonstration of Nixie tubes running at over 100KHz: https://www.youtube.com/watch?v=TK3E55fytC0
-
Test of Arduino clock accuracy: https://jorisvr.nl/article/arduino-frequency