In this article I describe the simple setup and explain the code to drive analog meters using PWM outputs from an Arduino and the LCD Smartie program. I also replace the meter face to show the proper scale. Replacing the meter scale is very easy to do with most meters and can really add some style to your project.
A few recent articles around the web have been about interfacing an analog gauge to the PC to show things like the CPU% load. I have been wanting to do something like this for a long while and had bought an analog gauge for the purpose. These articles used a Microchip PIC microcontroller and the LCD Smartie program. I built one using the Arduino. I also included an LED to signal high CPU usage and setup the serial command decoding so that the Arduino could support a meter on all six of it’s PWM outputs.
Everything you need to know about interfacing to analog gauges is included in the DIY Life article "Show PC stats on Analog Gauges", including a video. I followed these instructions for configuring LCD Smartie so I will not cover that in this article. I will show you how to use the Arduino instead of the PIC.
This program is commonly used to drive small LCD displays with information from your PC. It can show things like CPU load and temperature, memory usage, even how much email you have or the song playing from your WinAmp. If you have a parallel port and a small LCD you might want to get this program a try, it is very simple to interface the LCD to the parallel port.
Driving an analog meter.
The "Show PC stats on Analog Gauges" article describes the details very well. I highly recommend it for the basic understanding of analog gauges and driving them form a microcontroller. The basic idea is to use a PWM output signal to generate the average current needed to swing the needle.
Meters typically need a small current to operate. The typical meter needs 1mA to swing full scale. Some meters are 10mA and the extra sensitive meters used in handheld volt meters may be 1uA meters. To set the full scale for a volt meter a series resistor is used. For example you would use a 5.0K resistor to make a 1mA meter swing full scale at 5V. This is just ohms law, with the 5K series resistor, 5V drop would be 1mA. Of course you may need to consider the meters resistance as it is in series but typically the meter has a very low resistance so ignoring it will result in a very small error.
To drive the meter from a microcontroller we need to generate a voltage which can drop across our scaling resistor to be measured by the meter. We typically have a 1mA meter and a 5V supply so a 4.7K resistor will do the job. The meter will swing a bit past full scale but you could compensate for this in software if you wish. If you need high precession you can get a 1% 5K resistor. For my experiments I used a normal 5% 4.7K.
The other article suggest that you use a transistor to drive the meter. This is a good idea especially if you have a meter that requires more then 1mA. Most microcontrollers can output about 5mA, some less. The transistor will make the circuit insensitive to the amount of current a meter needs. I did not use the transistor myself, I had plenty of 1mA meters to play with.
PWM can generate the analog voltage for our meter. In the Arduino this is very simple. Just select a PWM capable pin and use the AnalogWrite() function. If you have set the meter to swing full scale with 5V then the AnalogWrite function will swing the meter from 0 to full scale with 0 to 100% PWM or 0-255 as the input to the function.
PWM is short for Pulse Width Modulation. PWM is a digital output that is either on or off, 0 or 5V in most systems. A digital I/O pin toggles at a given frequency with a square wave shape. The amount of on time verses off time is measured as a duty cycle.
The Arduino PWM outputs have a frequency of about 500Hz. This means that the pin cycles from 0 to 5V and back to 0 again 500 times a second. This frequency is fixed but the amount of time the signal is low vs. high is set by the second parameter in the AnalogWrite() function.
The way PWM generates an analog signal is that we average the voltage level as a function of the percentage duty cycle. Say for example that we have 5V supply so our PWM is switching form 0 to 5V at a 50% duty cycle. Half the time it’s at 0 and half it’s at 5V so the average is 2.5V. A simple resistor and capacitor will filter out the frequency component and give us a steady (DC) voltage. We don’t need the RC to drive a meter because it will filter the PWM for us.
If you did a software PWM by togging the pin using code as opposed to the hardware timers and the rate was slow, you might need a capacitor as described in the original article. If you keep the PWM frequency high enough, the meter should not respond by wiggling. For the Arduino code, the 500Hz PWM is plenty fast enough. A meter is not going to visibly wiggle at 500Hz.
The AnalogWrite() function takes two parameters, the pin to drive and a drive value in the range of 0-255. The pin must be one of the PWM ready Arduino digital pins (3, 5,6,9,10, or 11). The drive value of 0 would set the PWM pin to 0% or off, a drive value of 128 would be about 1/2 of the range and would give about 50% on the PWM pin. 255 would set the PWM to 100%, a steady 5V. The pin will begin to toggle at 500Hz after your first call to the function.
So to drive an analog meter we simply select the correct resistance to drive swing the needle to full scale at our supply voltage, 5V for the Arduino. The original article provides some example methods to determine the correct drive for a meter you might scrounge.
If you have a volt meter to play with, chances are it will have a scale much higher then 5V. If it was a 5V meter then you are all set, it has the built in resistor. One of the meters I played with had an 80V scale. I looked into the back of the meter and found a 1% precision 80K resistor so I knew it was a 1mA meter. I just removed the resistor from inside and changed the scale out.
Adding a warning LED
I drilled a small hole in the plastic back of my meter and inserted a high intensity red LED. This LED is driven from the Arduino and flashes each time the rate is updated. It can be set to be full on or flashing when the CPU load is over some level, Maybe 80%. The LED I used needs a bit more current to get fully bright but I went ahead with a simple series resistor to set the current to something the AVR could handle. It could be brighter but that will require a drive transistor.
I plan to either mount this board and a few meters into the side of my PC case or maybe use a separate box to set on my desk. I want to see several items displayed on the meters. I keep thinking about the line of meters in "Forbidden Planet". I could have a dozen meters mounted along the curve in my desk monitor riser.
For the initial setup I found a four conductor cable and routed a separate wire for each connection, two for the meter and two for the LED. Three wires would be enough as ground is common to the meter and LED but I had four wires so I did not bother to figure out which side of the LED would have been ground. For now, I set the meter on my monitor riser between my monitors so I could watch the CPU load and the little LED flash as I use my computer.
New Meter Face
So far I have not done anything really new compared to the original "Show PC stats on Analog Gauges" article. But I did take an extra step that really makes things nice. You can replace the scale behind the needle on most meters. The scale is usually a small painted piece of aluminum held in place by small screws.
To make a replacement meter face, I needed to get the scaling and placement of everything to match the existing scale. The first step was to use a flat bed scanner to scan the existing meter face. In the picture here you can see a scan from one of the meters I messed around with.
Once you have the scanned image, load it up into a graphics editing program and trim it to the exact size. If your program supports accurate scaling, set the height and width of the image precisely. I used a caliper to measure the meter face and set these numbers into Inkscape where I imported the scanned image. Draw your new meter face over the scanned image then delete the scanned image and print at a one to one scale. You can print in color to make it more snazzy. If you use plain paper, cut out the new scale and tape it to the original metal one. Place it back on the meter and your all set.
I had trouble with my color printer printing to scale correctly so I did a B/W meter scale on my laser printer. My fancy scale is shown here. I will get this on the meter when I find time to work out the printer issue.
I used cardstock for the scale so I was able to completely replace the metal scale. Cardstock paper is strong enough that it does not need a backing. I marked the screw holes and punched the paper with a jewelers screwdriver so that the original screws could be used to mount it. Unfortunately I lost one of the screws so I went ahead and stuck the scale down with some white tape. You can see the tape in the picture. I will improve all these cosmetic issues when I do the color scale.
This project was simple and fun. I plan on some neat analog gauges which show things like the number of visitors to the site. I hate to tie up one of my Arduino boards so I might do a separate board where I just plug in the microcontroller chip.
If you have a parallel port you might drive a few meters using a DAC on the digital output pins. I talk about the R2R DAC in a previous article. If you used 4 Bits for the DAC that would give 16 levels of control for the meter. I think you could drive about 3 meters directly with 4 Bit DACs on the parallel port.
You don’t have to show percentage on the meter. You can display anything you like so long as the display does not need to change fast. You could display the weather on a meter, of course you could display temperature but you could also show the cloud conditions. Sunny, partly cloudy, overcast, raining, snowing etc… Just print a scale with icons for each of the weather conditions and have the meter swing to the right value to represent the conditions.
How about a day clock that shows you how much time you have left at work. You could mark the scale with lunch time, breaks, etc… I look forward to comments on this article with interesting things to display on an analog meter face.
The simple protocol setup in the PIC based version of the PWM meter driver works great so I just implemented the same on the Arduino. Basically it’s just a number for the percent level and a letter identifying the channel. I assigned channel A to I/O 3 and B to I/O 5. The way I decode the protocol makes it very easy to add more channels. You just need another few lines of code in the switch statement.
Here is my version of the code. If you improve it, let us know with a comment.
I bought mine at All Electronics. The 1mA panel meter cost about $12. I would like to find a good meter that cost a less. I cant afford my "Forbidden Planet" meter set at $12/each. I also got a smaller meter to try out. It is similar to this one but has a fuel gauge scale that would be fine for a memory status indicator. One idea is to buy some of those really cheap volt meters and pull out the meter. This would likely be a 1uA meter and has a large face. It’s a shame to throw away the rest of the meter but for the price you get a good meter and maybe some other useful parts. Let us know if you have a good source.