makeIRLEngineering notes

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.