"ESP32" is a family. Picking the wrong member is a common reason for a redesign later.
| Chip | CPU | Wi-Fi | Bluetooth | IEEE 802.15.4 (Thread / Zigbee) | Typical use |
|---|---|---|---|---|---|
| ESP32-S3 | dual-core Xtensa LX7, up to 240 MHz, vector instructions | 802.11 b/g/n | 5 (LE) | no | displays, cameras, audio, on-device ML, USB devices |
| ESP32-C3 | single-core RISC-V, up to 160 MHz | yes (2.4 GHz) | 5 (LE) | no | cost-sensitive Wi-Fi/BLE sensors and switches |
| ESP32-C6 | RISC-V up to 160 MHz + low-power RISC-V core | Wi-Fi 6 (802.11ax) | 5 (LE) | yes | Matter/Thread/Zigbee devices that also need Wi-Fi |
| ESP32-H2 | RISC-V | no | 5 (LE) | yes | Thread/Zigbee end devices and radio co-processors |
The original ESP32 is still widely used and is the member associated with Bluetooth Classic support (Bluedroid, A2DP/SPP). The newer chips' product pages list Bluetooth 5 (LE) only, so check the datasheet if you need Classic.
How to choose
- Radio first. Need Thread or Zigbee → C6 (with Wi-Fi) or H2 (without). Need Wi-Fi 6 → C6. Need Bluetooth Classic → original ESP32.
- Compute. Camera, display, audio or ML → S3.
- Cost and simplicity. Plain Wi-Fi + BLE sensor → C3.
- Toolchain. Confirm your framework supports the chip (the Arduino core and ESP-IDF both publish support lists) and that the libraries you depend on do too.
Porting pitfalls between variants
- GPIO numbers, strapping pins and ADC channels differ per chip. Pin maps from an ESP32 tutorial are wrong on a C3 or S3. Use the GPIO page of the ESP-IDF docs for your chip.
- Peripheral sets differ (e.g. touch, DAC, number of UARTs). Check the datasheet or the product selector before porting.
- Xtensa vs RISC-V: portable C/C++ is fine; hand-written assembly or architecture-specific libraries are not.