These old analog gauges were in a one-dollar junk box at the market. Before there were LCD screens in everything, before LEDs, data was shown on these.
In a sort of retro mash-up, we'll make a USB device that displays PC status info on these gauges. The gauges can show CPU and memory usage, processor voltage -- just about any numerical data typically displayed on small HD44780 based LCD character displays commonly used in PC case mods.
You'll find all the details and project files after the fold. Check out the podcast for an overview of the project.
Instead of blinking LEDs, though, it pulses power to an analog gauge. The ratio of "on" and "off" pulses determines the needle position -- this is called pulse-width modulation (PWM). A signal that is on 75% of the time will read 75% on the gauge. This pulsed (or modulated) signal is smoothed by the magnetics inside the gauge. Analog gauges have a lot of inductance, so they give a steady reading without noticeable twitching.
Data for the gauges will be collected by LCD Smartie, an open source MS Windows program intended to drive small character LCD panels. We can finesse LCD Smartie to send raw data through a USB port to the gauge controller board in a format we can use. These readings will then be converted into a signal that positions the gauge needle.
This design uses surface mount parts, resulting in a very small circuit board that can be tucked inside a computer case. For a similar through-hole design, see the USB color changer project.
A PIC 18F2550 is used for USB connectivity, the support hardware is detailed in the USB color changer project. The gauges will always be connected to a PC, so I configured the PIC for USB power. This is a bit different than the USB color changer, a self powered device that uses a pin to sense the USB connection. The gauge driver doesn't need this pin because it's only powered when a USB cable is attached.
Analog gauges don't directly measure a voltage, they measure a small fraction through a resistor. The voltage meter in the picture is graduated to 600 volts, but reaches 100% at about one volt. A large-value resistor is used to reduce the measured voltage to an acceptable level. A new gauge should have a datasheet that lists the reduction ratio.
If you scrounge old gauges without documentation, you'll have to experiment to find the correct resistor. I started by connecting my gauge to a power supply (2.5 volts) through a 500K ohm resistor -- barely any movement. I cut the resistance in half until I found a value that held the needle at 100%. A variable resistor (potentiometer) would help dial in the exact calibration, but with the immense variation among gauges it would be impossible to specify a part. Instead, I just used regular through-hole resistors connected directly to the gauge.
A PIC pin outputs a positive voltage, like the + (positive) terminal of a battery. It can drive a gauge directly, as shown in the diagram. This won't work with gauges that need more than the 25ma of current/5 volts provided by a PIC. A much more robust configuration is to switch the gauge ground (-) through a transistor (Q1 in the diagram below). This lets us connect several gauges on the same output, or drive gauges that need a power supply not provided by the PIC.
Gauges are usually a light load. We can use a simple (and tiny) transistor to switch them. The transistor I used will switch loads up to 100ma -- dozens of gauges, but only 5 LEDs. The transistor (Q1 in the diagram above) requires a resistor (R3) to limit current from the PIC pin. I also included a spot for a capacitor (not shown) that will smooth the modulated signal - a low pass filter. Install this capacitor to eliminate twitching in ultra-sensitive gauges -- I didn't need to install them. It might be easier to attach a capacitor directly between the gauge leads if needed (see C1 in the "Connecting the Gauge" diagram below).
2.5 volt power supply
A separate 2.5 volt supply powers the gauges. An independent supply is a bit excessive, but there are three good reasons to do this. First, the USB spec allows a supply from 4.75-5.25 volts. This variation means that every computer would need different gauge resistors if we used the USB supply. Second, if you've ever watched your power supply stats you know that voltages can "sag", or decrease, under heavy system loads. Gauges connected directly to the USB supply would bounce along with the sag. Finally, many gauges require less than 1 ma of current at less than 1 volt, a ~5 volt supply is overkill. I used an LM317 adjustable regulator to convert the 4.75-5.25 volts from the USB port to a steady 2.5 volts. Two 240 ohm resistors set the 2.5 volt output, you can calculate resistors for custom voltages using a site like this.
Gauge Connection This diagram shows how to connect a gauge to the circuit board. The positive terminal of the gauge, usually labeled with a "+", is connected to a (2.5 volt) power supply through a limiting resistor (R1). Recall that we determined this resistor earlier using the datasheet or trial and error. The ground terminal of the gauge, usually labeled "-" or "GND", connects to one of the gauge drivers. Really sensitive gauges might need a capacitor between the two terminals to smooth the modulated signal.
Hardware Pulse-Width modulator (PWM)
I thought it would be clever to use a hardware PWM in this project to contrast the software PWM in the USB color changer. The PIC 18F2550 has two hardware PWMs that generate a gauge-driving pulse automatically, without any software or interrupts. Both of the output transistors are connected to pins with hardware PWMs (port C, pin 1 and 2). Here's a shortcut calculator to find the PWM register values, or read the Microchip PIC Mid-Range Manual [pdf!]. In the end, the software PWM was a better choice -- I'll discuss this more in the firmware section.
The circuit and PCB were made using Cadsoft's Eagle Layout Editor. These files are in the /pcb folder of the project archive. A freeware version of Eagle is available for download.
This board is all one layer, with no jumper wires. Parts are mostly surface mount, but the pin headers and USB socket are through-hole. Watch the USB socket orientation - its on the bottom, opposite the PIC, to better accommodate one-sided boards. If you were to accidentally install the socket on the SAME side as the PIC, it would probably damage the PIC or your PC.
The PIC is a very large SO size chip package, similar to a DIP (through-hole) chip with the legs pushed out. Resistors and capacitors are specified in mixed 1206 and 0805 sizes. I'm working towards all 0805 sized designs, but I still have tons of 1206 resistors. The smallest parts are the SOT-23 transistors and diodes. These are intimidating, but really no problem at all. My favorite way to solder surface mount parts (all the way to 0402):
Apply a bit of liquid flux to every solder pad.
Put a dot of solder on one pad.
Hold the part in place with tweezers.
Heat the part lead and solder dot, hold the part flush to the board when the solder melts.
Remove your iron but continue holding the part in place tweezers.
Release your tweezers.
Now solder the rest of the leads.
Breathe! It's not as pretty as machine placement, but it works.
There are some great soldering videos and tutorials in the links below.
The firmware is compiled in Microchip's MPLAB with the PIC C18 compiler. MPLAB is free, you can grab it here. Evaluation and free student editions of the C18 compiler are available to download here. A compiled .hex file, ready to program to a PIC, is included in the project archive.
The firmware uses Microchip's USB framework. This is the same framework used in the RGB color changer project. Read more about compiling the framework there.
The actual interface protocol, how values are put on the gauge, is dictated by the software we're using. LCD Smartie is an open source MS Windows program intended to drive small character LCD panels. It retrieves system information like CPU load, memory usage, current playlists, and more. It has a 'test driver' that will throw data down a serial port -- this is perfect because the USB firmware emulates a serial port. We can configure LCD Smartie to skip the typical HD44780 control commands, and just send raw system status info through the USB port. For example, in this setup:
the first line is my CPU usage followed by the upper-case letter 'B'. The second line is my memory usage followed by the upper-case letter 'A'. LCD Smartie sends command sequences every time one of the values changes. Take this example sequence:
This is a super simple protocol -- the value (100) followed by an identifier (A/B). The value is just a whole number percent between 0 and 100. The identifier tells the PIC which gauge gets the value. That's it! No newline characters, such as enter or return, are needed. The example sequence would set gauge A to 100%, then 80%, and finally 82%. The firmware receives the values as ASCII characters and decodes them to a usable form.
I had intended to use the PIC hardware to create a PWM signal. This is fine solution, but there are a ton of reasons that using the software PWM was easier. The soft PWM can to expand beyond 2 gauges. The PIC PWM is a bit complicated -- a period of 100 units and a duty cycle of 50 units doesn't always yield a 50% duty cycle. LCD Smartie sends data on a scale of 0-100 -- its easy to change the software PWM to work on 100 ticks instead of 255. This saves us from doing any messy divide operations on a tiny processor, or creating a lookup table. Read more about software PWM in the USB color changer project.
A compiled firmware .hex is included in the project archive. I included the modified source files, rather than the whole project. The easiest way to work with the source is to install the Microchip USB framework (I used version 1.2) and copy the modified source files over the fresh installation. For more info on this procedure see, yes, the USB color changer. These files were changed:
linker files for the 18f2550, use the 'I' version when using a debugging tool like the ICD2.
Set custom USB LED pin.
Enabled USB power mode.
Software PWM, USB interface.
Testing the USB connection
Check out the previous USB project for procedures to connect to a PC for the first time, get the COM port number, and setup Windows Hyperterminal.
Open Hyperterminal and start a connection to the device.
To set gauge A to 100%, type:
That's it, no enter or return, just "100A". The device will respond with "0" and the gauge should change positions.
To set gauge B to 50%, type:
The device will respond with "0" and the gauge should change.
Configure LCD Smartie
The LCD Smartie default settings send a bunch of unnecessary positioning data. In this section we'll configure it to send data through the USB port using our simple protocol instead. Grab LCD Smartie here. Read the complete LCD Smartie "test driver" documentation if you want the dirty details.
1. Extract LCD Smartie to a folder.
2. Find config.ini in the LCD Smartie folder, open it with an editor.
3. Paste this configuration information for our custom "screen" after the last line of the "[General Settings]" section:
Click the "Screens" tab and find the "Display settings" box.
Click the small "Plugin" tab.
For the "Display Plugin" choose "testdriver.dll".
Change the "Startup Parameters" COM port number to the COM port assigned to the virtual serial port by Windows (see the color changer project for instructions).
Next, click the small "Screen" table below the "Plugin" tab.
Set the "LCD size" to "2x16".
Find the "Screen settings" box, this is where we configure our "hypothetical" LCD display. In actuality, this is the data that is send through the USB port to the gauges.
Make sure the "Screen:" indicator reads "1" and the "Enabled" box is checked.
On the first line type "$CPUUsage%B", this will 'display' CPU use followed by the letter "B". On the next line type "$MemU%A", this will 'display' memory use followed by the letter "A". The actual order of A and B is unimportant.
Make sure all but the first screen are disabled by un-checking the "Enabled" box.
Click 'OK' and LCD Smartie should show a representation of the display on your monitor.
If everything is configured correctly, the gauges should being showing CPU and memory use.