⚡ ESP32 GPIO Not Working - Complete Fix Guide
🔍 Common Causes of GPIO Issues
- 📌 Input-Only Pins – GPIO 34, 35, 36, 39 are input-only (cannot be used as outputs)
- 📌 Strapping Pins – GPIO 0, 2, 5, 12, 15 affect boot behavior
- 📌 Pin Already in Use – Some pins are used by internal functions (flash, PSRAM, etc.)
- 📌 Incorrect Pin Mode – Using INPUT mode when you need OUTPUT
- 📌 Floating Pin – No pull-up/pull-down resistor on input pins
- 📌 Voltage Level Issues – ESP32 is 3.3V, not 5V tolerant on most pins
📊 ESP32 GPIO Pin Reference
| Pin Type | GPIO Numbers | Notes |
|---|---|---|
| Safe for OUTPUT | 4, 16, 17, 18, 19, 21, 22, 23, 25, 26, 27, 32, 33 | Best choices for beginners |
| Use with Caution | 0, 2, 5, 12, 15 | Affects boot; avoid if possible |
| Input Only | 34, 35, 36, 39 | Cannot be used as OUTPUT! |
| ADC1 (Good with WiFi) | 32, 33, 34, 35, 36, 37, 38, 39 | Use these for analog sensors |
| ADC2 (WiFi issues) | 0, 2, 4, 12, 13, 14, 15, 25, 26, 27 | Unreliable when WiFi is active |
1️⃣ Check Your Pin Mode Configuration
❌ WRONG - Using input-only pin as output:
pinMode(34, OUTPUT); // GPIO 34 is INPUT ONLY!
digitalWrite(34, HIGH); // This will NOT work
✅ CORRECT - Use proper output pins:
pinMode(4, OUTPUT); // GPIO 4 is safe for output
digitalWrite(4, HIGH); // This works!
🔧 Test with this simple sketch:
void setup() {
Serial.begin(115200);
pinMode(4, OUTPUT);
}
void loop() {
digitalWrite(4, HIGH);
Serial.println("Pin 4 HIGH");
delay(1000);
digitalWrite(4, LOW);
Serial.println("Pin 4 LOW");
delay(1000);
}
2️⃣ Avoid Strapping Pins at Boot
These pins affect how your ESP32 boots. Avoid using them or ensure proper pull-up/down resistors:
| Pin | Boot Behavior | Recommendation |
|---|---|---|
| GPIO 0 | LOW = Download mode | Pull HIGH (10kΩ to 3.3V) |
| GPIO 2 | Must be HIGH or floating | Avoid or pull HIGH |
| GPIO 5 | LOW = SD card mode | Pull HIGH |
| GPIO 12 | LOW = 1.8V flash | Pull HIGH (critical!) |
| GPIO 15 | LOW = boot from SD | Pull HIGH |
3️⃣ Add Pull-up or Pull-down Resistors
Floating input pins cause random readings. Use internal or external resistors:
Using internal pull-up (software):
pinMode(4, INPUT_PULLUP); // Enable internal pull-up
Using internal pull-down (ESP32 only):
pinMode(4, INPUT_PULLDOWN); // Enable internal pull-down
External resistor (more reliable for critical applications):
// Add 10kΩ resistor between GPIO and 3.3V for pull-up
// Add 10kΩ resistor between GPIO and GND for pull-down
4️⃣ Check Voltage Levels - 3.3V vs 5V
Use a level shifter for 5V devices:
// Connect 5V sensor through level shifter:
// 5V Sensor Output → Level Shifter (5V side)
// Level Shifter (3.3V side) → ESP32 GPIO
For analog inputs, use a voltage divider:
// Convert 5V to 3.3V:
// Use 2.2kΩ and 3.3kΩ resistors
// Max voltage: 5V * (3.3 / (2.2 + 3.3)) = 3.0V
5️⃣ Test with Minimal Hardware
Disconnect everything and test with just an LED:
// LED connected between GPIO 4 and GND (with 220Ω resistor)
void setup() {
pinMode(4, OUTPUT);
}
void loop() {
digitalWrite(4, HIGH);
delay(500);
digitalWrite(4, LOW);
delay(500);
}
If the LED blinks, your ESP32 is working! Then add components one by one.
📋 Complete ESP32 GPIO Reference
| GPIO | Input | Output | Notes |
|---|---|---|---|
| 0 | ✓ | ✓ | Boot mode (LOW = download) |
| 1 | ✓ | ✓ | UART TX (avoid) |
| 2 | ✓ | ✓ | Boot mode, built-in LED |
| 3 | ✓ | ✓ | UART RX (avoid) |
| 4 | ✓ | ✓ | Safe to use |
| 5 | ✓ | ✓ | Boot mode (VSPI CS) |
| 6-11 | - | - | Connected to flash (do not use) |
| 12 | ✓ | ✓ | Boot mode (must be HIGH) |
| 13 | ✓ | ✓ | ADC2 (WiFi issues) |
| 14 | ✓ | ✓ | ADC2 (WiFi issues) |
| 15 | ✓ | ✓ | Boot mode (must be HIGH) |
| 16 | ✓ | ✓ | Safe to use |
| 17 | ✓ | ✓ | Safe to use |
| 18 | ✓ | ✓ | Safe (SPI SCK) |
| 19 | ✓ | ✓ | Safe (SPI MISO) |
| 21 | ✓ | ✓ | Safe (I2C SDA) |
| 22 | ✓ | ✓ | Safe (I2C SCL) |
| 23 | ✓ | ✓ | Safe (SPI MOSI) |
| 25 | ✓ | ✓ | Safe (DAC) |
| 26 | ✓ | ✓ | Safe (DAC) |
| 27 | ✓ | ✓ | Safe |
| 32 | ✓ | ✓ | Safe (ADC1) |
| 33 | ✓ | ✓ | Safe (ADC1) |
| 34-39 | ✓ | ✗ | INPUT ONLY! |
✅ Best Practices for GPIO Pins
- Use GPIO 4, 16, 17, 18, 19, 21, 22, 23, 25, 26, 27, 32, 33 for reliable operation
- Avoid GPIO 0, 2, 5, 12, 15 unless you understand boot implications
- Remember: GPIO 34-39 are input only – never use them as outputs!
- Add pull-up/pull-down resistors to all input pins
- Use level shifters for 5V sensors
- Test each pin with a simple blink sketch before connecting components
❓ Frequently Asked Questions
Q: Why won't my ESP32 boot when I connect something to GPIO 0?
A: GPIO 0 is a strapping pin. When pulled LOW at boot, it puts the ESP32 into download mode. Add a 10kΩ pull-up resistor to keep it HIGH during boot.
Q: Can I use GPIO 1 and 3 for other things?
A: GPIO 1 (TX) and 3 (RX) are used for serial communication. You can use them, but you won't see Serial Monitor output.
Q: Why are my analog readings wrong when WiFi is on?
A: You're probably using ADC2 pins (GPIO 0,2,4,12-15,25-27). Use ADC1 pins (GPIO 32-39) for analog readings when WiFi is active.
Q: Does OceanRemote support custom pin mapping?
A: Yes! OceanRemote's firmware generator lets you configure which GPIO pins to use for relays and sensors. Try it free →
📚 Related Troubleshooting Guides
🚀 Need Ready-to-Use Firmware?
OceanRemote generates code with:
- ✓ Pre-configured GPIO pins
- ✓ Relay and sensor support
- ✓ WiFi and cloud connection
- ✓ No coding required