ESP32/Joining a network/40. Wi-Fi station mode
Your chip
Your language
Joining a network · 40 of 81

Wi-Fi station mode

Joining a network you do not own, and doing it in a way that survives a router being slow, a password being wrong, and the network disappearing halfway through.

/esp32/wifi-station-mode · arduino · S3

What it does

Station mode means the board joins a network somebody else runs, the same way a laptop does. It asks the router for an address, the router hands one out, and from then on the board can reach anything on that network and anything on the internet beyond it.

The part people underestimate is that joining takes time — usually two to six seconds, occasionally much longer, and sometimes never. Code that assumes the connection is up by the next line will work on your desk and fail in someone's house.

WiFi.begin() to an IP address
3.3 s
How slow the router is today1.0×
Time to an IP
3.3 s
Your code runs
not until it is up
Button still works
no
It works, and it works because your router is fast. Put a timeout on that loop — 15 seconds — and carry on offline when it expires. A thermostat that shows the temperature without Wi-Fi is a product; one that shows nothing is a brick.

Treat "connected" as something that becomes true later

Start the connection in setup(), then check the state once per pass through loop(). Everything that needs the network — a web server, an MQTT client, an NTP sync — waits for that check rather than assuming.

The alternative is a device that does nothing at all while the router is slow: no display, no button, no readings, and a watchdog reset if it goes on long enough.

Two facts that catch everybody

  • The ESP32, S2, S3, C3 and C6 have no 5 GHz radio. Only the C5 does. A network that works on your phone and not on the board is usually two bands sharing one name.
  • The reason code is worth printing. A bad password is reason 15 or 204, 201 is a network that was never found, and those two send you in completely different directions.
On your S3
ChipXtensa LX7 · 2 × 240 MHz
Board settingESP32S3 Dev Module
Default I2CSDA 8 · SCL 9
Watch out forThe port vanishes after upload

The code

Connect once in setup(), then check the state instead of assuming it. The loop below never blocks for longer than a second.

wifi_station.ino
#include <WiFi.h>

const char* SSID = "your-network";
const char* PASS = "your-password";
volatile uint8_t lastReason = 0;   // ESP-IDF disconnect reason code

void setup() {
  Serial.begin(115200);
  WiFi.onEvent([](WiFiEvent_t, WiFiEventInfo_t info) {
    lastReason = info.wifi_sta_disconnected.reason;
  }, ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
  WiFi.mode(WIFI_STA);
  WiFi.setSleep(false);        // otherwise replies wait for the next DTIM beacon
  WiFi.begin(SSID, PASS);

  unsigned long start = millis();
  while (WiFi.status() != WL_CONNECTED && millis() - start < 15000) {
    delay(250);
    Serial.print(".");
  }

  if (WiFi.status() != WL_CONNECTED) {
    Serial.printf("\nfailed, reason %d\n", lastReason);
    return;                    // carry on offline rather than hanging
  }
  Serial.println(WiFi.localIP());
}

void loop() {
  if (WiFi.status() != WL_CONNECTED) {
    WiFi.reconnect();          // cheap, and it does nothing if already up
    delay(1000);
  }
}

WiFi.setSleep(false) is the line most people are missing when a board answers slowly. The default, minimum modem sleep, wakes the radio only for DTIM beacons, so a reply can wait up to one DTIM period. Turning sleep off removes that wait and keeps the receiver on.

When it does not work

It joins on your desk and not at the customer's house

Almost always a 5 GHz network. The ESP32, S2, S3, C3 and C6 have no 5 GHz radio; only the C5 does. The phone that set up the router may be hiding that there are two bands with the same name.

It connects, then drops every few minutes

Check power before code. Transmit bursts pull over 300 mA and a thin USB cable browns the board out. The reboot looks exactly like a crash.

Analog readings go wrong the moment Wi-Fi starts

On the ESP32, S2 and S3 the second ADC block is shared with the radio, and reads on its pins fail while Wi-Fi is using it. Move the sensor to an ADC1 pin.

The password is right and it still refuses

Print the disconnect reason code instead of guessing. A bad password shows as reason 15 or 204, reason 201 means the network was never found, and those two send you in completely different directions.

Where this goes next

Joining somebody else's network is half of it. Running your own is what a board does when there is no network to join.

Access point mode →

Edit this page — content/esp32/wifi-station-mode.mdx

Discuss this article

Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.

Browse ESP32 on the forum →