Do You Need This Article?
You need this if:
- You've built at least one M5Stack or ESP32 project
- That project used WiFi and buttons at the same time
- Button behavior became unpredictable after WiFi connected
You don't need this if:
- You've never used M5Stack or ESP32 before
- Your project uses WiFi or buttons, but never both together
- Your buttons work fine even when WiFi is active
If you're not sure which category you're in — try the code below. If the button freezes after WiFi connects, you're in the right place.
The Code That Reproduces the Problem
\`cpp
include
include
void setup() {
M5.begin();
WiFi.begin("SSID", "PWD");
while (WiFi.status() != WL_CONNECTED) {}
M5.Lcd.println("Ready!");
}
void loop() {
if (M5.BtnA.wasPressed()) M5.Lcd.println("Button A");
M5.update();
}
`\
If Button A stops responding after "Ready!" appears, keep reading.
Why It Happens
M5Stack Button A uses GPIO 39 on the ESP32. This pin is also used by the WiFi radio during high-activity moments — connecting, receiving data, scanning for networks. When WiFi activity spikes, it temporarily takes over the pin.
This isn't a bug in your code or the M5Stack library. It's a hardware pin conflict — GPIO 39 was never yours to begin with.
The Three Fixes, Ranked by Cleanliness
Fix 1: Move to GPIO 32 (Cleanest)
\`cpp
// GPIO 32 is not used by WiFi — clean separation
const int BUTTON_PIN = 32;
volatile bool pressed = false;
void IRAM_ATTR isr() {
pressed = true;
}
void setup() {
Serial.begin(115200);
pinMode(BUTTON_PIN, INPUT_PULLUP);
attachInterrupt(BUTTON_PIN, isr, FALLING);
}
void loop() {
if (pressed) {
Serial.println("Pressed!");
pressed = false;
}
}
`\
Fix 2: Use Button C Instead (Easiest)
Button C on GPIO 37 is not affected by WiFi on most M5Stack units:
\cpp
if (M5.BtnC.wasPressed()) {
// Button C works fine during WiFi activity
}
M5.update();
\\
Fix 3: Poll Directly (Last Resort)
\cpp
bool checkA() {
return digitalRead(39) == LOW;
}
\\
The Mental Model That Prevents Future Confusion
ESP32 pins are not dedicated. GPIO 39 is also the RTC GPIO 3. GPIO matrix routes signals from WiFi, touch, ADC, and your buttons through the same physical pins. When two functions need the same pin, one wins — and it's not always your code.
When hardware stops working after adding WiFi: check for pin conflicts first, not code bugs.
If the GPIO conflict idea made sense, the next question is which other ESP32 pins have hidden dual roles. That's a different problem — and a different article.
Top comments (0)