A GPIO pin does nothing — pin identity, occupancy and drive mode
Question this page answers: “I set a pin high / I blink an LED and nothing happens — which assumption is wrong?”
Three assumptions break most often: which number you are driving, whether the pin is actually free on your board, and how the LED is driven. Check them in that order.
Step 1 — which number are you actually driving?
Physical pin number, board silkscreen, chip GPIO number and SDK name are four different things — the pin numbers guide disentangles them. Quick per-board traps:
- Pico / Pico 2 — code uses GP numbers (physical pin 4 is
GP2); the 40-pin header has its own physical numbering that does not match GP numbers. - Espressif boards — code uses GPIO numbers; the header row/column number on the board is not a GPIO number.
If the blink code compiles and runs but a different pin than expected toggles, this step already found the bug.
Step 2 — is the pin free on your board (and your module)?
A pin being a chip GPIO does not mean the board leaves it to you:
| Board | Pins to check | Why | Where the fact lives |
|---|---|---|---|
| ESP32-S3-DevKitC-1 | GPIO35 / 36 / 37 | occupied by internal storage on WROOM-1/1U Octal flash/PSRAM variants and on every WROOM-2 — a condition, not a blanket ban | guide |
| ESP32-DevKitC with a WROVER module | GPIO16 / 17 | used by the module’s internal PSRAM on WROVER-E / WROVER-IE; free on WROOM-32E / 32UE | module pages |
| Pico / Pico 2 | GP23 / 24 / 25 / 29 | internal board functions; not brought out to the J1/J2 headers at all | board pages |
If your pin is on this table, follow the link — the condition and its scope decide whether the pin can ever work for you.
Step 3 — is it an LED, and what kind?
- ESP32-S3-DevKitC-1 — the on-board RGB LED is addressable (one-wire protocol), on GPIO48 (v1.0) or GPIO38 (v1.1).
digitalWrite-style code will never light it; use an addressable-LED driver. Which GPIO depends on the revision: the RGB guide. - ESP32-DevKitC V4 — there is no user LED on this board; blinking “the LED” has no target. Wire your own, and see the V4 first flash guide.
- Pico / Pico 2 — GP25 drives the on-board LED as a plain GPIO (the SDK’s default LED pin); here the simple blink is the right model.
Step 4 — conflicts and direction
- A peripheral function on a pin (UART/I2C/SPI) is only legal on pins that actually mux it — “almost any GPIO” is not how hardware UART works on these chips. The bus guide’s check-before-wiring section shows how to verify a mapping instead of assuming it.
- Output direction and level: make sure nothing else drives the same net (an external pull-up/down or another device), and that you are not reading a pin you configured as input.
Step 5 — pins that affect boot
Some pins have a second job at power-up. On the ESP32-DevKitC the header marks GPIO0 as “Boot” — external circuitry that forces its level can stop the board from starting normally. If the board itself fails to boot only when your wiring is attached, suspect the boot-role pins before anything else. The pinned board guides list these roles where they document them; the full chip-level strapping tables are not reproduced here (see below).
What this page cannot tell you
- We did not reproduce these failures on hardware here. The page recombines already-verified board facts into a diagnostic order; the order is MCUID’s editorial work.
- The complete chip strapping tables. The chip datasheets own that content; the pinned board-level guides do not spell out every strapping pin’s internal pull state. We do not reconstruct them from memory — check the chip datasheet for your chip if Step 5 is your case.
- Your module’s variant, if unknown. Step 2’s conditions depend on which module your physical board carries; if you cannot tell, keep the condition open instead of assuming the pin is free.
Sources
- ESP32-DevKitC V4 User Guide — header table (GPIO0 marked “Boot”), module options (commit
5c06bf18) - ESP32-S3-DevKitC-1 v1.0 / v1.1 User Guides — GPIO35/36/37 storage condition, addressable RGB on GPIO48 (v1.0) / GPIO38 (v1.1) (commit
5c06bf18) - Pico SDK board headers — GP25 as the default LED pin (commit
079c6f39) - MCUID board data — Pico header occupancy (GP23/24/25/29 not on J1/J2, verified from the official board-level documentation), WROVER-E/IE GPIO16/17 internal-storage occupancy