Built-in project · Arduino Uno R3

Lamp power meter on an Arduino Uno

A MAX471 board in a 6 V lamp’s supply lead: the volts, milliamps and milliwatts on a 16x2 I2C LCD, and the surge a cold filament draws. The whole build, an Arduino Uno and 5 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.

Teaching? Assign it to your class in one click.

Beginner About 25 minutes to build and run. Runs in your browser. Free, and no account needed.

The parts retail for about $37. On Mokxi they're free.

The circuit runs here once the page has loaded.

What you'll learn

  • Measuring current with a sensor board in series
  • Scaling a voltage divider back to the real voltage
  • Power as volts times amps
  • Why a cold lamp filament draws a surge
  • Averaging samples to reduce noise
  • Difficulty: Beginner
  • Time: About 25 minutes
  • Board: Arduino Uno R3
  • Parts: 6

How it works

A MAX471 board sits in the lamp's supply lead, between the bench supply and the lamp, with a button to switch it on. The board gives two voltages the Uno can read: A0 is 1 V for each amp, and A1 is a fifth of the supply voltage.

Ten times a second, the sketch averages 16 readings of each. It turns them into millivolts, then milliamps and milliwatts, and shows voltage, current, power and the highest current seen on a 16x2 I2C LCD and on serial. A cold filament has low resistance, so pressing the button gives a surge before the current settles.

Parts list

6 parts, plus the jumper wires and a bench instrument. The parts retail for about $37; on Mokxi they're free, and so are the instruments.

Wiring table

Every connection, pin by pin, read from the circuit itself. Each row joins the pin on the left to the pin on the right, by a jumper wire or a breadboard strip.

Part and pinConnects to
Character LCD with I2C backpack pin VCCArduino Uno R3 pin 5V
Current and voltage sensor, MAX471 pin GNDArduino Uno R3 pin GND
Filament lamp pin 2Arduino Uno R3 pin GND
Bench power supply pin V-Arduino Uno R3 pin GND
Character LCD with I2C backpack pin GNDArduino Uno R3 pin GND
Current and voltage sensor, MAX471 pin ATArduino Uno R3 pin A0
Current and voltage sensor, MAX471 pin VTArduino Uno R3 pin A1
Character LCD with I2C backpack pin SDAArduino Uno R3 pin A4
Character LCD with I2C backpack pin SCLArduino Uno R3 pin A5
Pushbutton pin 2aCurrent and voltage sensor, MAX471 pin VIN
Filament lamp pin 1Current and voltage sensor, MAX471 pin VOUT
Bench power supply pin V+Pushbutton pin 1a

The code

The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.

sketch.ino · Arduino Uno R3
// Lamp power meter: a MAX471 current sensor board in a lamp's supply lead,
// and the voltage, current and power on a 16x2 I2C LCD.
//
//   A0      the MAX471 board's AT (1 V an amp)
//   A1      the board's VT (a fifth of the supply voltage)
//   GND     the board's GND, which is also the supply's minus
//   VIN     the bench supply's plus;  VOUT  to the lamp
//   LCD     SDA -> A4    SCL -> A5    VCC -> 5 V    GND -> GND
//
// The MAX471 puts 500 uA out for every amp through its 35 milliohm resistor,
// and the board turns that into a voltage across 2 kohm: 1 V an amp, so on a
// 5 V Uno one converter step is 4.9 mA. VT is the supply through a 30 k and
// 7.5 k divider, a fifth of it, so a step is 24 mV.
//
// Press the button to light the lamp. A cold tungsten filament has about a
// tenth of its hot resistance, so the current jumps and then settles as it
// warms up. The peak line keeps the highest reading, which with a reading
// every tenth of a second or so is the tail of that surge, not its top.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

const int AT_PIN = A0;
const int VT_PIN = A1;
LiquidCrystal_I2C lcd(0x27, 16, 2);
long peakMa = 0;

// The average of 16 readings, in millivolts.
long readMv(int pin) {
  long sum = 0;
  for (int i = 0; i < 16; i++) sum += analogRead(pin);
  return sum * 5000L / 1023L / 16;
}

void setup() {
  Serial.begin(115200);
  Serial.println("Mokxi Arduino Uno: lamp power meter");
  lcd.init();
  lcd.backlight();
}

void loop() {
  long mA = readMv(AT_PIN);        // 1 mV on AT is 1 mA
  long mV = readMv(VT_PIN) * 5;    // VT is a fifth of the supply
  long mW = mV * mA / 1000;
  if (mA > peakMa) peakMa = mA;

  lcd.setCursor(0, 0);
  lcd.print(mV / 1000);
  lcd.print('.');
  lcd.print((mV % 1000) / 100);
  lcd.print(" V  ");
  lcd.print(mA);
  lcd.print(" mA     ");
  lcd.setCursor(0, 1);
  lcd.print(mW);
  lcd.print(" mW pk ");
  lcd.print(peakMa);
  lcd.print("   ");

  Serial.print("V: ");
  Serial.print(mV);
  Serial.print(" mV  I: ");
  Serial.print(mA);
  Serial.print(" mA  P: ");
  Serial.print(mW);
  Serial.print(" mW  peak: ");
  Serial.println(peakMa);
  delay(100);
}

Code walkthrough

The key functions of the sketch, and what each one does.

readMv sketch.ino

Takes 16 analogRead samples on a pin, adds them up, then scales the sum to millivolts on a 5 V reference and divides by 16. The average steadies the reading.

// The average of 16 readings, in millivolts.
long readMv(int pin) {
  long sum = 0;
  for (int i = 0; i < 16; i++) sum += analogRead(pin);
  return sum * 5000L / 1023L / 16;
}

setup sketch.ino

Opens serial at 115200, prints a hello line, starts the LCD and turns on its backlight.

void setup() {
  Serial.begin(115200);
  Serial.println("Mokxi Arduino Uno: lamp power meter");
  lcd.init();
  lcd.backlight();
}

loop sketch.ino

Reads current in mA straight from AT, since 1 mV there is 1 mA. It multiplies the VT reading by 5 to get supply millivolts, then computes mW. It updates peakMa, writes two lines to the LCD, prints to serial, and waits 100 ms.

void loop() {
  long mA = readMv(AT_PIN);        // 1 mV on AT is 1 mA
  long mV = readMv(VT_PIN) * 5;    // VT is a fifth of the supply
  long mW = mV * mA / 1000;
  if (mA > peakMa) peakMa = mA;

  lcd.setCursor(0, 0);
  lcd.print(mV / 1000);
  lcd.print('.');
  lcd.print((mV % 1000) / 100);
  lcd.print(" V  ");
  lcd.print(mA);
  lcd.print(" mA     ");
  lcd.setCursor(0, 1);
  lcd.print(mW);
  lcd.print(" mW pk ");
  lcd.print(peakMa);
  lcd.print("   ");

  Serial.print("V: ");
  Serial.print(mV);
  Serial.print(" mV  I: ");
  Serial.print(mA);
  Serial.print(" mA  P: ");
  Serial.print(mW);
  Serial.print(" mW  peak: ");
  Serial.println(peakMa);
  delay(100);
  // ... 1 more lines in the editor

Troubleshooting

The usual mistakes with this circuit, and the fix for each.

  • The peak does not show the true surge top. This project
    That is expected. The meter samples about every tenth of a second, so the peak is the tail of the surge rather than its very top.
  • Voltage reads zero or current looks wrong. This project
    Check the bench supply's minus, the lamp's other end and the Uno GND are all joined to the board's GND, and that the button is closed.
  • The current reading is wrong. Current and voltage sensor
    Put the sensor in series with the supply, with the plus side toward the source. AT gives about 1 V per amp, so convert analogRead using your reference voltage (5 V for 1023).
  • The voltage reading is off. Current and voltage sensor
    VT is one fifth of the input voltage, so multiply by 5. It works only up to about 25 V, and the maximum current is 3 A.
  • The input reads random HIGH and LOW when the button is not pressed. Pushbutton
    A floating pin picks up noise. Add a 10 k pull-down or pull-up resistor, or use INPUT_PULLUP and wire the button between the pin and GND. Then pressed reads LOW.
  • The button seems always pressed, or never changes. Pushbutton
    A 4-leg tactile switch has legs joined in pairs. Place it across the breadboard center gap so the pairs sit on different rows. Wired along one side, the legs are already connected.
  • The lamp is dim or does not light when driven from a board pin. Filament lamp
    A lamp needs far more current than a pin gives (a pin is limited to about 20 mA). Switch it with a transistor or MOSFET from its own supply that matches the lamp's voltage rating.
  • The lamp's brightness lags or it burns out the switch when it first turns on. Filament lamp
    A cold filament draws several times its running current at first. Size the switch for that surge, not just the steady current.

Change it and keep it

Open it in the editor, change the circuit or the code, and keep your version in a free account.