Programming the ESP32-CAM with an FTDI or ESP32-CAM-MB Adapter

Unlike a NodeMCU or ESP32 DevKit, the AI-Thinker ESP32-CAM has no USB connector and no USB-to-serial chip. You program it over its UART pins using an external adapter, and you must put the chip into download mode by hand. Most first-time failures with this board are upload failures, not code problems.

This tutorial covers both common methods: a generic USB-to-TTL adapter such as an FT232RL (FTDI) or CP2102 module, and the ESP32-CAM-MB plug-in board with a CH340 chip. You will wire the board, set up the Arduino IDE, upload a test sketch and learn how to read and fix the usual error messages.

How the ESP32 Decides to Boot or Download

When the ESP32 comes out of reset, its ROM bootloader samples a few strapping pins. The important one is GPIO 0. If GPIO 0 is HIGH (it has an internal pull-up), the chip runs the program stored in flash. If GPIO 0 is held LOW at reset, the chip enters serial download mode and waits for the upload tool, esptool, to send a new program over UART0.

On DevKit boards two transistors driven by the DTR and RTS lines do this automatically. On a bare ESP32-CAM with a simple FTDI adapter you do it yourself: connect GPIO 0 to GND, press RESET, upload, then remove the link and press RESET again to run the new program.

You can confirm the mode on the serial monitor at 115200 baud. In download mode the ROM prints a line containing boot:0x3 (DOWNLOAD_BOOT...) followed by waiting for download. In normal mode it shows boot:0x13 (SPI_FAST_FLASH_BOOT) and then your sketch output.

Wiring an FTDI / USB-TTL Adapter

Set the adapter logic level jumper to 3.3 V if it has one. Power the ESP32-CAM from 5 V, because the 3.3 V output of most adapters cannot supply the current the board needs once Wi-Fi starts.

USB-TTL adapterESP32-CAM pinNotes
GNDGNDCommon ground is essential
5V / VCC (5 V)5VBoard regulator makes 3.3 V from this
TXU0R (GPIO 3)Adapter TX goes to ESP32 RX
RXU0T (GPIO 1)Adapter RX goes to ESP32 TX
-IO0 to GNDJumper wire only while uploading

Using the ESP32-CAM-MB Board

The ESP32-CAM-MB is a small base board with a micro-USB socket, a CH340 USB-serial chip, a 3.3 V regulator and an IO0 button. The ESP32-CAM plugs on top, with the camera facing away from the USB socket. Many MB boards reset the module into download mode automatically, so uploading works like a normal DevKit. If it does not, hold the IO0 button on the MB, press the RST button on the ESP32-CAM, release IO0, then start the upload. You may need the CH340 driver on older Windows versions.

Arduino IDE Settings

  1. Install the board package: in Boards Manager search for esp32 by Espressif Systems and install it.
  2. Select Tools > Board > esp32 > AI Thinker ESP32-CAM.
  3. Select the COM port of your adapter (check Device Manager if unsure).
  4. Leave Upload Speed at the default. If uploads fail half way, try 115200.
  5. Connect IO0 to GND (FTDI method) and press the RESET button.
  6. Click Upload. When you see Hard resetting via RTS pin... the upload is complete.
  7. Remove the IO0 link, open the Serial Monitor at 115200 baud and press RESET.

Test Sketch

Use a tiny sketch first, without the camera, so you can separate upload problems from camera problems. It blinks the red LED on GPIO 33 and prints a counter.

Minimal upload test: blink the on-board red LED and print to serial
// Upload test for AI-Thinker ESP32-CAM
// Red LED on GPIO 33 is active LOW (LOW = on)

#define RED_LED 33

unsigned long counter = 0;

void setup() {
  Serial.begin(115200);          // same baud rate as Serial Monitor
  pinMode(RED_LED, OUTPUT);
  Serial.println();
  Serial.println("ESP32-CAM upload test running");
  Serial.printf("CPU frequency: %u MHz\n", getCpuFrequencyMhz());
}

void loop() {
  digitalWrite(RED_LED, LOW);    // LED on
  delay(300);
  digitalWrite(RED_LED, HIGH);   // LED off
  delay(700);
  Serial.printf("Alive, count = %lu\n", counter++);
}

If the counter appears and the red LED blinks, your adapter, wiring and IDE settings are correct, and you can move on to camera sketches. If the serial monitor shows nothing, make sure IO0 is no longer connected to GND and press RESET once.

Common Upload Errors and Fixes

Message or symptomLikely causeFix
Failed to connect to ESP32: Timed out waiting for packet headerChip not in download mode, or TX/RX swappedCheck IO0 to GND, press RESET just before upload, swap TX and RX
Wrong boot mode detected (0x13)GPIO 0 was HIGH at resetConnect IO0 to GND, then press RESET
No serial port in the IDEMissing driver or charge-only USB cableInstall CP210x, FTDI or CH340 driver; try a data cable
Upload stops part wayNoisy wires or weak powerShorter wires, 5 V supply, lower upload speed
Brownout detector was triggeredSupply voltage dips when Wi-Fi startsUse 5 V with enough current, not the 3.3 V pin
Program uploads but nothing runsIO0 still connected to GNDRemove the link and press RESET
Garbage characters in Serial MonitorWrong baud rateSet 115200 to match Serial.begin
  • Some USB-TTL adapters label pins from the adapter's point of view, others from the target's. If unsure, simply swap TX and RX and try again; this cannot damage anything.
  • Do not leave anything connected to GPIO 12 during upload. A pull-up there changes the flash voltage at boot and makes the chip fail to start.
  • Breadboards with loose contacts are a frequent cause of random upload failures. Use female jumper wires directly on the header pins.
  • If the Serial Monitor keeps the MB board in reset, press the RST button after opening the monitor.

Summary

The ESP32-CAM is programmed through UART0 on GPIO 1 and 3. Pulling GPIO 0 to GND at reset puts it in download mode; releasing GPIO 0 and resetting runs the sketch. Power the board from a proper 5 V source, cross TX and RX, select the AI Thinker ESP32-CAM board, and test with a simple LED sketch before adding the camera. With the ESP32-CAM-MB adapter most of these steps become automatic, but the IO0 and RST buttons are still there when an upload refuses to start.