I’ve had this Vacuum Fluorescent Display – VFD recovered from a broken DVD player in the bits box for quite a while. I shall turn it into a clock and have it display the date at the press of a button, it will also set its time using the internet and the Network Time Protocol over a WiFi connection, I’ll be using a Teensy 3.1 Ardunio compatible micro-controller as this is compact and with the addition of a crystal and button battery has a clock built in.

This project is a complete replacement of the logic and driver that came in the DVD player, I have also used general electronic components as these are what I have available: 74HC595 8-Bit Shift Registers, ULN2803A Darlington Arrays and PNP transistors, rather than dedicated VFD driver chips, such as the MAX6920AWP+, Philips NE594N or the TI SN75518N available from eBay. If I were undertaking this again I would use a dedicated driver.
How A Vacuum Fluorescent Display Works
The VFD is made up of three layers, starting at the back these are:
- The Anodes – these are elements of your display that illuminate
- The Grid – to control a block of Anode elements
- The Cathode – also referred to as Filaments or the Heater

“The filament is heated, which causes it to release electrons, a process called thermionic emission. Since electrons are negatively charged, if there is a nearby piece of metal with a electrical charge more positive then the electrons from the cathode, the electrons will be attracted to it, allowing a current to flow.
The grid is positioned between the Anode and Cathode. If the grid is driven more negative than the cathode, it repels the electron cloud, which prevents any current from flowing. Since the grid is not heated, it does not emit any electrons itself.
A VFD is basically triode, except the anode is coated with phosphor. Therefore, when the the anode is more positive then the cathode, the free electrons in the cathode’s electron cloud flow towards the anode, and in the process strike the phosphor, exciting it.” Connor Wolf on stackexchange.com
The display brightness is set by the difference in voltage between the Cathode and Anode. The Cathode filament should be set to a low voltage, no more than 4 volts as it is made from thin tungsten wires which can melt very easily. The Anode uses a higher voltage around 12 to 15 volts.
Multiplexing is used to display the output. Each grid controls a fixed number of elements, the element connections are common to each grid. For a clock you will need to loop between the grids selecting the correct elements to display before moving onto the next, the persistence of vision effect maintains an illusion of a complete display.
Connecting and testing your Vacuum Fluorescent Display
You will need to find the connections that your VFD uses as well as the best voltages to supply. Unless you are really lucky its unlikely you will find a datasheet for your display, so a little reverse engineering is required.
A selection of test hooks are very useful at this stage. You will also need two power supplies, one low voltage for the Cathode filament, I use 3.3 volts supplied from the Teensy/Arduino. For the gates and Anodes a variable DC supply you can adjust from 10 to 20 volts preferably with the current limited to 1mA, in some cases displays from older equipment will need a higher voltage, 50V and above. The ground on both your power supplies will need be connected together.
The flat VFD’s you see in consumer electronics, such as the DVD player, all have a similar layout. The two pairs of outer pins connect to the Cathode and the pins between these divide into two blocks one side will be for the grids and the other for the Anode elements.
First, establish that the pins you suspect are for the filament are indeed so, with your multimeter in continuity (beep) mode you should see a connection when you probe across these pins. Connect your 3.3v supply to these pins, it doesn’t matter which way round.

The following connections should be made:
- 3.3 volts across the Cathode filaments (the red and black, above).
- Ground on the 3.3 volts is shared with the power supply.
- Two probes connected to the positive on the power supply for connecting to one of the Grids and one for connecting to a Cathode (white and green).
Next, set your variable power supply to its lower setting and with your positive power supply probes attach one probe to a Grid pin, and the other to an Anode element, on my display I started with a pin furthest left and another furthest right, see if anything lights up, at a low voltage this will be rather dim. If an element has lit up has then increase the voltage until the brightness is what you would expect. If nothing lights then first check you have connected a grid and an element not two grids or two elements by choosing different pins. Or if you are reasonably sure then carefully increase the voltage.
When you are driving the display as a clock, the multiplexing will make each element appear dimmer I increased the display voltage to 15 volts to fix that.

Now you can map out the grids and elements, on mine, there are eleven grids the first and last grids are for special characters and the rest contain digits. With a Grid connected, go through each element and make notes, each element will have the same connection on each grid, so all the digit elements and special characters/icons have the same pins.

Driving the Display
While the Cathode filaments are permanently on at 3.3V the 12V grid and Anodes require some kind of high voltage level shifter to have the 5V logic output from the Ardunio (or 3.3V logic on the Teensy) switch the 12V required at the display. The method I have used for switching is a NPN, PNP complimentary (Sziklai pair) output.

The NPN transistor is the switch controlled by the Ardunio this in turn switches the PNP transistor, the NPN transistor is being used to isolate the Ardunio from the high voltage required for the display. As the current being drawn is very low we only need small signal transistors NPN: BC549 and for the PNP: BC556.
For the PNP transistor to switch off the Base voltage needs to be close to that of the Emitter, as the Ardunio’s 5V logic is nowhere near the 12V used a NPN stage is added so when the Base of the NPN is on this pulls the Base of the PNP low and allows current to flow to the display. There are three resistors, R1 100K limits the current to the base of the NPN transistor to protect the transistor and Adrduino, R2 10K is biasing the output, working as the bottom half of a voltage divider, and R3 10K is both the top half of the voltage divider and pulls the PNP Base high keeping it off when not required.
Transistors as switches, further reading:
- Transistors: Switches
- High Side Switching
- High Side PNP Transistor Switching
- Using PNP Transistors to Switch Higher Voltage Loads
To reduce the component count and size of the project I have replaced the NPN transistors and the resistors R1 and R2 with ULN2803A Darlington transistor array, however the PNP transistor remains as the display requires a sinking output to provide a grounded connection to the load through the cathode.

Connecting to the Arduino
The next stage is to connect the 32 pin display to the Arduino. Obviously the micro-controller does not have enough I/O for this, so instead I have used four easy to use 74HC595 8-Bit Shift Registers with only a data, clock and latch to set up, they can be used to extend the number of output pins on the Arduino.

I have used the ShiftOutX library for my clock, but it helps to look at the Ardunio’s ShiftOut tutorial to see how they work.
Power
To power this Digital Clock I am using a mains to 12V DC brick from some old electronics equipment, I then use a Buck power supply to provide a 5 volt supply for the Teensy and electronics, and for the display a Boost supply to bump the 12V to 15V, search for XL6009 Module on ebay, check that it has the XL6009 rather than the older LM2577 and set the output voltage before connecting the display.

The Driver Circuit
Here is a quarter of the driver circuitry, for the 32 pin display I made four of these. You can see that there is an extra transistor, as the Darlington Array has seven inputs/outputs and also note that on the 74HC595 8-Bit Shift Register the Ardunio data pin connects to DS (pin 14) and the next register in series connects to to Q7S (pin 9) of the previous register.

Software
This demonstration uses the ShiftOutX library. It loops through each grid and each element within that grid, it does not use multiplexing.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
#include // http://playground.arduino.cc/Main/ShiftOutX (version 1.0) #include #define VFD_CLOCK 18 #define VFD_LATCH 17 #define VFD_DATA 16 #define MONITOR_LED 13 shiftOutX regOne(VFD_LATCH, VFD_DATA, VFD_CLOCK, MSBFIRST, 4); // these contain the 0's and 1's used by the registers to indicate LOW or HIGH. // after setup VFDblank is copied to VFDout, VFDout is modified, only the required // 74HC595 register pins are set high. char VFDout[33]; char VFDblank[33]; // stick the ShiftPins used by ShiftOutX into an array that matches the four 74HC595 registers static const uint32_t shPins[32] = { shPin1, shPin2, shPin3, shPin4, shPin5, shPin6, shPin7, shPin8, shPin9, shPin10, shPin11, shPin12, shPin13, shPin14, shPin15, shPin16, shPin17, shPin18, shPin19, shPin20, shPin21, shPin22, shPin23, shPin24, shPin25, shPin26, shPin27, shPin28, shPin29, shPin30, shPin31, shPin32 }; // as the display pins are not in the same numeric order as the 74HC595 registers // this maps the pins on the VFD display to the bits used by the registers. // The display pins are the array index, ignore the first element in the array (VFDlookup[0]) // x 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32 // | chip 1 | chip 4 | chip 2 | chip 3 static const int VFDlookup[33] = { 0, 0, 1, 2, 3, 4, 5, 6, 7,24,25,26,27,28,29,30,31, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23 }; // turns the 74HC595 register outputs on or off as required void outputToVFD() { for (int i = 0; i < 32; i++) { if (VFDout[i] == '1') { Serial.print("1"); regOne.pinOn(shPins[i]); } else { Serial.print("0"); regOne.pinOff(shPins[i]); } } } void setup() { delay(1000); Serial.begin(9600); Serial.println("ready"); pinMode(VFD_CLOCK, OUTPUT); pinMode(VFD_LATCH, OUTPUT); pinMode(VFD_DATA, OUTPUT); pinMode(MONITOR_LED, OUTPUT); regOne.allOff(); delay(1000); // setup VFDblank with zeros for (int i = 0; i < 32; i++) { VFDblank[i] = '0'; } VFDblank[33] = '\0'; digitalWrite(MONITOR_LED, LOW); } void loop() { for (int grids = 0; grids < 12; grids++) { strcpy(VFDout, VFDblank); VFDout[VFDlookup[grids]] = '1'; if (grids % 2 == 0) { digitalWrite(MONITOR_LED, LOW); } else { digitalWrite(MONITOR_LED, HIGH); } for (int element = 12; element <= 32; element++) { VFDout[VFDlookup[element]] = '1'; Serial.print(element); Serial.print("\t"); Serial.print(VFDlookup[element]); Serial.print("\t"); outputToVFD(); Serial.println(" "); delay(100); } Serial.println(" "); } } |
This second demonstration counts from 0 to 9999, with the digits right aligned on the display, it uses multiplexing and the display will appear dimmer than before:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
#include // http://playground.arduino.cc/Main/ShiftOutX (version 1.0) #include #define VFD_CLOCK 18 #define VFD_LATCH 17 #define VFD_DATA 16 #define MONITOR_LED 13 shiftOutX regOne(VFD_LATCH, VFD_DATA, VFD_CLOCK, MSBFIRST, 4); // these contain the 0's and 1's used by the registers to indicate LOW or HIGH. // after setup VFDblank is copied to VFDout, VFDout is modified, only the required // 74HC595 register pins are set high. char VFDout[33]; char VFDblank[33]; char VFDgrids[11][33]; unsigned long previousMillis = 0; unsigned long millisPause = 500; // update the number every 500 millis int number = 0; int maxNumber = 9999; int previousNumber = 1; // stick the ShiftPins used by ShiftOutX into an array that matches the four 74HC595 registers static const uint32_t shPins[32] = { shPin1, shPin2, shPin3, shPin4, shPin5, shPin6, shPin7, shPin8, shPin9, shPin10, shPin11, shPin12, shPin13, shPin14, shPin15, shPin16, shPin17, shPin18, shPin19, shPin20, shPin21, shPin22, shPin23, shPin24, shPin25, shPin26, shPin27, shPin28, shPin29, shPin30, shPin31, shPin32 }; // as the display pins are not in the same numeric order as the 74HC595 registers // this maps the pins on the VFD display to the bits used by the registers. // The display pins are the array index, ignore the first element in the array (VFDlookup[0]) // x 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32 // | chip 1 | chip 4 | chip 2 | chip 3 static const int VFDlookup[33] = { 0, 0, 1, 2, 3, 4, 5, 6, 7,24,25,26,27,28,29,30,31, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23 }; // pins on the display used for the grid: VFDgridPos and the digits: VFDdigitPos static const int VFDgridPos[11] = { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; // pins on the display static const int VFDdigitPos[17] = {15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30}; // pins on the display // not really needed for 0 - 9, but used when extending the display to use the alphabet static const char VFDdigitsLookup[10] { '0','1','2','3','4','5','6','7','8','9' }; // VFDdigits - which elements need to be illuminated to display the chosen number // pins on the display array index position // 29 28 15 14 // ------- ------- ------- ------- // 30 | \ 26| / | 24 16 | \ 12| / | 10 // | 27\ | /25 | | 13\ | /11 | // | \ | / | | \ | / | // 22 ------- ------- 23 8 ------- ------- 9 // | / | \ | | / | \ | // | 20/ | \18 | | 6 / | \4 | // 21 | / 19| \ | 17 7 | / 5| \ | 3 // ------- ------- ------- ------- // 16 15 2 1 // // 1234567890123456 static const char VFDdigits[10][17] = { "1110001001000111", // 0 "0010000001000000", // 1 "1100001111000110", // 2 "1110000111000110", // 3 "0010000111000001", // 4 "1110000110000111", // 5 "1110001110000111", // 6 "0010000001000110", // 7 "1110001111000111", // 8 "0010000111000111", // 9 }; // turns the 74HC595 register outputs on or off as required void outputToVFD() { for (int i = 0; i < 32; i++) { if (VFDout[i] == '1') { regOne.pinOn(shPins[i]); } else { regOne.pinOff(shPins[i]); } } } // find all the 1's in VFDdigits[digit] string and update VFDout // use VFDlookup to place the display pin into the correct position // for the registers void insertDigit(int d) { for (int i = 0; i < 16; i++) { if (VFDdigits[d][i] == '1') { int p = VFDlookup[VFDdigitPos[i]]; VFDout[p] = '1'; } } } // the number is split in to its individual digits, then starting with the right most // digit shown on the display in a right aligned format with leading zeos void VFDshowDigits(int number) { int gridPos = 9; // output some info to serial once every number boolean showNumber = false; if (number != previousNumber) { showNumber = true; Serial.print(number); previousNumber = number; } //extract the last digit using modulus and division //loop through the digits in the number for (byte i = 0; i < 4; i++) { int digit = number % 10; number = number / 10; strcpy(VFDout, VFDgrids[gridPos]); // get a blank record for the chosen grid insertDigit(digit); // update VFDout with the VFDdigits data if (showNumber == true) { Serial.print("\t"); Serial.print(digit); Serial.print(" : "); Serial.println(VFDout); } outputToVFD(); // display the digit delayMicroseconds(2000); strcpy(VFDout, VFDgrids[gridPos]); // blank the grid to reduce ghosting outputToVFD(); gridPos--; } if (showNumber == true) { Serial.println(" "); } } void setup() { delay(1000); Serial.begin(9600); Serial.println("ready"); pinMode(VFD_CLOCK, OUTPUT); pinMode(VFD_LATCH, OUTPUT); pinMode(VFD_DATA, OUTPUT); pinMode(MONITOR_LED, OUTPUT); regOne.allOff(); delay(1000); // setup VFDblank with zeros for (int i = 0; i < 32; i++) { VFDblank[i] = '0'; } VFDblank[33] = '\0'; // setup the VFDgrids array to contain the grid positions for (int i = 0; i < 11; i++) { strcpy(VFDgrids[i], VFDblank); int gridPos = VFDlookup[VFDgridPos[i]]; VFDgrids[i][gridPos] = '1'; } digitalWrite(MONITOR_LED, LOW); } void loop() { VFDshowDigits(number); if (millis() - previousMillis > millisPause) { Serial.println(number); number++; previousMillis = millis(); } if (number > maxNumber) { number = 0; } if (number % 2 == 0) { digitalWrite(MONITOR_LED, LOW); } else { digitalWrite(MONITOR_LED, HIGH); } } |
I’ve been looking at some info on how to drive a VFD and you’re the first site that offers a complete comprehensive package of the damn thing.
So thank you!
Hi friend, I’d like your help, kindly!
I have this VFD Display here: https://www.ebay.com/itm/Samsung-Temp-Cook-Time-SVM-06ME08-Vacuum-Fluroescent-Display-Tube-Part-M64-/371194582804?_ul=BR I would like to use it with a SN75518N and an Arduino to make a Clock. The 25 pins, from right to left are: pins 1-2 GND of Filaments; pins 3-16 are of the Anodes; pin 17 not connected; pins 18-23 are from Grids; pins 24-25 are 3.3v of Filaments. I would like to know what sequence I connect these pins in the SN75518N and how I define those pins in the Arduino sketch. Thank you
Daniel
The connections from the display to the SN75518N should be the most convenient for your PCB design.
In your software you need to an array that maps to the pins on the display driver – in my software have a look at VFDlookup[33]. then I have used VFDgridPos for the anodes and VFDdigitPos for the cathodes. The function VFDshowDigits outputs to the display.
Greetings Karl! First, thank you for the response.
The sketch I have is on the following website: https://www.instructables.com/id/Arduino-VFD-Display-Clock-Tutorial-A-Guide-To-VFD-/, in Step 7: VFD Clock – the Arduino Software (VFD7Segment.ino). The author is using discrete transistors but I would like to use the SN75518N instead. My display is similar to the author’s (small) display, with 4 digits and colons. I would like to know what I should change in the code to use the SN75518N; If you can help me, I thank you very much. If you prefer, you can reply in my email (meuviolino@hotmail.com)