Nixie Tube Clock with Seconds

Nixie Tube Clock with Seconds

Building a nixie-tube clock is a project that I wanted to do for ages. The clock was build around IN-12b Tubes (I got them for cheap from eBay) and the TPIC6B595 shift register.

The schematic is pretty straightforward. The clock consists of 3 PCBs with 2 tubes each. Because of the shift registers it's easy to daisychain multiple modules together.

The logic part is handled by an ESP8266 microcontroller. The ESP's WiFi functionality allows for NTP time synchronisation.

The code:

register.h:

#include <Arduino.h>

#ifndef REGISTER_H
#define REGISTER_H

#define CLK_TIME 1

class RegisterClock
{
public:
    RegisterClock(int dataPin, int clockPin, int WclockPin)
    {
        pData = dataPin;
        pClock = clockPin;
        pWclock = WclockPin;

        pinMode(pData, OUTPUT);
        pinMode(pClock, OUTPUT);
        pinMode(pWclock, OUTPUT);
    }

    void setHours(int val)
    {
        hours = val;
    }

    void setMinutes(int val)
    {
        minutes = val;
    }

    void setSeconds(int val)
    {
        seconds = val;
    }

    void doAntiCathodePoisoning()
    {
        for (int i = 0; i < 10; i++)
        {
            for (int j = 0; j < 3; j++) nixiePairPush(i, i);
            wClockPulse();

            delay(500);
        }
    }

    void display()
    {
        nixiePairPush(seconds / 10, seconds % 10);
        nixiePairPush(minutes / 10, minutes % 10);
        nixiePairPush(hours / 10, hours % 10);
        wClockPulse();
    }

private:
    int pData, pClock, pWclock;
    int hours, minutes, seconds;

    void clockPulse()
    {
        digitalWrite(pClock, 1);
        delay(CLK_TIME);
        digitalWrite(pClock, 0);
        delay(CLK_TIME);
    }

    void pushBit(uint8_t bit)
    {
        bit = bit & 1;
        digitalWrite(D2, bit);
        clockPulse();
    }

    void push0bits(int n)
    {
        for (int i = 0; i < n; i++)
            pushBit(0);
    }

    void pushSequence(char *const sequence, int len)
    {
        for (int i = 0; i < len; i++)
        {
            if (sequence[i] == '0')
                pushBit(0);
            if (sequence[i] == '1')
                pushBit(1);
        }
    }

    void nixiePush(int number)
    {
        switch (number)
        {
        case 0:
            pushSequence("1000000000", 10);
            break;
        case 1:
            pushSequence("0000000001", 10);
            break;
        case 2:
            pushSequence("0000000010", 10);
            break;
        case 3:
            pushSequence("0000000100", 10);
            break;
        case 4:
            pushSequence("0000001000", 10);
            break;
        case 5:
            pushSequence("0000010000", 10);
            break;
        case 6:
            pushSequence("0000100000", 10);
            break;
        case 7:
            pushSequence("0001000000", 10);
            break;
        case 8:
            pushSequence("0010000000", 10);
            break;
        case 9:
            pushSequence("0100000000", 10);
            break;
        }
    }

    void nixiePairPush(int n1, int n2)
    {
        push0bits(4);
        nixiePush(n2);
        nixiePush(n1);
    }

    void wClockPulse()
    {
        digitalWrite(pWclock, 1);
        delay(CLK_TIME);
        digitalWrite(pWclock, 0);
        delay(CLK_TIME);
    }
};

#endif

main.cpp

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>

#include "register.h"

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "0.de.pool.ntp.org", 3600 * 2, 120000);

RegisterClock rClock(D2, D3, D4);

void setup()
{
    WiFi.begin("xxx", "xxx");

    while (WiFi.status() != WL_CONNECTED)
    {
        delay(500);
    }

    timeClient.begin();
}

void loop()
{
    delay(100);
    timeClient.update();

    int h = timeClient.getHours();
    int m = timeClient.getMinutes();
    int s = timeClient.getSeconds();

    if (m == 0)
    {
        rClock.doAntiCathodePoisoning();
    }
    else
    {
        rClock.setHours(h);
        rClock.setMinutes(m);
        rClock.setSeconds(s);
        rClock.display();
    }
}
Show Comments