Links marked with a star (*) are Amazon affiliate links that help covering the costs of running the TheVFDCollective.com and keeping this blog ad free!
In this article, we’ll have a look at the PT6311 VFD display driver* and controller and see how to design a power supply circuit for it. Since I have a bunch of AOTOM 20070-1A04 (datasheet) 8 digit 14 segment VFDs I took from a trip to China some time ago, we’ll use the PT6311 to control such a display.
Along with other powerful VFD drivers by the Taiwanese IC manufacturer Princeton, it takes care of multiplexing and dimming of the VFD display, has LEDs outputs and offers the input of up to 12x4 keys and 4 general purpose. That’s a whole bunch of work you’d otherwise all have to time within your main microcontroller. The SPI interface makes it very easy to control with any microcontroller of choice. We’ll use an Arduino Uno* this time.
The article is targeted at those who have knowledge in electronics, as well as VFD displays and are interested in building something very similar. In case you don’t know how VFDs work, I suggest you to have a look at this Instructable first.
I’ve been upside down
Because PT6311 (datasheet) requires the cut off (segment/grid off) voltage to be negative! In fact this is why, for a long time, I was intimidated by the powerful driver. But wait, shouldn’t the VFD display voltage be very high? A teacher of mine once said that voltage is just a matter of perspective. I’ll tell you why it is perfectly applied here. For a VFD display, typically a voltage difference of 20V to 30V between the on and off voltage (and cathode/filament, which needs a small voltage of around 2V itself to generate the flying electrons). But really, all you need is just the voltage difference for the display to properly glow. This can be done by conveniently switching on the anode and grid with the power supply voltage of 5V, and when switching off, it gets pulled down to our negative supply (off voltage), which is 5V - 25V = -20V.
Take me to lower ground
So now we know we want to have a negative voltage for our cut off power supply, let’s design one. If you look into the datasheet of the VFD, the ideal anode/grid voltage is 22V apart from the off voltage. Subtracting this from the positive supply of 5V gives us -17V. This is what we aim for. While we used a positive boost converter to obtain a HV power supply, we’ll just a negative boost converter to get -17V: An LT1931 (datasheet) takes care of this. Designing is as simple as to look into its datasheet, calculating the feedback divider and look for appropriate inductor and capacitor values. Finally, we just replicate the typical application schematics, which is perfect for what we need.
The Filament Supply
Ideally, the filament of the VFD is driven with AC to prevent having a brightness gradient from where the higher voltage of 0V and 2V sits. The datasheet tells that you’ll need 2.4V AC RMS to drive the filament. From our filament, we can two a rectangular pulses with a 50% duty cycle, which will give us an RMS value of roughly 2.5V RMS, and that’s great.
We need to take the two pulses, and push them into the -17V domain. Have a look at the circuit above. It decouples the two phase inverted pulses generated by the LM4871 (datasheet) into zero mean pulses, and re-biases it to -17V with a zener diode in between. The LM4871 itself serves as a pulse generator with self oscillation connected to an H bridge. A zener diode is necessary to counteract unwanted illumination when the off voltage is higher than the bias voltage. I.e. the off voltage has to be slightly negative than the filament voltage.
All on board
As mentioned above, the PT6311 uses SPI to communicate with the outer world, it will use four pins: Data in (MOSI), Data Out (MISO), which in open drain configuration needs a pull up resistor, and Clock (SCK), as well as chip select (SS). The VFD differs between grid and segment pins. The grid pins will be attached to GR pins; the segments will (not fully) occupy the SG pins. Furthermore, two buttons are connected through SW1 and SW2 pins, respectively, and VEE is connected to our negative power supply output.
Have a look at the repository to save yourself time creating a library for PT6311 or the 8 grid 14 segment display. It also contains the PCB design in Eagle, putting it all together. The PCB measures 95mm x 25mm, and is part of a project that will be revealed later this year. How exciting!
Creating a PT6311 Arduino Driver
Finally, it’s time to talk about how exactly we want to communicate with PT6311, for that we want to write a library (well, a driver is more accurate, since it contains the lowest level functions only) for Arduino. We won’t be doing it in a classical sense, which is using the object oriented approach to create a class PT6311, but will just use plain functions for the sake of compatibility to upper layers, that will be written in plain C. According to the PT6311 datasheet, we differ between command, and display data:
A command can be one of four different types. The first two most significant bits tell what command it is, be it configuring how many digits and segments it has, read switch, write display mode or turning the display on, off or dimming it
When in increment address mode, the display data can follow consecutively after setting the base address using command 3. This is what we’ll do by default
We can see that it makes sense to have a basic function we can build everything upon, which simply transfers one byte to the PT6311 using the Arduino SPI library:
void _vfdco_pt6311_set_data(uint8_t data) { digitalWrite(VFDCO_PT6311_SS_PIN_ARDUINO, LOW); SPI.transfer(data); digitalWrite(VFDCO_PT6311_SS_PIN_ARDUINO, HIGH); }
The commands will consist of the command type OR’d with the actual command, which can be stored inside an enumeration or using macros. This is how a typical command can look like using or set data function:
_vfdco_pt6311_set_data( (uint8_t)VFDCO_PT6311_COMMAND_2 | (uint8_t)VFDCO_PT6311_OP_MODE_NORMAL | (uint8_t)VFDCO_PT6311_ADDR_MODE_INCR | (uint8_t)VFDCO_PT6311_RW_MODE_WRITE_DISPLAY );
Now the display data transfer can be put right after the configuration command. Since we’re sending consecutive bytes, we don’t want to use the set data function. Instead, we transfer four times: The address, where the multiplication by 3 takes you to the address of the digit position, followed by the 3 bytes of raw display data.
digitalWrite(VFDCO_PT6311_SS_PIN_ARDUINO, LOW); SPI.transfer((uint8_t)VFDCO_PT6311_COMMAND_3 | (digit_pos * 0x03)); SPI.transfer((uint8_t)(data )); SPI.transfer((uint8_t)(data >> 8)); SPI.transfer((uint8_t)(data >> 16)); digitalWrite(VFDCO_PT6311_SS_PIN_ARDUINO, HIGH);
Finally, there is only the special case left, where we would like to request data from the PT6311. We will see how this is done by asking for the bits of SW1…SW4:
uint8_t vfdco_pt6311_get_sw() { digitalWrite(VFDCO_PT6311_SS_PIN_ARDUINO, LOW); SPI.transfer( (uint8_t)VFDCO_PT6311_COMMAND_2 | (uint8_t)VFDCO_PT6311_OP_MODE_NORMAL | (uint8_t)VFDCO_PT6311_ADDR_MODE_INCR | (uint8_t)VFDCO_PT6311_RW_MODE_READ_SW ); uint8_t sw_in = SPI.transfer(0xFF) & 0x0F; digitalWrite(VFDCO_PT6311_SS_PIN_ARDUINO, HIGH); return sw_in; }
Level up!
What do we have so far? We have written a driver, which is able to send bytes, more specifically, bit patterns which PT6311 will pick up and interpret it as turning on and off the segments. So if we want to transfer the capital letter ‘A’, we need to align the bits so that the 8 digit 14 segment display (datasheet) turns on exactly those segments that are needed for an A. When using the send data function from above, it might look like this:
vfdco_pt6311_set_data(0, 0b0100001111110001);
Of course it doesn’t have to. We can comfortably save the ones and zeros into an array, and map it to the ASCII character map. While normally hand crafting the array is a time consuming, cumbersome process, you can feel super lucky that I have done it already, and you can simply make use of it! Yay! This is why it’s called level up. Instead of getting dirty with bits, you can simply use a higher level of abstraction and send characters, or even strings instead. And this is what the self explaining functions are for:
void vfdco_8d14s_write_char(uint8_t digit_position, char character); void vfdco_8d14s_write_string(char *text);
There are two more functions, finally, that deserve the attention for the last part of this little article. These are the write with overlay variants of write char and write string. Write string is more important:
// Multi bit overlay 0b[0|0|0|DPL|DPR|COL|COC|COR] void vfdco_8d14s_write_string_with_overlay(char *text, uint8_t overlay);
If you look at the display, you’ll find that it has an upper dot after the second digit, and symmetrically a lower dot after the sixth; and between 2 and 3, 4 and 5 as well as 6 and 7 there are colons. To turn on these, simply make use of the overlay parameter. To turn on the upper left dot and the center colon, the parameter would look like 0b00010010.
Have a happy time!
GitHub Repository
As always, the code is provided to you freely on GitHub. Have a happy time. The PCB files can be downloaded here: