DIYables Web Apps Web Digital Pins

Overview

This ESP32 S3 Uno digital pins tutorial shows you how to control and monitor the Uno header pins of the ESP32 S3 Uno form board from a web page. You switch outputs ON and OFF with one click, and you see input states change live in your browser. The DIYables ESP32 WebApps library builds the web GPIO control page and the WebSocket link for you, so your phone or PC becomes a remote control panel.

In this tutorial, you will:

  1. Install the DIYables ESP32 WebApps library in the Arduino IDE
  2. Control digital pins from a web browser on your phone or PC
  3. Monitor input pins in real time over WebSocket
  4. Map the web pin numbers to the real GPIO numbers of the board
  5. Use bulk buttons (All ON, All OFF, Toggle All) to test many outputs at once
ESP32 S3 Uno digital pins web control

A step-by-step video is at the bottom of this page.

Features

The Web Digital Pins app turns a browser tab into a small control panel. Here is what it gives you.

One button per pin

Every pin you enable gets its own button on the page. You control each pin by its Uno label (D2, D3 … D13), separately from the others.

Live status

Buttons change color with the pin state: green for ON and red for OFF. Input pins update by themselves when the signal changes.

Bulk control

Three buttons, All ON, All OFF and Toggle All, act on every output pin at the same time.

Input or output from the page

You can switch a pin between Input and Output mode directly in the web interface.

Works on every screen

The page fits desktop, tablet and phone screens. It talks to the board over WebSocket, so updates appear without a page refresh.

Hardware Preparation

1×ESP32 S3 Uno-form Board
1×USB Cable Type-A to Type-C (for USB-A PC)
1×USB Cable Type-C to Type-C (for USB-C PC)

Or you can buy the following kits:

1×DIYables Sensor Kit (18 sensors/displays)
Disclosure: Some of the links provided in this section are Amazon affiliate links. We may receive a commission for any purchases made through these links at no additional cost to you.
Additionally, some of these links are for products from our own brand, DIYables .

Setup Instructions

Detailed Instructions

The example sketch needs no extra parts to start. Connect a few LEDs later if you want to see the outputs change. Follow these steps in order:

  1. New to the ESP32 S3 Uno? Follow ESP32 S3 Uno - Getting Started first.
  2. Wire it up (optional): connect an LED with a 220Ω resistor to D13 (GPIO12), because this board has no built-in LED on D13.
  3. Connect the board to your computer with a USB Type-C cable.
  4. Open Arduino IDE, choose the ESP32S3 Dev Module board and the correct COM port.
  5. Open the Library Manager by clicking the Libraries icon on the left bar of the Arduino IDE.
  6. Search for the library: type "DIYables ESP32 WebApps" and find the DIYables ESP32 WebApps Library by DIYables.
  7. Install it by clicking the Install button.
  • Search for DIYables ESP32 WebApps created by DIYables and click the Install button.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32S3 Dev Module
Library Manager
Type:
All
Topic:
All
DIYables ESP32 WebApps by DIYables
A comprehensive library designed for ESP32 that provides multiple professional web applications including Web Monitor, Chat, Digital Pin Control, Sliders, Joystick, Analog Gauge, Rotator Control, and Temperature Display via WebSocket communication. Features modular architecture for memory efficiency, automatic config handling, and perfect for IoT projects, robotics, sensor monitoring, servo/stepper control, temperature monitoring, and remote ESP32 control. More info
1.0.1
INSTALL
Newbiely.ino
···
1 void setup() {
Output
Serial Monitor
Ln 1, Col 1
ESP32S3 Dev Module on COM15
1
  1. Install the dependencies: the IDE asks about other required libraries. Click Install All.
  2. Get the code: in the Arduino IDE, go to File Examples DIYables ESP32 WebApps WebDigitalPins, or copy the ESP32 S3 Uno code below into the editor.

The sketch below is made for the ESP32 S3 Uno. The web page always uses pin numbers 0–13, which here mean the Uno header labels D0–D13. A small table, UNO_TO_GPIO, turns each label into the real GPIO number, so digitalWrite() and digitalRead() drive the right pin. D0 and D1 are left disabled, because they carry the Serial Monitor on this board.

/* * This ESP32 S3 Uno code was developed by newbiely.com * * This ESP32 S3 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3-uno/diyables-web-apps-web-digital-pins */ /* * DIYables WebApp Library - Web Digital Pins Example * * This example demonstrates the Web Digital Pins feature with automatic command handling: * - Control output pins D0-D13 via web interface * - Monitor input pins D0-D13 in real-time * - Individual pin ON/OFF control for outputs * - Real-time pin status feedback for inputs * - Bulk operations (All ON, All OFF, Toggle All) for outputs * * Hardware: ESP32 S3 Uno * * The web app uses pin numbers 0-13. In this sketch, they are the Uno header * labels D0-D13 of the ESP32 S3 Uno. The UNO_TO_GPIO table below turns each * label into the real GPIO number used by pinMode/digitalWrite/digitalRead. * * Setup: * 1. Update WiFi credentials below * 2. Upload the sketch to your ESP32 S3 Uno * 3. Open Serial Monitor to see the IP address * 4. Navigate to http://[IP_ADDRESS]/web-digital-pins */ #include <DIYables_ESP32_Platform.h> #include <DIYablesWebApps.h> // WiFi credentials - UPDATE THESE WITH YOUR NETWORK const char WIFI_SSID[] = "YOUR_WIFI_SSID"; const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD"; // ESP32 S3 Uno header label (index = D0..D13) -> GPIO number const int UNO_TO_GPIO[14] = { 44, // D0 (GPIO44) - UART0 RX, used by the Serial Monitor 43, // D1 (GPIO43) - UART0 TX, used by the Serial Monitor 18, // D2 (GPIO18) 17, // D3 (GPIO17) 19, // D4 (GPIO19) 20, // D5 (GPIO20) 3, // D6 (GPIO3) - boot strapping pin 14, // D7 (GPIO14) 21, // D8 (GPIO21) 46, // D9 (GPIO46) - boot strapping pin 10, // D10 (GPIO10) 11, // D11 (GPIO11) 13, // D12 (GPIO13) 12 // D13 (GPIO12) }; // Create WebApp server and page instances using platform abstraction ESP32ServerFactory serverFactory; DIYablesWebAppServer webAppsServer(serverFactory, 80, 81); DIYablesHomePage homePage; DIYablesWebDigitalPinsPage webDigitalPinsPage; // Array to store the state of each digital pin (D0-D13). Index corresponds to the Uno pin label. int pinStates[16] = { 0 }; // Initialize all states to LOW (0) void setup() { Serial.begin(9600); delay(1000); Serial.println("DIYables ESP32 WebApp - Web Digital Pins Example"); // Add home and digital pins pages webAppsServer.addApp(&homePage); webAppsServer.addApp(&webDigitalPinsPage); // Optional: Add 404 page for better user experience webAppsServer.setNotFoundPage(DIYablesNotFoundPage()); // Pin Configuration Examples: // Method 1: Enable specific pins individually for output control // D0 and D1 are the Serial Monitor (UART0) pins on the ESP32 S3 Uno. // Using them as outputs stops the Serial Monitor, so they are disabled here. //webDigitalPinsPage.enablePin(0, WEB_PIN_OUTPUT); // D0 (GPIO44, RX - use with caution) //webDigitalPinsPage.enablePin(1, WEB_PIN_OUTPUT); // D1 (GPIO43, TX - use with caution) webDigitalPinsPage.enablePin(2, WEB_PIN_OUTPUT); // D2 (GPIO18) webDigitalPinsPage.enablePin(3, WEB_PIN_OUTPUT); // D3 (GPIO17) webDigitalPinsPage.enablePin(4, WEB_PIN_OUTPUT); // D4 (GPIO19) //webDigitalPinsPage.enablePin(5, WEB_PIN_OUTPUT); // Comment/uncomment to disable/enable //webDigitalPinsPage.enablePin(6, WEB_PIN_OUTPUT); // Comment/uncomment to disable/enable webDigitalPinsPage.enablePin(13, WEB_PIN_OUTPUT); // D13 (GPIO12) - connect an external LED here // Method 2: Enable pins for input monitoring webDigitalPinsPage.enablePin(8, WEB_PIN_INPUT); // D8 (GPIO21) webDigitalPinsPage.enablePin(9, WEB_PIN_INPUT); // D9 (GPIO46) //webDigitalPinsPage.enablePin(10, WEB_PIN_INPUT); // Comment/uncomment to disable/enable //webDigitalPinsPage.enablePin(11, WEB_PIN_INPUT); // Comment/uncomment to disable/enable // Method 3: Enable all pins at once (uncomment to use) // for (int pin = 2; pin <= 13; pin++) { // webDigitalPinsPage.enablePin(pin, WEB_PIN_OUTPUT); // or WEB_PIN_INPUT as needed // } // Method 4: Enable pins in a range using for loop (uncomment to use) // for (int pin = 7; pin <= 11; pin++) { // webDigitalPinsPage.enablePin(pin, WEB_PIN_OUTPUT); // or WEB_PIN_INPUT as needed // } // Initialize enabled pins int outputPins[] = { 2, 3, 4, 13 }; // Uno pin labels. D0/D1 are left out (Serial Monitor pins) for (int i = 0; i < 4; i++) { int pin = outputPins[i]; pinMode(UNO_TO_GPIO[pin], OUTPUT); digitalWrite(UNO_TO_GPIO[pin], LOW); pinStates[pin] = LOW; } int inputPins[] = { 8, 9 }; for (int i = 0; i < 2; i++) { int pin = inputPins[i]; pinMode(UNO_TO_GPIO[pin], INPUT); // Use INPUT_PULLUP if needed pinStates[pin] = digitalRead(UNO_TO_GPIO[pin]); } // Start the WebApp server if (!webAppsServer.begin(WIFI_SSID, WIFI_PASSWORD)) { while (1) { Serial.println("Failed to start WebApp server!"); delay(1000); } } // Return the current state to display on Web App webDigitalPinsPage.onPinRead([](int pin) { return pinStates[pin]; // Return the current state of the pin // You can implement custom read logic here if needed }); // Handle the control request from Web App (for output pins) webDigitalPinsPage.onPinWrite([](int pin, int state) { digitalWrite(UNO_TO_GPIO[pin], state); pinStates[pin] = state; // You can implement custom control logic here if needed }); // Handle pin mode change requests (optional) webDigitalPinsPage.onPinModeChange([](int pin, int mode) { if (mode == WEB_PIN_OUTPUT) { pinMode(UNO_TO_GPIO[pin], OUTPUT); digitalWrite(UNO_TO_GPIO[pin], LOW); pinStates[pin] = LOW; } else if (mode == WEB_PIN_INPUT) { pinMode(UNO_TO_GPIO[pin], INPUT); // or INPUT_PULLUP as needed pinStates[pin] = digitalRead(UNO_TO_GPIO[pin]); } // You can implement custom mode change logic here if needed }); } void loop() { // Handle WebApp server communications webAppsServer.loop(); // Monitor input pins for real-time updates static unsigned long lastInputCheck = 0; if (millis() - lastInputCheck > 100) { // Check every 100ms lastInputCheck = millis(); // Check input pins for changes and send real-time updates int inputPins[] = { 8, 9 }; for (int i = 0; i < 2; i++) { int pin = inputPins[i]; int currentState = digitalRead(UNO_TO_GPIO[pin]); if (currentState != pinStates[pin]) { pinStates[pin] = currentState; // Send real-time update to web clients webDigitalPinsPage.updatePinState(pin, currentState); } } } // Add your main application code here delay(10); }
  1. Set your WiFi: change these two lines to your network name and password:
const char WIFI_SSID[] = "YOUR_WIFI_SSID"; const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";
  1. Upload the code by clicking the Upload button in the Arduino IDE.
  2. Open the Serial Monitor and set it to 9600 baud. You should see something like this:
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32S3 Dev Module
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32S3 Dev Module' on 'COM15')
New Line
9600 baud
DIYables ESP32 WebApp - Web Digital Pins Example INFO: Added app / INFO: Added app /web-digital-pins DEBUG: Enabling pin 2 with mode OUTPUT DEBUG: Enabling pin 3 with mode OUTPUT DEBUG: Enabling pin 4 with mode OUTPUT DEBUG: Enabling pin 13 with mode OUTPUT DEBUG: Enabling pin 8 with mode INPUT DEBUG: Enabling pin 9 with mode INPUT DIYables WebApp Library Platform: ESP32 Network connected! IP address: 192.168.0.2 HTTP server started on port 80 Configuring WebSocket server callbacks... WebSocket server started on port 81 WebSocket URL: ws://192.168.0.2:81 WebSocket server started on port 81 ========================================== DIYables WebApp Ready! ========================================== 📱 Web Interface: http://192.168.0.2 🔗 WebSocket: ws://192.168.0.2:81 📋 Available Applications: 🏠 Home Page: http://192.168.0.2/ 📟 Digital Pins: http://192.168.0.2/web-digital-pins ========================================== WebSocket client connected from: 192.168.0.5 New WebSocket connection established
Ln 11, Col 1
ESP32S3 Dev Module on COM15
2
  1. No output? Press the RESET button on the board and watch the Serial Monitor again.
  2. Open the web page: write down the IP address and type it into the address bar of a browser on your phone or PC, for example http://192.168.0.2. The home page looks like this:
ESP32 S3 Uno DIYables WebApp Home page with Web Digital Pins app
  1. Open the Web Digital Pins app by clicking its link. You will see this interface:
ESP32 S3 Uno DIYables WebApp Web Digital Pins app
  1. Go there directly next time: add /web-digital-pins after the IP address, for example http://192.168.0.2/web-digital-pins.
  2. Tip: click the pin 13 button to switch it ON and OFF. If you wired the external LED to D13 (GPIO12), it lights up and goes dark with each click.

Creative Customization - Adapt the Code to Your Project

Your project decides which pins you need and in which mode. The sketch shows a few ways to pick them. In all of them, the number you pass is the Uno label (2 means D2), and the web page accepts 0 to 13 only.

2. Configure Pin Settings

Choose the method that fits the number of pins you use.

Method 1: Enable Specific Pins

Pick pins one by one. This is the clearest way when you use only a few pins.

// Enable individual pins (Uno labels) for web control webDigitalPinsPage.enablePin(2, WEB_PIN_OUTPUT); // D2 (GPIO18) as output webDigitalPinsPage.enablePin(3, WEB_PIN_OUTPUT); // D3 (GPIO17) as output webDigitalPinsPage.enablePin(4, WEB_PIN_INPUT); // D4 (GPIO19) as input

Method 2: Enable Pin Ranges

A for loop enables a block of pins in a few lines.

// Enable a range of pins (D2 to D13) for output control for (int pin = 2; pin <= 13; pin++) { webDigitalPinsPage.enablePin(pin, WEB_PIN_OUTPUT); }

Method 3: Enable All Pins

One call enables every pin from 0 to 13. On the ESP32 S3 Uno, D0 and D1 are the Serial Monitor pins, so disable them again if you still need the Serial Monitor.

// Enable all pins 0-13 for control webDigitalPinsPage.enableAllPins(); webDigitalPinsPage.disablePin(0); // D0 (GPIO44) - Serial Monitor RX webDigitalPinsPage.disablePin(1); // D1 (GPIO43) - Serial Monitor TX

4. Upload the Sketch

  1. Choose the board: Tools → Board → esp32 → ESP32S3 Dev Module
  2. Choose the port: Tools → Port → [your ESP32 S3 Uno port]
  3. Click the Upload button

5. Get the IP Address

  1. Open Tools → Serial Monitor
  2. Set the baud rate to 9600
  3. Wait until the ESP32 S3 Uno joins your WiFi
  4. Note the IP address it prints (for example 192.168.1.100)

6. Access the Digital Pins Interface

In your web browser, open this address:

http://[ESP32_S3_UNO_IP_ADDRESS]/web-digital-pins

Example: http://192.168.1.100/web-digital-pins

How to Use

The page is simple, but knowing what each part shows saves you time when you test real hardware.

Pin Control Interface

Each enabled pin appears as a card. The card shows the pin number (the Uno label, 0–13), the current state (ON in green or OFF in red), a button to toggle the state, and the pin type (Input or Output).

Individual Pin Control

  1. Turn a pin ON: click its button while it shows "OFF"
  2. Turn a pin OFF: click its button while it shows "ON"
  3. Watch the state: the buttons update by themselves to show the current state

Bulk Operations

The bulk buttons act on many pins with one click. They only change output pins. Input pins always show the real signal.

All ON

This sets every output pin to HIGH. It is a fast way to check that all connected LEDs or relays work.

All OFF

This sets every output pin to LOW. Use it as a safe "everything off" button.

Toggle All

This flips every output: ON pins go OFF and OFF pins go ON. Click it a few times for a simple blinking effect.

Real-time Monitoring

The page and the board talk over WebSocket, so a change shows up right away. If your code changes a pin and reports it, the page updates too. Several people can open the page at the same time and watch the same ESP32 S3 Uno.

ESP32 S3 Uno Pinout

The pinout diagram below shows the ESP32 S3 Uno form board. Use it to find each Uno header pin (D2, D9, D13…) and its GPIO number before you connect LEDs, relays or switches.

ESP32 S3 Uno pinout diagram

Hardware Connections

The web page only switches pins. What happens next depends on what you connect. Below are common examples, written with the Uno label and the GPIO number. Remember that ESP32 S3 Uno pins use 3.3V logic and are NOT 5V tolerant.

Output Pin Examples

LED Control

ESP32 S3 Uno Pin → LED (with resistor) → Ground D2 (GPIO18) → LED Anode → 220Ω Resistor → GND D3 (GPIO17) → LED Anode → 220Ω Resistor → GND

Relay Control

ESP32 S3 Uno Pin → Relay Input D4 (GPIO19) → Relay IN1 D5 (GPIO20) → Relay IN2

Motor Control (via Motor Driver)

ESP32 S3 Uno Pin → Motor Driver Input D6 (GPIO3) → Motor Driver IN1 D7 (GPIO14) → Motor Driver IN2 D9 (GPIO46) → Motor Driver ENA (PWM)

WARNING

D6 (GPIO3) and D9 (GPIO46) are boot strapping pins on the ESP32 S3 Uno. The chip reads them at startup to choose its boot mode. If a motor driver or another circuit pulls them to the wrong level during reset, the board may not boot or may fail to upload code. If that happens, unplug the wire from that pin while you upload, or move the signal to a free pin such as D2, D3, D4 or D5.

Input Pin Examples

Switch Input

Use 3.3V for the pull-up resistor, not 5V.

Switch → ESP32 S3 Uno Pin (with pull-up resistor) Switch → D8 (GPIO21) → 10kΩ resistor → 3.3V → GND

Sensor Input

Sensor Signal → ESP32 S3 Uno Pin PIR Sensor → D10 (GPIO10) Ultrasonic → D11 (GPIO11) (Echo)

WARNING

Many relay modules and ultrasonic sensors (like the HC-SR04) run at 5V. A 5V signal going INTO an ESP32 S3 Uno pin, such as the ultrasonic Echo pin, can damage the board. Use a voltage divider (for example 1kΩ and 2kΩ) or a logic level shifter. For relay modules, choose one that accepts a 3.3V input signal.

Code Customization

The library gives you callbacks, so you can add your own logic around each web action. In the snippets below, pin is always the Uno label (0–13), and UNO_TO_GPIO[pin] gives the real GPIO number.

Adding Pin Change Callbacks

The onPinWrite() callback runs every time someone clicks an output button. Add your own actions inside it, like printing a message.

void setup() { // Called when the web page changes an output pin webDigitalPinsPage.onPinWrite([](int pin, int state) { digitalWrite(UNO_TO_GPIO[pin], state); pinStates[pin] = state; Serial.print("Pin D"); Serial.print(pin); Serial.print(" changed to: "); Serial.println(state ? "HIGH" : "LOW"); // Add your custom logic here if (pin == 13 && state == HIGH) { Serial.println("LED on D13 (GPIO12) turned ON!"); } }); }

Custom Pin Initialization

The small helper below sets an output by its Uno label and tells the web page about it. The other snippets on this page use it too.

// Helper: set an output pin (Uno label) and update the web page void setPinState(int pin, int state) { digitalWrite(UNO_TO_GPIO[pin], state); pinStates[pin] = state; webDigitalPinsPage.updatePinState(pin, state); } void setup() { // Configure pin modes pinMode(19, INPUT_PULLUP); // D4 (GPIO19) as input with pull-up pinMode(20, OUTPUT); // D5 (GPIO20) as output // Set outputs to the states you want at startup pinMode(18, OUTPUT); // D2 (GPIO18) pinMode(17, OUTPUT); // D3 (GPIO17) setPinState(2, HIGH); // Turn on D2 setPinState(3, LOW); // Turn off D3 }

Reading Input Pins

This loop reads every enabled input once per second and sends the value to the page.

void loop() { static unsigned long lastRead = 0; if (millis() - lastRead > 1000) { // Read every second // Read input pins and update web interface for (int pin = 0; pin <= 13; pin++) { if (webDigitalPinsPage.isPinEnabled(pin) && webDigitalPinsPage.getPinMode(pin) == WEB_PIN_INPUT) { int currentState = digitalRead(UNO_TO_GPIO[pin]); webDigitalPinsPage.updatePinState(pin, currentState); } } lastRead = millis(); } }

Advanced Features

When the basic version works, you can group pins or run patterns from your own code. The page still shows every change.

Pin Groups

Put related pins in arrays, then switch a whole group with one function call.

// Define pin groups (Uno labels) const int LED_PINS[] = {2, 3, 4, 5}; // D2-D5 (GPIO18, 17, 19, 20) const int RELAY_PINS[] = {7, 8, 10, 11}; // D7, D8, D10, D11 (GPIO14, 21, 10, 11) void controlLEDGroup(bool state) { for (int pin : LED_PINS) { setPinState(pin, state); } } void controlRelayGroup(bool state) { for (int pin : RELAY_PINS) { setPinState(pin, state); } }

Pattern Generation

This "running light" turns on one pin at a time, from D2 to D13, every 500 ms.

void runLightPattern() { static unsigned long lastChange = 0; static int currentPin = 2; if (millis() - lastChange > 500) { // Change every 500ms // Turn off all pins D2-D13 for (int pin = 2; pin <= 13; pin++) { setPinState(pin, LOW); } // Turn on current pin setPinState(currentPin, HIGH); // Move to next pin currentPin++; if (currentPin > 13) currentPin = 2; lastChange = millis(); } }

PWM Control Integration

Every Uno digital pin on the ESP32 S3 Uno supports PWM, so you can mix ON/OFF control with brightness control.

void setup() { // Enable digital pins for on/off control webDigitalPinsPage.enablePin(9, WEB_PIN_OUTPUT); // D9 (GPIO46) webDigitalPinsPage.enablePin(10, WEB_PIN_OUTPUT); // D10 (GPIO10) // Set PWM pins for brightness control analogWrite(46, 128); // D9 (GPIO46): 50% brightness analogWrite(10, 255); // D10 (GPIO10): 100% brightness }

Safety Considerations

A wrong connection can stop the board from booting or even damage a pin. Read these notes before you connect real loads.

Pin Usage Guidelines

D0 and D1 (RX/TX)

On the ESP32 S3 Uno, D0 (GPIO44) and D1 (GPIO43) are the UART0 pins that carry the Serial Monitor and code upload. Avoid them. Using them as outputs stops Serial Monitor messages and can get in the way of uploading.

D13

D13 (GPIO12) is a good pin for your first test, but the ESP32 S3 Uno has no built-in LED on it. Connect an external LED with a 220Ω resistor to see the result.

D6 and D9

D6 (GPIO3) and D9 (GPIO46) are boot strapping pins. They work fine as normal I/O after startup, but a circuit that pulls them to the wrong level during reset can stop the board from booting or uploading.

D2–D5, D7, D8, D10–D12

These are the safest pins for general digital input and output. Use them first in your projects.

Current Limitations

Maximum current per pin

An ESP32 S3 Uno pin can give only a small current. Keep it under about 20mA, and never go above the 40mA absolute limit. Always use a resistor with LEDs, and use a transistor or a relay module for motors, lamps and other big loads. Also watch the total current of all pins together.

Voltage levels

ESP32 S3 Uno pins use 3.3V logic and are NOT 5V tolerant. Make sure every connected device works with 3.3V signals, and use a level shifter or voltage divider for 5V signals.

Common Problems and Debug Tips

Common Issues

1. A pin does not respond

Check that the pin is enabled in the code and that its mode (Input or Output) is right. Then check the wiring and look for short circuits. Remember that the code number 13 means D13 (GPIO12), not GPIO13.

2. The web page does not update

Look at the WebSocket status and refresh the browser page. Make sure your phone or PC is on the same WiFi network, and check the Serial Monitor for error messages.

3. Bulk buttons do nothing

The bulk buttons only change output pins, so make sure your pins are set as outputs. Also check that your power supply can feed all loads at the same time.

4. Input pins show the wrong state

A floating input reads random values. Add a pull-up or pull-down resistor (or use INPUT_PULLUP), keep the signal at 3.3V, keep the wires short, and check the pin mode.

Debug Tips

This function prints the state and mode of every enabled pin. Call it from loop() when something looks wrong.

void debugPinStates() { Serial.println("=== Pin States ==="); for (int pin = 0; pin <= 13; pin++) { if (webDigitalPinsPage.isPinEnabled(pin)) { Serial.print("D"); Serial.print(pin); Serial.print(" (GPIO"); Serial.print(UNO_TO_GPIO[pin]); Serial.print("): "); Serial.print(digitalRead(UNO_TO_GPIO[pin]) ? "HIGH" : "LOW"); Serial.print(" ("); Serial.print(webDigitalPinsPage.getPinMode(pin) == WEB_PIN_OUTPUT ? "OUTPUT" : "INPUT"); Serial.println(")"); } } Serial.println("=================="); }

Project Ideas

A web page with ON/OFF buttons fits many real projects. Here are some ideas to start from.

Home Automation

Switch room lights, move window blinds with a motor driver, turn heating or cooling on and off, or arm a simple security system.

Garden Automation

Start and stop an irrigation pump, switch grow lights, and control fans for temperature and humidity.

Tutorial Control

Power tools on and off through relays, control the tutorial lights and ventilation, and add safety interlocks.

Educational Projects

Show how logic gates work, build a traffic light, make an alarm system, or run remote control experiments in class.

Integration Examples

These two examples mix web control with your own logic. They use the setPinState() helper from above.

Motion-Activated Lighting

A PIR sensor on D3 turns on an LED on D2 for 5 seconds. Most PIR modules (like the HC-SR501) give a 3.3V output, which is safe for the ESP32 S3 Uno.

void setup() { webDigitalPinsPage.enablePin(2, WEB_PIN_OUTPUT); // D2 (GPIO18): LED webDigitalPinsPage.enablePin(3, WEB_PIN_INPUT); // D3 (GPIO17): PIR sensor pinMode(18, OUTPUT); // D2 (GPIO18) pinMode(17, INPUT); // D3 (GPIO17) } void loop() { if (digitalRead(17) == HIGH) { // Motion detected on D3 (GPIO17) setPinState(2, HIGH); // Turn on LED delay(5000); // Keep on for 5 seconds setPinState(2, LOW); // Turn off LED } }

Temperature-Controlled Fan

A fan (through a relay or transistor) on D4 turns on when the temperature goes above 25°C.

void loop() { float temperature = getTemperature(); // Your temperature reading function if (temperature > 25.0) { setPinState(4, HIGH); // D4 (GPIO19): turn on fan } else { setPinState(4, LOW); // D4 (GPIO19): turn off fan } }

Next Steps

When you are comfortable with Web Digital Pins, try these apps from the same library:

  1. WebSlider – for PWM and analog-style control
  2. WebJoystick – for direction control
  3. WebMonitor – for debugging and monitoring in the browser
  4. MultipleWebApps – to combine all features on one board

Video Tutorial

Watch the video below to see this ESP32 S3 Uno project step by step.

The code below is the demo version. It enables D8 to D11 as outputs: a buzzer on D8 (GPIO21) beeps at 3000 Hz when you switch pin 8 ON, and D9 (GPIO46), D10 (GPIO10) and D11 (GPIO11) work as normal outputs, for example with LEDs. D9 is a boot strapping pin, so read the warning in the Hardware Connections section if the board does not boot.

/* * This ESP32 S3 Uno code was developed by newbiely.com * * This ESP32 S3 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3-uno/diyables-web-apps-web-digital-pins */ /* * DIYables WebApp Library - Web Digital Pins Example * * This example demonstrates the Web Digital Pins feature with automatic command handling: * - Control output pins D0-D13 via web interface * - Monitor input pins D0-D13 in real-time * - Individual pin ON/OFF control for outputs * - Real-time pin status feedback for inputs * - Bulk operations (All ON, All OFF, Toggle All) for outputs * * Hardware: ESP32 S3 Uno * - Buzzer on D8 (GPIO21) * - Outputs (e.g. LEDs) on D9 (GPIO46), D10 (GPIO10), D11 (GPIO11) * * The web app uses pin numbers 0-13 = the Uno header labels D0-D13. * The UNO_TO_GPIO table turns each label into the real GPIO number. * * Setup: * 1. Update WiFi credentials below * 2. Upload the sketch to your ESP32 S3 Uno * 3. Open Serial Monitor to see the IP address * 4. Navigate to http://[IP_ADDRESS]/web-digital-pins */ #include <DIYables_ESP32_Platform.h> #include <DIYablesWebApps.h> // WiFi credentials - UPDATE THESE WITH YOUR NETWORK const char WIFI_SSID[] = "YOUR_WIFI_SSID"; const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD"; // ESP32 S3 Uno header label (index = D0..D13) -> GPIO number const int UNO_TO_GPIO[14] = { 44, 43, 18, 17, 19, 20, 3, 14, 21, 46, 10, 11, 13, 12 }; #define BUZZER_PIN 21 // The ESP32 S3 Uno pin D8 (GPIO21) connected to the buzzer // Create WebApp server and page instances using platform abstraction ESP32ServerFactory serverFactory; DIYablesWebAppServer webAppsServer(serverFactory, 80, 81); DIYablesHomePage homePage; DIYablesWebDigitalPinsPage webDigitalPinsPage; // Array to store the state of each digital pin (D0-D13). Index corresponds to the Uno pin label. int pinStates[16] = { 0 }; // Initialize all states to LOW (0) bool buzzerOn = false; void setup() { Serial.begin(9600); delay(1000); Serial.println("DIYables ESP32 WebApp - Web Digital Pins Example"); // Add home and digital pins pages webAppsServer.addApp(&homePage); webAppsServer.addApp(&webDigitalPinsPage); // Optional: Add 404 page for better user experience webAppsServer.setNotFoundPage(DIYablesNotFoundPage()); // Method 4: Enable pins in a range using for loop for (int pin = 8; pin <= 11; pin++) { webDigitalPinsPage.enablePin(pin, WEB_PIN_OUTPUT); // or WEB_PIN_INPUT as needed } // Initialize enabled pins int outputPins[] = { 8, 9, 10, 11 }; // Uno pin labels D8-D11 for (int i = 0; i < 4; i++) { int pin = outputPins[i]; pinMode(UNO_TO_GPIO[pin], OUTPUT); digitalWrite(UNO_TO_GPIO[pin], LOW); pinStates[pin] = LOW; } // Start the WebApp server if (!webAppsServer.begin(WIFI_SSID, WIFI_PASSWORD)) { while (1) { Serial.println("Failed to start WebApp server!"); delay(1000); } } // Return the current state to display on Web App webDigitalPinsPage.onPinRead([](int pin) { return pinStates[pin]; // Return the current state of the pin // You can implement custom read logic here if needed }); // Handle the control request from Web App (for output pins) webDigitalPinsPage.onPinWrite([](int pin, int state) { if (pin == 8) { // D8 = buzzer buzzerOn = state; } else { digitalWrite(UNO_TO_GPIO[pin], state); } pinStates[pin] = state; // You can implement custom control logic here if needed }); // Handle pin mode change requests (optional) webDigitalPinsPage.onPinModeChange([](int pin, int mode) { if (mode == WEB_PIN_OUTPUT) { pinMode(UNO_TO_GPIO[pin], OUTPUT); digitalWrite(UNO_TO_GPIO[pin], LOW); pinStates[pin] = LOW; } else if (mode == WEB_PIN_INPUT) { pinMode(UNO_TO_GPIO[pin], INPUT); // or INPUT_PULLUP as needed pinStates[pin] = digitalRead(UNO_TO_GPIO[pin]); } // You can implement custom mode change logic here if needed }); } void loop() { // Handle WebApp server communications webAppsServer.loop(); if (buzzerOn) { tone(BUZZER_PIN, 3000); } else { noTone(BUZZER_PIN); } // Monitor input pins for real-time updates static unsigned long lastInputCheck = 0; if (millis() - lastInputCheck > 100) { // Check every 100ms lastInputCheck = millis(); // Check input pins for changes and send real-time updates int inputPins[] = { 2, 3 }; // D2 (GPIO18), D3 (GPIO17) for (int i = 0; i < 2; i++) { int pin = inputPins[i]; int currentState = digitalRead(UNO_TO_GPIO[pin]); if (currentState != pinStates[pin]) { pinStates[pin] = currentState; // Send real-time update to web clients webDigitalPinsPage.updatePinState(pin, currentState); } } } // Add your main application code here delay(100); }

Support

If you need more help, read the other DIYables ESP32 WebApps tutorials for the ESP32 S3 Uno on this site. The Arduino and Espressif community forums are also good places to ask.

FAQ

Why does the web page show pin numbers 0–13 and not GPIO numbers?

The Web Digital Pins page only accepts pin numbers from 0 to 13, like a classic Uno. In the ESP32 S3 Uno code, these numbers are the Uno header labels D0–D13. The UNO_TO_GPIO table turns each label into the real GPIO, for example 7 → GPIO14 and 13 → GPIO12. If you call pinMode(), digitalWrite() or digitalRead() yourself, always use the GPIO number.

Why are D0 and D1 disabled in the ESP32 S3 Uno code?

D0 (GPIO44) and D1 (GPIO43) are the UART0 pins that the USB-serial chip uses for the Serial Monitor and for uploading. If you set them as outputs, the Serial Monitor stops working and you cannot see the IP address. On the UNO R4 WiFi these pins are free, which is why the original example enables them.

Where is the built-in LED on pin 13?

The ESP32 S3 Uno has no built-in LED on D13. Connect an external LED with a 220Ω resistor between D13 (GPIO12) and GND to see the pin 13 button work.

Can I control 5V relay modules from the web page?

Yes, if the relay module accepts a 3.3V input signal. Many modules power the coil from 5V but switch with a 3.3V signal. Never feed a 5V signal back into an ESP32 S3 Uno pin, because the pins are NOT 5V tolerant.

Is it safe to use D6 and D9 as web-controlled pins?

They work as normal pins after the board starts. But D6 (GPIO3) and D9 (GPIO46) are boot strapping pins, so a circuit that pulls them to the wrong level during reset can stop the board from booting or uploading. Use D2–D5, D7, D8 and D10–D12 first.

What if my project needs more pins than the Uno headers give?

The ESP32 S3 Uno has two extra rows of holes with more GPIOs: GPIO15 and GPIO16 (I/O, PWM, analog), GPIO45 and GPIO35–GPIO42 (I/O, PWM), and GPIO47/GPIO48 (output only, PWM). Solder pin headers to use them and write the GPIO number in code. The web page still only knows numbers 0–13, so give an unused number a new GPIO in the UNO_TO_GPIO table (for example, put 15 in place of D0's 44). For buttons and other inputs, GPIO15, GPIO16 or GPIO35–GPIO42 are good choices; never use GPIO47/GPIO48 as inputs. Be careful with two things: (1) GPIO47/GPIO48 may run at 1.8V instead of 3.3V on some modules (especially ones with "V" in the name, like R8V or R16V), so 3.3V devices can be damaged or act strangely; (2) GPIO0, GPIO3 (D6), GPIO45 and GPIO46 (D9) are boot strapping pins, and a wrong connection can stop the board from booting or uploading code. Use the other extra pins first.

Troubleshooting

Problem Possible Cause Solution
No COM port appears in the Arduino IDE USB driver missing or charge-only cable Install the CP210x or CH340 driver, use a data USB cable, or hold BOOT while you press RESET
Serial Monitor shows nothing or stops D0 or D1 enabled as an output, or wrong baud rate Keep D0 and D1 disabled and set the Serial Monitor to 9600 baud
Board does not connect to WiFi Wrong SSID or password, or a 5 GHz network Check WIFI_SSID and WIFI_PASSWORD and use a 2.4 GHz WiFi network
Web page does not open Phone or PC on another network, or wrong IP address Join the same WiFi and use the IP address printed in the Serial Monitor
Clicking pin 13 shows no light The board has no built-in LED on D13 Connect an external LED with a 220Ω resistor to D13 (GPIO12)
Wrong pin reacts to a button digitalWrite() uses the Uno label instead of the GPIO Use UNO_TO_GPIO[pin] or the GPIO number from the pinout
Input pin flickers between ON and OFF Floating input with no pull-up or pull-down Add a 10kΩ resistor to 3.3V or GND, or use INPUT_PULLUP
Board does not boot or upload after wiring A circuit pulls D6 (GPIO3) or D9 (GPIO46) at reset Disconnect that wire during upload or move the signal to another pin

※ OUR MESSAGES

  • As freelancers, We are AVAILABLE for HIRE. See how to outsource your project to us
  • Please feel free to share the link of this tutorial. However, Please do not use our content on any other websites. We invested a lot of effort and time to create the content, please respect our work!