If you've ever tried to use GPIO pins 34, 35, 36, 37, 38, or 39 as outputs on
your ESP32 and found that digitalWrite() simply doesn't work, you're not alone.
This is one of the most common frustrations for ESP32 beginners. The answer lies in the
hardware architecture of the ESP32 chip itself.
📋 Quick Answer
GPIO pins 34-39 on ESP32 are INPUT-ONLY. They physically lack the output driver circuitry. This is a hardware limitation that cannot be changed with software. These pins can only read signals, not drive them. Check our ESP32 Pinout Reference for complete pin mapping.
1. The Hardware Reason
The ESP32 chip is designed with different types of GPIO pins. While most GPIO pins (0-33) have both input and output capabilities, pins 34-39 are specifically designed as input-only pins.
Looking at the ESP32's internal architecture:
- GPIO 0-33: Full bidirectional I/O with push-pull and open-drain output drivers
- GPIO 34-39: Input-only pins with no output driver transistors
These pins are connected directly to the internal ADC (Analog-to-Digital Converter) and are optimized for high-impedance analog sensing. The silicon simply doesn't include the output stage transistors for these pins.
⚠️ No Software Workaround
This is a physical hardware limitation. No amount
of code, register manipulation, or library changes can make these pins output signals. Even
setting pinMode(34, OUTPUT) will silently fail.
2. Which Pins Exactly?
Here's a complete list of the input-only pins on ESP32:
| GPIO Pin | ADC Channel | Common Use |
|---|---|---|
| GPIO 34 | ADC1_CH6 | Analog input, sensor reading |
| GPIO 35 | ADC1_CH7 | Analog input, potentiometer |
| GPIO 36 (VP) | ADC1_CH0 | Sensor VP, high-precision ADC |
| GPIO 37 | ADC1_CH1 | Analog input (not exposed on all boards) |
| GPIO 38 | ADC1_CH2 | Analog input (not exposed on all boards) |
| GPIO 39 (VN) | ADC1_CH3 | Sensor VN, high-precision ADC |
Note: On many ESP32 dev boards (like the ESP32-DevKitC), GPIO 37 and 38 are not broken out to pins and are used internally.
3. Why Did Espressif Design It This Way?
There are several engineering reasons for this design decision:
A. Silicon Area Optimization
Output drivers require additional transistors (typically a push-pull pair). By omitting these on six pins, Espressif saved valuable silicon real estate, reducing chip cost and power consumption.
B. Dedicated Analog Inputs
These pins are connected to ADC1 (Analog-to-Digital Converter 1). ADC1 is special because it works even when WiFi is active (unlike ADC2). Having dedicated input-only pins ensures:
- Lower noise for analog measurements
- No accidental output driver interference
- Higher input impedance for sensitive sensors
C. Pin Count Constraints
The ESP32 has limited package pins. Espressif needed to balance between GPIO count and other dedicated functions (power, crystal, flash, etc.). Making some pins input-only was a practical trade-off.
4. Common Symptoms When You Try to Use Them as Outputs
Here's what happens when you mistakenly try to use these pins as outputs:
// This code will NOT work!
void setup() {
pinMode(34, OUTPUT); // Silently ignored
pinMode(35, OUTPUT); // Silently ignored
}
void loop() {
digitalWrite(34, HIGH); // Pin stays LOW
delay(500);
digitalWrite(34, LOW); // No change
delay(500);
}
Symptoms you'll observe:
- No compiler or upload errors
- The pin stays at whatever voltage level the external circuit pulls it to
- LEDs connected to these pins won't light up
- Relays or transistors won't trigger
5. How to Check If a Pin Is Input-Only
You can write a quick test function to verify pin capabilities:
void testPinOutput(int pin) {
Serial.print("Testing GPIO ");
Serial.print(pin);
Serial.print(": ");
pinMode(pin, OUTPUT);
// Try to set HIGH
digitalWrite(pin, HIGH);
delayMicroseconds(100);
int highRead = digitalRead(pin);
// Try to set LOW
digitalWrite(pin, LOW);
delayMicroseconds(100);
int lowRead = digitalRead(pin);
if (highRead == HIGH && lowRead == LOW) {
Serial.println("OUTPUT capable ✓");
} else {
Serial.println("INPUT-ONLY (or externally pulled)");
}
}
void setup() {
Serial.begin(115200);
delay(1000);
// Test specific pins
testPinOutput(33); // Should work
testPinOutput(34); // Will report input-only
testPinOutput(35); // Will report input-only
}
6. Which Pins SHOULD You Use for Outputs?
✅ Safe Output Pins on ESP32
These GPIO pins are safe to use as outputs in most applications. For detailed pinouts and wiring diagrams, see our interactive ESP32 Pinout Reference:
- GPIO 2, 4, 5, 12, 13, 14, 15: General purpose I/O
- GPIO 16, 17, 18, 19, 21, 22, 23: Commonly used for SPI, I2C, and general output
- GPIO 25, 26, 27, 32, 33: Available on most boards
⚠️ Pins to Avoid or Use Carefully
- GPIO 0: Boot mode pin - must be HIGH during boot (requires pull-up resistor)
- GPIO 1, 3: UART TX/RX - used for serial communication
- GPIO 6-11: Connected to internal flash - DO NOT USE
- GPIO 12: Boot mode (must be LOW for 3.3V flash)
7. Alternative Solutions
If you've run out of output pins, consider these alternatives:
A. Use a GPIO Expander
I2C GPIO expanders like MCP23017 or PCF8574 add 8-16 additional I/O pins using just 2 ESP32 pins (SDA/SCL).
// Using MCP23017 with Adafruit library
#include
Adafruit_MCP23X17 mcp;
void setup() {
mcp.begin_I2C();
mcp.pinMode(0, OUTPUT); // Expander pin 0 as output
}
void loop() {
mcp.digitalWrite(0, HIGH);
delay(500);
mcp.digitalWrite(0, LOW);
delay(500);
}
B. Use Shift Registers
A 74HC595 shift register can provide 8 outputs using only 3 ESP32 pins. Chain multiple for even more outputs.
C. Multiplex with Transistors
Use matrix techniques with transistors to control many outputs with fewer GPIO pins (common in LED matrices).
8. ESP32-S2, S3, and C3 Differences
Different ESP32 variants have different input-only pin configurations:
| ESP32 Variant | Input-Only Pins |
|---|---|
| ESP32 (Original) | GPIO 34, 35, 36, 37, 38, 39 |
| ESP32-S2 | GPIO 46 |
| ESP32-S3 | None (all GPIO are bidirectional) |
| ESP32-C3 | None (but fewer total GPIO) |
If you need maximum flexibility, the ESP32-S3 is an excellent choice as all its GPIO pins support both input and output.
Summary
🚀 Key Takeaways
- GPIO 34-39 are INPUT-ONLY on the original ESP32 - this is a hardware limitation
- These pins are optimized for analog sensing with ADC1
- No software workaround exists - you cannot make them output signals
- Use GPIO 2, 4, 5, 12-19, 21-27, 32-33 for outputs instead
- Consider GPIO expanders or shift registers if you need more outputs
- ESP32-S3 has no input-only pins if you need maximum flexibility
- Use our ESP32 Pinout Reference for complete pin documentation
Understanding these hardware limitations will save you hours of debugging. Always consult the official ESP32 datasheet when planning your pin assignments!