Lesson 3: PWM output

On the UNO R3, analogWrite() doesn’t produce a steady voltage between 0 and 5 V. It writes a PWM wave: the pin switches fully on and off, and the value you pass sets how much of the time it’s on1.

What you need

  • Arduino UNO R3
  • USB cable
  • An LED and a current-⁠limiting resistor
  • The potentiometer from Lesson 2
  • Jumper wires

Wire it, then check it

Run the LED and a resistor in series from pin 9 to GND, and keep the knob on A0 from Lesson 2. Each UNO R3 I/O pin is rated for 20 mA DC5.

Before you run it on a real board, check each connection

Not working on a real board? Start with the wiring checklist.

Arduino version

l3-fade-arduino.ino
// Lesson 3, Arduino version: the knob on A0 sets how
// bright the LED on pin 9 is.
void setup() {
  pinMode(9, OUTPUT);
}

void loop() {
  int reading = analogRead(A0);  // 0 to 1023
  analogWrite(9, reading / 4);   // 0 to 255
}

analogWrite(9, value) takes a duty cycle from 0 (always off) to 255 (always on), so the sketch divides the 0–1023 reading by 41. Pin 9’s PWM comes from Timer14.

Register version

l3-fade-registers.ino
// Lesson 3, register version: Timer1 drives pin 9 (OC1A)
// directly.
void setup() {
  DDRB |= (1 << DDB1);  // pin 9 (PB1, OC1A) is an output
  // Non-inverting PWM on OC1A, 8-bit phase-correct (mode 1)
  TCCR1A = (1 << COM1A1) | (1 << WGM10);
  // Timer clock = 16 MHz / 64
  TCCR1B = (1 << CS11) | (1 << CS10);
}

void loop() {
  // Still read with analogRead: this lesson is about PWM
  int reading = analogRead(A0);
  OCR1A = reading / 4;  // duty = OCR1A / 255
}

Arduino’s startup code puts Timer1 in 8-⁠bit phase-⁠correct PWM with a prescaler of 64, using CS11 and CS103. This version writes the registers itself. In TCCR1A, COM1A1 clears the output when counting up past OCR1A and sets it when counting down, and WGM10 selects mode 1: phase-⁠correct PWM with TOP = 255. The frequency is 16 MHz ÷ (2 × 64 × 255), about 490 Hz. OCR1A sets the share of time the pin is on, from always off at 0 to always on at 2552.

Timer1's count and the pin 9 output for OCR1A = 64, 128 and 192The count climbs from 0 to 255 and falls back to 0 once every 2.04 ms. Pin 9 is HIGH while the count is below OCR1A, so each pulse is centred on the count's lowest point: HIGH 25.1%, 50.2%, 75.3% of each cycle at OCR1A = 64, 128, 192.TCNT1TOP025564128192BOTTOMBOTTOMOCR1AHIGH6425.1%12850.2%19275.3%one period: 510 ticks × 4 µs = 2.04 msTimer1's count and the pin 9 output for OCR1A = 64, 128 and 192The count climbs from 0 to 255 and falls back to 0 once every 2.04 ms. Pin 9 is HIGH while the count is below OCR1A, so each pulse is centred on the count's lowest point: HIGH 25.1%, 50.2%, 75.3% of each cycle at OCR1A = 64, 128, 192.TCNT1TOP025564128192BOTTOMBOTTOMOCR1AHIGH6425.1%12850.2%19275.3%period 2.04 ms
Timer1 in 8-⁠bit phase-⁠correct PWM. The count climbs to TOP and falls back to BOTTOM. With COM1A1 set, pin 9 is cleared when the count passes OCR1A on the way up and set again on the way down, so every HIGH pulse is centred on BOTTOM and lasts OCR1A ÷ 255 of the cycle2. One cycle is 510 ticks; at 16 MHz with Arduino’s prescaler of 64, a tick is 4 µs, so the period is 2.04 ms3, 5.

Registers in this lesson (ATmega328P data-⁠space addresses)2

RegisterAddressBit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0
TCCR1A0x80COM1A1COM1A0COM1B1COM1B0––WGM11WGM10
TCCR1B0x81ICNC1ICES1–WGM13WGM12CS12CS11CS10
OCR1AL0x88bit 7bit 6bit 5bit 4bit 3bit 2bit 1bit 0

Run it in the lab

At 1.25 V the reading is 256, OCR1A is 64, and the LED is on about 25% of the time2.

Drill

  1. Why divide the reading by 4?

    Show the answer

    analogRead gives 0 to 1023; analogWrite takes 0 to 255. Arduino’s own analogWrite example does the same division. 1

  2. What PWM frequency does pin 9 run at?

    Show the answer

    About 490 Hz. Phase-⁠correct PWM runs at 16 MHz ÷ (2 × 64 × 255), with the prescaler of 64 that Arduino sets up. 2, 3

  3. What does the pin do when OCR1A is 0 in this mode?

    Show the answer

    It stays LOW the whole time. In non-⁠inverting phase-⁠correct PWM, OCR1A at BOTTOM gives a continuously low output. 2

Sources

  1. Arduino reference: analogWrite
  2. Microchip ATmega328P datasheet DS40002061A: Timer1 PWM frequency (p135), extreme values (p136), Tables 16-3 and 16-4 (p141)
  3. ArduinoCore-⁠avr, cores/arduino/wiring.c: Timer1 prescaler 64, 8-⁠bit phase-⁠correct PWM
  4. ArduinoCore-⁠avr, variants/standard/pins_arduino.h: pin 9 is TIMER1A
  5. Arduino UNO R3 technical specifications: Clock speed: ATmega328P 16 MHz; DC Current per I/O Pin: 20 mA

Back to the course map