LabWired The easy way to build hardware
ESP32-S3-DevKitC-1 development board with an ESP32-S3-WROOM-1 module, two 22-pin headers, BOOT and RST buttons, and USB-C plus USB-to-UART ports.
ESP32-S3-DevKitC-1 N16R8, the board used here.

Blink, a button, and Wi-Fi on the ESP32-S3, with a lab for each step

Category: Tutorial

This is the first hour on an ESP32-S3-DevKitC-1 N16R8. Three programs: write GPIO4, read GPIO5, then WiFi.begin and GET /status. Each one has the connections, the sketch, and a LabWired lab on this page. Press Run. The chip in the iframe is a model of this S3. The sketch is the Arduino you flash.

The longer lesson, including Arduino IDE settings and the upload failures, is Getting started with the ESP32.

The board

The metal shield reads ESP32-S3-WROOM-1-N16R8 or ESP32-S3-N16R8. GPIO4 is the first GPIO on the left header, under the two 3V3 pins and RST. GPIO5 is the next pin down.

This is not a SuperMini and not an S3-Zero. Those boards have different headers.

Official Espressif pin layout for the ESP32-S3-DevKitC-1 v1.1, with each pin labelled with its GPIO number and alternate functions.
ESP32-S3-DevKitC-1 v1.1. GPIO35 to GPIO37 are occupied by octal PSRAM. Diagram (c) Espressif Systems, from esp-dev-kits, Apache-2.0.

Connections

Board pinGoes toNotes
GPIO4330 ohm resistor, one endLeft header, first GPIO under RST
resistor (other end)LED anodeLong leg. Resistor in series
GNDLED cathodeShort leg, flat edge of the plastic
Connection diagram: GPIO4 to a 330 ohm resistor, resistor to the LED anode, LED cathode to GND.
GPIO4 drives the resistor. The LED cathode returns to GND.

Code

LED_PIN is 4 because that is the net above.

#include <Arduino.h>

const int LED_PIN = 4;
uint32_t count = 0;

void setup() {
  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);
  Serial.println("ESP32-S3 up. First blink.");
}

void loop() {
  digitalWrite(LED_PIN, HIGH);
  Serial.print("blink ");
  Serial.println(++count);
  delay(500);
  digitalWrite(LED_PIN, LOW);
  delay(500);
}

Lab. Press Run. The LED follows GPIO4. Serial prints blink and a count. Change delay(500) and run it again.

Open the full lab →

On silicon this is the same sketch. Arduino IDE: ESP32S3 Dev Module, flash 16MB, OPI PSRAM, USB CDC on boot enabled. The full list is in the lesson.

Read GPIO5

Keep the LED. Add the button.

Connections

Board pinGoes toNotes
GPIO4330 ohm, then LED anode, then GNDSame as the blink
GPIO5one pair of button legsLeft header, under GPIO4. Not GPIO0 (BOOT)
GNDthe other pair of button legsINPUT_PULLUP, so no extra resistor
Connection diagram: LED still on GPIO4 through 330 ohm to GND. Button from GPIO5 to GND. INPUT_PULLUP, do not use GPIO0.
Four-leg buttons are two pairs. Sit the body across the breadboard centre gap.

Code

INPUT_PULLUP holds GPIO5 high. A press to GND reads LOW.

#include <Arduino.h>

const int LED_PIN = 4;
const int BUTTON_PIN = 5;

void setup() {
  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  Serial.println("ESP32-S3 up. Button on GPIO5.");
}

void loop() {
  bool pressed = digitalRead(BUTTON_PIN) == LOW;
  digitalWrite(LED_PIN, pressed ? HIGH : LOW);
  Serial.println(pressed ? "pressed" : "open");
  delay(50);
}

Lab. Click the button on the canvas. The LED follows GPIO5. Serial prints pressed or open.

Open the full lab →

Join Wi-Fi and GET /status

Keep the LED on GPIO4. Drop a Wi-Fi AP on the canvas. It has no pins. The S3 associates over the air. The sketch is still WiFi.begin and WiFiClient.

SSID in the lab is labwired-ap. The AP answers GET /status at 192.168.4.1. On silicon, change the SSID (and add a password) to your 2.4 GHz network, and GET a host on that network.

Connections

Board pinGoes toNotes
GPIO4330 ohm, then LED anode, then GNDSame as the blink
(none)Wi-Fi APDrop wifi-ap on the canvas. SSID labwired-ap. No jumper.
Connection diagram: LED still on GPIO4 through 330 ohm to GND. Wi-Fi AP on the canvas, SSID labwired-ap, HTTP GET 192.168.4.1/status. No jumper to the AP.
The AP has no copper. The station joins `labwired-ap` and reads `/status` from `192.168.4.1`.

Code

#include <Arduino.h>
#include <WiFi.h>

const int LED_PIN = 4;

void setup() {
  Serial.begin(115200);
  delay(2000);
  pinMode(LED_PIN, OUTPUT);
  Serial.println("joining labwired-ap");
  WiFi.begin("labwired-ap");
  while (WiFi.status() != WL_CONNECTED) {
    delay(400);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("joined");

  WiFiClient c;
  if (!c.connect(IPAddress(192, 168, 4, 1), 80)) {
    Serial.println("GET failed");
    return;
  }
  c.print("GET /status HTTP/1.1\r\nHost: 192.168.4.1\r\nConnection: close\r\n\r\n");
  unsigned long dl = millis() + 5000;
  while (millis() < dl && (c.connected() || c.available())) {
    while (c.available()) {
      Serial.write(c.read());
    }
    delay(10);
  }
  c.stop();
  digitalWrite(LED_PIN, HIGH);
}

void loop() {
  delay(1000);
}

Lab. Press Run. Serial prints joining labwired-ap, then joined, then the HTTP response from the AP. The LED goes high after the GET.

Open the full lab →

Dots forever in the lab: the SSID in the sketch is not labwired-ap, or the AP part is missing. Dots forever on silicon: the name or password is wrong, or the network is 5 GHz only.

What to do next

Flash the same three sketches. Arduino IDE settings and the failures that stop the first upload are in the getting-started lesson.

Open the Playground to wire the next circuit. The MCP server runs the same chip model from an agent.

Andrii Shylenko
Andrii Shylenko

Founder, LabWired.