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 adapter | ESP32-CAM pin | Notes |
|---|---|---|
| GND | GND | Common ground is essential |
| 5V / VCC (5 V) | 5V | Board regulator makes 3.3 V from this |
| TX | U0R (GPIO 3) | Adapter TX goes to ESP32 RX |
| RX | U0T (GPIO 1) | Adapter RX goes to ESP32 TX |
| - | IO0 to GND | Jumper 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
- Install the board package: in Boards Manager search for esp32 by Espressif Systems and install it.
- Select Tools > Board > esp32 > AI Thinker ESP32-CAM.
- Select the COM port of your adapter (check Device Manager if unsure).
- Leave Upload Speed at the default. If uploads fail half way, try 115200.
- Connect IO0 to GND (FTDI method) and press the RESET button.
- Click Upload. When you see
Hard resetting via RTS pin...the upload is complete. - 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.
// 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 symptom | Likely cause | Fix |
|---|---|---|
| Failed to connect to ESP32: Timed out waiting for packet header | Chip not in download mode, or TX/RX swapped | Check IO0 to GND, press RESET just before upload, swap TX and RX |
| Wrong boot mode detected (0x13) | GPIO 0 was HIGH at reset | Connect IO0 to GND, then press RESET |
| No serial port in the IDE | Missing driver or charge-only USB cable | Install CP210x, FTDI or CH340 driver; try a data cable |
| Upload stops part way | Noisy wires or weak power | Shorter wires, 5 V supply, lower upload speed |
| Brownout detector was triggered | Supply voltage dips when Wi-Fi starts | Use 5 V with enough current, not the 3.3 V pin |
| Program uploads but nothing runs | IO0 still connected to GND | Remove the link and press RESET |
| Garbage characters in Serial Monitor | Wrong baud rate | Set 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.