Built-in project · Arduino Uno R3

Dimmer on an Arduino Uno

A potentiometer on A0 sets the brightness of an LED on pin 9. Turn the knob while it runs. The whole build, an Arduino Uno and 3 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 15 minutes to build and run. Runs in your browser. Free, and no account needed.

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

Step by step, with the wiring and the common mistakes: Arduino Potentiometer Wiring and Code: Dim an LED

The circuit runs here once the page has loaded.

What you'll learn

  • Reading a voltage with an analog input
  • PWM as a way to dim an LED
  • Scaling 10 bits to 8 bits with a shift
  • Smoothing a noisy reading with a simple filter
  • Difficulty: Beginner
  • Time: About 15 minutes
  • Board: Arduino Uno R3
  • Parts: 5

How it works

The potentiometer's middle pin is wired to A0, so turning the knob changes the voltage the Uno reads. The sketch turns that reading into a PWM level on pin 9, which sets how bright the LED is.

analogRead gives 0 to 1023 and analogWrite wants 0 to 255, so the sketch shifts the reading right by two bits to fit.

A pot is slightly noisy, so the reading is smoothed first, which stops the LED flickering at low brightness. The serial monitor prints the knob percentage only when it changes.

Parts list

5 parts, plus the jumper wires. They retail for about $33; 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, 220 Ω pin 1Arduino Uno R3 pin 9
Potentiometer pin 3Arduino Uno R3 pin 5V
Potentiometer pin 1Arduino Uno R3 pin GND
LED, yellow pin CArduino Uno R3 pin GND
Potentiometer pin 2Arduino Uno R3 pin A0
LED, yellow pin AResistor, 220 Ω 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
// Dimmer: a potentiometer sets how bright an LED is.
//
//   A0     the pot's wiper (pin 2); its other two legs go to 5 V and GND
//   pin 9  the LED, through 220 ohm to GND
//
// The smallest complete analogue circuit there is: read a voltage, write a
// brightness. Turn the knob while it runs.
//
// # Ten bits in, eight bits out
//
// analogRead gives 0 to 1023 and analogWrite takes 0 to 255, so the reading is
// shifted right by two rather than divided: 1023 >> 2 is 255, and a shift on an
// AVR is one instruction where a divide is a call.
//
// # Why the reading is smoothed
//
// A pot's wiper is a sliding contact and the ADC's last bit is noise, so a
// steady knob still reads a count or two either way. Left alone, that makes the
// LED flicker at the bottom of its range where the eye is most sensitive. The
// filter here is the cheapest one that works: three quarters of the old value
// plus a quarter of the new, once every five milliseconds. It settles in about
// thirty milliseconds, which is faster than a hand can turn a knob.
//
// The serial line says the percentage, but only when it has moved by a percent,
// so turning the knob prints a sentence rather than a waterfall.

const int KNOB = A0;
const int LAMP = 9;

int smoothed = 0;
int said = -1;

void setup() {
  pinMode(LAMP, OUTPUT);
  analogWrite(LAMP, 0);
  Serial.begin(115200);
  Serial.println("Mokxi Arduino Uno: dimmer");
  Serial.println("turn the knob to set the brightness");
  smoothed = analogRead(KNOB);
}

void loop() {
  int raw = analogRead(KNOB);
  // A quarter of the new reading, three quarters of what we had.
  smoothed += (raw - smoothed) / 4;

  int level = smoothed >> 2;
  if (level > 255) {
    level = 255;
  }
  analogWrite(LAMP, level);

  int percent = (int)(((long)smoothed * 100L) / 1023L);
  if (percent != said) {
    said = percent;
    Serial.print("knob ");
    Serial.print(percent);
    Serial.print("% -> pwm ");
    Serial.println(level);
  }

  delay(5);
}

Code walkthrough

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

setup sketch.ino

Makes LAMP an output and turns it off, opens serial at 115200 baud, and takes a first reading of the knob so the smoothing starts from the right place.

void setup() {
  pinMode(LAMP, OUTPUT);
  analogWrite(LAMP, 0);
  Serial.begin(115200);
  Serial.println("Mokxi Arduino Uno: dimmer");
  Serial.println("turn the knob to set the brightness");
  smoothed = analogRead(KNOB);
}

loop sketch.ino

Reads the knob and moves smoothed a quarter of the way toward it. It shifts that value right by two to get 0 to 255, writes it to the LED, and prints the percentage when it changes. A 5 ms delay sets the pace.

void loop() {
  int raw = analogRead(KNOB);
  // A quarter of the new reading, three quarters of what we had.
  smoothed += (raw - smoothed) / 4;

  int level = smoothed >> 2;
  if (level > 255) {
    level = 255;
  }
  analogWrite(LAMP, level);

  int percent = (int)(((long)smoothed * 100L) / 1023L);
  if (percent != said) {
    said = percent;
    Serial.print("knob ");
    Serial.print(percent);
    Serial.print("% -> pwm ");
    Serial.println(level);
  }

  delay(5);
}

Troubleshooting

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

  • The LED does not change This project
    The pot's middle pin must go to A0, with its end pins on 5V and ground. The LED goes through the 220 ohm resistor from pin 9.
  • The knob works backward This project
    Swap the pot's 5V and ground legs.
  • The LED does nothing This project
    Check the LED's direction: anode toward the resistor, cathode to ground.
  • The reading jumps around or only covers part of the range. Potentiometer
    Wire the two outer legs to 5 V and ground and the middle leg (the wiper) to an analog pin. Using the wrong two legs gives a dead or partial range.
  • Turning the knob does nothing, or the value is stuck at 0 or 1023. Potentiometer
    Check that the wiper goes to an analog input (A0 to A5 on an Uno), not a digital pin. Make sure both ends are connected, since a floating end gives noise.
  • 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 LED does not light, or it lights once and then dies. LED
    LEDs have polarity. The longer leg (anode) goes toward the positive side. Always add a series resistor, about 220 ohms to 1 k ohm on a 5 V pin.

Change it and keep it

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