WiFi is the ESP32's superpower. While many microcontrollers can read sensors and blink LEDs, the ESP32 can do all of that and send data to the internet, receive commands from a server, or host its own web page -- all for under five dollars. In this article, you will learn how to connect your ESP32 to a WiFi network and make your first HTTP request.
🔗Connecting to WiFi (Station Mode)
The most common WiFi use case is Station mode (STA): your ESP32 connects to an existing WiFi network, just like your phone or laptop does.
Here is the minimal code to connect:
#include <WiFi.h>
const char* ssid = "YourNetworkName";
const char* password = "YourPassword";
void setup() {
Serial.begin(115200);
delay(1000);
Serial.printf("Connecting to %s", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConnected!");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {
// Your code here
}Upload this sketch, open the Serial Monitor at 115200 baud, and you should see something like:
Connecting to YourNetworkName......
Connected!
IP address: 192.168.1.47That IP address means your ESP32 is on the network and reachable by other devices.
🔗What Each Part Does
| Code | Purpose |
|---|---|
#include <WiFi.h> | Includes the ESP32 WiFi library (built into the ESP32 Arduino core) |
WiFi.begin(ssid, password) | Starts the connection process |
WiFi.status() | Returns the current connection status |
WL_CONNECTED | Constant indicating a successful connection |
WiFi.localIP() | Returns the IP address assigned by your router |
🔗WiFi Modes
The ESP32 supports three WiFi modes:
| Mode | Description | Use Case |
|---|---|---|
| Station (STA) | Connects to an existing network | Sending sensor data to the internet |
| Access Point (AP) | Creates its own WiFi network | Configuration portal, direct device-to-device |
| STA + AP | Both at the same time | Connect to internet while serving a config page |
🔗Access Point Mode
In AP mode, the ESP32 creates its own WiFi network that other devices can join. This is useful when there is no existing network available, or when you want to set up a configuration portal:
#include <WiFi.h>
const char* ap_ssid = "ESP32-Setup";
const char* ap_password = "12345678"; // Must be at least 8 characters
void setup() {
Serial.begin(115200);
delay(1000);
WiFi.softAP(ap_ssid, ap_password);
Serial.println("Access Point started!");
Serial.print("AP IP address: ");
Serial.println(WiFi.softAPIP());
}
void loop() {
// Serve a web page, handle configuration, etc.
}When this runs, you will see a new WiFi network called "ESP32-Setup" appear on your phone or laptop. The ESP32's IP in AP mode is usually 192.168.4.1.
Tip: AP mode is commonly used for initial setup -- the ESP32 starts in AP mode, serves a web page where you enter your home WiFi credentials, then switches to Station mode to connect to your network. Many commercial IoT devices work this way.
🔗Making HTTP Requests
Once connected to WiFi, the ESP32 can talk to web servers just like a browser. The HTTPClient library makes this straightforward.
🔗HTTP GET Request
This example connects to WiFi and fetches data from a public API:
#include <WiFi.h>
#include <HTTPClient.h>
const char* ssid = "YourNetworkName";
const char* password = "YourPassword";
void setup() {
Serial.begin(115200);
delay(1000);
// Connect to WiFi
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConnected!");
}
void loop() {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
http.begin("http://httpbin.org/ip"); // Public test API
int httpCode = http.GET();
if (httpCode > 0) {
Serial.printf("HTTP response code: %d\n", httpCode);
String payload = http.getString();
Serial.println(payload);
} else {
Serial.printf("HTTP request failed: %s\n",
http.errorToString(httpCode).c_str());
}
http.end(); // Free resources
}
delay(10000); // Wait 10 seconds before next request
}This fetches your ESP32's public IP address from httpbin.org and prints it to the Serial Monitor.
🔗HTTP POST Request
To send data to a server (for example, a sensor reading to a logging service):
void sendSensorData(float temperature) {
if (WiFi.status() != WL_CONNECTED) return;
HTTPClient http;
http.begin("http://yourserver.com/api/data");
http.addHeader("Content-Type", "application/json");
String json = "{\"temperature\":" + String(temperature, 1) + "}";
int httpCode = http.POST(json);
if (httpCode > 0) {
Serial.printf("POST response: %d\n", httpCode);
} else {
Serial.printf("POST failed: %s\n",
http.errorToString(httpCode).c_str());
}
http.end();
}🔗Checking Signal Strength
The WiFi.RSSI() function returns the Received Signal Strength Indicator in dBm. This is useful for diagnosing connectivity issues or choosing the best location for your device:
void printSignalStrength() {
int rssi = WiFi.RSSI();
Serial.printf("Signal strength: %d dBm", rssi);
if (rssi > -50) {
Serial.println(" (Excellent)");
} else if (rssi > -60) {
Serial.println(" (Good)");
} else if (rssi > -70) {
Serial.println(" (Fair)");
} else {
Serial.println(" (Weak - consider moving closer to router)");
}
}| RSSI Range | Signal Quality |
|---|---|
| -30 to -50 dBm | Excellent |
| -50 to -60 dBm | Good |
| -60 to -70 dBm | Fair |
| -70 to -80 dBm | Weak |
| Below -80 dBm | Unreliable |
🔗Handling Disconnections
WiFi connections are not permanent -- routers restart, signals drop, interference happens. A robust project should handle disconnections gracefully:
#include <WiFi.h>
const char* ssid = "YourNetworkName";
const char* password = "YourPassword";
unsigned long lastReconnectAttempt = 0;
const unsigned long reconnectInterval = 5000; // Try every 5 seconds
void connectToWiFi() {
Serial.printf("Connecting to %s", ssid);
WiFi.begin(ssid, password);
// Wait up to 10 seconds for connection
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
delay(500);
Serial.print(".");
attempts++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nConnected!");
Serial.print("IP: ");
Serial.println(WiFi.localIP());
} else {
Serial.println("\nConnection failed.");
}
}
void setup() {
Serial.begin(115200);
delay(1000);
WiFi.mode(WIFI_STA);
WiFi.setAutoReconnect(true); // ESP32 will try to reconnect automatically
connectToWiFi();
}
void loop() {
if (WiFi.status() != WL_CONNECTED) {
unsigned long now = millis();
if (now - lastReconnectAttempt > reconnectInterval) {
lastReconnectAttempt = now;
Serial.println("WiFi disconnected. Reconnecting...");
connectToWiFi();
}
}
// Your main code here -- check WiFi.status() before making requests
}Tip:
WiFi.setAutoReconnect(true)tells the ESP32 to automatically try to reconnect when the connection drops. The manual reconnection logic above acts as a fallback in case auto-reconnect does not succeed.
🔗A Note on Credentials
In these examples, the WiFi SSID and password are hardcoded directly in the source code. This is perfectly fine for learning and personal projects. However, for anything you plan to share or publish:
- Do not commit WiFi credentials to public repositories.
- Consider storing credentials in a separate
config.hfile that you add to.gitignore. - For a more polished approach, use the AP mode configuration portal described earlier to let users enter their own credentials.
A simple config.h approach:
// config.h (do not commit this file)
#define WIFI_SSID "YourNetworkName"
#define WIFI_PASSWORD "YourPassword"// main sketch
#include "config.h"
#include <WiFi.h>
void setup() {
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
// ...
}🔗A Note on ADC2 and WiFi
If you are using analog input pins while WiFi is active, be aware that ADC2 (GPIOs 0, 2, 4, 12, 13, 14, 15, 25, 26, 27) cannot be used while WiFi is on. The WiFi driver uses the ADC2 hardware internally.
If you need analog readings while connected to WiFi, use ADC1 pins (GPIOs 32, 33, 34, 35, 36, 39). These work fine alongside WiFi.
Warning: This is a hardware limitation, not a software bug. If your analog readings return 0 or garbage values while WiFi is connected, check whether you are using an ADC2 pin.
🔗Complete Example: WiFi Weather Logger
Here is a more complete example that ties together the concepts from this article -- connecting to WiFi, handling reconnection, and making periodic HTTP requests:
#include <WiFi.h>
#include <HTTPClient.h>
const char* ssid = "YourNetworkName";
const char* password = "YourPassword";
unsigned long lastRequestTime = 0;
const unsigned long requestInterval = 30000; // Every 30 seconds
void connectToWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi");
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
delay(500);
Serial.print(".");
attempts++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.printf("\nConnected! IP: %s | RSSI: %d dBm\n",
WiFi.localIP().toString().c_str(),
WiFi.RSSI());
} else {
Serial.println("\nFailed to connect.");
}
}
void setup() {
Serial.begin(115200);
delay(1000);
connectToWiFi();
}
void loop() {
// Reconnect if needed
if (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi lost. Reconnecting...");
connectToWiFi();
return;
}
// Make periodic requests
unsigned long now = millis();
if (now - lastRequestTime >= requestInterval) {
lastRequestTime = now;
HTTPClient http;
http.begin("http://httpbin.org/ip");
int httpCode = http.GET();
if (httpCode == 200) {
Serial.println("Response: " + http.getString());
} else {
Serial.printf("Request failed (code %d)\n", httpCode);
}
http.end();
}
}🔗What's Next?
HTTP requests are useful, but for IoT applications you often need something lighter, faster, and more suitable for real-time communication. In the next article, we will learn about MQTT -- the lightweight messaging protocol that is the backbone of most IoT systems.