Built-in project · Arduino Uno R3

Lamp inrush on an Arduino Uno

An Uno switches a 6 V filament lamp with a MOSFET and samples its current every millisecond: the surge of a cold filament, and how long it takes to settle. The whole build, an Arduino Uno and 4 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.

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

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

The circuit runs here once the page has loaded.

What you'll learn

  • Switching a load with a logic level MOSFET
  • Measuring current with a shunt resistor
  • Why filament lamps surge when cold
  • Sampling once per millisecond with millis
  • Difficulty: Intermediate
  • Time: About 25 minutes
  • Board: Arduino Uno R3
  • Parts: 6

How it works

A cold tungsten filament has a very low resistance, so a lamp draws a surge when first switched on. An IRLZ44N MOSFET on pin 9 switches a 6 V lamp from four AA cells. A 1 ohm resistor to ground turns the lamp current into a voltage, one volt per amp, which A0 reads.

Each cycle the sketch turns the lamp on and takes 300 readings, one per millisecond. It prints the peak of the first five, the reading at 10 ms, the final running current and how many ms it took to settle within a tenth of that. Then the lamp rests for 3 seconds.

Parts list

6 parts, plus the jumper wires. They retail for about $35; on Mokxi they're free.

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
Resistor, 1 Ω pin 2Arduino Uno R3 pin GND
Battery: AA, coin cell, LiPo pin V-Arduino Uno R3 pin GND
MOSFET pin GArduino Uno R3 pin 9
MOSFET pin SArduino Uno R3 pin A0
Resistor, 1 Ω pin 1Arduino Uno R3 pin A0
Filament lamp pin 1MOSFET pin D
Battery: AA, coin cell, LiPo pin V+Filament lamp pin 2

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 inrush: an Uno switches a 6 V filament lamp with a MOSFET and measures
// its current through a 1 ohm resistor, a millisecond at a time, to catch
// the surge a cold filament draws.
//
//   lamp      6 V 0.3 A, from the + of four AA cells to the MOSFET's drain
//   MOSFET    IRLZ44N: gate -> pin 9, source -> A0 and 1 ohm to GND
//   cells     - to GND, shared with the Uno
//
// Tungsten's resistance climbs with its temperature, and a lamp's filament is
// about a twelfth of its hot resistance when it is cold. So for the first few
// milliseconds after it is switched on it draws several times its rated
// current, until it heats up and its resistance rises. That surge is why
// lamps usually fail at the moment they are switched on.
//
// The 1 ohm resistor turns the current into a voltage, a volt an amp, and
// one ADC count is 4.9 mA. Each cycle prints the peak of the first five
// readings (the surge),
// the reading 10 ms in, the running current, and how long it took to come
// within a tenth of it. A warm filament draws less: the cycles after the
// first start from a lamp that has not cooled all the way down.

const int GATE_PIN = 9;
const int SHUNT_PIN = A0;

long milliamps(int counts) {
  return (long)counts * 5000 / 1023;  // 1 ohm: a volt an amp
}

int samples[300];

void setup() {
  Serial.begin(9600);
  pinMode(GATE_PIN, OUTPUT);
  Serial.println("Lamp inrush: 6 V 0.3 A lamp, 1 ohm shunt");
}

void loop() {
  digitalWrite(GATE_PIN, HIGH);
  unsigned long start = millis();
  for (int i = 0; i < 300; i++) {
    while (millis() - start < (unsigned long)i) {
    }
    samples[i] = analogRead(SHUNT_PIN);
  }
  long running = milliamps(samples[299]);
  int settled = 299;
  while (settled > 0 && milliamps(samples[settled - 1]) * 10 <= running * 11) settled--;

  int peak = 0;
  for (int i = 0; i < 5; i++) peak = max(peak, samples[i]);

  Serial.print("inrush ");
  Serial.print(milliamps(peak));
  Serial.print(" mA, 10 ms ");
  Serial.print(milliamps(samples[10]));
  Serial.print(" mA, running ");
  Serial.print(running);
  Serial.print(" mA, settled in ");
  Serial.print(settled);
  Serial.println(" ms");

  delay(700);
  digitalWrite(GATE_PIN, LOW);
  delay(3000);
}

Code walkthrough

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

milliamps sketch.ino

Converts an ADC count into milliamps. With a 1 ohm shunt, a volt is an amp, so it scales the count by 5000 over 1023. One count is about 4.9 mA.

long milliamps(int counts) {
  return (long)counts * 5000 / 1023;  // 1 ohm: a volt an amp
}

setup sketch.ino

Opens serial, sets pin 9 as an output for the MOSFET gate and prints a line naming the 6 V 0.3 A lamp and the 1 ohm shunt.

void setup() {
  Serial.begin(9600);
  pinMode(GATE_PIN, OUTPUT);
  Serial.println("Lamp inrush: 6 V 0.3 A lamp, 1 ohm shunt");
}

loop sketch.ino

Switches the lamp on and fills samples with 300 readings of A0, one per ms. It works out the running current from the last one, finds when readings first stay within ten percent of it, and prints the results. The lamp then stays on 700 ms and off 3 seconds.

void loop() {
  digitalWrite(GATE_PIN, HIGH);
  unsigned long start = millis();
  for (int i = 0; i < 300; i++) {
    while (millis() - start < (unsigned long)i) {
    }
    samples[i] = analogRead(SHUNT_PIN);
  }
  long running = milliamps(samples[299]);
  int settled = 299;
  while (settled > 0 && milliamps(samples[settled - 1]) * 10 <= running * 11) settled--;

  int peak = 0;
  for (int i = 0; i < 5; i++) peak = max(peak, samples[i]);

  Serial.print("inrush ");
  Serial.print(milliamps(peak));
  Serial.print(" mA, 10 ms ");
  Serial.print(milliamps(samples[10]));
  Serial.print(" mA, running ");
  Serial.print(running);
  Serial.print(" mA, settled in ");
  Serial.print(settled);
  Serial.println(" ms");

  delay(700);
  digitalWrite(GATE_PIN, LOW);
  delay(3000);
  // ... 1 more lines in the editor

Troubleshooting

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

  • The readings are all zero This project
    Check the MOSFET gate goes to pin 9, its source to A0 and the 1 ohm resistor, and the battery's negative to the Uno's GND.
  • No surge shows up This project
    The lamp may still be warm from the last cycle. A warm filament draws less, so the surge shrinks.
  • Currents look too high or low This project
    The math assumes a 1 ohm shunt. Use that value, or change the scale in milliamps.
  • The load stays partly on or flickers when the pin is not driving, such as at boot or in input mode. MOSFET
    A floating gate picks up noise. Add a pull-down of about 10 k from gate to source on an N-channel part, or pull a P-channel gate up to its source voltage.
  • The N-channel load is always on or never turns on. Source, gate, and drain legs were mixed up. MOSFET
    Use the N-channel as a low-side switch: load to the supply, drain to the load, source to ground. Check your datasheet pinout, since 2N7000 and BS250 differ. Share the grounds.
  • The LED is dim, burns out, or the pin reads wrong because the resistor value is off. Resistor
    Read the color bands again. A 220 ohm to 330 ohm resistor suits a typical LED on 5 V. 10k is a common pull-up or pull-down value. Check with a multimeter if unsure.
  • A pull-up or pull-down resistor is missing, so the input floats and reads random values. Resistor
    Tie the input to 5 V or ground through about 10k. Or use INPUT_PULLUP and wire the switch to ground.
  • 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.

Change it and keep it

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