Arduino 101 meetup prep – day 7 – VU meter needle gauge

11May2009 – old stuff that may still be useful


Another bit of scavenged gear to serve as an Arduino output device.  Somebody please chime in here to tell me the official name for these type of gauges.  This could be an interesting device to give an amusing analog measurement for something like your bug count, web server hit rate, outdoor temperature, number of unread xkcd entries, etc.

Arduino_output_needle_gauge 003

Pretty simple device:

  • lower pair of terminals marked “+” and “-” drive the needle (measured 800 ohms on the multimeter)
  • upper pair of terminals drive the lamp (measured 1.2 ohms on the meter, but you can’t really conclude much from that with lamps — resistance increases as they heat up).  I left the lamp alone for this example as it sucks a lot of current (@5V I measured ~160mA)

Popped the bezel off to admire the guts that drive the needle

Arduino_output_needle_gauge 006

I wish I could tell you I was all scientific about reversing this one, but I just did a sanity-checking I=V/R calc (giving 5V/800 =~6mA) per late-night lab protocol to ensure the gauge wouldn’t melt on the bench when I applied voltage.  Seemed ok, and putting 5V across it pinned the needle, so it appeared basically functional.

The idea was to drive the gauge from one of the Duemilanove’s PWM outputs (if that wikipedia link freaked you out, PWM in this case is just 5V on and off at a given frequency with more or less time on).  Now using the Arduino analogWrite(pin, value) function allows you to specify 0 to 255 for value.  0 is always off, 255 is always on, 127 is on half the time.  Out of the box I think the frequency was 500 Hz (but I later discovered you can change that with magical register-setting incantations that look vaguely familiar from doing lower level C on AVR chips while deciphering datasheets).  Ideally, with value == 0 I wanted the needle full left, and with value == 255 I wanted the needle full right, and to have that 0-255 range evenly distributed in between.  I really took seriously the “don’t worry about the math” notion from The Art of Electronics so I just started hooking things up.

Since the gauge was pinning hard on straight 5V I thought I’d just throw a resistor in line on +.

Arduino_output_needle_gauge 008

That’s a 2.2K resistor.  Also seemed prudent to put a protection diode (1N5187 schottky) across the terminals since we’re driving a coil of wire.  When I drove this with varying values in analogWrite() I really only got completely on and completely off behaviour.  Hmmm.  Fail Opportunity for Further Thinking.  Checked the waveform out of Arduino pin 6 on the oscilloscope and it was varying the duty cycle as expected, but anything beyond 0% duty cycle pinned the needle.  Oh, right, where’s your voltage divider?  More thinking led to this:

Arduino_output_needle_gauge 022

which then lead to this:

Arduino_output_needle_gauge 011

which seemed to work well after tweaking the resistor and cap values.  So I committed to solder freestyle:

Arduino_output_needle_gauge 014

and wrote this test sketch (below) to sweep the needle full scale (like a POST), and then waggle the needle around a bit on this clean-looking rig

Arduino_output_needle_gauge 016

With this sorted out, I can get on with adapting the other 5 gauges on the bench.  It would be nice to replace the bulb in this unit with some SMT LEDs… now where is that old desk phone with the tiny LEDs backlighting the keypad?

Make: your move.

Arduino code:

Purpose: drive a needle-gauge VU meter from Arduino's PWM output
Author: Darin Whte
Date: 2009-05-10

-Arduino pin 6 (PWM) to "conditioning" circuit (see schematic)
-Arduino Gnd to needle gauge

int VUpin = 6;
int valVU = 0;
int valVUlast = 0;
int prescalerVal = 0x07; //create a variable called prescalerVal and set it equal to the binary number "00000111"
const int centreVal = 110;
const int maxVal = 255;
const int waggleVal = 50;

void setup()
  pinMode(VUpin, OUTPUT);
  analogWrite(VUpin, 0);

void loop()
  for (int i=0;i<maxVal;i++) {  // sweep needle full range
    analogWrite(VUpin, i);
    if (i==0) delay(1000);
  analogWrite(VUpin, centreVal);  // bring needle to centre
  for (int j=0;j<8;j++) {             // waggle the needle back and forth
     for (int k=centreVal;k<centreVal+waggleVal;k++) {
       analogWrite(VUpin, k); 
     for (int m=centreVal+waggleVal;m>centreVal-waggleVal;m--) {
        analogWrite(VUpin, m);
     for (int n=centreVal-waggleVal;n<centreVal;n++) {
         analogWrite(VUpin, n);
This entry was posted in arduino and tagged , , . Bookmark the permalink.