Product images are for informational purposes only and may vary slightly depending on the batch and supplier. Product specifications and prices may be subject to change without notice. We do our best to provide accurate and complete product specifications, but they may not be completely accurate. If you encounter any such situation, please let us know.
The product is intended for specialists and requires qualified and authorized personnel. The product does not include assembly/use instructions . Putting the product into operation by unqualified persons leads to the loss of the warranty according to the Terms and Conditions on the site.
The specified technical parameters (current, power, etc.) represent maximum allowable values under ideal operating conditions. For safe use and optimal lifespan, it is recommended to operate the product continuously at no more than 50% of the specified maximum values.
ESP32-CAM development board with CH340G, WiFi, Bluetooth, OV5640 5MP
Compact solution for artificial vision projects, video streaming and IoT, with an ESP32 dual-core processor up to 240MHz, WiFi 802.11 b g n and Bluetooth 4.2 LE connectivity for wireless control and transmission, a 5MP OV5640 camera for detailed images, 4MB PSRAM memory for efficient capture and processing, easy programming in Arduino IDE via CH340G with USB Type C.
Buying this product earns you 4.58 RON in loyalty points.
International fast shipping within EU. Free Shipping for orders above 100 EUR in most EU countries.
We ship from our stock within 24H
You earn points with every order, worth 5%.
The ESP32-CAM development board combines the ESP32 processor with WiFi and Bluetooth and a 5 MP OV5640 camera attached via a flex cable to the board’s FPC connector on a single module. It is a complete solution for image capture and transmission in artificial vision projects, video streaming, and IoT. The board can operate independently, sending images and video streams over the network via WiFi, or it can be programmed to respond to commands received through UART, making it suitable for surveillance, object recognition, remote monitoring, and automated photography.
The board comes with a dedicated programmer, equipped with CH340 or FT232 (depending on the batch), with a USB Type-C port.
The processor is a 32-bit dual-core LX6 ESP32, with an operating frequency between 80 and 240 MHz and processing power of up to 600 DMIPS. The internal 520 KB SRAM memory is complemented by 4 MB of external PSRAM, required for processing high-resolution images before compression and transmission. The OV5640 camera offers a maximum resolution of 2592 x 1944 pixels (5 MP) and connects to a 24-pin FPC connector. The module supports WiFi 802.11 b/g/n, Bluetooth 4.2 LE, images in JPEG, BMP or grayscale format, and low-power modes Deep-sleep, Modem-sleep and Light-sleep.
Among the main features are the FPC connector for the camera, the microSD card slot of up to 4 GB, a white LED used as a flash, the printed PCB antenna, two rows of pins (16 in total) that expose power, free GPIOs and the UART interface, and a RESET button. Power is supplied at 5 VDC on the 5V pin, with a stable supply of at least 2 A; the board can also be powered at 3.3 VDC through the 3V3 pin.
Through the UART interface (U0T and U0R pins), the board is programmed and tested using a USB-serial adapter connected to the computer, and after connecting to the network, the images and video stream can be accessed directly from a browser on any computer or phone on the local network. The remaining free GPIO pins allow connection of additional sensors or modules compatible with Arduino, ESP32, STM32 or Raspberry Pi, using the board’s 3.3 V logic level.
Specifications:

Supply voltage: 5 VDC (5V pin)
Current consumption: 180 mA (Flash LED off) / 310 mA (Flash LED on, maximum brightness)
Deep-sleep current consumption: 6 mA minimum
Modem-sleep current consumption: 20 mA minimum
Light-sleep current consumption: 6.7 mA minimum
Number of pins: 16
WiFi: 802.11 b/g/n
Bluetooth: 4.2 LE
CPU: Dual core LX6, 32-bit
CPU frequency: 80 - 240 MHz
Internal memory: 520 KB SRAM
External memory: 4 MB PSRAM
SPI Flash memory: 32 Mbit
Supported interfaces: UART, SPI, I2C, PWM, ADC, DAC
Included camera: OV5640, 5 MP, maximum resolution 2592 x 1944 pixels
Camera connector: FPC, 24 pins
Image formats: JPEG, BMP, grayscale
Memory card: microSD (TF), up to 4 GB
Low-power modes: Deep-sleep, Modem-sleep, Light-sleep
Integrated software stack: LwIP, FreeRTOS
Network operating modes: STA / AP / STA+AP
Smart Config / AirKiss: Yes
FOTA update: Yes
Included programmer: Yes, with Type-C, CH340 or FT232 depending on the batch
Dimensions: 42 x 27 x 12 mm
WARNING!
Read carefully before buying
OV5640 camera (current batch)
This module is shipped with an OV5640 (5MP) camera instead of OV2640, due to supply issues with quality OV2640 cameras. The sensor heats up significantly during operation and may become hot to the touch. This is normal behavior for this board-camera combination, not a defect.
The programmer may use a CH340 or FT232 driver, depending on the batch.
Mandatory conditions of use:
Heatsink mounted on the back of the camera, with thermal tape or pad.
Good ventilation; do not use the module in closed enclosures without airflow.
Stable 5V power supply, minimum 2A, on the 5V pin. Do not power the module from the USB-serial adapter at 3.3V.
Reducing OV5640 camera heating on the ESP32-CAM board
The ESP32-CAM (AI Thinker) board was designed for the OV2640 camera and powers the camera connector with 3.3V (DOVDD), 2.8V (AVDD) and 1.2V (DVDD). The OV5640 sensor, however, requires 1.5V on the core (DVDD). To operate under these conditions, the OV5640 enables its internal 1.5V regulator by default, powered from the 3.3V supply. The voltage difference is converted into heat inside the sensor itself, which is why the module heats up significantly during continuous operation. Above approximately 50°C, noise and a violet tint may appear in the image. The solution is to replace the 1.2V regulator with a 1.5V one, followed by disabling the internal regulator in software.
Required
Regulator: XC6206P152MR or ME6206A15XG (1.5V, SOT-23)
Tools: hot air station, multimeter
OV5640 register: 0x3031, bit 3 (value 0x08)
Use
Disconnect the camera and power the board at 5V.
Using a multimeter, measure the output of the SOT-23 regulators next to the camera connector relative to a GND pin on the board, and identify the one that provides approximately 1.2V. The 2.8V regulator and AMS1117 (3.3V) are not modified.

Note the pin positions VIN (3.3V), VOUT (1.2V) and GND of the identified regulator.
Desolder the 1.2V regulator and replace it with the 1.5V regulator, after checking in the datasheet that VIN, VOUT and GND match the pads.
Power the board without the camera and verify that the new regulator output is between 1.45V and 1.55V.
Connect the camera and add to the code, immediately after esp_camera_init(), the disabling of the internal regulator (example below).
Check in Serial Monitor that register 0x3031 has the value 0x08.
Optionally, mount a small aluminum heatsink on the back of the camera module, attached with thermal tape.
// OV5640: disable the internal 1.5V core regulator (register 0x3031, bit 3)
// Use ONLY when DVDD is supplied externally with 1.5V
sensor_t *s = esp_camera_sensor_get();
if (s->id.PID == OV5640_PID) {
s->set_reg(s, 0x3031, 0x08, 0x08);
Serial.printf("OV5640 reg 0x3031 = 0x%02X\n", s->get_reg(s, 0x3031, 0xFF));
}
After modification, the camera works correctly at all tested resolutions, up to 2560x1920, and the module temperature decreases. A heatsink is still necessary because the camera still reaches around 50°C during operation.
Alternative without soldering
Mount a heatsink on the camera, use resolutions no higher than SVGA or HD in streaming, and put the sensor into standby between captures (register 0x3008 = 0x42 for standby, 0x02 for active).
Warning! Do not disable the internal regulator on an unmodified board with 1.2V on DVDD. The sensor core would operate below the specified minimum voltage, with risk of corrupted images and lockups. On a board without a DVDD regulator, disabling it leaves the core completely unpowered.
After modification, the board is no longer suitable for the OV2640 camera, which requires 1.2V on the core. Mark the board accordingly. The modification requires experience in soldering SMD components.
Layout:
| Element | Function |
|---|---|
| ESP32-S module with PCB antenna | The dual-core ESP32 processor and the WiFi / Bluetooth antenna printed on the board. |
| White LED | Used as the camera flash and controlled by GPIO4. It turns on when GPIO4 is HIGH and turns off when GPIO4 is LOW. |
| Red status LED | LED on the back of the board, controlled by GPIO33. It turns on when GPIO33 is LOW and can be used as a free indicator in the program. |
| Camera FPC connector | 24-pin connector to which the OV5640 camera flex cable is attached. |
| OV5640 camera | 5 MP camera module, mounted separately from the board and connected via flex cable. |
| microSD (TF) card slot | Local storage for images and files, cards up to 4 GB. Uses pins IO2, IO4, IO12, IO13, IO14 and IO15. |
| Two rows of pins (dual header) | Expose power, free GPIOs and the UART interface, 16 pins in total. |
| IO0 pin | Selects the boot mode. Connected to GND (the GND pin next to it) during reset, the board enters program upload mode. Left unconnected, the board runs the program from Flash memory. |
| RESET button | Resets the ESP32 microcontroller. Press it after connecting IO0 to GND to enter upload mode and after removing the jumper to run the program. |
| Voltage regulator | Converts the 5 V supply to the 3.3 V required by the board circuits. |
| Mounting holes | Two holes between the rows of pins for fixing the board. |
Pinout:

| Connector | Pin | Function |
|---|---|---|
| 5V header | 5V | Board power supply, 5 VDC |
| 5V header | GND | Ground |
| 5V header | IO12 | GPIO12, also used as MicroSD DATA2 |
| 5V header | IO13 | GPIO13, also used as MicroSD DATA3 |
| 5V header | IO15 | GPIO15, also used as MicroSD CMD |
| 5V header | IO14 | GPIO14, also used as MicroSD CLK |
| 5V header | IO2 | GPIO2, also used as MicroSD DATA0 |
| 5V header | IO4 | GPIO4, also used as MicroSD DATA1, controls the flash LED |
| 3V3 header | 3V3 | Board power supply, 3.3 VDC |
| 3V3 header | IO16 | GPIO16, free line, can be UART2 RX |
| 3V3 header | IO0 | GPIO0, selects boot mode, tied to GND for program upload |
| 3V3 header | GND | Ground |
| 3V3 header | VCC | 3.3 V or 5 V output, do not power the board through this pin |
| 3V3 header | U0R (IO3) | UART RX, serial data reception |
| 3V3 header | U0T (IO1) | UART TX, serial data transmission |
| 3V3 header | GND | Ground |
| Camera signal (FPC) | ESP32 GPIO | Function |
|---|---|---|
| D0 | GPIO5 | Camera data line (Y2) |
| D1 | GPIO18 | Camera data line (Y3) |
| D2 | GPIO19 | Camera data line (Y4) |
| D3 | GPIO21 | Camera data line (Y5) |
| D4 | GPIO36 | Camera data line (Y6) |
| D5 | GPIO39 | Camera data line (Y7) |
| D6 | GPIO34 | Camera data line (Y8) |
| D7 | GPIO35 | Camera data line (Y9) |
| XCLK | GPIO0 | Input clock for the camera sensor |
| PCLK | GPIO22 | Pixel output clock |
| VSYNC | GPIO25 | Frame vertical sync |
| HREF | GPIO23 | Line horizontal sync |
| SIOD (SDA) | GPIO26 | I2C / SCCB, sensor configuration |
| SIOC (SCL) | GPIO27 | I2C / SCCB, sensor configuration |
| PWDN | GPIO32 | Sensor power-down, HIGH for standby between captures |
Use:
If the camera module is not already mounted, attach it to the board’s FPC connector respecting the contact orientation and close the connector locking tab.
Mount a small heatsink, with thermal tape or pad, on the back of the OV5640 camera before first use, because the sensor heats up significantly during operation and may become hot to the touch; this is normal behavior for this board-camera combination.
Ensure good ventilation around the module and do not use it in a closed enclosure without airflow.
Power the board at 5 VDC, minimum 2 A, on the 5V pin, using a stable supply, and do not power the module from the 3.3 V output of a USB-serial adapter. Do not apply voltage to the VCC pin, as it is an output.
For programming, connect an FT232 or equivalent adapter to pins U0R, U0T and GND, with the adapter jumper set to 3.3 V, connecting the adapter TXD to U0R and RXD to U0T, and the adapter ground to the board ground.
In Arduino IDE install the esp32 board package by Espressif Systems from Boards Manager, select the AI Thinker ESP32-CAM board and open the CameraWebServer example from the File - Examples menu.
In the code, select the line with the camera model CAMERA_MODEL_AI_THINKER and fill in the WiFi network name and password.
Before uploading, temporarily connect IO0 to GND, press the RESET button and upload the program.
After upload, remove the jumper between IO0 and GND and press RESET again. Open Serial Monitor at 115200 baud and note the IP address displayed, then enter it in the browser of a computer or phone on the same network.
For continuous streaming, choose JPEG format and a reduced resolution (SVGA or HD), and use the maximum resolution only for photos. If you take periodic captures, put the sensor into standby between shots by setting GPIO32 HIGH.
If you use the microSD card, keep in mind that IO2, IO4, IO12, IO13, IO14 and IO15 are occupied by the card, and IO4 also controls the white LED.
The module is not recommended for continuous 24/7 streaming. For stable results, use a good power supply, short power cables and a WiFi network with strong signal where the board is mounted.
Dimensions diagram:

Tutorial:

- Supply voltage
- 5 V DC
- Dimensions
- 42 x 27 x 12 mm
- Number of pins
- 16
- Interface
- UART, SPI, I2C, PWM, ADC, DAC
- Flash memory
- 32 Mbit SPI
- Power consumption
- 180 mA / 310 mA
- Processor
- Dual core LX6, 32-bit
- WiFi
- 802.11 b/g/n
- Bluetooth
- 4.2 LE
- Standby consumption
- 6 mA
- SRAM memory
- 520 KB
- Processor frequency
- 80-240 MHz
- Memory card slot
- microSD (TF), up to 4 GB
Produs destinat utilizarii in proiecte electronice, automatizari, prototipare, educatie si cercetare.
Produsul trebuie utilizat numai conform specificatiilor tehnice mentionate in descriere si/sau in documentatia produsului.
Avertismente generale de siguranta:
Nu utilizati produsul la tensiuni, curenti sau temperaturi peste valorile specificate.
Montajul si conectarea trebuie realizate de persoane cu cunostinte tehnice minime in domeniul electric/electronic.
Evitati scurtcircuitele, inversarea polaritatii si conectarea gresita a alimentarii.
Nu lasati produsul alimentat nesupravegheat in timpul testelor.
Produsul nu este jucarie si nu este destinat copiilor.
Pentru modulele electronice, se recomanda utilizarea in carcase, panouri sau montaje protejate, dupa caz.
Identificare produs:
Denumirea produsului, codul/SKU-ul si caracteristicile tehnice sunt mentionate in pagina produsului si/sau pe eticheta ambalajului.
Producator / Importator / Distribuitor:
Sigmanortec S.R.L.
Calea Bucuresti nr. 9, Targu Jiu, Gorj, Romania
E-mail: [email protected]
Website: www.sigmanortec.ro
Persoana responsabila in UE:
Sigmanortec S.R.L.
Calea Bucuresti nr. 9, Targu Jiu, Gorj, Romania
E-mail: [email protected]
Documentatie si siguranta:
Pentru informatii suplimentare, fise tehnice, declaratii de conformitate sau instructiuni, ne puteti contacta la [email protected].
/*
Test sketch for ESP32-CAM (AI-Thinker) with OV5640 5MP camera
Board selected in Arduino IDE: "AI Thinker ESP32-CAM" (Tools > Board > esp32)
Board package: esp32 by Espressif Systems (installed from Boards Manager)
Boards Manager URL (File > Preferences): https://dl.espressif.com/dl/package_esp32_index.json
Libraries: none to install, esp_camera.h comes with the esp32 package
Wiring: camera attached to the onboard FPC connector, board powered at 5 V (min 2 A) on the 5V pin,
FT232 TXD -> U0R, FT232 RXD -> U0T, FT232 GND -> GND, IO0 bridged to GND only during upload
This sketch does not use WiFi. It checks that the camera starts and reports the frame size.
*/
#include "esp_camera.h"
// AI-Thinker camera pin map
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
bool cameraReady = false;
void setup() {
Serial.begin(115200);
delay(500);
Serial.println("ESP32-CAM OV5640 test starting");
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.pixel_format = PIXFORMAT_JPEG;
// SVGA keeps the sensor cooler than the maximum resolution
config.frame_size = psramFound() ? FRAMESIZE_SVGA : FRAMESIZE_CIF;
config.jpeg_quality = 12;
config.fb_count = psramFound() ? 2 : 1;
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x\n", err);
return;
}
sensor_t *s = esp_camera_sensor_get();
Serial.printf("Camera init OK, sensor PID: 0x%04X\n", s->id.PID);
cameraReady = true;
}
void loop() {
if (!cameraReady) {
delay(1000);
return;
}
camera_fb_t *fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Frame capture failed");
} else {
Serial.printf("Captured frame: %u x %u pixels, %u bytes\n",
(unsigned)fb->width, (unsigned)fb->height, (unsigned)fb->len);
esp_camera_fb_return(fb);
}
delay(5000);
}
The ESP32-CAM board with OV5640 5 MP camera is an ESP32 module with a built-in camera, used to capture and transmit images over WiFi without any additional components. It is used in surveillance projects, remote monitoring, automatic photography and image recognition.
The tutorial uses the AI-Thinker ESP32-CAM board as the platform, programmed from the Arduino IDE. The board has no USB port, so the program is uploaded through an FT232RL USB-to-serial adapter, and the power is supplied separately from a 5 VDC source with at least 2 A. The program starts the camera and serves a video stream through a simple web server.

How it works:
The OV5640 sensor captures the image and sends it to the ESP32 over 8 parallel data lines (D0 - D7), synchronized by the XCLK signals (the clock given to the sensor), PCLK (the pixel clock), VSYNC (frame start) and HREF (valid line). The sensor configuration, that is the resolution, exposure and white balance, is done over an I2C / SCCB bus on the SIOD (GPIO26) and SIOC (GPIO27) lines. The PWDN pin (GPIO32) can shut down the sensor when it is not in use.
The calculation below shows why the image is JPEG compressed directly in the sensor. The maximum resolution is 2592 x 1944 = 5 038 848 pixels. With 2 bytes per pixel (RGB565 format), one frame would be a little over 10 MB (10 077 696 bytes), more than the 4 MB of PSRAM on the board. In JPEG, a frame takes up much less and fits easily in memory.
At SVGA resolution (800 x 600 = 480 000 pixels), a JPEG frame is, depending on the scene and the quality set in the code, approximately 10 - 40 KB. In our tests, at quality 12, the average was about 13 KB per frame. If the WiFi network delivers 400 KB/s in practice, and a frame is 40 KB, this gives 400 / 40 = 10 frames per second. Above HD resolution, the sensor delivers only 4 - 6 frames per second with the 20 MHz XCLK clock. The maximum resolution therefore remains reserved for individual photos, and for video streaming SVGA or HD is chosen. The esp32-camera library offers QSXGA, 2560 x 1920 pixels, as its maximum resolution, slightly below the 2592 x 1944 pixels of the sensor.
Connection:
The board is powered from a separate 5 VDC source with at least 2 A, on the 5V pin. Do not power it from the USB-to-serial adapter, because the adapter and the USB port cannot supply the peak current required by the OV5640 camera together with WiFi, and the adapter's 3.3 V output is not suitable for this board. The VCC pin of the FT232RL adapter stays unconnected, and the adapter jumper is set to 3.3 V, so that the TXD and RXD signals have the 3.3 V logic level of the ESP32 GPIOs. The serial lines cross over: the TXD of the adapter goes to U0R, and the RXD of the adapter to U0T. The jumper between IO0 and GND is placed only while the program is being uploaded.
| Product pin | Connect to | Role |
|---|---|---|
| 5V | 5 VDC source, + terminal | Board power supply, minimum 2 A |
| GND (5V header) | 5 VDC source, - terminal | Power supply ground |
| U0R (GPIO3) | FT232 TXD | Serial data reception on the board |
| U0T (GPIO1) | FT232 RXD | Serial data transmission from the board |
| GND (next to U0T) | FT232 GND | Common ground with the adapter |
| IO0 | GND (pin next to IO0) | Temporary jumper for the program upload mode |
The image below shows how the board is connected to the FT232 programmer.

Buttons, settings and indicators:
| Element | What it does | How to use it |
|---|---|---|
| RESET button | Resets the ESP32 microcontroller. | Press it briefly after connecting IO0 to GND to enter the upload mode, then after removing the jumper to run the program. |
| IO0 - GND jumper | Selects the boot mode. | When placed during reset, the board waits for a program to be uploaded. When removed during reset, the board runs the program from Flash. |
| White LED (flash) | Lights the scene for the camera, controlled by GPIO4. | It turns on when GPIO4 is HIGH. In the tutorial program it stays off. |
| Red status LED | Indicator on the back of the board, controlled by GPIO33. | It turns on when GPIO33 is LOW. It is not used by the tutorial program. |
For uploading, connect IO0 to GND, press RESET and upload the program. The board has entered the correct mode if the Arduino IDE starts the upload without the connection error.
After uploading, remove the jumper between IO0 and GND and press RESET. The board now runs the program, and the startup messages appear in the Serial Monitor.
The white LED stays off in the program. If you want additional lighting, control GPIO4 from the code, keeping in mind that the LED at maximum brightness adds approximately 130 mA to the consumption. In our tests, the board with the OV5640 camera consumed approximately 340 - 360 mA at 5 V, with the camera active and the LED off.
Board and libraries:
In the Arduino IDE, go to File - Preferences and add in the Additional Boards Manager URLs field the address https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json. Then open Tools - Board - Boards Manager, search for esp32 and install the esp32 by Espressif Systems package, in a recent version (2.0.x or newer).
After installation, select the AI Thinker ESP32-CAM board from Tools - Board - esp32. The screenshots below illustrate the configuration steps in the Arduino IDE.
No library needs to be installed from the Library Manager, because esp_camera.h and WiFi.h come with the esp32 by Espressif Systems package.
The code:
The program initializes the camera with the pin mapping of the AI-Thinker board, connects to the WiFi network and sends the JPEG video stream to a client connected on port 80. Replace the network name and password before uploading.
/*
ESP32-CAM (AI-Thinker) with OV5640 5MP camera - WiFi MJPEG video stream
Board selected in Arduino IDE: "AI Thinker ESP32-CAM" (Tools > Board > esp32)
Board package: esp32 by Espressif Systems (installed from Boards Manager)
Boards Manager URL (File > Preferences): https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
Libraries: none to install, esp_camera.h and WiFi.h come with the esp32 package
Upload wiring: FT232 TXD -> U0R, FT232 RXD -> U0T, FT232 GND -> GND,
5V supply (min 2 A) on the 5V pin, IO0 bridged to GND only during upload
*/
#include "esp_camera.h"
#include <WiFi.h>
// ---- Wi-Fi credentials (replace with your own) ----
const char* WIFI_SSID = "YOUR_WIFI_SSID";
const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";
// ---- AI-Thinker camera pin map ----
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
// White flash LED on GPIO4 (also SD card DATA1)
#define FLASH_LED_GPIO_NUM 4
WiFiServer server(80);
// Configure and start the camera
bool startCamera() {
camera_config_t config = {}; // start from a zeroed structure
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sccb_sda = SIOD_GPIO_NUM;
config.pin_sccb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000; // 20 MHz clock for the sensor
config.pixel_format = PIXFORMAT_JPEG; // the sensor compresses the image itself
if (psramFound()) {
config.frame_size = FRAMESIZE_SVGA; // 800x600, a good balance for streaming
config.jpeg_quality = 12; // lower number = better quality, bigger file
config.fb_count = 2; // two frame buffers for smoother streaming
config.fb_location = CAMERA_FB_IN_PSRAM;
config.grab_mode = CAMERA_GRAB_LATEST; // always send the newest frame
Serial.println("PSRAM found, using SVGA with 2 frame buffers");
} else {
config.frame_size = FRAMESIZE_CIF;
config.jpeg_quality = 15;
config.fb_count = 1;
config.fb_location = CAMERA_FB_IN_DRAM;
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
Serial.println("No PSRAM, using CIF with 1 frame buffer");
}
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x\n", err);
return false;
}
// Read the sensor ID to confirm which camera is attached
sensor_t *s = esp_camera_sensor_get();
Serial.printf("Camera init OK, sensor PID: 0x%04X\n", s->id.PID);
if (s->id.PID != OV5640_PID) {
Serial.println("Warning: the attached sensor is not an OV5640");
}
return true;
}
// Read and ignore the HTTP request header sent by the browser
void skipRequest(WiFiClient &client) {
unsigned long start = millis();
while (client.connected() && millis() - start < 1000) {
if (client.available()) {
String line = client.readStringUntil('\n');
if (line.length() <= 1) break; // blank line ends the header
}
}
}
// Send frames to the client until it disconnects
void streamTo(WiFiClient &client) {
client.print("HTTP/1.1 200 OK\r\n");
client.print("Content-Type: multipart/x-mixed-replace; boundary=frame\r\n\r\n");
Serial.println("Streaming started");
uint32_t frames = 0;
while (client.connected()) {
camera_fb_t *fb = esp_camera_fb_get(); // get one JPEG frame
if (!fb) {
Serial.println("Frame capture failed");
break;
}
size_t len = fb->len;
client.print("--frame\r\n");
client.print("Content-Type: image/jpeg\r\n");
client.printf("Content-Length: %u\r\n\r\n", (unsigned)len);
size_t sent = client.write(fb->buf, len);
client.print("\r\n");
esp_camera_fb_return(fb); // give the buffer back to the driver
if (sent != len) break; // client is gone
frames++;
}
Serial.printf("Client disconnected after %u frames\n", (unsigned)frames);
}
void setup() {
Serial.begin(115200);
delay(500);
Serial.println();
Serial.println("ESP32-CAM OV5640 stream example");
// Keep the white flash LED off
pinMode(FLASH_LED_GPIO_NUM, OUTPUT);
digitalWrite(FLASH_LED_GPIO_NUM, LOW);
if (!startCamera()) {
return; // stop here if the camera did not start
}
// Connect to Wi-Fi
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
WiFi.setSleep(false); // no Wi-Fi power saving, better for streaming
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.print("WiFi connected, IP address: ");
Serial.println(WiFi.localIP());
Serial.print("Open http://");
Serial.print(WiFi.localIP());
Serial.println("/ in a browser to see the stream");
server.begin();
}
void loop() {
WiFiClient client = server.available(); // wait for a browser
if (client) {
Serial.println("Client connected");
skipRequest(client);
streamTo(client);
client.stop();
}
}
How the code works:
The first part contains the definitions. The constants WIFI_SSID and WIFI_PASSWORD hold the network details, and the lines with PWDN_GPIO_NUM, XCLK_GPIO_NUM, SIOD_GPIO_NUM, SIOC_GPIO_NUM, Y2_GPIO_NUM - Y9_GPIO_NUM, VSYNC_GPIO_NUM, HREF_GPIO_NUM and PCLK_GPIO_NUM describe the pins between the ESP32 and the camera connector, the same as in the table in the description. FLASH_LED_GPIO_NUM is GPIO4, and the server object listens on port 80.
The startCamera() function fills the camera_config_t structure with the camera pins, the 20 MHz XCLK clock and the PIXFORMAT_JPEG format. The structure starts empty (= {}), so that the fields that are not set do not contain random values. If psramFound() returns true, FRAMESIZE_SVGA is chosen with two frame buffers in PSRAM (fb_count = 2) and the CAMERA_GRAB_LATEST mode, which always sends the newest frame. Otherwise FRAMESIZE_CIF is chosen with a single buffer in the internal memory. After esp_camera_init(), the function reads the sensor with esp_camera_sensor_get(), prints the PID identifier, which for the OV5640 is 0x5640, and warns if the connected sensor is a different one.
The skipRequest() function reads and ignores the HTTP request header sent by the browser, up to the first empty line. The streamTo() function sends the multipart/x-mixed-replace header, then repeats in a loop: it gets a frame with esp_camera_fb_get(), sends the boundary, the type and the length, writes the JPEG data with client.write() and releases the buffer with esp_camera_fb_return(). The loop stops when the client disconnects.
In setup(), Serial is started at 115200 baud, the white LED is kept off, startCamera() is called, the board connects to WiFi with WiFi.begin() and the received IP address is printed. In loop() the program waits for a client with server.available() and, when one appears, serves it the stream through streamTo().
Result:
Open the Serial Monitor at 115200 baud. After startup, the confirmation of the camera initialization with PID 0x5640 should appear, followed by the IP address of the board. Enter the address in the browser and the real-time image will appear.
ESP32-CAM OV5640 stream example
PSRAM found, using SVGA with 2 frame buffers
Camera init OK, sensor PID: 0x5640
Connecting to WiFi......
WiFi connected, IP address: 192.168.1.57
Open http://192.168.1.57/ in a browser to see the stream
Client connected
Streaming started
Client disconnected after 412 frames
Common problems:
The upload stops with a connection error. The usual cause is the wrong boot mode. Check that IO0 is connected to GND, press RESET before uploading and check that TXD goes to U0R and RXD to U0T, not directly.
After uploading, nothing happens and a message about waiting for the program upload appears in the Serial Monitor. The jumper between IO0 and GND was left in place. Remove it and press RESET.
The board resets continuously or the message Brownout detector was triggered appears. The power supply is insufficient, usually because the board is powered from USB or from a weak source. Use a stable 5 VDC source with at least 2 A, with short cables.
The message Camera init failed appears with an error code. The camera flex cable is not fully inserted or the FPC connector latch is not closed. Disconnect the power, reinsert the cable with the contacts in the correct position and close the latch.
The image has noise or a purple tint after a period of operation. The OV5640 sensor has overheated. Mount a heatsink on the back of the camera, ensure ventilation and reduce the resolution to SVGA or HD.
The board connects to WiFi, but the image freezes or has few frames per second. The WiFi signal is weak or the resolution is too high. Move the board closer to the router and reduce the resolution in the code.
Limitations and tips:
The module is not recommended for continuous streaming 24 hours a day, because the OV5640 camera heats up strongly on this board. The reason is that the board was designed for the OV2640 camera and supplies the camera connector with 3.3 V, 2.8 V and 1.2 V, while the OV5640 powers its core from an internal 1.5 V regulator driven from 3.3 V. The voltage difference turns into heat right in the sensor, and above approximately 50 degrees C noise and a purple tint can appear in the image.
Without hardware modifications, use a heatsink on the camera, resolutions of at most SVGA or HD in streaming, and put the sensor into standby between captures through register 0x3008 (value 0x42 for standby and 0x02 for active). In our tests, the consumption of the board dropped from approximately 338 mA to 163 mA with the sensor in standby. The maximum resolution offered by the library, 2560 x 1920 pixels, is suitable for photos.
Users experienced in soldering SMD components can reduce the heating by replacing the 1.2 V regulator next to the camera connector with a 1.5 V one (for example XC6206P152MR or ME6206A15XG) and by disabling the internal sensor regulator from software, through bit 3 of register 0x3031 (value 0x08), right after esp_camera_init(). After this modification, the camera heatsink stayed noticeably cooler in our tests.
// Only on a board where the DVDD regulator was replaced with a 1.5 V one
sensor_t *s = esp_camera_sensor_get();
if (s->id.PID == OV5640_PID) {
s->set_reg(s, 0x3031, 0x08, 0x08); // bypass the internal 1.5 V core regulator
}
Do not disable the internal regulator on an unmodified board, because the sensor core would operate below its minimum voltage, with the risk of corrupted images and crashes. A modified board is no longer suitable for the OV2640 camera and must be marked accordingly.
Based on this tutorial you can build a surveillance camera with browser access, a periodic photography system with saving to a microSD card, or an object recognition project, using the free GPIOs for motion sensors or other modules.