For a 2×8 matrix = 16 LEDs, don’t drive all LEDs directly one-pin-per-LED unless you have lots of GPIO. Use a multiplexed matrix:
2 row lines
8 column lines
16 LEDs
8 current-limiting resistors, usually one per column
That uses 10 GPIO total.
Typical wiring:
Text
ROW1 ── LED LED LED LED LED LED LED LED ── columns
ROW2 ── LED LED LED LED LED LED LED LED ── columns
COL1 COL2 COL3 COL4 COL5 COL6 COL7 COL8
Use one resistor per column, e.g.:
Text
ESP32 GPIO column pin ── 150Ω to 330Ω ── LED column
Then scan rows quickly:
Enable row 1.
Set the 8 column pins for row 1 pattern.
Wait ~0.5–2 ms.
Disable row 1.
Enable row 2.
Set the 8 column pins for row 2 pattern.
Repeat forever.
For ESP32 at 3.3 V with red 0805 LEDs, I’d start with:
220 Ω if multiplexing and you want decent brightness
330 Ω for safer/lower current
470 Ω–1 kΩ if they only need to be dim indicators
Important: because each row is only on ~50% of the time, each LED appears dimmer than a continuously driven LED. You can compensate with slightly lower resistors, but keep ESP32 GPIO current limits in mind. For a clean design, use transistor/MOSFET row drivers if more than a few LEDs can be on at once.