Skip to content

Instantly share code, notes, and snippets.

@rex
Last active October 7, 2025 01:19
Show Gist options
  • Save rex/ae64193d415b356b96572a38fef0199a to your computer and use it in GitHub Desktop.
Save rex/ae64193d415b356b96572a38fef0199a to your computer and use it in GitHub Desktop.
ESP32 Capabilities and Pinouts

ESP32 Audio & Peripherals Quickstart — with Pinout & Mermaid Diagram

Author: Bex (for Pierce)
Scope: How to generate real audio (polyphony) on ESP32, what “peripherals” are, and a practical overview of ESP32 (WROOM-32 class) pins & capabilities. Includes a ready-to-run chord synth and a Mermaid pinout diagram.

⚠️ Board variance note: The mapping below targets the common ESP32-WROOM-32 / DevKit v1 family. Some boards re-label or reserve certain pins (e.g., PSRAM modules, onboard flash). Always confirm with your module’s schematic/datasheet.


1) Real Polyphony on ESP32 (Why DAC beats PWM)

The problem with tone() / pure PWM

tone() uses a single timer—great for one square wave. Ask for multiple different notes simultaneously and later calls override earlier ones. PWM (“LEDC”) can give you separate channels, but channels share timers so true polyphony becomes tricky and often sounds harsh (square waves + beating).

The DAC advantage

ESP32 has two 8‑bit DACs:

  • DAC1 → GPIO25
  • DAC2 → GPIO26

They output true analog voltage (0–3.3V), so you can mix multiple voices in software and feed the composite waveform to a small amplifier → speaker. Result: smooth, musical tones.


2) Minimal “Chord Synth” Example (3-voice sine mix → DAC)

#include <driver/dac.h>
#include <math.h>

// --- Config ---
#define SAMPLE_RATE 44100          // Hz (try 22050 for lighter CPU)
#define VOLUME 127                 // 0-127 for 8-bit DAC range
#define DAC_CHANNEL DAC_CHANNEL_1  // GPIO 25 (DAC1)

// --- Frequencies for a C major chord (C4, E4, G4) ---
float freqs[] = {261.63f, 329.63f, 392.00f};

void setup() { 
  dac_output_enable(DAC_CHANNEL); 
}

void loop() {
  static uint32_t t = 0;   // sample counter
  float sample = 0.0f;

  // Mix 3 sines
  for (int i = 0; i < 3; i++) {
    sample += sinf(2.0f * M_PI * freqs[i] * (float)t / SAMPLE_RATE);
  }

  // Average to -1..+1 → scale to 0..255
  sample = (sample / 3.0f + 1.0f) * VOLUME;        // center & scale
  uint8_t out = (uint8_t) sample;

  dac_output_voltage(DAC_CHANNEL, out);

  // ~44.1 kHz sample rate
  delayMicroseconds(1000000 / SAMPLE_RATE);
  t++;
}

Hookup: GPIO25 → 1kΩ → small audio amp input (PAM8302/MAX98357A/etc.) → speaker. GND to GND.
(Driving a speaker directly from the pin is only for quick, very low volume tests.)

Where to go next: Use I²S in built-in DAC mode to DMA-stream audio (cleaner and non‑blocking).


3) What Are “Peripherals” on ESP32?

They’re dedicated hardware blocks that handle time‑critical tasks so your CPU isn’t bit‑banging everything.

Peripheral Role Typical Uses
GPIO Digital I/O Buttons, LEDs, relays
UART Serial Console logs, GPS modules
SPI High‑speed serial Displays, flash, SD cards
I²C 2‑wire serial Sensors, RTC, IO expanders
LEDC (PWM) Timed pulses LED dimming, motors, buzzers
ADC Analog→digital Potentiometers, sensors
DAC Digital→analog Audio/synth, CV outputs
I²S Audio serial DAC/amp streaming, DMA
RMT Precise waveforms IR, NeoPixels, custom protocols
Timers/Watchdog Scheduling/safety Periodic tasks, hang recovery
Wi‑Fi / BT Radios Connectivity, BLE sensors

4) ESP32 (WROOM‑32 / DevKit v1 class) Pinout & Capabilities

Key categories: Input‑only, ADC, DAC, Touch, PWM (LEDC), I²C/SPI/UART defaults, Strapping/boot pins. Most pins are highly multiplexed—you can remap many functions in software.

4.1 Quick capabilities map

GPIO Notes / Special ADC Touch PWM Default Uses (common)
0 Strapping (boot), Touch T1 ADC2 T1 ✔︎ Often used with care; boot mode select
1 (TX0) UART0 TX (USB Prog) ✔︎ Serial TX to USB bridge
2 Strapping, LED on some boards, Touch T2 ADC2 T2 ✔︎ Keep low on boot for some modules
3 (RX0) UART0 RX (USB Prog) ✔︎ Serial RX from USB bridge
4 Touch T0 ADC2 T0 ✔︎ General I/O
5 VSPI CS (default), Strapping ✔︎ SPI CS or general I/O
12 Strapping (MTDI), Touch T5 ADC2 T5 ✔︎ Beware boot mode with pull‑ups/downs
13 HSPI MOSI, Touch T4 ADC2 T4 ✔︎ SPI alt or general I/O
14 HSPI SCLK, Touch T6 ADC2 T6 ✔︎ SPI alt or general I/O
15 HSPI CS, Touch T3, Strapping (MTDO) ADC2 T3 ✔︎ Boot strap pin—use carefully
16 UART2 RX (default) ✔︎ General I/O / UART
17 UART2 TX (default) ✔︎ General I/O / UART
18 VSPI SCLK (default) ✔︎ SPI clock
19 VSPI MISO (default) ✔︎ SPI MISO
21 I²C SDA (common) ✔︎ Any I/O; popular SDA
22 I²C SCL (common) ✔︎ Any I/O; popular SCL
23 VSPI MOSI (default) ✔︎ SPI MOSI
25 DAC1, ADC2 ADC2 ✔︎ Analog out (DAC), also ADC
26 DAC2, ADC2 ADC2 ✔︎ Analog out (DAC), also ADC
27 Touch T7 ADC2 T7 ✔︎ General I/O
32 Input‑only, Touch T9, RTC ADC1 T9 ✖︎ Safe input, great for sensors
33 Input‑only, Touch T8, RTC ADC1 T8 ✖︎ Safe input
34 Input‑only ADC1 ✖︎ No output; sensor input
35 Input‑only ADC1 ✖︎ No output; sensor input
36 (SVP) Input‑only ADC1 ✖︎ Internal sensors, analog in
39 (SVN) Input‑only ADC1 ✖︎ Internal sensors, analog in

Touch map: T0=4, T1=0, T2=2, T3=15, T4=13, T5=12, T6=14, T7=27, T8=33, T9=32
ADC1: 32–39 (works even with Wi‑Fi active) • ADC2: 0, 2, 4, 12–15, 25–27 (contention with Wi‑Fi)
DAC: 25 (DAC1), 26 (DAC2)
Input‑only: 34, 35, 36 (SVP), 39 (SVN)
Strapping pins (boot‑mode sensitive): 0, 2, 4, 5, 12, 15

Rule of thumb: Prefer ADC1 for analog reads when Wi‑Fi is on. Avoid using strapping pins for outputs unless you know the boot constraints.

4.2 Common default buses (can be remapped)

  • UART0: TX0=GPIO1, RX0=GPIO3 (USB programming/Serial Monitor)
  • UART1: TX1=GPIO10, RX1=GPIO9 (usually used by flash on many modules; avoid)
  • UART2: TX2=GPIO17, RX2=GPIO16 (nice spare UART)
  • I²C (soft‑assignable): common default SDA=GPIO21, SCL=GPIO22
  • VSPI: SCLK=18, MISO=19, MOSI=23, CS=5
  • HSPI (alt SPI): SCLK=14, MISO=12, MOSI=13, CS=15

5) Mermaid Diagram — ESP32 Pinout Overview

Mermaid isn’t a PCB layout tool, but this summary graph shows categories & key purposes. (Open this file in a Mermaid‑capable viewer/editor to render.)

flowchart LR
  subgraph ESP32 [ESP32 WROOM-32 Class]
    A[Analog & Touch<br/>GPIO32-39 ADC1<br/>GPIO0,2,4,12-15,25-27 ADC2<br/>Touch T0-T9<br/>Input-only: 34,35,36,39]
    D[Digital I/O<br/>Most GPIOs PWM -LEDC-<br/>Avoid boot straps: 0,2,4,5,12,15]
    U[UART<br/>UART0 TX1/RX3<br/>UART2 TX17/RX16]
    S[SPI<br/>VSPI 18/19/23/5<br/>HSPI 14/12/13/15]
    I2C[I²C<br/>SDA=21<br/>SCL=22]
    DAC[DAC<br/>DAC1=25<br/>DAC2=26]
    RMT[RMT<br/>Precision waveforms<br/>-NeoPixels/IR-]
    I2S[I²S<br/>Audio DMA → DAC/Codecs]
    WIFI[Wi-Fi/BT Radios]
  end

  A --> DAC
  D --> RMT
  D --> S
  D --> U
  D --> I2C
  DAC --> I2S
  I2S --> WIFI
Loading

GPIO Pin Capabilities

GPIO Pin Capabilities/Usabilities

Which GPIOs are safe to use?

Although the module has a lot of pins with various functions, some of them may not be suitable for your projects. The table below shows which pins are safe to use and which pins should be used with caution.

  • ✅ Your top priority pins. They are perfectly safe to use.
  • ⚠️ Pay close attention because their behavior, particularly during boot, can be unpredictable. Use them only when absolutely necessary.
  • ❌ It is recommended that you avoid using these pins.
Pin Pin Label GPIO Safe to use? Reason
4 SENSOR_VP GPIO36 ⚠️ Input only GPIO, cannot be configured as output
5 SENSOR_VN GPIO39 ⚠️ Input only GPIO, cannot be configured as output
6 IO34 GPIO34 ⚠️ Input only GPIO, cannot be configured as output
7 IO35 GPIO35 ⚠️ Input only GPIO, cannot be configured as output
8 IO32 GPIO32
9 IO33 GPIO33
10 IO25 GPIO25
11 IO26 GPIO26
12 IO27 GPIO27
13 IO14 GPIO14
14 IO12 GPIO12 ⚠️ must be LOW during boot
16 IO13 GPIO13
17 SHD/SD2 GPIO9 Connected to Flash memory
18 SWP/SD3 GPIO10 Connected to Flash memory
19 SCS/CMD GPIO11 Connected to Flash memory
20 SCK/CLK GPIO6 Connected to Flash memory
21 SDO/SD0 GPIO7 Connected to Flash memory
22 SDI/SD1 GPIO8 Connected to Flash memory
23 IO15 GPIO15 ⚠️ must be HIGH during boot, prevents startup log if pulled LOW
24 IO2 GPIO2 ⚠️ must be LOW during boot and also connected to the on-board LED
25 IO0 GPIO0 ⚠️ must be HIGH during boot and LOW for programming
26 IO4 GPIO4
27 IO16 GPIO16
28 IO17 GPIO17
29 IO5 GPIO5 ⚠️ must be HIGH during boot
30 IO18 GPIO18
31 IO19 GPIO19
33 IO21 GPIO21
34 RXD0 GPIO3 Rx pin, used for flashing and debugging
35 TXD0 GPIO1 Tx pin, used for flashing and debugging
36 IO22 GPIO22
37 IO23 GPIO23

ADC Pins

The ESP32-WROOM-32 module has two ADC (Analog to Digital Converter) blocks; ADC1 and ADC2. Each block has multiple channels:

  • ADC1: contains 6 channels (labeled as ADC1_CH0 and ADC1_CH3 to ADC1_CH7).
  • ADC2: contains 10 channels (labeled as ADC2_CH0 to ADC2_CH9).

esp32 wroom 32 adc pins

he resolution of the ADCs on the ESP32 can be configured up to 12 bits. This means that the ADC can detect 4096 (2^12) discrete analog levels. This results in a resolution of 3.3 V (operating voltage) / 4096 units, or 0.0008 volts (0.8 mV) per unit.

⚠️ Warning:

When Wi-Fi is enabled, the ADC2 pins cannot be used. If you need Wi-Fi, consider using the ADC1 pins instead.

DAC Pins

The ESP32-WROOM-32 module contains two 8-bit Digital-to-Analog Converters (DACs). These DACs are useful for converting digital signals into analog voltages.

esp32 wroom 32 dac pins

Touch Pins

The ESP32-WROOM-32 module has ten capacitive touch-enabled GPIOs labeled TOUCH0 through TOUCH9. These pins work by measuring the change in capacitance when a finger or conductive object is near the surface of the pin.

They can be used for various applications, such as touch buttons, touch sliders, or even basic gesture recognition. They can also be used to wake the ESP32 from deep sleep, which is particularly useful in power-sensitive applications.

esp32 wroom 32 touch pins

I2C Pins

The ESP32-WROOM-32 module has two I2C bus interfaces, but no dedicated I2C pins. Instead, it allows for flexible pin assignment, meaning any GPIO pin can be configured as I2C SDA (data line) and SCL (clock line).

However, GPIO21 (SDA) and GPIO22 (SCL) are commonly used as the default I2C pins to make it easier for people using existing Arduino code, libraries, and sketches.

esp32 wroom 32 i2c pins

SPI Pins

The ESP32-WROOM-32 module features three SPIs (SPI, HSPI, and VSPI). HSPI and VSPI are commonly used for general purposes, while the third one is used for interfacing with the SPI flash memory integrated on the module.

Similar to I2C, the ESP32 allows flexible pin assignment for SPI. This means that any GPIO pin can be configured as SPI pins.

esp32 wroom 32 spi pins

UART Pins

The ESP32-WROOM-32 module has three UART interfaces: UART0, UART1, and UART2. These interfaces enable serial communication with various peripherals or for logging and debugging purposes.

esp32 wroom 32 uart pins

⚠️ Please note that the UART1 pins (GPIO 9 and GPIO 10) are used for interfacing with the SPI flash memory integrated on the module, so you can’t use them. However, you can still use UART1 by bit-banging the UART protocol on other GPIO pins.

Besides the basic TX and RX pins, UART interfaces on the ESP32 also support RTS (Request To Send) and CTS (Clear To Send) for hardware flow control, though these are less commonly used.

PWM Pins

Almost all GPIO pins on the module can be configured to generate PWM output.

esp32 wroom 32 pwm pins

The PWM on the ESP32 can be configured with high resolution, typically up to 16 bits, allowing for fine control over the PWM signals. PWM frequency can also be adjusted, with a typical range from a few Hz to tens of MHz, making it suitable for a wide range of applications, from controlling motors to dimming LEDs.

RTC GPIO Pins

Some GPIOs are routed to the RTC low-power subsystem and are known as RTC GPIOs. These GPIOs can be used for waking up the ESP32 from deep sleep and for interfacing with RTC peripherals.

esp32 wroom 32 rtc gpio pins

Strapping Pins

There are five strapping pins on the ESP32: GPIO0, GPIO2, GPIO5, GPIO12, and GPIO15. The state of these pins determines whether the ESP32 enters BOOT mode (to run the program stored in flash memory) or FLASH mode (to upload a program to flash memory) upon power-up.

esp32 wroom 32 strapping pins

Be aware that if peripherals are connected to these pins, you might face issues when trying to flash the ESP32 with new firmware. This is because these peripherals could prevent the ESP32 from entering the correct mode.

Power Pins

The power pins provide the necessary voltage to the module to operate:

3V3 is the main supply voltage pin. It should be provided with a stable 3.3V power supply.

GND is the ground pin.

esp32 wroom 32 power pins

Enable Pin

The EN pin is the enable pin for the ESP32. When pulled HIGH, the chip is enabled and operational; when pulled LOW, the chip is disabled.

esp32 wroom 32 en pin


6) Practical Tips

  • Use DAC + I²S for clean audio playback (DMA → non‑blocking).
  • Use LEDC only for simple beeps/tones (square waves).
  • For analog reads with Wi‑Fi: stick to ADC1 pins.
  • Treat GPIO0/2/4/5/12/15 with care (boot straps).
  • Avoid using GPIO34–39 for outputs (they’re input‑only).
  • For WS2812/NeoPixels under Wi‑Fi, prefer RMT‑based drivers for rock‑solid timing.

7) Where to go next

  • Swap the hand‑timed loop for I²S DAC mode with a circular buffer.
  • Add envelopes (ADSR) and basic filters to the synth.
  • Stream WAV from SPIFFS/SD: 8‑bit @ 22 kHz is very doable.
  • Try stereo (GPIO25 & GPIO26) with separate voices per channel.

Have fun. The ESP32 isn’t just microcontroller‑with‑Wi‑Fi — it’s a pocket‑sized audio workstation when you use the right peripherals. 🎛️🎶

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment