A Nixie Clock

A Nixie Clock

IMGP1004Last year, I found the time (no puns) to design and build a nixie clock. I’d like to share some of my design notes, as well as the schematic, board, and how I would have done it differently had I to do all over.

I’d like to start by saying that I’m embarrassed to show anyone the schematic. At the time, I was just beginning to learn how Eagle (the software I used) worked, and I was more concerned about getting the project done, rather than doing it to show off. So please excuse the sloppy schematic, as I’m not going to redo it.

shit

The first part is the high voltage generation, which is achieved by the use of a 555 driving a boost converter. I used the schematic from http://www.dos4ever.com/flyback/flyback.html. Alternatively, if you Google 555 nixie driver, you’ll come across the page as well.

A couple notes on the driver: I did not need a heat sink for the irf730, something which I first though I’d need. Also, you have to make sure you’re using a diode (on the boost converter) that is fast or ultrafast. I used the MUR440, and it worked well. Don’t use a capacitor that is too large. The schematic on the earlier link specifies the use of a .47uF cap. I originally thought something larger would be better (such an American way of thinking), but I was wrong, and it introduced problems in my circuit later on.

Testing the HV driver out on breadboard

Testing the HV driver out on breadboard

The 12 volts used for the 555 timer and boost stage was then fed to an lm7805 to reduce the voltage to 5 volts for use with the atmega328. I really don’t want to hear any comments about the timekeeping accuracy of the 328, as I don’t really care. It’s good enough for me.

I coupled the 328 with a 16mhz crystal as outlined in just about every tutorial and gave it a header for onboard programming. If I were doing the same project today, I’d use an ATtiny85 since you really only need 5 pins. One pin for hour button, one for minute button (to advance and set the time) and 3 for the shift registers (Clock, data, latch). The 328 added unnecessary components and is just plain overkill for such a simple task IMO.

The ATmega328 was connected to 6 shift registers since I needed 45 outputs to control the 6 tubes, and 6 registers gave me 48 pins. Number of outputs = (3)+(10):(6)+(10):(6)+(10) H:M:S

The 328 had no problems driving all 6 registers inline (e.g. I did not need anything to boost the signal), and frankly I’m not sure that’s a concern with only 6. I used the highly popular 74hc595 shift registers. Also note that the tutorial I used for the shift registers, http://arduino.cc/en/Tutorial/ShiftOut, instructs to use a .1uF cap across the latch pin to ground, while the circuit diagram image actually shows a 1uF cap across the latch to ground. The cap is not needed, and you should not use it. I had problems with some of the later shift registers in the chain not unlatching, and therefore not allowing the nixie tube to display. After replacing some shift registers (try desoldering a couple of those) it worked o.k., but I didn’t find out until nearly a year later when I built a nixie thermometer that that capacitor shouldn’t be there. Thanks, Arduino.

The shift registers then fed the base of an array of HV darlington transistors. The ones I used were 16 pin, SN75468N, with 7 100v darlingtons in each package. The collector were attached to the nixie tubes, and the ordering of the whole thing was figured out in software. It’s my opinion that it’s best to just hook things up, then worry about what’s driving what number later in software, rather than to make anything sequential. It’s much easier to change a variable than to jump wires over one another, especially when your board is one sided.

The nixies I used were In-12b that I purchased off of ebay. I bought a box of 50 for $100, which is a pretty good price. The box was sealed with Russian pinout diagrams, really neat stuff. There is a pot in the HV driver for adjusting output voltage. I was able to get the IN-12b nixie tubes to light up nicely at 160 volts, using a 33k resistor on the anode.

Below is a picture of the board design in Eagle. I had just purchased, not too earlier, a cnc machine for making PCBs and I did not have the right tools to mill it. I ended up using a dremel with a really large bit on the end of it to mill the board, which explains the unusually large tracks.

board

 

Also, as a result of having large tracks, I had to route the tracks through some of the unused pins. I ended up clipping off the pins that were not used so there was not interference from the tracks. Yes, it was a horrible way to do things, but that’s what I did, and I’m here to document it.

PCB, right after milling on CNC machine

PCB, right after milling on CNC machine

The code I used for the ATmega328 can be seen below, from the Arduino IDE:

1
2
3
4
5
6
7
8
9
10
//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 11;
// hour advance
int hourbutton = 6;
// minute advance
int minutebutton = 5;

unsigned long lastmillis = 0;
int second = 0;
int minute = 0;
int hour = 12;
boolean timechange = true;
int sregister[] = {0,0,0,0,0,0};

void setup() {
//set pins to output so you can control the shift sregister
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(hourbutton, INPUT);
pinMode(minutebutton, INPUT);

}

void loop() {

if(timechange){
timechange = false;
int secondr = second % 10;
int secondl = second / 10;
int minuter = minute % 10;
int minutel = minute / 10;
int hourr = hour % 10;
int hourl = hour / 10;
int spillover = 0;
int bit = 0;

// Seconds ones ******************************************************
if(secondr == 1 || secondr == 2){
sregister[5] = 0;
if(secondr == 2){
spillover = 1;
} else {
spillover = 2;
}
} else {
if(secondr == 0){
sregister[5] = 1;
} else {
sregister[5] = 0;
bit = 10 – secondr;
bitWrite(sregister[5], bit, HIGH);
}
}

// Seconds tens ******************************************************
if(secondl == 0){
sregister[4] = 4 + spillover;
spillover = 0;
} else {
bit = 8 – secondl;
sregister[4] = 0;
bitWrite(sregister[4], bit, HIGH);
sregister[4] = sregister[4] + spillover;
spillover = 0;
}

// Minutes ones ******************************************************
if((minuter == 1) || (minuter == 2)){
sregister[3] = 0;
if(minuter == 2){
spillover = 1;
} else {
spillover = 2;
}
} else {
if(minuter == 0){
sregister[3] = 1;
} else {
sregister[3] = 0;
bit = 10 – minuter;
bitWrite(sregister[3], bit, HIGH);
}

}

// Minutes tens *****************************************************
if(minutel == 0){
sregister[2] = 4 + spillover;
spillover = 0;
} else {
bit = 8 – minutel;
sregister[2] = 0;
bitWrite(sregister[2], bit, HIGH);
sregister[2] = sregister[2] + spillover;
spillover = 0;
}

// Hours ones ********************************************************
if((hourr == 1) || (hourr == 2)){
sregister[1] = 0;
if(hourr == 2){
spillover = 1;
} else {
spillover = 2;
}
} else {
if(hourr == 0){
sregister[1] = 1;
} else {
sregister[1] = 0;
bit = 10 – hourr;
bitWrite(sregister[1], bit, HIGH);
}

}

// Hours tens *********************************************************
bit = 2 + hourl;
sregister[0] = 0;
bitWrite(sregister[0], bit, HIGH);
sregister[0] = sregister[0] + spillover;
spillover = 0;
digitalWrite(latchPin, LOW);
for(int x = 5; x >= 0; x–){
shiftOut(dataPin, clockPin, LSBFIRST, sregister[x]);
}
digitalWrite(latchPin, HIGH);

}

//check to see if a second has gone by, if so update time variables
if(millis() – lastmillis >= 1000){
if(digitalRead(hourbutton) == HIGH) hour++;
if(digitalRead(minutebutton) == HIGH) minute++;
lastmillis += 1000;
timechange = true;
second++;
}
if(second > 59){
second = 0;
minute++;
}
if(minute > 59){
minute = 0;
hour++;
}
if(hour > 12){
hour = 1;
}
}

PXK50472

In the end, I ended up building another board with neon tubes as periods between each number. The final result was pretty nice. If I had it to do over, I’d make smaller tracks, place the tubes in the center of the board, add a relay or buzzer for tick sounds, add a header for buttons to plug in (for setting time – minute, second), and use an ATtiny85 or 84.