Skip to content

The NTPixie, A WiFi Nixie Tube Clock

Caden Kraft
6 min read
The NTPixie, A WiFi Nixie Tube Clock

I have always thought that nixie tubes are one of the coolest inventions ever made. The novelty of having such an intricate assembly of blown glass and spot welded numbers just to simply display digits is something I've always admired.

What's a Nixie Tube?

Before the invention of the LED or the seven segment display, engineers needed a device capable of displaying digits for things like voltmeters, multimeters, and frequency counters.

To solve this problem Engineers in the USSR created nixie tubes which were made of 10 digits encased in blown glass that was sealed with Neon gas. The tubes have a wire mesh anode with multiple digits acting as the cathodes. When voltage is applied across the two the Neon gas directly around the digit glows.

Project Requirements

I've looked into simply purchasing a nixie tube clock in the past but there were always a few key wants that I had for a clock that could not be found in available models online.

The project requirements I've set for this clock are listed below.

  • 6 Digits in order to display seconds
  • Neon bulb colons between the hours, minutes, and seconds
  • WiFi, or atomic capability to have a perfect synchronized time

I decided to use the IN-12 nixie tube due to its relatively low cost and the horizontal mounting making them ideal for the design I had in mind.

IN-12 Nixie Tube

For the time accuracy I decided on using the Raspberry Pi Pico W and using the WiFi capability to sync to NTP time servers.

Design

For the design I started on the PCB side of things as that is what I was less familiar with. To drive the nixie tubes I decided on using the K155ID1 nixie tube driver. For the power supply I decided on using the NCH8200HV. Finally, for the colons I decided on using NE-2 bulbs.

After a few design revisions this is the final PCB and schematic that I came up with.

To save cost on ordering the PCB I decided to design it to be snapped in half and then both pieces stacked on top of each other connected via B2B connectors.

Soldered Assembly

As for the design of the case, I was originally thinking of making a wooden case but did not have a wood shop at my disposal so I decided on making a clear resin SLA enclosure to sell the retro N64 look. The final case design I came up with is below.

Final Case Design

Firmware

For this project I decided to use MicroPython on the Pico as it has more documentation and support online for this type of project. Below is the code I wrote for the firmware running on the clock.

import network
import ntptime
from machine import Pin, Timer
from time import localtime, sleep, time

# Define the pins for each nixie tube

nixie_pins = [
    [6, 4, 5, 7],  # nixie tube 1
    [22, 20, 21, 28],  # nixie tube 2
    [2, 0, 1, 3],  # nixie tube 3
    [18, 16, 17, 19],  # nixie tube 4
    [10, 8, 9, 11],  # nixie tube 5
    [14, 12, 13, 15]  # nixie tube 6
]

colon_pin_1 = Pin(26, Pin.OUT)
colon_pin_2 = Pin(27, Pin.OUT)

# Define the lookup table for digit to binary conversion
digit_to_binary = {
    0: [0, 0, 0, 0],
    1: [0, 0, 0, 1],
    2: [0, 0, 1, 0],
    3: [0, 0, 1, 1],
    4: [0, 1, 0, 0],
    5: [0, 1, 0, 1],
    6: [0, 1, 1, 0],
    7: [0, 1, 1, 1],
    8: [1, 0, 0, 0],
    9: [1, 0, 0, 1]
}

# Connect to Wi-Fi
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
sta_if.connect("WIFI_SSID_HERE", "WIFI_PASSCODE_HERE")
while not sta_if.isconnected():
    pass

# Set up the pins for each nixie tube
nixie_tubes = []
for pins in nixie_pins:
    nixie_tube = []
    for pin in pins:
        nixie_tube.append(Pin(pin, Pin.OUT))
    nixie_tubes.append(nixie_tube)
    #print(nixie_tubes)

# Set up a timer to update the display every second
timer = Timer(-1)

ntptime.settime()
# Define a function to update the display
def update_display(timer):
    # Get the current time from the NTP server
    print(time())
    current_time = localtime()
    # Apply the UTC offset (in seconds)
    seconds_offset = 0 #using https://time.is
    utc_offset = -5 * 60 * 60 - seconds_offset # for example, 1 hour ahead of UTC
    # -5 = CST -7 = PST 
    current_time = localtime(time() + utc_offset)
    if current_time[4]==10 and current_time[5]==10:
        ntptime.settime()
        print("NTP SYNC")
    if current_time[3]>12:
        twelve_hour_time = current_time[3]-12
    else:
        twelve_hour_time = current_time[3]
    #print(current_time)
    #print(twelve_hour_time)
    # Convert the time to digits
    digits = [
        twelve_hour_time // 10,  # hour tens
        twelve_hour_time % 10,  # hour ones
        current_time[4] // 10,  # minute tens
        current_time[4] % 10,  # minute ones
        current_time[5] // 10,  # second tens
        current_time[5] % 10   # second ones
    ]

# Code below is to cycle less common digits to in order to prevent leaking this section should be reworked some day

    if current_time[3]==3 and current_time[4]==0:
        digits = [0,0,0,0,0,0]
    elif current_time[3]==3 and current_time[4]==1:
        digits = [1,1,1,1,1,1]
    elif current_time[3]==3 and current_time[4]==2:
        digits = [2,2,2,2,2,2]
    elif current_time[3]==3 and current_time[4]==3:
        digits = [3,3,3,3,3,3]
    elif current_time[3]==3 and current_time[4]==4:
        digits = [4,4,4,4,4,4]
    elif current_time[3]==3 and current_time[4]==5:
        digits = [5,5,5,5,5,5]
    elif current_time[3]==3 and current_time[4]==6:
        digits = [6,6,6,6,6,6]
    elif current_time[3]==3 and current_time[4]==7:
        digits = [7,7,7,7,7,7]
    elif current_time[3]==3 and current_time[4]==8:
        digits = [8,8,8,8,8,8]
    elif current_time[3]==3 and current_time[4]==9:
        digits = [9,9,9,9,9,9]
        
    print(digits)
    # Convert the digits to binary and display them on the nixie tubes
    for i in range(6):
        binary = digit_to_binary[digits[i]]
        for j in range(4):
            nixie_tubes[i][j].value(binary[j])
    colon_pin_1.value(1)
    colon_pin_2.value(1)
    sleep(0.5)
    colon_pin_1.value(0)
    colon_pin_2.value(0)

# Start the timer
timer.init(period=1000, mode=Timer.PERIODIC, callback=update_display)

# Put the device to sleep to save power
while True:
    sleep(1)  # can be interrupted by timer events

Input WiFi SSID, password, and timezone for this code to run

Final Assembly

Below are renders and pictures of the final design up and running.

You can see an orbital view of the design by dragging on the model below.


Conclusions

I have been using it on my bedside for the past few weeks now and it has kept time perfectly and I haven't yet noticed any major issues. One issue I am running into is that two of the four bulbs on the colons don't seem to light up consistently. I've read online about needing time for the bulbs to polarize and as they do turn on some of the time I think that's what the problem is.

This has been one of my favorite projects because it was very interdisciplinary in the amount of skills that I had to use in order to complete it. Second, thanks mostly to the superb quality of the SLA print (plus 2 coats of Rust-Oleum Crystal Clear Enamel), this project looks the most polished and least DIY out of anything I've ever done. This clock allowed me to hone in on my PCB design skills and I hope I can use them more on future projects.

Thanks for reading, please check out some of my other posts below!

CodingBuild

Related Posts

Members Public

3D Printed Dual Cycloidal Actuator

MotorsBuild

This project builds on my previous axial flux motor. To improve the torque output of the motor I designed a cycloidal gearbox that integrates into the current motor design allowing for more torque.

6 min read
3D Printed Dual Cycloidal Actuator
Members Public

Solar Car HV Bus Bar Distribution

Solar CarBuild

I designed a high voltage distribution assembly for the solar car that centralizes all of our high voltage connections, contactors, and fuses into a centralized location.

4 min read
Solar Car HV Bus Bar Distribution
Members Public

Ironless Axial Flux Motor

MotorsBuild

Building off my first motor project, I designed and tested an axial flux motor by mathematically calculating all of the motor parameters needed to meet the design requirements that I set.

8 min read
Ironless Axial Flux Motor