DEV Community

張旭豐
張旭豐

Posted on

Why Your M5Stack Button Freezes When WiFi Connects

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)