The ESP32-CAM is one of the most capable and affordable development boards available to Indian makers today. For under Rs. 400, you get a dual-core 240 MHz processor, built-in WiFi and Bluetooth, an OV2640 2MP camera, a microSD card slot, and enough GPIO to add sensors and peripherals. This guide takes you from an unboxed ESP32-CAM to a working WiFi security camera — covering specs, programming without a dedicated FTDI adapter, live video streaming, face detection, motion-triggered SD card snapshots, and Telegram bot alerts for real-time notifications.
Table of Contents
ESP32-CAM Specs & Board Overview
The ESP32-CAM uses the Ai-Thinker ESP32-S module and an OV2640 image sensor. Key specifications:
- MCU: ESP32-S dual-core Xtensa LX6, 240 MHz
- RAM: 520 KB SRAM + 4 MB PSRAM (external, used for frame buffering)
- Flash: 4 MB
- Camera: OV2640, up to 2MP (1600×1200), JPEG and YUV422 output, 30 fps at QVGA (320×240)
- WiFi: 802.11 b/g/n, 2.4 GHz, STA + AP + STA+AP modes
- Bluetooth: BLE 4.2 + BR/EDR (Classic)
- MicroSD: Up to 4 GB (FAT32), connected via SPI on GPIO 14/15/2/4
- LED flash: White high-brightness LED on GPIO 4
- Power supply: 5V input via the 5V pin; internal 3.3V LDO; current draw up to 310 mA during WiFi TX + camera active
- Programming: Serial (UART0 on GPIO 1/3), no USB-to-serial chip on board
The board has one important gotcha: there is no USB port. All programming is done via the UART pins using an external USB-to-TTL adapter. The on-board flash button (GPIO 0) is pulled low to enter bootloader mode.
Programming Without FTDI: Using Arduino Uno as USB-to-Serial
If you do not have an FTDI or CP2102 USB-to-serial adapter, you can use an Arduino Uno as a pass-through programmer. Here is the exact wiring:
Arduino Uno ESP32-CAM
----------- ---------
RESET ------> RESET (or GND the Arduino RESET to disable its MCU)
GND ------> GND
5V ------> 5V
TX ------> U0R (GPIO 3)
RX ------> U0T (GPIO 1)
GND ------> GPIO 0 (hold LOW to enter flash mode)
Short the Arduino’s RESET pin to GND to disable the Uno’s ATmega328P so it acts purely as a USB-to-serial bridge. Connect GPIO 0 of the ESP32-CAM to GND before powering up to enter download mode. After flashing, disconnect GPIO 0 from GND and press the ESP32-CAM reset button (or cycle power) to boot normally.
The dedicated ESP32-CAM-MB module is a much cleaner alternative — it plugs directly onto the ESP32-CAM and provides a Micro-USB port for programming, with the GPIO 0 boot button already wired. Highly recommended for regular development work.
Arduino IDE Setup
Follow these steps to configure the Arduino IDE for the ESP32-CAM:
- Install Arduino IDE 2.x from arduino.cc
- Go to File > Preferences > Additional Boards Manager URLs and add:
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json - Go to Tools > Board > Boards Manager, search for “esp32” and install the esp32 by Espressif Systems package (version 2.0.x or later)
- Select board: Tools > Board > esp32 > AI Thinker ESP32-CAM
- Set partition scheme: Huge APP (3MB No OTA/1MB SPIFFS) — this gives more space for the camera libraries
- Set upload speed: 115200 (reliable with Arduino Uno bridge) or 921600 (with dedicated FTDI)
Basic Camera Web Server (Live Stream)
The ESP32 Arduino core includes a ready-to-use CameraWebServer example that streams MJPEG video to any browser on your network. Find it at File > Examples > ESP32 > Camera > CameraWebServer.
You only need to modify two lines:
// In CameraWebServer.ino
#define CAMERA_MODEL_AI_THINKER // Uncomment this line
// Comment out all other CAMERA_MODEL_ defines
const char* ssid = "YourWiFiSSID";
const char* password = "YourWiFiPassword";
After uploading, open Serial Monitor at 115200 baud. The board will print its local IP address. Open that IP in any browser on the same WiFi network to see the camera control panel. Click Start Stream to begin MJPEG streaming. The panel also lets you adjust resolution, brightness, contrast, saturation, and special effects.
For stable streaming, use SVGA (800×600) resolution at 10–15 fps. The PSRAM handles frame buffering. At UXGA (1600×1200) full resolution, frame rate drops to 2–5 fps — fine for still captures but not smooth video.
Face Detection
The CameraWebServer example includes built-in face detection and recognition using the dl_lib library from Espressif. In the browser control panel, scroll down to find the Face Detection toggle. When enabled, the firmware draws bounding boxes around detected faces in the stream.
Face detection works at CIF (400×296) resolution and requires PSRAM. The algorithm is a lightweight MobileNet-based model running entirely on the ESP32 — no cloud required. Face recognition (enrolling specific faces) is also available: click Enroll Face while a face is in frame to save an embedding, then the system will label that face in future frames.
Performance: face detection adds ~200 ms latency per frame. At CIF resolution you get roughly 3–5 detected fps. For a doorbell camera that logs face presence with a timestamp, this is perfectly adequate.
Saving Images to SD Card
The ESP32-CAM’s microSD slot uses SPI mode. Here is a complete sketch that captures a JPEG image every 30 seconds and saves it to the SD card with a sequential filename:
#include "esp_camera.h"
#include "SD_MMC.h"
#include "FS.h"
#define CAMERA_MODEL_AI_THINKER
#include "camera_pins.h"
int photoCount = 0;
void setup() {
Serial.begin(115200);
// Camera config
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;
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 12;
config.fb_count = 1;
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed: 0x%xn", err);
return;
}
// Mount SD card (1-bit SDMMC mode — compatible with AI Thinker)
if (!SD_MMC.begin("/sdcard", true)) {
Serial.println("SD card mount failed");
return;
}
Serial.println("SD card mounted");
}
void loop() {
camera_fb_t *fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Camera capture failed");
delay(1000);
return;
}
String path = "/photo_" + String(photoCount++) + ".jpg";
File file = SD_MMC.open(path.c_str(), FILE_WRITE);
if (!file) {
Serial.println("Failed to open file for writing");
} else {
file.write(fb->buf, fb->len);
Serial.printf("Photo saved: %s (%d bytes)n", path.c_str(), fb->len);
file.close();
}
esp_camera_fb_return(fb);
delay(30000); // capture every 30 seconds
}
Important SD card notes: Format the SD card as FAT32 (not exFAT). Use Class 10 or higher cards. The SD_MMC library uses GPIO 2 and 4 for the SD data lines, which share with the LED flash — do not use the LED while SD writes are in progress or you will corrupt the write. Use 1-bit mode (SD_MMC.begin("/sdcard", true)) to free up GPIO 15 for other uses.
Telegram Bot for Instant Alerts
Sending a photo to your Telegram when motion is detected (or on a schedule) is a practical use case. Install the UniversalTelegramBot library (by Brian Lough) and ArduinoJson from the Arduino Library Manager.
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include "esp_camera.h"
#include <UniversalTelegramBot.h>
#include <ArduinoJson.h>
#define CAMERA_MODEL_AI_THINKER
#include "camera_pins.h"
const char* ssid = "YourSSID";
const char* password = "YourPassword";
String BOT_TOKEN = "YOUR_BOT_TOKEN_HERE";
String CHAT_ID = "YOUR_CHAT_ID_HERE";
WiFiClientSecure client;
UniversalTelegramBot bot(BOT_TOKEN, client);
void sendPhoto() {
camera_fb_t *fb = esp_camera_fb_get();
if (!fb) { Serial.println("Camera capture failed"); return; }
String caption = "Motion detected at ESP32-CAM";
bool sent = bot.sendPhotoByBinary(
CHAT_ID, "image/jpeg", fb->len,
[](uint8_t *buffer, size_t &size, size_t maxSize) -> bool {
// Streaming callback — handled internally
return false;
}
);
// Simpler: save to SD, then send URL — or use multipart upload
Serial.println(sent ? "Photo sent to Telegram" : "Send failed");
esp_camera_fb_return(fb);
}
void setup() {
Serial.begin(115200);
// (camera init as shown in SD card example above)
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println("nWiFi connected: " + WiFi.localIP().toString());
client.setInsecure(); // Accept Telegram's certificate
}
void loop() {
// In a real project, trigger this from a PIR sensor on GPIO 13
sendPhoto();
delay(60000);
}
To create a Telegram bot: message @BotFather on Telegram, use /newbot, and copy the token. To get your Chat ID: message @userinfobot with /start. For motion triggering, connect a PIR sensor (HC-SR501) to GPIO 13 (one of the few free GPIOs on the AI Thinker board) and call sendPhoto() on a rising edge interrupt.
Enclosure, Power & Night Vision
3D Printed Enclosure
The Ai-Thinker ESP32-CAM PCB dimensions are 40mm x 27mm x 3mm (without camera module). Dozens of free enclosure designs are available on Thingiverse and Printables — search “ESP32-CAM enclosure.” For outdoor mounting: print in PETG (better UV and temperature resistance than PLA), add an M3 nut insert for mounting, and seal the USB/serial opening with silicone sealant. A transparent dome or flat acrylic window in front of the camera preserves optical clarity while protecting from dust.
Power Supply Options
The ESP32-CAM draws up to 310 mA peak during WiFi transmission. Power options:
- USB power adapter (5V, 1A+): Most reliable for fixed installations. Use a good quality adapter — cheap phone chargers with poor regulation cause random resets during WiFi bursts.
- 18650 lithium cell: A single 3.7V 18650 (2600 mAh) with a TP4056 charger + MT3608 boost converter to 5V. At 100 mA average draw (with deep sleep between snapshots), runtime is approximately 20–25 hours. With 1-minute wakeup intervals and 5-second active windows, deep sleep extends this to several days.
- Solar: A 5V 2W panel + 18650 + TP4056 keeps the camera running indefinitely in Indian sunlight conditions for outdoor garden or gate cameras.
Night Vision Limitations
The standard OV2640 on the ESP32-CAM has no IR cut filter, which means it is slightly sensitive to near-infrared light — but the white LED flash is not an IR LED. Night vision (meaningful illumination beyond 1–2 meters in darkness) requires adding external 850nm or 940nm IR LEDs with a separate driver circuit. Without this, the ESP32-CAM produces grainy, unusable footage in low light. For a proper night vision camera, add a 5-LED IR array board (~Rs. 100) powered from the 5V rail, switched via a transistor controlled from GPIO 12.
ESP32-CAM vs Commercial Cameras
| Feature | ESP32-CAM DIY | TP-Link Tapo C100 | Reolink E1 |
|---|---|---|---|
| Price | Rs. 350–450 | Rs. 2,000–2,500 | Rs. 2,500–3,000 |
| Resolution | 2MP (1600×1200) | 1080p (2MP) | 1080p (2MP) |
| Night Vision | Poor (no IR LEDs) | Good (IR LEDs built-in) | Good (IR LEDs built-in) |
| Local Storage | MicroSD (4 GB max) | MicroSD (128 GB) | MicroSD (64 GB) |
| Cloud Dependency | None (fully local) | Required for remote view | Required for remote view |
| Customisability | Full (open source) | None | None |
| Setup Complexity | High (programming required) | Very low (app setup) | Very low (app setup) |
| Home Automation Integration | Excellent (MQTT, HTTP, HA) | Good (via Tapo binding) | Limited |
The ESP32-CAM is not a replacement for a commercial security camera in terms of night vision, reliability, and video quality. Its value is in customisation, zero cloud dependency, Home Assistant integration, and the ability to add custom logic (face detection, counting, MQTT alerts, GPIO-triggered events) that commercial cameras simply cannot offer.
Frequently Asked Questions
Q: Why does my ESP32-CAM keep rebooting or failing to stream?
The most common cause is insufficient power. The ESP32-CAM draws up to 310 mA during active WiFi + camera operation. USB ports on computers and cheap phone chargers often cannot source enough current, causing brownout resets. Use a dedicated 5V 2A power adapter. Also check that the camera ribbon cable is firmly seated — the connector is fragile and a loose connection causes random init failures.
Q: Can the ESP32-CAM stream to a smartphone over mobile data (not local WiFi)?
Not directly, since the camera runs a web server on your local network and does not have a public IP. Options: (1) Use a VPN like WireGuard or ZeroTier on your router to access your home network remotely. (2) Use an MQTT broker (HiveMQ Cloud free tier) and send JPEG frames as binary MQTT payloads for a low-bandwidth snapshot feed. (3) Use ngrok or Cloudflare Tunnel to expose the local web server temporarily — not recommended for permanent security use.
Q: How do I add motion detection to the ESP32-CAM?
Two approaches: (1) Hardware — connect a PIR sensor (HC-SR501) to GPIO 13. This is the simplest and most power-efficient method. (2) Software — compare consecutive frames in firmware using the Motion Detection feature in some ESP32-CAM firmwares, or use frame difference algorithms. Hardware PIR is more reliable and does not require continuous camera processing.
Q: What is the maximum range of the ESP32-CAM WiFi?
The onboard PCB antenna (inverted-F trace antenna) gives roughly 50–80 meters in open air and 10–20 meters through walls. The AI Thinker board has an IPEX connector for an external antenna — adding a 2.4 GHz external antenna extends range significantly. Some variants of the ESP32-CAM board include an external antenna slot; check your specific board version.
Q: Is the ESP32-CAM OV2640 camera good enough for number plate recognition (ANPR)?
No. The OV2640 fixed-focus lens is optimised for 60–80 cm (typical selfie/wide shot distance). Number plates at 3–5 metres are blurry and too small in the frame for reliable OCR. The Ai-Thinker AF2569 autofocus variant is better but still limited. For ANPR, use a dedicated IP camera with a varifocal lens and run plate recognition software (like OpenALPR or Plate Recognizer) on a Raspberry Pi or server.
Start Building Your ESP32-CAM Security Camera
Zbotic.in stocks the ESP32-CAM module, the ESP32-CAM-MB programming board, and all the components you need for your DIY security camera project. Order today with fast delivery across India.
Add comment