← All projects
Basics Intermediate

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.

Difficulty
Intermediate
Time
30 min
Category
Basics
Updated

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.