Prototype VFD Driver Tested With Placeholder LED

PIC16F18345 VFD driver PCB

Once I had assembled our first prototype vacuum fluorescent display (VFD) driver circuit board, it’s tempting to connect it right up to our salvaged VFD and bask in its glow. But that would have been premature: there were bugs still to be ironed out with potential for fatal errors to damage or destroy our one and only salvaged VFD.

The first tests were what we used to test our bread board prototype: drive a 4-digit 7-segment LED, a Lite-On LTC4627-JR from my earlier PIC display driver project. From there I could verify 8 of 11 segments on this driver board functioned as expected by a demo program that constantly flips between two patterns, one spells “Hello” and the other “Ahoy”.

I then tested the I²C capability with a small update, changing the second pattern from “Anoy” to a very mutilated “MLE”. (It’s hard to do “M” on 7 segments.)

These experiments exposed a few minor bugs, just as tests were supposed to. After they were fixed I expanded my test with a second LTC4627-JR for eight total segments. I also expanded my use of I²C by continuously updating all digits from Raspberry Pi to create a text marquee. This experiment exposed some timing issues that is visible as a slight lag just as the “u” in “thank you” came up on screen.

That lag was diagnosed to my code inside a timer interrupt service routine (ISR). On a simple chip like this PIC, a hardware interrupt signal could not interrupt another ISR already in progress. So when my code inside a timer ISR grew beyond a certain point, it started interfering with timely response to hardware interrupts necessary for I²C communication. The solution is to put my timer ISR on a severe diet, moving almost all of its bulk elsewhere so that I²C handlers could run with minimal interference.

Once the software problems were sorted out, I started experimenting with the flexibility given by this project’s design decision to keep PIC code simple. It meant I could play with patterns that have nothing to do with displaying letters or text. I decided to try a pattern that keeps a single lighted segment running through the display in a figure 8. When cycled through all digits like a text marquee, it gave us a neat looking wave. I look forward to more experiments in driving a multi-segmented display in unusual ways.

Assembling Prototype VFD Driver PCB

PIC16F18345 VFD driver PCBIn addition to exploring the idea of aggressively packing chips densely, there were a few other design considerations in building our prototype driver PCB.

Why I²C?

When I was tearing my hair out trying to figure out why a tried-and-true piece of template code has stopped working, I was sorely tempted to move to some communication protocol other than I²C… good old TTL Serial always looks good whenever I run into a problem.

The answer is voltage compatibility: I want my driver board to be capable of running at either 3.3V or 5V, which is easy to do with an old 8-bit chip like the PIC16F18345 I’m using: give it power anywhere in its specified range (and probably a bit beyond that range) and it’ll happy run. But this doesn’t necessarily apply to whatever my driver board will accept commands from. Fortunately, I²C was designed from the start to accommodate devices that work off different VCC levels. So something like a Raspberry Pi (3.3V) can communicate with my PIC. (5V).

Pin Assignments

In addition to moving the decoder output pins so it could be placed immediately adjacent to my PIC, I also took advantage of my particular PIC’s feature of Peripheral Pin Select (PPS) by moving the I²C pins (handled by Master Synchronous Serial Peripheral – MSSP) from their default to RA4 & RA5 for easier routing on the PCB and easier data writes in my code.

Pin Isolation

This is the first time I planned to use pins RA0 and RA1 on a PIC16F18345 project. I usually avoid them because they are used as in-circuit system programming data (ICSPDAT) and clock (ICSPCLK) pins. They’re perfectly usable outside of this scenario, but they must be disconnected from the rest of the circuit during programming. In this case, it meant I had to put in two jumpers that are removed during programming. The jumpers are installed exactly where my PICkit 3 programmer would attach, so there’s no way for me to forget to remove them when reprogramming this chip.

Wires From CAT-5E Network Cable

Even with all these concessions to easier routing on a prototype PCB, there will still be an unavoidable nest of wires. In order to keep things tamed, I harvest my spool of CAT-5E network cable for wires that are thin and rigid. Thin wires help me fit more wires in a small volume, and rigid wires stay where I’ve put them. In addition to being affordable and easily available, the four twisted pairs of wires give me eight different insulation colors to help me keep track of which wire goes where.

Chip Packing Experiment On Prototype VFD Driver PCB

While we were building a breadboard prototype for our VFD driver, we weren’t terribly concerned with chip layout as it was largely constrained by the practicalities of a bread board anyway. Once we start thinking about transferring it to a PCB, however, we had more flexibility to be creative. The prototype printed circuit board is a grid of through-holes that we can use in any way we like. How shall we abuse this power?

While looking at how wires were run on our bread board, I noticed that there were a few pins that were perfectly aligned from one chip to the next. Placing the decoder output on PIC pins RB4, RB5, and RB6 lines them up perfectly with the input pins of 74138 decoder. As for the decoder output, six out of eight pins were directly lined up with a ULN2003.

Chip pin alignment

This allows some fairly straightforward wiring solder as these wires will not cross over each other and won’t tangle up and make a big mess. By itself that is valuable, but we were tempted to go one step further: how about we eliminate the wires entirely and jam those chips together? If they share the same PCB through-hole, that would eliminate wire soldering entirely.

It sounded good in theory, but in practice the chips are just a little too large for us to fit them three-abreast. I could push my decoder up against my PIC, but couldn’t push the Darlington array alongside the decoder as well. This is probably for the best – there’s value in having the ULN2003 lined up with its siblings.

Chips tightly packed on PCB

We may learn in the near future why this is a bad idea, but it’s all part of the fun: trying things and seeing how they work. (Or not, as the case may be.)

Breadboard Prototype of VFD Driver Project

Once we had some idea of what we wanted to do, it’s time to start wiring things up on a breadboard to see if it actually does anything interesting. Dealing with actual chips meant reading their data sheets and figure out where the rubber meets the road and how well theory meets practice.

Not having a lot of first-hand experience with such modules, it was a great way to learn by doing. The first surprise was behavior of the 74HC138 decoder module: Conceptually it takes a three-bit input and decodes it to one of eight pins. Conceptually we thought that meant raising one of eight pins high, but it actually lowers one of eight pins low.

We thought this was going to be a problem and started looking into inverters… before we realized it is a perfect pairing with ULN2003 to do what we actually wanted: The ULN2003 line inverts its input in the sense that when an input pin is high it connects the output pin to ground. So the output of a 74HC138 decoder (seven pins high, one pin low) driving ULN2003 results in seven pins connected to ground and one floating. We can work with this.

A 4-digit, 7-segment LED module stood in for the vacuum fluorescent display while all the logic got worked out. This flexibility is exactly where a breadboard is strong, letting us experiment and verify pieces of our circuit piecemeal. But it is not great for looking respectable or for long-term reliability, so once it successfully ran the LED module, we start planning to commit the design to soldering parts on a prototype PCB.

PIC16F18345 VFD breadboard and PCB

Hardware Side of Keeping PIC Driver Simple

For the VFD driver project, there were software design motivations to keep things simple. But that’s not the whole picture, there were also motivation from hardware constraints too. My previous projects to make a PIC drive a multi-segmented LED display had fairly simple wiring that connected most output pins of my PIC to current-limiting resistors. A few of the lines could have seen current flow higher than what a PIC is capable of handling, and those were handled with simple transistors. I knew there existed chips designed specifically to drive LEDs, but I wanted to learn the principles of controlling one myself.

Building something to drive a VFD requires dealing with voltages different and sometimes far higher than what is required to drive LED display modules. During our probe of this specific VFD we saw 2.5V AC and 30V DC, atypical of logic circuits. And just as there existed dedicated LED driver chips, there exist chips specifically designed to drive VFD modules, but again the project goal was to learn by building one ourselves.

So we turn to our standard electronic hobbyist toolbox item for controlling power and voltage beyond what our standard parts can handle: the ULN2003A line of Darlington arrays. The go-to solution for controlling inductive loads like relays and small motors, it can handle voltages up to 50V which we need for a VFD.

And again, with multiple different display projects on the horizon, it didn’t make sense to create a controller with hardware pinout specifically tailored to a specific unit. To keep things simple and consistent across displays, all of our controller outputs will be either left floating or tied to ground. If a particular device desires a particular pin to be at a higher voltage, we’ll have to wire up a pull-up resistor on that device’s specific interface board. We will learn if this concession to consistency will cause problems down the line.

VFD driver schematic

Why And How Of Simpler PIC Display Driver

Earlier in my outline for starting a new PIC display driver project for a vacuum fluorescent display (VFD), I mentioned one objective was to “keep the PIC side very simple and move more display-specific logic into driving code“. Let’s go into more detail on that part of the plan.

In my previous PIC display projects, the code was written for a specific multi-segment display unit as part of the overall project. This meant the source code reflected whether the LED was a common-anode or common-cathode design, it also knew about which segment represented which parts of a particular digit. This knowledge was required because I put priority on making control communication interface easy. For the temperature demo, making my display unit show “72.3F” was a matter of sending the actual UTF-8 text string “72.3F” as bytes. The PIC then parsed that string and determined which segment to illuminate.

But there’s a good chance we have several other matrix display projects in the future, and I didn’t want to invest the time to hard code intricacies of each unit into the PIC. It would be much easier to adapt and experiment if such logic was moved to a more developer-friendly environment like Python on a Raspberry Pi. In the case of the current NEC VFD under consideration, there are segments corresponding to days of the week and other function specific segments like an “On and “Off” text, “OTR”, little clock icon, etc. Most of which won’t necessarily be present on another VFD unit, why spend the time to embed such knowledge in my PIC driver?

NEC VSL0010-A VFD Annotated

We also want the flexibility to explore using the display in ways that are far afield of its original intent. For starters, that seven-segment display in the center doesn’t have to be constrained to display numbers for a clock. All these desires meant moving away from performing data interpretation on the PIC.

Instead, the PIC will accept a raw data stream where each bit corresponds to whether a segment is on or off. Each byte will correspond to 8 segments in a grid, and so forth. This means the task of mapping a desired digit to a set of segments will be the responsibility of driver code on host device rather than PIC peripheral. PIC will only concern itself with rapidly cycling through the matrix of digits keeping them all illuminated.

Getting Microchip Foundation Services Library I2C Boilerplate To Compile

PIC16F18345 VFD driver PCBMotivated by the desire to get an old VFD up and running for fun, I set up my PIC16F18345 to act as an I²C peripheral. I could write my own code from scratch, or I could build on top of boilerplate code published by Microchip for implementing an I²C slave device. My problem is that I had two choices – the new thing that doesn’t compile, or the old thing that is deprecated.

I’ve since figured out how to resolve the two error messages to compile the new thing, formally called Foundation Services Library.

The first compiler error message was this:

In file included from mcc_generated_files/USBI2C_app.c:25:
mcc_generated_files/drivers/i2c_slave.h:55:34: error: unknown type name 'interruptHandler'
void i2c_slave_setReadIntHandler(interruptHandler handler);
^

Searching elsewhere in the generated boilerplate, I found a declaration for interruptHandler in another different header file. Copying it into i2c_slave.h addressed the “unknown type name” error.

typedef void (*interruptHandler)(void);

However, that error was replaced by a warning that there are now duplicate declarations of interruptHandler. This seems silly – if there were a declaration to collide with, it should not have thrown an unknown type name error signifying the declaration’s absence.

MPLAB should either not throw the error, or not raise the warning, but it is doing both. I have yet to figure out if the toolchain is busted or if the boilerplate code is. For now, though, I could proceed to the next problem.

The second compiler error message was this:

mcc_generated_files/USBI2C_app.c:30:14: error: no member named 'SSP1IE' in 'PIE3bits_t'
PIE3bits.SSP1IE = 1;
~~~~~~~~ ^
1 error generated.

This one was easier to figure out – go into the header files for this chip and look for SSP1IE. I found it declared on PIE1bits instead of PIE3bits. So to get this code to compile, I changed the boilerplate code from this:

void USBI2C_Initialize(void){
PIE3bits.SSP1IE = 1;
i2c_slave_open();
}

To this:

void USBI2C_Initialize(void){
PIE1bits.SSP1IE = 1;
i2c_slave_open();
}

What does PIE1bits.SSP1IE actually do? I’m not sure so I’m not positive this is actually the correct fix. But at least all of the foundation boilerplate compiles, and I start browsing through sample code for MikroElektronika USB-I2C Click module to figure out what it does and what I can do with it. Reading through code and comments, I saw this comment block.

- This module only supports byte operations. Block read and write operations is
not yet supported by MCC Foundation I2C Slave Drivers.

This comment implies Microchip has decided to deprecate their previous I²C library even though the new library is unable to duplicate important functionality. If true, this is… unsatisfactory. I want block read and write operations for my project.

Now I’m even more motivated to stay with the old code, but unfortunately there were some complications with that, too…

I2C on PIC: Microchip Foundation Services Library Is Less Beginner-Friendly

About a year and a half ago I poked my head into the world of I²C programming with my PIC16F18345 chip. I was pleasantly surprised the MCC boilerplate code actually included an example implementation emulating an I²C EEPROM. That turned out to be a great way for me to get started.

Now that I have another PIC project in mind, I retraced my steps and saw this:

I2C driver will be removed soon

In file included from mcc_generated_files/mcc.h:55:
mcc_generated_files/i2c1.h:55:2: warning: "This version of the I2C driver will be removed soon and the correct driver to use is the Foundation Services driver" [-W#warnings]
#warning "This version of the I2C driver will be removed soon and the correct driver to use is the Foundation Services driver"

Looks like what I had used before is on its way out.

Since this is a new project, I thought I might as well check out what the new shiny object has to offer. Reading around the web, I found complaints that the previous MCC I²C code would work when conditions are ideal, but it was not very good at letting developers write code to handle error conditions. This might not be important in hobbyist projects like mine, but it was of great importance to people trying to engineer real products.

I added the Foundation Services Library module for my PIC’s MSSP. After code generation was complete, I went into the generated header files and saw a lot more functions declared than previous boilerplate code. There were a few related to overflow and bus collision errors, which I assume were there to address complaints about error handling capability.

Unfortunately, there is no longer a friendly example implementation to reference. There are a lot of declarations but no information on how to use those functions. Microchip’s claim that the Foundation Services Library code is self-documenting has been wholeheartedly laughed at by other forum users. But the forums did point me to Microchip’s  MikroElektronika Click Library which interfaces between those nifty little Click modules to a PIC using Foundation Services Library. The trick is finding one that most closely matches what I’m trying to do. Many Click modules are I²C slaves controlled by a PIC acting as master, I wanted my PIC to act as I²C slave accepting commands. A first pass through the Click library found only the USB-I2C Click module, so I installed sample code corresponding to that module and tried to build it.

unknown type name interruptHandler

In file included from mcc_generated_files/USBI2C_example.c:36:
mcc_generated_files/drivers/i2c_slave.h:54:34: error: unknown type name 'interruptHandler'
void i2c_slave_setReadIntHandler(interruptHandler handler);

Sample code that fails to compile is… not the height of beginner friendliness.

After 30 minutes of hunting around, I failed to find a solution to this problem and decided to return to the old deprecated I²C driver. It may not be the newest and shiniest thing, but it does compile and run.

Dusting off Past PIC LED Driver Projects For Potential VFD Driver

While the VFD salvaged from a VHS timer/tuner unit was designed to run on voltages unfamiliar to me, once we probed the control pinout I found it much less intimidating. The entire array can be treated as a matrix with its eight grids along one axis and ten elements along another axis. The array is only partially filled: there aren’t actually 80 elements on the VFD. A driver chip will energize one grid at a time, and energize the desired elements within that grid. After some time, the driver will move on to the next grid and its corresponding elements. When the switching happens quickly enough, our human eye sees only a completely illuminated display and would not notice that grid-to-grid cycling.

NEC VSL0010-A VFD Annotated

This general principle is identical to how I drove a LTC-4627JR 7-segment LED array in an earlier PIC project. The only real difference is that the transistors I had used earlier is only good for the +5V used by that LED array and not suitable for +30V for this VFD, but that can be addressed by substituting some switching components.

IMG_5272

In the previous project, I was interested in learning KiCAD and the process of ordering custom PCBs for a device for potential low-volume production. Many lessons were learned, most of which discouraged me from pursuing the thought further. This time around there is no fantasy of volume production, this will be an one-off project for a single salvaged VFD.

But now that I know the concept of a display matrix is generically applicable across multiple units, this time around I’m more inclined to keep the PIC side very simple and move more display-specific logic into driving logic which usually runs on a more programmer-friendly device like an Arduino or Raspberry Pi. (Or maybe even a ESP32!) So this time around I’m not going to decode ASCII characters or anything along those lines: I’m going to create a PIC driver that listens for commands over I2C specifically about cycling through and toggling pins. The idea is to avoid unnecessary PIC code churn that uselessly reinvent the wheel from one LED display to another, instead moving that to the Arduino/Pi/ESP32/etc side.

IMG_5238

Original NEC VSL0010-A VFD Power Source

Now that we have a better understanding of how a NEC VSL0010-A vacuum fluorescent display (VFD) works, figuring out its control pinout with the help of an inkjet power supply, we returned to the carcass we salvaged that VFD out of. Now that we knew each pins’ function, we picked those that supplied 2.5V AC for filament power to track. We expect they are least likely to pass through or be shared by other devices. We traced through multiple circuit boards back to the main power transformer output plug. We think it’s the two gray wires on the left side of this picture, but our volt meter probes are too big to reach these visible contact points. And the potential risk of high voltage made us wary of poking bare wires into that connector as we did for the inkjet power supply.

NEC VSL0010-A VFD Power Supply - Probes Too Fat

Our solution came as a side benefit of decision made earlier for other reasons. Since we were new to VFD technology, our curiosity-fueled exploratory session was undertaken with an inexpensive Harbor Freight meter instead of the nice Fluke in the shop. Originally the motivation was to reduce risk: we won’t cry if we fry the Harbor Freight meter, but now we see a secondary benefit: With such an expensive device, we also feel free to modify these probes to our project at hand. Off we go to the bench grinder!

NEC VSL0010-A VFD Power Supply - Probes Meet Grinder

A few taps on the grinding wheel, and we have much slimmer probes that could reach in towards those contacts.

NEC VSL0010-A VFD Power Supply - Probes Now Thin

Suitably modified, we could get to work.

NEC VSL0010-A VFD Power Supply - Probes At Work

We were able to confirm the leftmost pair of wires, with gray insulation, is our 2.5VAC for VFD filament. The full set of output wires from this transformer, listed by color of their insulation, are:

  • Gray pair (leftmost in picture): 2.6V AC
  • Brown pair (spanning left and right sides): 41V AC
  • Dark blue pair: (center in picture) 17.2V AC
  • Black pair (rightmost in picture): 26.6V AC

There was also a single light-blue wire adjacent to the pair of dark blue wires. Probing with volt meter indicated it was a center tap between the dark blue pair.

NEC VSL0010-A VFD Power Supply Transformer

Once determined, we extracted the transformer as a single usable unit: there was a fuse holder and an extra power plug between it and the device’s AC power cord. We’re optimistic this assembly will find a role in whatever project that VFD will eventually end up in. 2.6V AC can warm filament, rectified 26.6V AC should work well for VFD grid and segments. And with proper rectification and filtering, a microcontroller can run off one of these rails. It’ll be more complex than driving a LED display unit, but it’ll be worth it for that distinctive VFD glow.

HP Inkjet Printer Power Supply For NEC VSL0010-A VFD

One of the reasons LED has overtaken VFD in electronics is reduced power requirements. Not just in raw wattage of power consumed, but also the varying voltage levels required to drive a VFD. The NEC VSL0010-A VFD whose pinout we just probed ran on 2.5V AC and ~30V DC. In contrast, most LED can run at the same 5V or 3.3V DC power plane as their digital drive logic, vastly simplifying design.

We didn’t have a low voltage AC source handy for probing, so we used 2.5V DC. We expected this to have only cosmetic effects. One side of our VFD will be brighter than the other, since one side will have a filament-to-grid/element voltage difference of 30V but the other will only have 27.5V.

But putting 2.5V DC on the filament occupied our only bench power supply available at the time. What will we use for our 30V DC power source? The answer came from our parts pile of previously disassembled electronics, in this case a retired HP inkjet printer’s power supply module labeled with the number CM751-60190.

HP CM751-60190 AC Power Adapter

According to the label, this module could deliver DC at 32V and 12V. Looking at its three-conductor output plug, it was easy to come to the conclusion we have one wire for ground, one wire for 32V, and one wire for 12V. But that easy conclusion would be wrong. Look closer at the label…

HP CM751-60190 AC Power Adapter pinout

We do indeed have a ground wire in the center, but there is only one power supply wire labelled +32V/+12V. It actually delivers “32 or 12” volts, not “32 and 12” volts. That last pin on the left has an icon. What did that mean? Our hint comes from power output specifications: +32V 1095mA or +12V 170mA. We deduced this meant the icon is a moon, indicating a way to toggle low-power sleep mode where the power supply only delivers 12V * 170mA = 2 watts vs. full 32V * 1095mA = 35 W.

With that hypothesis in hand, it’s time to hook up some wires and test its behavior.

HP CM751-60190 AC Power Adapter test

When “sleep mode” pin is left floating, voltage output is 32VDC. When that pin is grounded, voltage output drops to 12VDC. Since we’re looking for 32VDC to drive our VFD grid and elements, it’s easy enough to leave sleep wire unconnected and solder wires to the remaining two wires to obtain 32V DC for our VFD adventures.

HP CM751-60190 AC Power Adapter new wires

Sleuthing NEC VSL0010-A VFD Control Pinout

Vacuum Fluorescent Display (VFD) technology used to be the dominant form of electronics display. But once LEDs became cheap and bright enough, they’ve displaced VFDs across much of the electronics industry. Now a VFD is associated with vintage technology, and its distinctive glow has become a novelty in and of itself. Our star attraction today served as display for a timer and tuner unit that plugs into the tape handling unit of a Canon VC-10 camera to turn it into a VCR. A VFD is very age-appropriate for a device that tunes into now-obsolete NTSC video broadcast for recording to now-obsolete VHS magnetic tape.

Obviously, in this age of on-demand internet streaming video, there’s little point in bringing the whole system back to life. But the VFD appears to be in good shape, so in pursuit of that VFD glow, salvage operation began at a SGVHAK meetup.

NEC VSL0010-A VFD Before

We have the luxury of probing it while running, aided by the fact we can see much of its implementation inside the vacuum chamber through clear glass. The far right and left pins are visibly connected to filament wires, probing those pins saw approximately 2.5V AC. We can also see eight grids, each with a visible connection to its corresponding pin. That leaves ten pins to control elements within a grid. Probing the grid and element pins indicate they are being driven by roughly 30V DC. (It was hard to be sure because we didn’t have a constant-on element to probe…. like all VCRs, it was blinking 12:00)

This was enough of a preliminary scouting report for us to proceed with desoldering.

NEC VSL0010-A VFD Unsoldering

Predating RoHS solder that can be finicky, it was quickly freed.

NEC VSL0010-A VFD Freed

Now we can see its back side and, more importantly, its part number which immediately went into a web search on how to control it.

NEC VSL0010-A VFD Rear

The top hit on this query is this StackExchange thread, started by someone who has also salvaged one of these displays and wanted to get it up and running with an Arduino. Sadly the answers were unhelpful and not at all supportive, discouraging the effort with “don’t bother with it”.

We shrugged, undeterred, and continued working to figure it out by ourselves.

NEC VSL0010-A VFD Front

If presented with an unknown VFD in isolation, the biggest unknown would have been what voltage levels to use. But since we have that information from probing earlier, we could proceed with confidence we won’t burn up our VFD. We powered up the filament, then powered up one of the pins visibly connected to a grid and touched each of the remaining ten non-grid pins to see what lights up. For this part of the experiment, we got our 32V DC from the power supply unit of a HP inkjet printer.

We then repeated the ten element probe for each grid, writing down what we’ve found along the way.

NEC VSL0010-A VFD Annotated

We hope to make use of this newfound knowledge in a future project, and we hope this blog post will be found by someone in the future and help them return a VFD to its former glowing glory.