How does a microcontroller control LED?

2025-10-28 15:02:30 23

Here’s a crisp, engineer-friendly guide to how a microcontroller (MCU) drives LEDs—from a single status LED to RGB strips—plus drop-in code snippets.

How does a microcontroller control LED?


1) The basics: one LED on one GPIO

Idea: A GPIO pin switches current through an LED with a series resistor to set the current.

  • Wiring (sourcing): MCU pin → resistor → LED → GND

  • Wiring (sinking): VCC → resistor → LED → MCU pin (pin pulls low)

Choose the resistor

R=(VCC−VF)/ILED

  • Example @ 5 V, red LED VF≈2.0 V, I=10 mA=0.01 A:
    R=(5.0−2.0)/0.01=300 Ω (pick 300–330 Ω)

  • Example @ 3.3 V, red LED VF≈2.0 V, I=10 mA:
    R=(3.3−2.0)/0.01=130 Ω (pick 150 Ω to be safe)

Notes

  • Don’t exceed per-pin current (often 2–20 mA) or per-port / package totals.

  • “Sinking” often lets you drive slightly more current on some MCUs.

  • Use push-pull outputs for normal LEDs; open-drain needs an external pull-up.


2) Brightness control: PWM

Idea: Keep the LED on for a fraction of time (duty cycle).

  • Frequency: ≥ 500 Hz for no flicker by eye; 1–4 kHz plays nicer with cameras.

  • Duty: 0% (off) … 100% (full bright).

Arduino (Uno, etc.)

 
const int LED = 9; // PWM pin
void setup(){ pinMode(LED, OUTPUT); }
void loop(){
  for(int d=0; d<=255; d++){ analogWrite(LED, d); delay(5); }
  for(int d=255; d>=0; d--){ analogWrite(LED, d); delay(5); }
}
 

STM32 HAL (concept)

 
// Init: GPIO as AF, TIMx CHy in PWM mode (CubeMX can generate this)
// Set brightness (0..Period):
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, duty);
 

Raspberry Pi Pico (MicroPython)

 
from machine import Pin, PWM
pwm = PWM(Pin(15)); pwm.freq(1000)
for d in range(0,65535,512): pwm.duty_u16(d)
 

3) RGB LEDs (3 channels)

Common-cathode/anode package: drive R, G, B separately with three GPIOs + three resistors.

  • Color = mix of PWM duties on each channel.

Arduino example

 
int R=9, G=10, B=11;
void setup(){ pinMode(R,OUTPUT); pinMode(G,OUTPUT); pinMode(B,OUTPUT); }
void color(uint8_t r,uint8_t g,uint8_t b){ analogWrite(R,r); analogWrite(G,g); analogWrite(B,b); }
void loop(){ color(255,0,0); delay(500); color(0,255,0); delay(500); color(0,0,255); delay(500); }
 

4) Many LEDs: multiplex, charlieplex, or drivers

  • Row/column multiplexing: Scan rows fast; each LED sees a duty slice.

  • Charlieplexing: Uses tri-state pins; great pin efficiency, trickier firmware.

  • Driver ICs (recommended):

    • Constant-current sinks (e.g., TLC5940, MBI, STP16) for precise brightness.

    • I²C PWM expanders (e.g., PCA9685 16-ch) for simple dimming.

    • LED matrix drivers (e.g., MAX7219) for 7-segment/dot-matrix displays.

Use NPN/N-MOSFETs to switch rows/columns when current per line > MCU pin rating.


5) High-power LEDs (1–3 W and up)

Don’t drive directly from GPIO. Use:

  • A constant-current LED driver (buck/linear) set to the LED’s current (e.g., 350 mA).

  • MCU controls EN/PWM pin of the driver for dimming.

  • Provide heatsinking; observe LED forward voltage (often 2.8–3.6 V for white/blue).


6) Addressable LED strips (WS2812B/NeoPixel, SK6812, etc.)

  • One data wire; 5 V power; each LED has an internal driver.

  • Level shifting 3.3 V → 5 V recommended; budget power (e.g., 60 mA/LED worst case).

  • Use libraries to meet tight timings.

Arduino (Adafruit_NeoPixel)

 
#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel strip(30, 6, NEO_GRB + NEO_KHZ800);
void setup(){ strip.begin(); strip.show(); }
void loop(){ strip.fill(strip.Color(255,0,0)); strip.show(); delay(500); }
 

7) Common pitfalls (and quick fixes)

  • LED reversed (flat edge/cathode to GND in sourcing topology) → flip it.

  • No resistor → LED or pin damage; always add one unless driver is constant-current.

  • Pin left as input → LED dim/always off; set OUTPUT/push-pull.

  • Too much current → lower duty/drive, increase resistor, or add a transistor/driver.

  • Flicker in videos → raise PWM frequency (2–4 kHz), or use constant-current drivers.


8) Minimal reference circuits

  • Simple indicator (sourcing): MCU pin → 330 Ω → LED → GND (5 V red LED @ ~9 mA).

  • Transistor switch (for >20–40 mA):
    MCU pin → 1–10 kΩ base/gate resistor → NPN/N-MOSFET → LED chain to +V; add current-set resistor in LED path.

  • Driver IC: MCU I²C/SPI → constant-current driver → LEDs (no per-LED resistors needed with many drivers).

Harendra Kumar
Harendra Kumar
Harendra Kumar holds a Ph.D. in Electrical Engineering with a specialization in power electronics. His academic expertise and years of experience allow him to break down complex concepts into clear, actionable information for his audience. Through his work, he aims to bridge the gap between advanced technology and its real-world applications. Harendra is an accomplished writer who specializes in creating high-quality, long-form technical articles on power electronics for B2B electronics platforms. His content combines deep technical knowledge with practical insights, making it a valuable resource for professionals in the electronics industry.