A Simple Nixie Display Driver
Arduino Version

Caution! this project involves high voltages which can be lethal. Do not attempt to build this, unless you are experienced working with these voltages. Proceed at your own risk.

I’ve received a number of comments from people who were interested in building my simple low parts count Nixie display, but were not comfortable working with PIC microcontrollers, or having to buy the programming hardware for them. Since speed is not a concern for interfacing with the high voltage driver IC, an Arduino is a practical alternative, and can be programmed with nothing more than a USB cable. I had some inexpensive Arduino Pro-mini clone controller boards on hand, and wrote a program for controlling my 3½ digit Nixie display described on the above referenced page. To test it out, I simply removed the PIC controller from the display board, and connected three Arduino digital output lines and a ground to the empty socket. Otherwise, the driver electronics remain the same. The test setup is shown in the photo above. The connections between the Arduino and the MAX6922 (or older Allegro A6818) are as follows:

Note, there is nothing special about using Arduino digital output numbers 10, 11 and 12. Any three digital outputs may be used by simply changing the pin assignments in the program code.

I have created two Arduino sketches. The first is a simple counter that starts at 0, counts up by itself to 1999, then resets to 0 and repeats indefinitely. The second reads Analog input A0, scales it to the range 0..1999 and sends it to the display, essentially a simple Nixie voltmeter. The sketch files are here:

Download Nixie Sketches

These programs are extremely simple, but form the basis for more advanced functionality. Since the HV driver IC’s can be daisy-chained to drive an unlimited number of Nixies with no additional wiring to the Arduino, the software provides for this option. It's only necessary to change the value of one constant nNixies, to match the number of Nixies being controlled.

Although I mentioned above that the only hardware required for programming an Arduino is a USB cable, there are some inexpensive Arduinos that don’t have USB capabilities, and therefore require an additional USB/Serial adapter for programming. The Arduino Pro-Mini, that I used for this project, is one that doesn’t have USB capabilities. So, take care to get the controller that best suits your needs. If you choose to use a separate USB/Serial adapter, the one available from Sparkfun is one of the most popular.

The schematic used for the prototype can be downloaded from this link:

PIC Arduino version schematic

Having been warned about the dangerous voltages present in this circuit, you’ll not only need to take appropriate precautions to protect yourself, but also to avoid costly wiring errors. I strongly recommend using sockets for the HV driver IC and the Arduino. That way, the circuit can be initially powered up for voltage checks, without these chips in place. Carefully, check all wiring for errors before applying the high voltage. Then, when it’s confirmed that there are no wiring errors, power the circuit without the HV driver IC plugged in and without the Arduino connected. Using a voltmeter, make sure that there are no high voltages present on any Arduino connections or driver IC pins other than the HV output lines Out00..Out31, or the VBB anode supply. Make special note that on the MAX6955 the VBB pin is immediately adjacent to the VCC pin. A short between these will put 60 or more volts on the VCC line, and destroy the driver IC and the Arduino.

Although the Nixie anode supply is 150 volts, the Nixies will drop approximately 100 volts. Voltage drop varies slightly from digit to digit within the tube depending on distance between each cathode and the anode, and also depending on which other digits may be illuminated at the time. There should never be more than about 60 volts at the cathodes. If wired correctly, none of the pins on the HV driver IC will see more than this value. The MAX6922 is designed to handle up to 76 volts which is higher than the rating of the old 7441 & 74141 TTL Nixie driver IC’s. If you see 150 volts on any pin of the HV driver IC socket, there is definitely a wiring error.

Note that the MAX6922 is available only in surface mount packages. The PLCC44 version is the most convenient for hobbyists, because PLCC44 sockets are available. There are also PLCC44 breakout boards available as shown in the photo below.

These breakout boards adapt the driver IC to a set of standard 0.1 inch spaced pins, equivalent to the pinout of a 44 pin dual inline IC. These breakout boards are available from several sources online. However, before purchasing these, make sure that all 44 IC connections are brought out to pins. Some PLCC44 breakout boards are intended for use with ICs that use only 40 of the 44 IC connections (such as certain PIC microcontrollers) and consequently have only 40 pins, making them unsuitable.


In the earlier PIC based project, I expected that if anyone decided to build the project, there wouldn't likely be any desire to modify the Assembly Language program code. Accordingly, I didn't provide any description of how the program worked aside from providing the source listing. Since the C source code is provided in the linked sketch files and is easier to follow, there's a reasonable likelihood that users will modify it for different applications.

Although the A6818 and MAX6922 are functionally the same, and have the same pinout, the A6818 datasheet numbers the shift register positions from 1 to 32, while the MAX6922 datasheet numbers them from 0 to 31. For the following discussion, I'll use the MAX6922's 0..31 numbering.

The MAX6922 is a 32 bit serial in, parallel out shift register. Data is clocked in one bit at a time. I'll refer to the shift register stage outputs as Q0..Q31. The state of the shift register bits are not transferred to the outputs until the latch input is toggled high then low. This allows even an extremely slow processor to transfer all 32 bits of data without causing any display flicker. All HV outputs will change at the same time, when the latch input is toggled.

Each new bit is clocked into position Q0, with Q0's previous state shifted to Q1, Q1 shifted to Q2, and so on down the line. After 32 clock pulses, the first bit clocked in is now at position Q31, and the last bit is at Q0. It's important to remember this order; it's easy to get it backwards. Because the Nixies in the prototype are connected with the least significant digit to the lowest data outputs, it means that the data for the most significant digit must be clocked in first, then the 2nd most significant, and so on, with the least significant digit being the last.

Before getting into further detail, it's important to clarify a point of terminology: the difference between a numeral and a digit. A 'digit' corresponds to one Nixie tube which contains a collection of the 10 different numerals 0..9. A digit refers to a physical position in a display: the ones, tens, hundreds, thousands, etc., while a numeral refers to the particular symbol being displayed at a given digit position.

The program uses two nested for{} loops to send the output data. This is a slightly simplified version of the code:

for (int i=nDigits-1;i>=0;i--) { for (int j=0;j<10;j++){ nixBitOut((reRoute[myDigits[i]]!=j)?1:0); } } nixPush();

The outer loop counts the number of digits. Since this prototype uses a 3 digit display, the outer loop repeats 3 times. The inner loop counts the numeral positions for each Nixie. Thus, the inner loop repeats 10 times for each digit. If the Nixie cathodes are connected to the driver outputs in decreasing numerical order, then to turn on a certain numeral, it's only necessary to check to see if the value of loop counter j is equal to the desired numeral value. If it is, then clock out a zero; otherwise clock out a one. If the cathodes are connected in the opposite order, it's almost as simple. Just check to see if the desired numeral value is equal to (9−j). If true, clock out a zero, otherwise a one.

The function nixBitOut() performs the task of clocking out the bit: a zero or one depending on the value of its argument. The final line in the code, nixPush(), is a subroutine that simply toggles the latch input of the driver IC to send all of the shift register data to the parallel HV outputs updating the display.

Many Nixies have the cathodes connected to the tube pins in either ascending or descending order. But there are some where the order is non-sequential. The Russian IN-16's that I used in this project are an example of non-sequential pinout. In order to avoid the need for convoluted circuit board traces, it's much easier to connect the Nixie pins to the driver IC by pin order, so that no crossovers are required. This wiring arrangement is shown in the following diagram.

For viewing, the IN-16 is oriented so that the position between pins 7 and 8 faces the user. The cathode connections then run back around both sides of the tube to the driver IC. This leaves the anode connection in the middle of the cathode connections. The anode supply can be routed on the opposite side of the board to that of the cathodes to avoid wiring difficulties.

To handle the non-sequential numeral arrangement in the program code, a 10 element reRoute array is provided. Essentially, it's a lookup table giving the number of bit positions from the start to the specified numeral cathode. The contents of the reRoute array for the IN-16 implementation is {5,4,8,2,1,0,9,3,7,6}.

Here's how it works. The myDigits array contains the desired numerals for each Nixie. Suppose we wish to display the number 750. The array myDigits will contain {0,5,7}. (The least significant digit is in array element zero.) Since we need to send the most significant digit first, the outer loop counts in reverse order from 2 down to 0. Thus, the first numeral to be loaded will be the 7. From the above diagram we see that we need to set OUT6 low and the other nine bits high.

Since the bits are clocked into the shift register in descending order 9876543210, we have to clock out the bits 1110111111 to display a 7. We see that element 7 in the reRoute array is a 3 (array element numbers start at zero). Therefore, when the inner loop counter variable j is equal to 3 we clock out a zero bit. For all other values of j, we clock out a one bit. Similarly, for the next digit we need to turn on numeral 5. So we need to clock out the bit pattern 0111111111. Element 5 in the reRoute array is 0. Thus, when j is zero we clock out a zero bit and a one bit for all other values of j. Finally, we need to set the least significant digit to 0. We see that element 0 of the reRoute array is 5. So, we clock out the bit pattern 1111101111.

For different Nixie pinouts the reRoute array values can be changed to suit. However, it is assumed that all Nixies in the circuit will have the same connection order. Otherwise, the rerouting code becomes more complex.

At times, it may be desirable not to display any numeral in one or more digit positions. For example, we may wish to blank leading zeros. To do this, simply set the value of the corresponding element of myDigits to a value greater than 9.

Two other details remain to be discussed. First, in the prototype circuit, output OUT20 is connected to a colon lamp, interrupting the sequence of Nixies digits. In retrospect, this was not the best design choice. To deal with this, an additional line of code is added in the outer loop of the program:

for (int i=nDigits-1;i>=0;i--) { if (i==1) nixBitOut(1); //skip past colon position. for (int j=0;j<10;j++) { nixBitOut((reRoute[myDigits[i]]!=j)?1:0); } } nixPush();

The if statement checks to see if the current digit number is 1, and if so, it clocks out a single bit to skip past the colon. For new applications, I recommend not inserting miscellaneous outputs between the digits. These can be handled as described in the following paragraph.

The remaining detail is that each MAX6922 controls 32 bits, not 30. So, we have two bits left over after setting the three digits. If we daisy-chain more drivers, each one will add an additional two extraneous bits. We may accumulate up to 8 extra bits if we daisy-chain four drivers. (If we daisy-chain multiples of five, then we get a full digit, and there are no extra bits left over.) These extra bits can be used to control things such as the most significant ‘one’ digit neon lamp—the half digit in this 3½ digit display—or decimal points or colons. These outputs are controlled by the bit values of the byte variable miscBits. These are clocked out before any of the Nixie digits, so that they end up in the highest output positions. If there are fewer than 8 extra outputs, the excess bits simply disappear out the end of the shift register. The code for this is straightforward, and can be found in the sketch files.

Back to:
This page last updated: April 4, 2023
Copyright 2019, 2023, Robert Weaver