Close
0%
0%

Just Another Nixie Clock

An arduino based multiplexed, cross-fading IN-14 Nixie tube clock.

Similar projects worth following
An IN-14 Nixie clock, multiplexed in groups of 3 (hours, minutes, seconds), which functions by switching on and off the anode with high side switch transistors.

The code is written on a stand alone Arduino, an ATMEGA328P chip in a 28 pin DIP configuration. Using timer interrupts, and direct port writes, the clock is capable of smooth cross-fading of the digits. There is a custom library for debouncing buttons. Current software todo: create menu to set the time, date, and other settings such as cross-fade speed, sleep/wake up functions, etc.

Power is supplied through a 12 VDC barrel jack, and it steps up the voltage to 170 volts using the kit from Threeneuron's Pile o'Poo, and it steps it down to 5V for the MCU. Since the clock is designed to be off most of the time, time is kept with a DS1307 RTC, with 56 bytes of NVRAM for config settings.

The code/schematics will be available on github via a GPL3 license.

Crossfade demo:

  • PCB ordered!!!

    Kevin Mossey06/08/2021 at 22:15 0 comments

    I'm skipping over the post I was going to do on timer interrupts to just fawn over the fact that I finally ordered my first ever custom PCBs, which are for this project.  I had to bite the bullet and order the board because I'm designing the body in parallel, and I'm going to need the guts of the clock done and fully assembled before I can finalize the design of the body.  Sent this to oshpark.com, I should have it in less than a month.  While their preview images are purple, I went with the After Dark motif.

    I spent a lot of time working on making it a piece of art - I can see why Steve Wozniak redid the Apple motherboard just to get it slightly better.  This is all through-hole tech, no attempting surface mount soldering for board number 1!  The 8 jumpers at the bottom correspond to the 8 pins on the Arduino I have not yet used.  I know I'll be using 4 of them for signals from the buttons, but which ones exactly I'm not sure of yet, so this gives me the flexibility to get the board made now and figure out the buttons later.

  • Digit fade-in, fade out

    Kevin Mossey05/26/2021 at 14:19 0 comments

    In the last log I talked about having gotten the anode switching working, but the Arduino's built in pw modulation doesn't run at a frequency that is fast enough to actually do a proper crossfade.

    Nevertheless, when not multiplexing (aka direct drive of each digit) the built in pw modulation is enough to fade digits out, switch to the next one, and fade it in.

    The code I used to do this was something like this: (again, recreated from memory after the fact and I haven't debugged it so it might not work).  This would be the replacement of the for loop from the last log.

      for (int x=0; x<9; x++) {
        for (int pw=250; pw>0; pw=pw-25) {
          analogWrite(anode, pw);
          delayMicroseconds(10);
        }
        analogWrite(anode, 0);      // turn off anode before changing digit
        update_tube(x);
        for (int pw=0; pw<250; pw=pw+25) {
          analogWrite(anode, pw);
          delayMicroseconds(10);
        }
        analogWrite(anode, 255);
        while (current_micros - step_start_time < 750)
        {
          current_micros = micros();
        }
      }

    Even though I'm not using this effect in my clock, I think it's beautiful.  Maybe in the next one!  Next up: replacing all the delayMicroseconds() and weird while{} loops with timer interrupts.

  • Crossfade attempt #1 - learning from failure

    Kevin Mossey05/21/2021 at 04:03 0 comments

    Once I got the digits displaying, I wanted to crossfade them.  This was something I had seen people talk about doing, and I saw videos of people successfully doing it, but I couldn't find examples of it being done.  I figured the Arduino had pulse width modulation on some pins, so I thought I could use one of those with the anode and increase the brightness on the new digit and decrease the brightness on the old digit.

    I wanted the bulb to transition over about a quarter second.  The following is just representative of what I originally wrote, which has been long since lost because I didn't have any version control set up yet as I was just trying different things, and not really trying to write a formal clock yet.  

    #define anode 3
    #define A 8
    #define B 9
    #define C 10
    #define D 11
    
    void setup() {
      pinMode(anode, OUTPUT);
      pinMode(A, OUTPUT);
      pinMode(B, OUTPUT);
      pinMode(C, OUTPUT);
      pinMode(D, OUTPUT);
    }
    
    void loop() {
    static int previous=9;
      for (int i=0; i<10; i++) {
        transition_tube(i, previous);
        delay(750);
      }
    }
    
    void transition_tube(int new_digit, int old_digit) {
      unsigned long step_start_time = micros();
      unsigned long current_micros = micros();
      int delay_array[] = {100,200,300,400,500,600,700,800,900};  
      int pw_array[] = {30,60,90,120,150,180,210,240,255};
      for (int x=0; x<9; x++) {
        analogWrite(anode, 0);      // turn off anode before changing digit
        update_tube(old_digit);
        analogWrite(anode, 255 - pw_array[x]);
        step_start_time = micros();
        while (current_micros - step_start_time < 1000 - delay_arr[x])
        {
          current_micros = micros();
        }
        analogWrite(anode, 0);      // turn off anode before changing digit
        update_tube(new_digit);
        analogWrite(anode, pw_array[x]);
        step_start_time = micros();
        while (current_micros - step_start_time < delay_arr[x])
        {
          current_micros = micros();
        }
    }
    
    void updateTube(int val)
    {
      digitalWrite(A, val & 1 ? HIGH : LOW);
      digitalWrite(B, val & 2 ? HIGH : LOW);
      digitalWrite(C, val & 4 ? HIGH : LOW);
      digitalWrite(D, val & 8 ? HIGH : LOW);
    }
    

    There are a few problems with what I originally did here.  What I was trying to do was turn the tube on with the new digit for 0.1ms at a pulse width of about 12%, then turn the tube on with the old digit for 0.9ms at roughly 88%.  But all I got was a hot mess as you can see with the video below, taken in slow motion on my phone.

    I learned a lot in troubleshooting the issue. I had assumed (yes, Mom, I know what happens when I assume something!) that it was working at some magical percentage of the 16MHz clock that was really fast, like in the microsecond range. When I started I didn't know that the Arduino's pulse width modulation through analogWrite() only works between about 490Hz to 980Hz. At it's fastest, though, it can only work to a resolution of 1.0ms, which means that my attempts to drive it at 0.1ms intervals was useless.  It just can't work for what I'm trying to do.  It also explains why the bulb appears to have no fade in or out - it just flickers between the old and new until it "pops" to the new digit. 

    While troubleshooting the awful flickering, I discovered that the digitalWrite() function is slow.  Like really slow.  About 20x times slower than direct port writes.  https://roboticsbackend.com/ has a fantastic explanation and benchmark comparison of doing direct port writes vs using the Arduino functions.  I love the fact that Arduino is easy to get started with, but I really love the fact that when you're ready to get more advanced, you can.

    I think another big problem with my approach was I was trying to replace delayMicroseconds() with my own loop so that I might be able to execute other code instead of freezing my program, but the loop once through took longer to execute than I intended the loop to be, so I couldn't get accurate timings.  

    I benchmarked the mostly-empty while loop (which only updates the current_micros), looping...

    Read more »

  • Driving the tubes, part 2

    Kevin Mossey05/19/2021 at 15:46 3 comments

    IN-14 nixie tube pin layout
    IN-14 nixie tube pin layout

    In the last post I mentioned you shouldn't change the digits of the nixie tube by changing the cathode.  So let's take a look at the anatomy of a tube and one possible method of turning them on/off.  A nixie tube has one anode - this is the positive terminal where the 170V comes from.  It also has around 10 cathodes, depending on the tubes.  By making a complete circuit through the anode and one cathode, you light up that particular digit.

    The IN-14 tube has two extra cathodes beyond the digits 0-9, one for the left decimal point and one for the right.  Other tubes, like the IN-12a or IN-8, only have the digits cathodes.

    There are a number of ways to turn the anode on and off.  A common one you will find online (and also the original kit this project started from) is using an NPN transistor and a PNP transistor together.  The baldengineer.com site has a really good write up on this, which helped me to understand what's going on here.  The takeaway is that this is NOT a Darlington pair - which is what people think two transistors connected like this are.  This is using an NPN transistor as a low side switch (meaning the switch, in this case the transistor, is on the low side of the voltage, after the load has used some of the power) to turn on a PNP transistor, which acts as a high side switch, (meaning the switch is on the high side of the voltage, before the load).

    The big advantage to using this method is that you can electrically isolate the 5V from the Arduino logic from the 170V the tubes need to light up.  Yes, this could be done with MOSFETs, optocouplers, or any of a number of other methods, but the high voltage MPSA42 and MPSA92 transistors I used have a 50MHz frequency, which is >3x faster than the Arduino (16MHz), and the tubes themselves can't really be driven much faster than 10-20kHz or else you get bleed through from previous digits. (Though if you don't care about ghosting, they can be driven REALLY FAST!) 

    NPN transistor driving PNP transistor driving load.


    Since I'm turning on each pair of tubes at the same time, there are two anodes being driven by one switch.  You could easily have one of these circuits for each tube but I was trying to save output pins.  "Logic" is the Arduino digital output, "Low_Anode" is the one's places tube and "High_Anode" is the ten's places tube.  Each tube normally uses only 2.5mA, so there is a current limiting resistor before the tube, though with the multiplexing it's a little higher at around 7-13mA.

    I looked and looked for some simple formulas to calculate the appropriate values of the resistors, but could not find anything. If you know of a good resource for this please leave a comment below.  Ultimately though, I ended up copying the values from the existing circuit because I knew that worked.

    Full disclosure: I'm not an electrical engineer.  I studied some basic circuits in college but it was only one class and then never touched it again until this project.  I copied the circuits I used from what's available online and tried to understand what's happening as best I could.  When I first built this circuit, it didn't work, and I spent days troubleshooting it.  Finally I realized that the transistor datasheet was garbage and it made it look like the order of the pins was backwards when facing the flat side, at least to my newbie eyes.  Once I flipped the transistors around it worked perfectly!  I can now turn off the anode before changing digits!

    Next up: Cross-fade attempt #1 which resulted in failure.

  • Driving the tubes, flipping digits, part 1

    Kevin Mossey05/17/2021 at 13:31 5 comments

    The Russian K155ID1 chip (which is equivalent to the SN74141) is a BCD (binary coded decimal) decoders with a weird pinout.  There are 16 pins, of which 2 are used for power/ground, leaving 14.  This gives you the outputs for digits 0-9 via just 4 inputs, which acting as a binary number gives you 16 possible inputs.  The truth table is easy enough - an input of 0 turns on the "0" output, an input of 1 turns on the "1" output, etc, through to an input of 9 (binary 1001) turns on the "9" output pin.  Values 10-15 as inputs have no output.

    Two warnings about invalid values: First, this blanks the Nixie tube on the cathode side, not the anode side.  If you are going to blank a Nixie tube you should do it by turning off the anode. Second, there is a pair of chips similar to the K155ID1/SN74141 that have similar specs, but the digital inputs 10-15 turn on pins 0-5.  My code is taking advantage of the invalid output to turn off a bulb at the cathode by sending invalid codes - even though I just said you shouldn't do this!  This is to save output pins on the 'duino and it's only for some of the setup pages - so it won't be an issue for very long.  If you come across the 5441A/7441A chips, the setup pages will act funky and you'll need to add more anode high side switches.

    Back to the pinout! Pins 3, 4, 6, and 7 are the inputs, but they don't correspond to binary places the way you might expect in order.  Instead, they are out of order:

    Chip Driver Pin
    3
    4
    6
    7
    Binary position you'd expect:
    2^0
    2^1
    2^2
    2^3
    Or maybe you'd expect this:
    2^3
    2^2
    2^1
    2^0
    ??? But this is how it actually is: ???
    2^0
    2^3
    2^1
    2^2

    My first go I just set up the chip on a breadboard, with jumpers going from digital out pins on the Arduino to the driver chip, and I criss-crossed the jumpers and just turned on pins 8-11 with digitalWrite() and a direct drive to the anode from the 170V power supply (through a 10K resistor!!!) and switched the value by changing the cathode.  Not ideal, but I can be impatient and wanted to see the pretty tubes light up.

    I wrote a simple program which was really something like this:

    #define A 8
    #define B 9
    #define C 10
    #define D 11
    
    void setup() {
      pinMode(A, OUTPUT);
      pinMode(B, OUTPUT);
      pinMode(C, OUTPUT);
      pinMode(D, OUTPUT);
    }
    
    void loop() {
    
      for (int i=0; i<10; i++) {
        digitalWrite(A, i & 1 ? HIGH : LOW);
        digitalWrite(B, i & 2 ? HIGH : LOW);
        digitalWrite(C, i & 4 ? HIGH : LOW);
        digitalWrite(D, i & 8 ? HIGH : LOW);
        delay(1000);
      }
    }

    And here's the video:


  • Powering the tubes

    Kevin Mossey05/16/2021 at 16:27 0 comments

    So the first thing you need with Nixie tubes is a power source capable of creating approximately 170V.  Working with high voltage and electrocuting myself doesn't seem like a good idea, so for this part of my project I'm going to let someone else do the hard work.  

    The HV kit from ThreeNeurons is right up the alley.  It's affordable, configurable to a range of voltages, and ships from the USA (which is where I am).  There is a ton of supporting documentation in case you have issues.  And it comes with pins so I can just put a header on my final board and run it from there!

    To test the power output, I started with a multimeter, but then I wanted to see a bulb light up - so I got one of my IN-8's and built a housing with an old floppy drive ribbon cable with sockets soldered on and drove it through a breadboard directly.  While it's 170V - the current for each bulb is only 2.5mA, which means the power draw is small and the ribbon cable can handle it no problem.  NOTE: Use a 10K resistor in between the 170V source and the anode pin. IN-8's are the same size as the IN-14 but with pins instead of wires and normal 5's instead of upside-down 2's.  They will be used in my next nixie project, where I focus more on the style than the electronics.

  • The beginning

    Kevin Mossey05/16/2021 at 04:47 0 comments

    This log is just the basic background of why of the clock project - for example, why am I multiplexing, or why did I do X?  Feel free to skip this log if you just want the technical details.


    I have wanted to build a Nixie clock for at least 10 years now, and finally got around to it.  The board that holds the tubes is scavenged from a kit from tubehobby.com (the NCV2.1-14), which was a present to my wife from her father.  Unfortunately the kit sat for a couple of years before we put it together - and then it didn't work.  Lacking the knowledge or experience to troubleshoot, we put it in back a box and it sat there for several moves.

    This last March (2021 for those reading years in the future) I finally got it out of it's box and began troubleshooting, and discovered the control board was bad.  Several connections on the board weren't making contact across their respective traces - I don't know if this is because the board was bad to begin with or because I damaged it in the hack job I did soldering.  (I've since gotten better at that!)  Since it was so long since it was purchased, I figured any warranty would be moot, plus I might have been the one to destroy it.

    So I decided this was the perfect time to learn some basic electronics, copy the relevant parts of the circuit, and design my own board.  Also I figured I could write the software since I actually already knew how to do that.


    The clock kit comes with two boards, one for just the tubes, and one for all the control logic.  I tested all the traces and the board that holds the tubes was fine, so I decided to reuse it.  Unfortunately this meant I would have to multiplex my design - the cathodes (each digit of a nixie tube is a cathode) of the tens places are all connected, and the same for the ones place. 

    You control each tube by turning on it's anode.  In the original design this was done with transistors configured as a high side switch.  I've seen many other people do this same technique as well, so I copied that.  The original designer put his schematics on line, so I was able to copy the transistor hss since that was essentially black magic to me when I started this.

    Power conversion isn't really my thing though, so I decided I'd just buy the High Voltage Nixie power supply kit from ThreeNeurons and use that board directly.  Also, I highly recommend reading his page if you want to learn how to make a nixie clock because he has a lot of good information.  Especially if you plan on multiplexing!

    This was also an excuse to design and build my own PCB.  It's something I've wanted to do for a while, so this is a win.  Plus, I plan on building a second clock (I have lots of tubes from years ago not part of any kit), so this project is really just a warm up act!


View all 7 project logs

Enjoy this project?

Share

Discussions

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates