Not Your Average Nixie Clock

Not Your Average Nixie Clock, front and center

Not Your Average Nixie Clock is just what it sounds like, a nixie clock with more functionality than just a standard clock. This 10-tube display reports time, date, temperature, humidity, and pressure and can be controlled directly over serial to display anything that the tubes used can display. The clock uses a single Arduino Nano to run the backplane with all of the sensors and controls 10 display driver boards which each run a discrete ATMega328 processor to drive a single tube.

Update! 4/4/2017

Another small update to fix a couple of quirks. I noticed that very occasionally, the clock would display 100.00kPa as the barometric pressure, but added an extra space before the number that misaligned the units and didn't display them. After some considering and digging around, as well as witnessing some properly formatted 100.00kPa displays, I found out the issue - an odd rounding error with the way arduino processes floating point numbers. The normal default is to display two digits of precision and round, so what was happening is that when the pressure was 99.995kPa or more, it would round up to display 100.00kPa, which is fine for accuracy's sake, but which meant the calculations to add leading spaces to get it positioned right added one too many until the value actually hit 100.00kPa. This is now fixed, and on other ranges where I never saw the problem, but where it should theoretically exist.

The only other significant change was in the calculating of the displayed relative humidity. Because there's no active ventilation for the clock, the interior (where the temperature sensors are) heats up somewhat above ambient. To fix this, I measured the outside temperature with a thermocouple and set a fixed offset assuming no forced air from an outside source. It works fine, but it means the relative humidity value read at the higher temperature is actually a ways off from the real one, and it measured about 6-7% low consistently. Rather than just add another offset and accept whatever error that made, I decided to convert relative humidity to absolute, then convert back to relative factoring in the displayed (adjusted) temperature. Unfortunately, there's quite a few variables in the calculation of relative and absolute humidity, so I found a formula with a set of constants that was accurate within about -35C to +35C and only requires the other humidity and the current temperature. So now the clock converts the sensor-read relative humidity to absolute humidity at the same temperature, and then back to relative humidity at the adjusted temperature. As a result, I can see an increased humidity display right in line with the offset I had measured, but which is calculated rather than just manually offset.

There were a couple of other minor changes and a couple modified EEPROM settings, but I also found that the RTC module kept extremely accurate time - the last time it was set to internet time from the computer was almost two and a half years before, before the backplane was even finished, and it was only 15 seconds off of internet time when I resynchronized it as part of this update. The updated code can be found on github!

 

Update! 3/17/2016

Daylight Savings Time in the US rolled around and I realized I never wrote anything into the code to compensate for it... so within a few days I had an update coded up to do just that. I also wrote in a handle to set the RTC module via serial (I originally used a separate sketch to set it, and I hadn't need to set it since I built the backplane), and modified the provided processing sketch to send the needed code. There was a bug that after a month or something of run time, the short press for the capacitive sensor stopped working (long press still worked), so I've swapped a variable type and added an additional check - I believe this broke when the uptime in milliseconds overflowed the signed long variable it resided in. All this should make the clock a more robust platform, but the testing for all the new code has consisted of about an hour of runtime, so if something shows up down the line, I'll tweak it and reupload. The revised code only effects the backplane and is uploaded to the GitHub page!

 

Original page:

Development time for this project is just about two months, and it totals almost 1400 lines of code and uses 473 electronic components by my count. It is intentionally overbuilt from what a clock would normally need to do and very similar functionality can be done with less, but I wanted to make some modular and swappable elements (every driver module is the same and be inserted in any order to drive any one of the four tubes). I also wanted to include lots of debug and status options that would be entirely unnecessary in a final product. I think the 10 vertical riser boards that drive the display look pretty nice too!

The backplane houses the main Arduino Nano controller which manages everything and acts as the interface to an external device. For sensors, it uses a DHT22 for temperature and humidity, a BMP180 for temperature (the two are averaged) and pressure, and a DS3232 RTC for timekeeping. It reads the value of a variable resistor to drive the NCH6100HV high voltage step up converter from with a PWM signal to control display brightness. Each of the 10 driver modules uses an ATMega328 with custom firmware to control 11 MPSA42 high voltage transistors and drive each pin of a 12 pin nixie tube - designed for Soviet IN-12 and IN-15 tubes in A and B variants. Each driver has a switch to choose IN-12 or IN-15 and detects the A or B portion automatically, and each driver communicates to the backplane processor through an I2C bus, deriving its I2C address from a resistor in the backplane to control ordering without having any difference in software. An aluminum bracket holds the tube sockets and tubes in place while an aluminum band around it which is electrically isolated from it acts as a capacitive touch sensor for a simple one-button input. Any tube can be connected to any socket or left unpopulated and driver modules can be inserted and configured in any way - the normal clock display won't work right with a totally different configuration, but the display can still be driven properly through the serial port in any combination.

I ran into countless problems developing it as I was working with several things I hadn't worked with before and because the scale was fairly large, but I'll run through a few things I worked through and how I fixed the problem, because it could be useful to someone using the same sorts of parts or general design.

From the left side. From the right side.

The tube datasheets for the IN-12 and IN-15 tubes indicate a pinout and specify cathode and anode, but they are somewhat misleading. Pin one on the tube data sheet is actually pin 7 on the number written on the back of the sockets - which are intended for these tubes - and counts up going clockwise. What makes this more confusing is that you can actually power a cathode pin and ground the anode and still light the display... but for certain pins the entire tube will light somewhat instead of seeing a normal digit or symbol. It was a headache to deal with until I figured out just hooking up the socket leads in a different order made things act as I expected.

Making things work on the I2C bus seems straightforward, but it gets more complicated when you're sharing the bus with commercial sensors. Making sure the addresses don't overlap helps, but you also have to build in some replies to differentiate between types of things on the bus. It helped me to display the data that was coming back from the I2C scan, and then I configured the module code to reply in ways that didn't interfere with or get confused with other sensors on the bus. It's also worth checking the solder joints, with the pullups and the capacitors over the power, probing the connections could give incomplete information and early on I had a bit of trouble with some high-resistance shorts between the SDA and SCL lines that made the initial scan just lock up.

While I expected it going in, when I added the capacitive touch sensor, I was surprised at how much noise the tubes made. I originally used the socket mounting bracket as the sensor, but it auto-triggered itself when there were many tubes enabled (like in test mode where everything is running). While the sensor would increase in reading by a thousand or more when you touched it, if in some modes the noise was 300-400 and some it was 2000-2500, it would take some serious data analysis to determine whether it was actually touched, and you'd have to factor the number of on tubes and the lengths of the cathodes in use to eliminate the noise from the reading. Instead of that, I put a thin insulating layer on the edge of the bracket and surrounded it with another strip of aluminum, then grounded the bracket. This provided some noise isolation (not a huge amount since the tubes were still close and a straight shot through open air), but also increased the sensor value when pressed because of the close proximity ground.

From the top. From the back.

Dimming the display was more complicated than I expected, after realizing the power supply module could be toggled with a logic level drive to the SHDN pin it seemed like a simple PWM would suffice. I got that PWM from an analogRead() of a pin connected to a voltage divider and a potentiometer, but I should have used a single turn potentiometer, the 10-15 turn one in place now simply takes forever to adjust the brightness of. You then scale down that value, factor in a minimum and maximum duty cycle to let the display be lit even at lower brightness settings, then invert it to drive an analogWrite signal. The defauly PWM frequency is 490Hz, though, which means an audible hum from your high voltage circuitry. Configuring timer prescaler bits you can go to 980Hz and a step much higher, but 980 is still quite easily audible and the only option was to go well above that and the 20kHz human hearing range, but the circuit in the power supply stopped responding at such a frequency. My solution was to go the other way, around 30Hz meant visible flashing, but 122.5Hz was much less audible and was still a fast enough signal to keep from seeing the flicker of the display. There is still some noise, but I believe at least a little is from the tubes themselves and would be impossible to eliminate.

Not Your Average Nixie Clock, front and center

Finally, right as I was writing the last few features into my program, I ran into memory overflow issues. The ATMega328 software doesn't really have overflow protection, so if you've got most of the SRAM used and you enter a function which allocates more than is available, it just reads or writes over existing data. I managed to get to more than 90% usage in the compiler before issues sprang up, but ultimately to get all of the serial communication stuff working properly, I had to optimize memory management quite a bit - unsigned ints instead of longs, bytes instead of ints (even in for loops), and surprisingly, reducing the length of Serial.print commands. As it turns out, returning a long string of text over the serial port actually allocates a good bit of RAM, so moving from returning "Invalid command" to "Bad command" saves a few bytes of RAM when you're running. I wanted the serial commands to be a direct user interface - no computer-side software and plaintext responses to queries, and I had to go over every line and swap for shorter synonyms or other tweaks to get more memory. When the memory was overflowing some of the symptoms included: entire lockups of the system, partial writes to drivers, garbled serial replies, missing received data, valid command strings being read correctly but then misinterpreted... memory problems are intermittent and hard to guess at a lot of times, so they can be particularly nasty to troubleshoot.

I made a short video showing the clock in operation and demonstrating some of the features:

 

 

 

 

 

 

 

 

 

 

 

 

 

Full source code and schematics are available on github: Not Your Average Nixie Clock on Github

 

 

 

December 7, 2015

 

  • The Tyranid Swarm

    The Tyranid Swarm

  • Sim Petri Dish

  • Liquid level Sensor

    Liquid Level Sensor

  • Warhammer 40k Terrain

Copyright