Nixie Bargraph Clock
---------------------------------
Edit 9/11/17
With the help of Kickstarter I have now released a kit for this clock kit! It includes a driver board and 2 Nixie IN-9 tubes. All you need to add is your own Arduino/Raspberry Pi/other. The kit can be found but clicking on this link !
---------------------------------
So I have seen lots of Nixie clocks online and thought they looked great, however I didn't want to spend $100+ on a clock that doesn't even include the tubes!
So with a little electronics knowledge I hunted around the various nixie tubes and circuits. I wanted to make something a little different to the large range of generally fairly similar looking nixie clocks. In the end I opted to use Nixie IN-9 bargraph tubes. These are long thin tubes and the height of the glowing plasma depends on the current through the tubes. The tube on the left is in hour increments and the tube on the right is in minutes. They only have two leads and so make building a circuit more straight forward.
In this design, there is an hour and a minute tube, with the heights of the plasma in each tube representing the current time. The time is kept using an Adafruit Trinket microcontroller and real time clock (RTC).
Assembling the Parts
There are two sections, first the electronics and secondly the mounting and finishing.
The electronic components required are:
Adafruit Trinket 5V - $7.95 (www.adafruit.com/products/1501)
Adafruit RTC - $9 (www.adafruit.com/products/264)
2x Nixie IN-9 bargraph ~ $3 per tube on eBay
1x Nixie 140v power supply ~$12 on eBay
4x 47 uF electrolyte capacitors
4x 3.9 kOhm resistors
2x 1 kOhm potentiometer
2x Transistor MJE340 NPN high voltage ~$1 each
1x LM7805 5v regulator ~$1
1x 2.1mm socket ~$1
1x project box with pcb ~$5
1x 12v DC power supply (I found an old one from some long forgotten gadget)
Solder, hookup wire, etc
Mounting:
I decided to mount the electronics in a small black plastic project box, then mount the tubes on an antique clock movement. To mark the hour and minutes I used copper wire wrapped round the tubes.
Mounting parts:
Antique clock movement - $10 eBay
Copper wire - $3 eBay
Hot glue gun
Circuit
The first step is to build the Nixie power supply. This came as a nice little kit from eBay, including a little PCB and just needed the components to be soldered to the board. This particular supply is variable between 110-180v, controllable with a small pot on the board. Using a small screw driver adjust the output to ~140v.
Before I went to whole way I wanted to test out my nixie tubes, to do this I built a simple test circuit using one tube, transistor and a 10k potentiometer I had laying around. As can been seen in the first figure, the 140v supply is attached to the tube anode (right leg). The cathode (left leg) is then connected to the collector leg of the MJE340 transistor. A 5v supply is connected to a 10k pot dividing to ground into the transistor base. Finally the transistor emitter is connect through a 300 ohm current limiting resistor to ground. If you are not familiar with transistors and electronics it doesn't really matter, just wire it up and change the plasma height with the pot knob!
Once that is working we can look at making our clock. The full clock circuit can be seen in the second circuit diagram. After some research I found a perfect tutorial on the Adafruit learn website doing almost exactly what I wanted to do. The tutorial can be found here: http://learn.adafruit.com/trinket-powered-analog-m...
This tutorial uses a Trinket controller and a RTC to control two analogue amp meters. Using pulse width modulation (PWM) to control the deflection of the needle. The coil of the amp meter averages the PWM into a effective dc signal. However if we use the PWM directly to drive the tubes then the high frequency modulation means the the plasma bar wont stay "clamped" to the base of the tube and you will have a hovering bar. To avoid this I averaged the PWM using a low pass filter with a long time constant to get an almost dc signal. This has a cut off frequency of 0.8 Hz, this is fine as we are updating the clock time only every 5 seconds.
Additionally since bargraphs have a finite life span and might need replacing and not every tube is exactly the same I included a 1k pot after the tube. This allows tweaking to adjust the plasma height for the two tubes.
To wire up the trinket to the real time clock (RCT) connect Trinket-pin 0 to RTC-SDA, Trinket-pin 2 to RTC-SCL and Trinket-5v to RTC-5v and the Trinket GND to the RTC ground. For this part it may be helpful to view the Adafruit clock instruction, http://learn.adafruit.com/trinket-powered-analog-... .
Once the Trinket and RTC are correctly wired, wire up the nixie tubes, transistors, filters etc on a breadboard carefully following the circuit diagram.
To get the RTC and Trinket talking you first need to download the correct libraries from the Adafruit Github. You need TinyWireM.h and TInyRTClib.h. First we want to calibrate the tubes, upload the calibrate sketch at the end of this instructable. If neither of the sketches at the end work then try the Adafruit clock sketch. I have tweaked the Adafruit clock sketch to work most effectively with the nixie tubes but the Adafruit sketch will work fine.
Calibration
Once you have uploaded the calibration sketch the graduations need to be marked.
There are three modes for the calibration, the first sets both nixie tubes to the maximum output. Use this to adjust the pot so that the plasma height in both tubes is the same and that it is slightly below the maximum height. This ensures the response is linear over the whole clock range.
The second setting calibrates the minutes tube. It changes between 0, 15, 30, 45 and 60 minutes every 5 seconds.
The last setting repeats this for each hour increment. Unlike the Adafruit clock the hour indicator moves in fixed increments once every hour. It was difficult to get a linear response for each hour when using an analog meter.
Once you have adjusted the pot upload the sketch to calibrate for minutes. Take the thin copper wire and cut a short length. Wrap this round the tube and twist the two ends together. Slide this to the correct position and using a hot glue gun place a small blob of glue to keep in the right place. Repeat this for each minute and hour increment.
I forgot to take any pictures of this process but you can see from the pics how the wire is attached. Though I used much less glue just to attach the wire.
Mounting and Finishing
Once the tubes are all calibrated and working it is now the time to permanently make the circuit and mount onto some form of base. I choose an antique clock movement as I liked the mix of antique, 60's and modern technology.
When transferring from the breadboard to strip board be very careful and take your time ensuring all the connections are made. The box I bought was a little small but with some careful placement and a little forcing I managed to get it all to fit. I drilled a hole in the side for the power supply and another for the nixie leads. I covered the nixie wires in heat shrink to avoid any shorts.
When the electronics are mounted in the box glue it to the back of the clock movement. To mount the tubes I used hot glue and glued the points of twisted wire to the metal, being careful to ensure they were straight. I probably used too much glue but it isn't very noticeable. It might be something that can be improved on in the future.
When it is all mounted up, load the Nixie clock sketch at the end of this instructable and admire your lovely new clock!
Arduino Sketch - Calibration
#define HOUR_PIN 1 // Hour display via PWM on Trinket GPIO #1
#define MINUTE_PIN 4 // Minute display via PWM on Trinket GPIO #4 (via Timer 1 calls)
int hours = 57;
int minutes = 57; //set minimum pwm
void setup () {
pinMode(HOUR_PIN, OUTPUT);
pinMode(MINUTE_PIN, OUTPUT);
PWM4_init(); //set up PWM outputs
}
void loop () {
// Use this to tweak the nixie pots to make sure the maximum tube height matches
analogWrite(HOUR_PIN, 255);
analogWrite4(255); // Use this to calibrate the minute increments
/*
analogWrite4(57); // minute 0
delay(5000);
analogWrite4(107); // minute 15
delay(5000);
analogWrite4(156); // minute 30
delay(5000);
analogWrite4(206); // minute 45
delay(5000);
analogWrite4(255); // minute 60
delay(5000);
*/
// Use this to calibrate the hour increments /*
analogWrite(HOUR_PIN, 57); // 57 is the minimum output and corresponds to 1am/pm
delay(4000); //delay 4 seconds
analogWrite(HOUR_PIN, 75); // 75 is the output that corresponds to 2am/pm
delay(4000);
analogWrite(HOUR_PIN, 93); // 93 is the output that corresponds to 3am/pm
delay(4000);
analogWrite(HOUR_PIN, 111); // 111 is the output that corresponds to 4am/pm
delay(4000);
analogWrite(HOUR_PIN, 129); // 129 is the output that corresponds to 5am/pm
delay(4000);
analogWrite(HOUR_PIN, 147); // 147 is the output that corresponds to 6am/pm
delay(4000);
analogWrite(HOUR_PIN, 165); // 165 is the output that corresponds to 7am/pm
delay(4000);
analogWrite(HOUR_PIN, 183); // 183 is the output that corresponds to 8am/pm
delay(4000);
analogWrite(HOUR_PIN, 201); // 201 is the output that corresponds to 9am/pm
delay(4000);
analogWrite(HOUR_PIN, 219); // 219 is the output that corresponds to 10am/pm
delay(4000);
analogWrite(HOUR_PIN, 237); // 237 is the output that corresponds to 11am/pm
delay(4000);
analogWrite(HOUR_PIN, 255); // 255 is the output that corresponds to 12am/pm
*/
}
void PWM4_init() {
// Set up PWM on Trinket GPIO #4 (PB4, pin 3) using Timer 1
TCCR1 = _BV (CS10); // no prescaler
GTCCR = _BV (COM1B1) | _BV (PWM1B); // clear OC1B on compare
OCR1B = 127; // duty cycle initialize to 50%
OCR1C = 255; // frequency
}
// Function to allow analogWrite on Trinket GPIO #4
void analogWrite4(uint8_t duty_value) {
OCR1B = duty_value; // duty may be 0 to 255 (0 to 100%)
}
Arduino Sketch - Clock
// Adafruit Trinket analog meter clock
// Date and time functions using a DS1307 RTC connected via I2C and the TinyWireM lib
// Download these libraries from Adafruit's Github repository and // install in your Arduino Libraries directory
#include <TinyWireM.h>
#include <TinyRTClib.h>
//For debug, uncomment serial code, use a FTDI Friend with its RX pin connected to Pin 3
// You will need a terminal program (such as freeware PuTTY for Windows) set to the
// USB port of the FTDI friend at 9600 baud. Uncomment out Serial commands to see what's up //
#define HOUR_PIN 1 // Hour display via PWM on Trinket GPIO #1
#define MINUTE_PIN 4 // Minute display via PWM on Trinket GPIO #4 (via Timer 1 calls)
//SendOnlySoftwareSerial Serial(3); // Serial transmission on Trinket Pin 3
RTC_DS1307 rtc; // Set up real time clock
void setup () {
pinMode(HOUR_PIN, OUTPUT); // define PWM meter pins as outputs
pinMode(MINUTE_PIN, OUTPUT);
PWM4_init(); // Set timer 1 to work PWM on Trinket Pin 4
TinyWireM.begin(); // Begin I2C
rtc.begin(); // Begin DS1307 real time clock
//Serial.begin(9600); // Begin Serial Monitor at 9600 baud
if (! rtc.isrunning()) {
//Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(__DATE__, __TIME__));
}
}
void loop () {
uint8_t hourvalue, minutevalue;
uint8_t hourvoltage, minutevoltage;
DateTime now = rtc.now(); // Get the RTC info
hourvalue = now.hour(); // Get the hour
if(hourvalue > 12) hourvalue -= 12; // This clock is 12 hour
minutevalue = now.minute(); // Get the minutes
minutevoltage = map(minutevalue, 1, 60, 57, 255); // Convert minutes to PWM duty cycle
if(hourvalue == 1){
analogWrite(HOUR_PIN, 57);
}
if(hourvalue == 2){
analogWrite(HOUR_PIN, 75); // each hour corresponds to +18
}
if(hourvalue == 3){
analogWrite(HOUR_PIN, 91);
}
if(hourvalue == 4){
analogWrite(HOUR_PIN, 111);
}
if(hourvalue == 5){
analogWrite(HOUR_PIN, 126);
}
if(hourvalue ==6){
analogWrite(HOUR_PIN, 147);
}
if(hourvalue == 7){
analogWrite(HOUR_PIN, 165);
}
if(hourvalue == 8){
analogWrite(HOUR_PIN, 183);
}
if(hourvalue == 9){
analogWrite(HOUR_PIN, 201);
}
if(hourvalue == 10){
analogWrite(HOUR_PIN, 215);
}
if(hourvalue == 11){
analogWrite(HOUR_PIN, 237);
}
if(hourvalue == 12){
analogWrite(HOUR_PIN, 255);
}
analogWrite4(minutevoltage); // minute analogwrite can remain the same as the mapping works
// code to put the processor to sleep might be preferable - we will delay
delay(5000); // check time every 5 seconds. You can change this.
}
void PWM4_init() { // Set up PWM on Trinket GPIO #4 (PB4, pin 3) using Timer 1
TCCR1 = _BV (CS10); // no prescaler
GTCCR = _BV (COM1B1) | _BV (PWM1B); // clear OC1B on compare
OCR1B = 127; // duty cycle initialize to 50%
OCR1C = 255; // frequency
}
// Function to allow analogWrite on Trinket GPIO #4
void analogWrite4(uint8_t duty_value) {
OCR1B = duty_value; // duty may be 0 to 255 (0 to 100%)
}