Modules
Status LEDs Done Right: Current-Limiting Resistors
Calculate a status LED resistor from voltage, forward drop, and target current; then check GPIO limits, boot behavior, polarity, PWM, and PCB placement.
Published Updated
Pick brightness current, not the resistor first
A status LED is a diode. Once forward-biased, a small voltage change can cause a large current change, so a series element must limit current. For an ordinary indicator driven from a voltage rail, that element is a resistor:
R = (V_drive - V_F) / I_LED
V_F is the LED forward voltage at the chosen current, not a universal number. It varies with color, part, current, and temperature. Use the exact LED datasheet’s typical and maximum/minimum curves. Modern high-efficiency LEDs are often clearly visible at 0.5–2 mA; starting at 10 or 20 mA wastes power and may exceed a microcontroller pin budget.
For a 3.3 V GPIO, a red LED with about 1.9 V forward drop at a 2 mA target gives:
R = (3.3 V - 1.9 V) / 0.002 A = 700 Ω
Choose a nearby standard value such as 680 Ω or 750 Ω, then calculate the worst cases. At maximum supply and minimum LED forward voltage, current is highest. At minimum supply, maximum forward voltage, and a non-ideal GPIO output level, brightness is lowest.
For a blue LED with 2.8 V forward drop, the same nominal calculation gives 250 Ω, so 270 Ω is a reasonable starting value. But a blue part whose forward voltage approaches the rail may dim sharply as battery voltage falls. Measuring a sample at the intended current is better than designing from a color name.
Choose source or sink drive deliberately
An active-high, sourcing connection is:
GPIO -> resistor -> LED anode; LED cathode -> GND
Writing the pin high turns it on. An active-low, sinking connection is:
3V3 -> resistor -> LED anode; LED cathode -> GPIO
Writing the pin low turns it on. Some MCUs sink more current than they source, but check the electrical-characteristics table. Include the specified V_OH or V_OL at the intended current in the resistor calculation when margins matter.
Label the schematic net LED_STATUS_N for an active-low signal and document the firmware polarity. That avoids a driver that turns the light on during sleep. Either order—resistor before or after the LED—limits the same series current; choose the order that makes routing and probing clear.
Check pin and package limits
The absolute-maximum current is a damage boundary, not an operating target. Use the recommended GPIO current and verify total limits for the I/O bank, supply pins, and package. Four LEDs at 8 mA each may violate an aggregate limit even when each pin looks acceptable.
Also consider the rail budget. A battery product with a 20 µA sleep target cannot tolerate a “small” 1 mA power LED. Use a much lower current, blink briefly, drive it only when needed, or omit it from the production variant.
If the required LED current exceeds a safe GPIO load, drive an N-channel MOSFET or transistor. This is also appropriate for LED strips or multiple indicators on a higher-voltage rail. Add the gate/base components and off-state pull resistor from a proven circuit; the GPIO should control the switch, not carry load current.
Keep LEDs away from boot straps and critical nets
At reset, a GPIO may be an input, have an internal pull, or emit a short pulse. An LED resistor becomes an external pull-up or pull-down and can alter a boot strap. On ESP32-C3, avoid casual LED connections to GPIO2, GPIO8, and GPIO9. If a strap pin is unavoidable, calculate the resistor network and verify startup at voltage and temperature corners.
An LED on a regulator enable, chip-select, reset, crystal, USB, or I2C line changes that circuit too. Use a dedicated GPIO where possible. The ESP32 and RP2040 reset/boot guide shows why passing ERC is not enough for sampled startup pins.
Power LEDs wired directly across a rail also affect debug. Put the resistor and LED downstream of the protection/regulator whose status they represent. A “5 V present” LED connected after the 3.3 V regulator does not actually prove 5 V is present; name and place it according to the measured rail.
Use PWM without creating noise
PWM reduces average brightness by switching the LED fully on and off. Set peak current with the resistor exactly as for steady drive; duty cycle does not make an unsafe peak current acceptable. Choose a frequency above visible flicker, while considering camera banding and electromagnetic noise.
Fast edges can inject current into ground and supply. For a single 1 mA LED this is usually minor, but a multiplexed display is a real switching load and needs local decoupling. Avoid synchronizing noisy LED PWM with sensitive ADC sampling, or pause PWM during measurements.
Verify polarity, footprint, and optics
The KiCad symbol and physical package encode polarity in different ways. Confirm symbol pin numbers map to the footprint’s anode and cathode pads. Then check the manufacturer drawing: a package mark may identify the cathode, while a library footprint’s silkscreen mark could be subtle or reversed. This is a concrete example of the difference between a symbol and footprint.
Put a visible polarity mark on fabrication silkscreen that survives assembly. For hand assembly, orient all indicators consistently. Verify the resistor value is not confused with a nearby pull-up during placement.
Include polarity and actual fitted value in the preflight review; both appear on the list of PCB mistakes that cost a respin.
Mechanical placement determines usefulness. Check viewing angle, enclosure wall thickness, light-pipe position, and light leakage between indicators. Keep LEDs back from an unprotected board edge and provide courtyard clearance for a light pipe. Render the full assembly in 3D, but confirm with a printed drawing or enclosure prototype.
Make a tiny verification table
For each LED, record:
| Item | Example |
|---|---|
| Function/polarity | Status, active low |
| Rail and GPIO level | 3.3 V, sink drive |
| Exact LED/forward voltage | MPN, 1.9 V typ at 2 mA |
| Resistor/current range | 750 Ω, calculated corners |
| Reset state | Off, external pull checked |
| Firmware test | On, off, PWM, sleep |
On the first board, measure voltage across the resistor and calculate actual current with I = V_R / R. Test cold boot before firmware configures the pin, reset, sleep, and the lowest supply voltage. A status LED is simple enough to calculate fully—and visible enough that every mistake reaches the user.