ESP32-S3 DevKitC-1: Two USB Ports, PSRAM, the RGB LED and the Pins Best Left Alone
The most powerful of the current ESP32s: two cores at 240 MHz, up to 8 MB of PSRAM, native USB and 14 touch inputs. We look at which USB port to plug into, why GPIO35–37 are taken, how to drive the RGB LED, and how touch on the S3 differs from the classic ESP32.
About the board
The ESP32-S3 is a dual-core 240 MHz Xtensa LX7 with Wi-Fi 4, Bluetooth 5 LE, vector instructions for neural networks and native USB. The ESP32-S3-DevKitC-1 board has 44 pins, two USB-C ports and a WS2812 RGB LED. It is the best pick for cameras, LVGL displays, voice recognition and USB devices: keyboards, MIDI controllers, flash drives.
Which USB port
The board has two connectors:
- UART — through a CP2102N/CH343 bridge. It always works, even with a "broken" firmware, and resets the board into the bootloader by itself.
- USB — the chip's own native USB (GPIO19/20). You need it for USB HID (
USB.h,USBHIDKeyboard), MIDI and MSC. To see Serial here, enable Tools → USB CDC On Boot → Enabled.
For a first try use the UART port.
Modules and PSRAM
The module marking tells you the memory: N8R8 is 8 MB flash and 8 MB PSRAM, N16R8 is 16 and 8, N8 has no PSRAM. In modules with octal PSRAM (R8), pins GPIO35, 36 and 37 belong to the memory — do not use them, even though they are on the header. GPIO26–32 always belong to the flash. In the Arduino IDE enable PSRAM with Tools → PSRAM → OPI PSRAM.
The pinout in short
| What | Pins |
|---|---|
| ADC1 | GPIO1–10 |
| ADC2 (not with Wi-Fi) | GPIO11–20 |
| Touch | GPIO1–14 (T1–T14) |
| Default I2C | SDA 8, SCL 9 |
| Default SPI | SCK 12, MISO 13, MOSI 11, SS 10 |
| UART0 | TX 43, RX 44 |
| RGB LED | GPIO48 (GPIO38 on revision v1.1) |
| Strapping | GPIO0 (BOOT), 3, 45, 46 |
| USB | GPIO19 (D−), GPIO20 (D+) |
| Taken | GPIO26–32 (flash), 35–37 (octal PSRAM) |
Safe for anything: GPIO4–7, 15–18, 21, 38–42, 47.
The RGB LED
The on-board LED is an addressable WS2812, so digitalWrite() on GPIO48 does nothing... almost. The arduino-esp32 3.x core defines RGB_BUILTIN and intercepts digitalWrite(RGB_BUILTIN, HIGH), switching on white. For colours there is rgbLedWrite():
// ESP32-S3: the on-board RGB LED without any library
void setup() {
Serial.begin(115200);
}
void loop() {
rgbLedWrite(RGB_BUILTIN, 40, 0, 0); // red (0–255 per channel; 40 is already bright)
delay(500);
rgbLedWrite(RGB_BUILTIN, 0, 40, 0); // green
delay(500);
rgbLedWrite(RGB_BUILTIN, 0, 0, 40); // blue
delay(500);
digitalWrite(RGB_BUILTIN, LOW); // off
delay(500);
}
Touch on the S3 works the other way round
On the classic ESP32 touchRead() drops under a finger (from about 70 to about 20). On the S3 the values are large — tens of thousands — and rise when touched. A sketch written for the ESP32 with touchRead(T0) < 30 never triggers on an S3. Calibrate at start-up and compare with the idle level: touchRead(pin) > baseline * 1.3. Also note that the S3 has no T0, and the touch channel number equals the GPIO number.
Try it in the simulator
Pick ESP32-S3 DevKitC-1 in the list next to the examples. Try the touch dimmer — it is adapted to rising touch values and the RGB LED — or the web server.
Good to know
- Current. With Wi-Fi active the S3 draws peaks of up to 500 mA. A weak USB hub is a common cause of resets with
Brownout detector was triggered. - Camera. Boards with a camera connector (ESP32-S3-EYE, XIAO ESP32S3 Sense) use the same modules; a camera requires PSRAM.
- Speed. The S3 vector instructions speed up ESP-NN and TensorFlow Lite Micro several times over the classic ESP32.