# ESP32-S3-CAM N16R8 — Coding Hardware Reference

This reference describes the ESP32-S3 camera board sold as ESP32-S3-CAM or ESP32-S3 WROOM CAM
(silkscreen `ESP32-S3 WROOM`, module marking `ESP32-S3-N16R8`, OV5640 camera). Its camera and header
wiring matches the Freenove ESP32-S3-WROOM camera-board layout. Use these assignments explicitly; do
not assume the pinout of a generic ESP32-S3 board.

"Left" and "right" below always mean: component side up, antenna at the top, USB connectors at the
bottom.

## Target configuration

| Item | Value |
|---|---|
| MCU | ESP32-S3, dual-core Xtensa LX7 with single-precision FPU, up to 240 MHz |
| Module | ESP32-S3-WROOM-1-N16R8, PCB antenna, 18 × 25.5 × 3.1 mm |
| Module marking | `ESP32-S3-N16R8` |
| Flash | 16 MB, Quad SPI |
| PSRAM | 8 MB, Octal SPI (OPI) |
| Wireless | 2.4 GHz Wi-Fi 802.11 b/g/n, Bluetooth LE 5 (no Classic Bluetooth) |
| Camera fitted | OV5640, 8-bit DVP, SCCB control, 24-pin FPC connector |
| Camera maximum sensor output | 2592 × 1944 |
| Storage | microSD via SDMMC, 1-bit mode |
| GPIO logic | 3.3 V only; GPIOs are not 5 V tolerant |
| Supply | module needs a source able to deliver at least 0.5 A |
| Operating ambient temperature | −40 to +65 °C (variant with Octal PSRAM) |

For Arduino-ESP32, use `ESP32S3 Dev Module` with `Flash Size: 16MB (128Mb)`,
`Flash Mode: QIO 80MHz` and `PSRAM: OPI PSRAM`. Select a partition scheme with at least 3 MB for the
application, for example `16M Flash (3MB APP/9.9MB FATFS)`. `OPI 80MHz` flash mode is for modules
with Octal flash and does not apply here. In ESP-IDF, select the ESP32-S3 target and enable Octal
PSRAM (`CONFIG_SPIRAM=y`, `CONFIG_SPIRAM_MODE_OCT=y`).

## Camera pin configuration

PWDN and RESET are not connected and must be set to `-1`.

```c
#define CAM_PIN_PWDN  -1
#define CAM_PIN_RESET -1
#define CAM_PIN_XCLK  15
#define CAM_PIN_SIOD  4
#define CAM_PIN_SIOC  5

#define CAM_PIN_D0    11  // OV5640 Y2
#define CAM_PIN_D1    9   // OV5640 Y3
#define CAM_PIN_D2    8   // OV5640 Y4
#define CAM_PIN_D3    10  // OV5640 Y5
#define CAM_PIN_D4    12  // OV5640 Y6
#define CAM_PIN_D5    18  // OV5640 Y7
#define CAM_PIN_D6    17  // OV5640 Y8
#define CAM_PIN_D7    16  // OV5640 Y9

#define CAM_PIN_VSYNC 6
#define CAM_PIN_HREF  7
#define CAM_PIN_PCLK  13
```

This map is identical to Espressif's ESP32-S3-EYE. In the Arduino-ESP32 `CameraWebServer` example,
select `CAMERA_MODEL_ESP32S3_EYE` in `board_config.h`; the default there, `CAMERA_MODEL_ESP_EYE`, is a
board built on the original ESP32. For `CAMERA_MODEL_ESP32S3_EYE` the example calls
`set_vflip(s, 1)`, so toggle V-Flip if the image is upside down. Never use the AI-Thinker ESP32-CAM
map: it points at GPIO26–32, which the ESP32-S3 uses for its internal flash and PSRAM, and at
GPIO22–25, which do not exist on the ESP32-S3.

Camera GPIOs `4–13` and `15–18` (all of `4–18` except `14`) are unavailable for other uses while the
camera is active. Frame buffers should be allocated in PSRAM (`CAMERA_FB_IN_PSRAM`) for normal camera
resolutions.

Full resolution (`FRAMESIZE_5MP`, 2592 × 1944) requires `PIXFORMAT_JPEG`: a raw RGB565 frame of that
size (10,077,696 bytes, about 9.6 MiB) does not fit in 8 MB of PSRAM.

**OV5640 clock.** Owners of this board have reported black frames from the OV5640 with the example's
default `xclk_freq_hz = 20000000`, while an OV2640 worked on the same board; setting
`xclk_freq_hz` to `24000000` or `12000000` fixed it for them. This has not been verified on this
particular board yet. Keep the ribbon cable fully seated and the board ventilated.

## microSD configuration

The onboard socket is wired for SDMMC 1-bit mode:

| SD signal | GPIO |
|---|---:|
| CMD | 38 |
| CLK | 39 |
| D0 | 40 |

GPIO38–40 are unavailable when microSD is enabled. GPIO39 and GPIO40 also correspond to default JTAG
signals MTCK and MTDO, so external JTAG and microSD can conflict. Debugging through the native USB
Serial/JTAG (left connector) needs none of these pins.

Arduino-ESP32:

```cpp
SD_MMC.setPins(39, 38, 40);       // CLK, CMD, D0
SD_MMC.begin("/sdcard", true);    // true = 1-bit mode
```

## USB and serial

| Connector | Position | Function | Pins |
|---|---|---|---|
| `USB-UART` | Right | External USB-to-UART bridge; normal flashing and UART0 logs | GPIO43 TX, GPIO44 RX |
| `USB-OTG` | Left | Native ESP32-S3 USB device/OTG and USB Serial/JTAG | GPIO19 D−, GPIO20 D+ |

The connector labels are printed on the back of the board. Seen from the back they appear the other
way round (`USB-UART` on the left, `USB-OTG` on the right); from the component side the USB-UART
connector is on the right.

The native USB OTG and USB Serial/JTAG controllers share the ESP32-S3 internal USB PHY. The
USB-to-UART bridge is separate (Freenove's original board uses a CH343; clones may use a different
chip, so check the reported VID/PID). Do not repurpose GPIO19/20 when native USB is required, or
GPIO43/44 when the USB-UART port is required.

In Arduino-ESP32, `USB CDC On Boot: Disabled` makes `Serial` UART0 (right connector) and `Enabled`
moves `Serial` to the native USB (left connector). `USB Mode: Hardware CDC and JTAG` keeps the
built-in USB Serial/JTAG; `USB-OTG (TinyUSB)` is for custom USB devices. `Upload Mode:
UART0 / Hardware CDC` flashes through either connector. The ROM bootloader prints to both UART0 and
USB Serial/JTAG by default.

## Onboard controls and LEDs

| Board marking | Connection | Use |
|---|---|---|
| `EN` | EN | Active-low reset button |
| `BOOT` | GPIO0 | Bootloader/strapping button; hold while resetting for download mode if required |
| `ON` | Power rail | Power indicator, always lit |
| `TX`, `RX` | UART0 / USB-UART bridge | Serial activity indicators |
| `IO2` | GPIO2 | User LED |
| `48` | GPIO48 | WS2812-compatible addressable RGB LED |

Manual download mode: hold `BOOT`, press and release `EN`, release `BOOT`.

In Arduino-ESP32 (`ESP32S3 Dev Module`), `LED_BUILTIN` and `RGB_BUILTIN` refer to the GPIO48 RGB LED;
`digitalWrite(RGB_BUILTIN, HIGH)` lights it white at `RGB_BRIGHTNESS`. Set a colour with
`rgbLedWrite(RGB_BUILTIN, r, g, b)`; `neopixelWrite()` is deprecated.

## Strapping pins

GPIO0, GPIO3, GPIO45 and GPIO46 are strapping pins. External circuits must not force an incorrect
level on them during reset.

| Pin | Default at reset | Function |
|---|---|---|
| GPIO0 | weak pull-up | Boot mode: high = SPI boot (run firmware); low together with GPIO46 low = download mode |
| GPIO46 | weak pull-down | Boot mode together with GPIO0; GPIO0 low with GPIO46 high is invalid |
| GPIO45 | weak pull-down | VDD_SPI voltage: low = 3.3 V, high = 1.8 V. This module's flash and PSRAM are 3.3 V, so GPIO45 must be low at reset |
| GPIO3 | floating | JTAG signal source, only when `EFUSE_STRAP_JTAG_SEL` is burned; ignored with factory eFuses |

## Header pinout

Orientation: component side up, antenna at top, USB connectors at bottom.

| Left header, top → bottom | Function | Right header, top → bottom | Function |
|---|---|---|---|
| `3V3` | 3.3 V rail | `GPIO43 / TX` | UART0 TX / USB-UART |
| `EN` | Reset/enable | `GPIO44 / RX` | UART0 RX / USB-UART |
| `GPIO4` | Camera SIOD | `GPIO1` | ADC1_CH0, Touch1 |
| `GPIO5` | Camera SIOC | `GPIO2` | User LED, ADC1_CH1, Touch2 |
| `GPIO6` | Camera VSYNC | `GPIO42` | GPIO, default JTAG MTMS |
| `GPIO7` | Camera HREF | `GPIO41` | GPIO, default JTAG MTDI |
| `GPIO15` | Camera XCLK | `GPIO40` | microSD D0, default JTAG MTDO |
| `GPIO16` | Camera D7 | `GPIO39` | microSD CLK, default JTAG MTCK |
| `GPIO17` | Camera D6 | `GPIO38` | microSD CMD |
| `GPIO18` | Camera D5 | `GPIO37` | Internal octal PSRAM |
| `GPIO8` | Camera D2 | `GPIO36` | Internal octal PSRAM |
| `GPIO3` | Strapping pin | `GPIO35` | Internal octal PSRAM |
| `GPIO46` | Strapping pin | `GPIO0` | BOOT / strapping |
| `GPIO9` | Camera D1 | `GPIO45` | Strapping pin |
| `GPIO10` | Camera D3 | `GPIO48` | Addressable RGB LED |
| `GPIO11` | Camera D0 | `GPIO47` | General-purpose GPIO |
| `GPIO12` | Camera D4 | `GPIO21` | General-purpose GPIO |
| `GPIO13` | Camera PCLK | `GPIO20` | Native USB D+ |
| `GPIO14` | General-purpose GPIO | `GPIO19` | Native USB D− |
| `5V` | 5 V board rail | `GND` | Ground |

The silkscreen marks taken pins: underlined numbers belong to the camera, `~` marks the microSD pins
and `*` the PSRAM pins; the legend is printed on the back.

## GPIO selection guide

| Category | GPIOs | Coding rule |
|---|---|---|
| Best general-purpose choices | `1`, `14`, `21`, `41`, `42`, `47` | Prefer these, subject to ADC/JTAG notes below |
| Camera | `4–13`, `15–18` | Reserved while camera is used |
| microSD | `38–40` | Reserved while SD is used |
| Octal PSRAM | `35–37` | Never use; connected internally on the N16R8 module |
| Native USB | `19`, `20` | Reserved when native USB is used |
| USB-UART / UART0 | `43`, `44` | Avoid if flashing or logging through USB-UART; still wired to the bridge |
| Onboard LEDs | `2`, `48` | Usable only with awareness of attached LEDs |
| Strapping pins | `0`, `3`, `45`, `46` | Avoid for ordinary peripherals; boot-time levels matter |

GPIO41/42 are valid general-purpose pins when external JTAG is not being used (by default the
ESP32-S3 routes JTAG to the USB Serial/JTAG controller). GPIO1 is a good ADC1 input. GPIO14 is also
available but belongs to ADC2.

## ADC and touch mapping

- ADC1: GPIO1–10 map to channels 0–9.
- ADC2: GPIO11–20 map to channels 0–9.
- Capacitive touch: GPIO1–14 map to Touch1–Touch14.
- ADC2 access is shared with Wi-Fi and may be delayed or fail while the radio is busy; prefer ADC1
  for analog sensing in Wi-Fi applications.
- Continuous ADC DMA should use ADC1. ADC2 DMA is disabled by default on ESP32-S3 because of a
  documented hardware limitation.
- Camera use occupies most ADC-capable pins. With the camera active, GPIO1 is the cleanest exposed
  ADC1 choice; GPIO2/3 are possible only if their LED/strapping implications are acceptable.

## Power and electrical constraints

- GPIO logic is 3.3 V. Never apply 5 V to a GPIO.
- The module's absolute maximum supply voltage is 3.6 V; treat it as a limit, not a normal logic
  level.
- `5V` is the board's 5 V rail; `3V3` is the regulated 3.3 V rail.
- The module needs a supply able to deliver at least 0.5 A. Camera operation, Wi-Fi transmission, SD
  writes and the RGB LED create current peaks; a weak supply shows up as brownout resets when the
  stream starts. Use a stable USB supply or a regulated 5 V source.
- Modules with Octal PSRAM are rated for −40 to +65 °C ambient. With PSRAM ECC enabled, Espressif
  allows up to 85 °C at the cost of 1/16 of the PSRAM. Ventilate enclosures.
- Not optimised for battery use: the `ON` LED is always lit and the camera PWDN pin is not
  connected, so the sensor can only be put into software standby over SCCB.
- Do not drive a GPIO before checking whether it is connected to the camera, PSRAM, SD card, USB, an
  LED, or a strapping function.

## Agent implementation checklist

Before generating firmware for this board:

1. Target ESP32-S3 with 16 MB Quad flash and 8 MB OPI PSRAM.
2. Copy the camera pin constants above exactly (they equal `CAMERA_MODEL_ESP32S3_EYE`); do not use
   AI-Thinker ESP32-CAM pins.
3. Enable PSRAM, allocate camera frame buffers there and prefer `PIXFORMAT_JPEG`.
4. Initialize microSD in 1-bit SDMMC mode with CMD/CLK/D0 on GPIO38/39/40.
5. Choose the intended USB path, right USB-UART or left native USB, and set `USB CDC On Boot` to
   match.
6. Select new peripheral pins from the GPIO selection guide and check every shared function.
7. Preserve safe reset levels on GPIO0, GPIO3, GPIO45, and GPIO46.
8. If the OV5640 returns black frames, try `xclk_freq_hz` of 24 MHz or 12 MHz.

## Primary references

- [Espressif ESP32-S3-WROOM-1 / WROOM-1U Datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3-wroom-1_wroom-1u_datasheet_en.pdf)
- [Espressif ESP32-S3 Series Datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf)
- [ESP-IDF GPIO summary for ESP32-S3](https://docs.espressif.com/projects/esp-idf/en/stable/esp32s3/api-reference/peripherals/gpio.html)
- [Espressif Arduino camera pin definitions](https://github.com/espressif/arduino-esp32/blob/master/libraries/ESP32/examples/Camera/CameraWebServer/camera_pins.h)
- [Espressif esp32-camera driver](https://github.com/espressif/esp32-camera)
- [arduino-esp32 discussion: OV5640 black frames on the ESP32-S3-WROOM CAM](https://github.com/espressif/arduino-esp32/discussions/11960)
- [Freenove ESP32-S3-WROOM Board repository](https://github.com/Freenove/Freenove_ESP32_S3_WROOM_Board)
