Guide no. 61
A slider on the web page sets the LED in real time, and every connected phone sees it move. With ESPAsyncWebServer.
By Ada Intelisano · informaticait.it technical team
- The WebSocket stays open: browser and board write to each other whenever they want.
- AsyncTCP and ESPAsyncWebServer libraries from the ESP32Async group.
textAllupdates every connected browser.ws.cleanupClients()in the loop, always.
In the weather station from guide no. 56 the browser asked for the data every 5 seconds. To control something you need more: move the slider on your phone and the LED changes immediately; and if another phone is connected, it sees its slider move by itself. That is the job of WebSockets.
1How it works
2The libraries
You need AsyncTCP and ESPAsyncWebServer, now maintained by the ESP32Async group: they work with ESP32 packages
2.x and 3.x. In PlatformIO the two lib_deps lines are enough; in Arduino IDE install them from the Library Manager, searching for the exact names.
3The sketch
No wires to connect: we use the LED already on the board (GPIO 2). Write your network name and password. The page is inside the sketch, as in guide no. 56.
// A slider on the web page sets the LED brightness. With WebSockets the value arrives at once // and all the connected phones see the slider move together. #include <WiFi.h> #include <AsyncTCP.h> #include <ESPAsyncWebServer.h> const char* NETWORK = "your-network-name"; const char* PASSWORD = "your-network-password"; const int LED = 2; int brightness = 0; // from 0 to 255 AsyncWebServer server(80); AsyncWebSocket ws("/ws"); const char PAGE[] PROGMEM = R"rawliteral( <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"> <title>LED</title><style>body{font-family:sans-serif;text-align:center;margin:24px}input{width:90%}b{font-size:40px;color:#1f7a3a}</style> </head><body><h1>LED brightness</h1><b id="v">0</b><br><br> <input type="range" id="c" min="0" max="255" value="0"> <script> const ws = new WebSocket('ws://' + location.host + '/ws'); const c = document.getElementById('c'), v = document.getElementById('v'); c.oninput = () => ws.send(c.value); ws.onmessage = e => { c.value = e.data; v.textContent = e.data; }; </script></body></html> )rawliteral"; void wsEvent(AsyncWebSocket* s, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t length) { if (type == WS_EVT_CONNECT) { client->text(String(brightness)); // whoever arrives sees the current value right away } else if (type == WS_EVT_DATA) { AwsFrameInfo* info = (AwsFrameInfo*)arg; if (info->final && info->index == 0 && info->len == length && info->opcode == WS_TEXT) { // a complete text message String text; for (size_t i = 0; i < length; i++) text += (char)data[i]; brightness = constrain(text.toInt(), 0, 255); analogWrite(LED, brightness); ws.textAll(String(brightness)); // tells everyone connected } } } void setup() { Serial.begin(115200); WiFi.mode(WIFI_STA); WiFi.begin(NETWORK, PASSWORD); while (WiFi.status() != WL_CONNECTED) delay(500); Serial.print("Open http://"); Serial.println(WiFi.localIP()); ws.onEvent(wsEvent); server.addHandler(&ws); server.on("/", HTTP_GET, [](AsyncWebServerRequest* r) { r->send(200, "text/html", PAGE); }); server.begin(); } void loop() { ws.cleanupClients(); // closes the connections the browser left half-open delay(10); }
wsEvent function is called by the library when something happens: a browser connects (WS_EVT_CONNECT) or a message arrives (WS_EVT_DATA). We never call it ourselves: we “register” it with ws.onEvent(wsEvent).4Try it
- The page opens but the slider does nothing: the browser cannot open the WebSocket; reload the page.
- Compile errors in AsyncTCP: you installed an old copy of the library; keep only the ESP32Async ones.
- After a while the board freezes:
ws.cleanupClients()is missing from the loop.
5Two things to know
- The “asynchronous” server works on its own: the
loopstays free for other things. That is why you do not put long waits insidewsEvent. - The library accepts only a few browsers at a time (8 at most, by default): enough for a home.
- The WebSocket here is not protected: anyone on your network can open the page and move the slider.
6Challenge yourself
- Instead of the LED, the servo from guide no. 41: the slider goes from 0 to 180 degrees.
- Three sliders for the RGB LED from guide no. 46.
- Have the board send the BME280 temperature to everyone every 2 seconds, with
ws.textAll().
- a WebSocket is a channel open in both directions;
- with
textAllthe board updates every connected browser; - the asynchronous server leaves the
loopfree.
Useful products
Other guides
- Resistor colour code and tolerances
- N-channel and P-channel MOSFETs
- Bipolar transistor (BJT) or MOSFET?
- Relays: how to drive them and how much current they draw
- THT and SMD/SMT components
- XIAO board pinouts
- LEDs: forward voltage and series resistor
- The multimeter: measuring voltage and current
- Wemos D1 mini: first steps
- MOSFET module with Arduino and ESP32
- Relay module with Arduino and ESP32
- 3D printing filaments: PLA, PETG and fibre-filled versions
- Analog and digital: the differences
- ADS1115: 16-bit converter with Arduino and ESP32
- From bits to real values: converting sensor readings
- DS3231 RTC clock with Arduino and ESP32
- Linear or switching regulator: which one to choose
- Step-down, step-up and buck-boost: choosing the right module
- Voltage divider: reading voltages higher than 5 V or 3.3 V
- Pull-up, pull-down and bounce: wiring a button properly
- 3.3 V and 5 V logic levels: getting an ESP32 and an Arduino to talk
- The I²C bus: addresses, pull-ups and the scanner
- Lithium batteries: voltages, charging and protection
- ESP32 power consumption and deep sleep: how long the battery lasts
- Temperature sensors compared
- ESP32: which pins to use and which to avoid
- Getting started with the ESP32 in Arduino IDE 2 and PlatformIO
- SSD1306 OLED display and 16×2 I²C LCD with Arduino and ESP32
- PIR motion sensor and HC-SR04 ultrasonic sensor
- Date and time from the Internet with the ESP32: NTP, Italian time zone and daylight saving time
- MicroSD data logger: saving measurements to CSV
- Solar-powered ESP32: panel, charger and the numbers for Italy
- Web server on the ESP32: control a relay from your phone
- Your first LED: wire it up and make it blink
- The button: let Arduino decide
- The potentiometer: turn a knob and read its value
- Soft light: adjusting the brightness of an LED
- The buzzer: playing notes and melodies
- The traffic light: three LEDs in sequence
- The thermometer: reading the temperature with the TMP36
- The servo motor: moving an arm with Arduino
- The night light: the photoresistor and your first decision
- The relay: switching on a light bulb with Arduino
- The LCD display: making Arduino write
- The electronic dice: your first complete project
- The RGB LED: every color from three lights
- The joystick: two-axis control with a shield
- The LED ring: twelve colors from a single pin
- The DC motor: driving it with a MOSFET
- Soil moisture: the plant that asks for water
- The stepper motor: turn exactly as far as you want
- The parking sensor: faster and faster beeps
- The 7-segment display: big, bright numbers
- Automatic watering: the plant that waters itself
- The keypad: a lock with a secret code
- Networked weather station: values and chart on your phone
- A Telegram bot on the ESP32: your home from your phone
- MQTT with the ESP32: the language of connected devices
- Updating the ESP32 over Wi-Fi (OTA)
- ESP-NOW: two ESP32 boards talking without a router
- Readings on a Google sheet, with deep sleep
- WiFiManager: choose the Wi-Fi from your phone
- Bluetooth LE with the ESP32: the phone without a network
- The camera in your browser with the ESP32-S3
- A portable Bluetooth speaker you build yourself
- Bluetooth desktop speakers, 2 × 20 W
- Stereo MP3 player with two buttons
- The shelf that plays music: a Visaton exciter
- How to solder well
- How much does it draw? Current and power with the INA219
- Load-cell scale with the HX711
- CO2 traffic light: when to open the windows
- RFID card door opener
- GPS: track logger on microSD
- LoRa: how far does it go? A range test with two boards
- Battery weather sign with an e-paper display
- Web radio with an ESP32 and an I2S amplifier
- Getting started with the Raspberry Pi Pico 2 in MicroPython
- Your first amplifier: the LM386 and a speaker
- Talking Arduino: the DFR0760 speech synthesis module
- The spectrum of your music on an LED matrix
- Drawing with 64 LEDs: the 8×8 matrix with the MAX7219
- A real voltage: the 12-bit MCP4725 DAC
- The heartbeat on Arduino: an ECG with the AD8232