ESP32 & IoT24 October 202620 mins

Build an Edge License Plate Recognition & Gate Access Controller with ESP32-CAM

Step-by-step engineering guide for building an automatic number plate recognition (ANPR) parking gate controller using ESP32-CAM, edge optical extraction, and relay triggers.

M
M F Haque
Founder & Hardware Architect, Mentora
Share this GuideFree & Unlimited on Mentora
Share with friends and study groups — anyone with the link can read free on Mentora.
Key Strategic Takeaways
  • Complete hardware pinout and wiring schematic mapping
  • Production-tested Arduino C++ firmware with event-driven callbacks
  • Electrical safety constraints, level-shifting & sensor calibration heuristics

2. Overview & Engineering Objectives

Commercial automatic number plate recognition (ANPR) systems rely on dedicated servers and costly industrial cameras. This project implements an embedded edge camera unit that captures approaching vehicle license plates, extracts alphanumeric characters against an authorized security whitelist, and actuates an electric boom barrier or magnetic gate lock.

Core Engineering Capabilities:

Optical Contrast Tuning: Configures the OV2640 camera sensor with custom exposure, gain, and contrast levels to capture reflective high-contrast vehicle plates under harsh daytime sunlight or nighttime headlights.

PSRAM Buffer Management: Prevents ESPERRNO_MEM panics by enforcing double-buffered SVGA/XGA capture pools within the 4MB external PSRAM.

Whitelisted Gate Actuation: Pulses an optoisolated relay on GPIO 13 for 3.5 seconds when an authorized vehicle plate is verified, sending an MQTT audit log to the facility management server.

Flash Glitch Suppression: Addresses the GPIO 4 high-power flash LED boot artifact, ensuring the bright LED does not blind incoming drivers during device reboots.

3. Bill of Materials (BOM)

Component

Quantity

Specification / Rating

Est. Cost (INR)

Sourcing / Affiliate Link

AI-Thinker ESP32-CAM Board

1

Includes OV2640 2MP Camera Sensor + 4MB PSRAM

₹450

Buy on Mentora Store

ESP32-CAM MB USB Programmer Base

1

CH340 USB programmer base with reset & boot buttons

₹180

Buy on Mentora Store

5V Optocoupled Relay Module

1

10A 250VAC / 30VDC rated, Active-LOW trigger

₹95

Buy on Mentora Store

1000µF 16V Decoupling Capacitor

1

Low-ESR filter capacitor across 5V and GND rail

₹15

Buy on Mentora Store

5V 2A Regulated DC Power Supply

1

Dedicated clean wall adapter

₹180

Buy on Mentora Store

IP65 Outdoor Camera Housing

1

Weatherproof plastic enclosure with optical acrylic window

₹240

Buy on Mentora Store

Total Hardware Cost

~₹1,160

4. Hardware Architecture: Overcoming ESP32-CAM Memory & Flash Traps

1. Frame Buffer Overflow at UXGA

Attempting to allocate a raw 1600x1200 (UXGA) frame buffer in standard internal SRAM crashes the ESP32-CAM instantly:

Internal SRAM: Only ~320kB available.

UXGA JPEG Frame: Requires ~150kB–350kB per frame buffer.

The Solution: Always verify PSRAM presence (psramFound()). Restrict resolution to FRAMESIZESVGA (800x600) or FRAMESIZEHD (1280x720) with config.jpegquality = 10 and config.fbcount = 2.

2. GPIO 4 Flash LED Boot Bug

The onboard ultra-bright white LED is hardwired to GPIO 4.

During bootloader execution, GPIO 4 can float HIGH momentarily, pulsing the dazzling LED into drivers' eyes.

Furthermore, GPIO 4 is shared with HS2_DATA1 of the microSD card. If you use a microSD card in 4-bit bus mode, every write command flashes the LED!

The Solution: If local SD logging is required, initialize the SD card in 1-bit SPI mode (SD_MMC.begin("/sdcard", true)), which leaves GPIO 4 completely free for software-controlled flash assist.

5. Plate Verification & Gate Relay Logic

1. Vehicle enters induction loop or PIR proximity trigger.

2. ESP32-CAM activates Flash LED (GPIO 4) for 200ms to illuminate license plate.

3. Camera driver grabs frame buffer: espcamerafb_get().

4. Firmware extracts alphanumeric candidate string (e.g., "MH12AB1234").

5. Database Verification: Compares string against flash-stored PROGMEM whitelist.

  • MATCH FOUND:

-> Drive Relay Pin (GPIO 13) LOW (Active) for 3.5 seconds.

-> Send HTTP / MQTT telemetry log: {"plate":"MH12AB1234", "access":"GRANTED"}.

  • MATCH FAILED:

-> Keep Gate Locked.

-> Log security alert to cloud dashboard.

6. Return frame buffer immediately: espcamerafb_return(fb).

6. Real-World Troubleshooting FAQs

Q1: Why does espcamerainit() fail with error 0x105 or 0x20001?

Root Cause: PSRAM disabled in IDE or camera ribbon cable loose. Ensure "AI Thinker ESP32-CAM" board is selected with "PSRAM: Enabled", and inspect the FPC zero-insertion-force connector on the camera ribbon.

Q2: Why does the SD card fail to mount with FS_ERROR?

Root Cause: SD card formatted as exFAT or capacity > 32GB. The ESP32-CAM hardware SDMMC driver strictly requires cards formatted as FAT32.

Q3: Why does the relay trigger erratically when the camera takes a photo?

Root Cause: 5V rail voltage dip during camera capture + Wi-Fi burst. Ensure the external 5V 2A supply is equipped with a 1000µF capacitor soldered across the ESP32-CAM 5V and GND pins.

7. Mentora Monetization & Student Support Hooks

🛒 Official Mentora ANPR Gate Controller Kit: ESP32-CAM module, MB USB programmer, high-torque 12V gate solenoid relay, 5V 2A power adapter, and IP65 enclosure for ₹1,899.

⚡ ₹49 Mentora Token Vault: Instantly unlock the companion Python Flask cloud ANPR OCR fallback server, Node-RED gate access logger, and vehicle RFID dual-factor authentication sketch.

🛠️ ₹299 1-on-1 Mentora Live Video Debugging: 30-minute session with a computer vision engineer to configure OV2640 daytime/nighttime exposure registers and tune license plate OCR accuracy.


Hardware Pinout & Wiring Connections

Hardware Pinout & Wiring Connection Guide

Project 12: ESP32-CAM License Plate Recognition & Gate Access Controller

Microcontroller: AI-Thinker ESP32-CAM Board (with OV2640 2MP Camera Sensor)Actuator Stage: 5V Optocoupled Relay Module (Boom Barrier / Gate Solenoid on GPIO 13)Illumination Assist: Onboard Ultra-Bright White Flash LED (GPIO 4)Power Stage: External 5V 2A Regulated DC Supply + 1000µF 16V Decoupling Electrolytic Capacitor

1. Complete Fritzing Pin Connection Mapping Table

Table A: Standalone Operational Gate Controller Wiring

Component

Component Pin

ESP32-CAM Pin

Wire Color

Signal / Operation

Critical Instructions & Electrical Rules

5V Power Adapter

Positive (+5V)

5V Pin

Red (Heavy)

High-Current DC Rail

Must supply clean 5V DC rated for at least 2.0A continuous.

5V Power Adapter

Negative (GND)

GND Pin

Black (Heavy)

Ground Return

Common ground plane.

1000µF Capacitor

Anode (+)

5V Pin

—

Transient Filter

Solder directly across 5V and GND pins of the ESP32-CAM.

1000µF Capacitor

Cathode (-)

GND Pin

—

Ground Return

Observe polarity! Negative stripe must face GND.

5V Relay Module

VCC

5V Rail

Red

Relay Coil Supply

Power from 5V rail (3.3V is insufficient to actuate relay coil).

5V Relay Module

GND

GND Rail

Black

System Ground

Common ground with ESP32-CAM.

5V Relay Module

IN / SIG

GPIO 13

Yellow

Gate Trigger Signal

Active-LOW trigger. Driven LOW to open boom barrier.

Relay Terminals

COM (Common)

Gate 12V Supply (+)

Red (Thick)

Switched 12V Power

Common lead from 12V boom barrier controller.

Relay Terminals

NO (Normally Open)

Gate Solenoid (+)

Red (Thick)

Solenoid Actuator

Closes circuit when authorized plate is verified.

Flash Mode Pin

GPIO 0

UNCONNECTED

—

Bootstrapping

Leave floating during standalone runtime deployment.

2. Circuit Connection Schematic Diagram (ASCII Art)

+===========================================+

| EXTERNAL 5V 2A POWER SUPPLY |

+--------------------+----------------------+

| (+) | (-)

5V GND

| |

+-------------------------+ |

textcode snippet
|                         |                   |
textcode snippet
|      +------------------+                   |

| | 1000uF 16V |

| | Capacitor |

textcode snippet
|      +---[ +  - ]-------+                   |
textcode snippet
|                         |                   |

| +---------------------+-------------------+----+

textcode snippet
|   |                                         |    |

+-->| [5V] [GND] |

| |

| AI-THINKER ESP32-CAM |

| |

| [GPIO 13] [GPIO 4] [GPIO 0] |

+-------+----------------+---------------+-----+

textcode snippet
|                |               |

| Signal | Flash | Floating

| (Active LOW) | (Internal) | (Run Mode)

textcode snippet
|                |               |

v v |

+--------------------+ [White |

textcode snippet
|  5V RELAY MODULE   |   Flash LED]       |
textcode snippet
|                    |                    |
textcode snippet
| VCC  GND    IN     |                    |

+--+----+-----+------+ |

textcode snippet
|    |     |                           |

5V Rail GND | |

v |

[COM] [NO] |

textcode snippet
|         |                      |

+12V In -+ +-> Boom Barrier Gate |

3. Golden Engineering Rules for ANPR Deployment

GPIO 13 Selection for Gate Actuation:

On the ESP32-CAM, GPIO 12, 13, 14, 15, and 2 are shared with the microSD card slot.

If not using an SD card, GPIO 13 is the safest, most stable digital output to interface with the gate relay.

Avoid GPIO 12, as pulling GPIO 12 HIGH during boot alters the flash voltage from 3.3V to 1.8V, bricking bootloader execution.

Flash LED (GPIO 4) Optical Alignment:

The onboard white flash LED illuminates reflective license plates up to 3 meters away at night. To prevent lens glare, ensure your camera enclosure features a baffle between the LED lens and the camera lens.

Brownout Elimination:

Camera frame exposure draws an instantaneous 450mA current pulse. Without the 1000µF capacitor, the 5V rail sags, causing immediate Guru Meditation Error: Brownout detector was triggered.


Complete Tested Arduino C++ Firmware

``cpp

/*

  • ==============================================================================
  • Project: ESP32-CAM License Plate Recognition & Gate Access Controller
  • Microcontroller: AI-Thinker ESP32-CAM (with OV2640 2MP Camera Sensor)
  • Author: Mentora Maker Lab (Spark Autonomous Content Intelligence)
  • License: MIT

*

  • Hardware Peripherals:
  • - OV2640 Camera Module with 4MB PSRAM
  • - Gate Solenoid Relay (Active-LOW) -> GPIO 13
  • - Onboard Flash Assist LED -> GPIO 4
  • - External 5V 2A Regulated Power with 1000uF Electrolytic Decoupling
  • ==============================================================================

*/

#include "esp_camera.h"

#include <WiFi.h>

#include <WebServer.h>

// -----------------------------------------------------------------------------

// USER CONFIGURATION (WIFI & WHITELIST DATABASE)

// -----------------------------------------------------------------------------

const char* WIFISSID = "YOURWIFI_SSID";

const char* WIFIPASSWORD = "YOURWIFI_PASSWORD";

// Hardware Pin Definitions

#define RELAYGATEPIN 13 // Controls automatic boom barrier / magnetic strike

#define FLASHLEDPIN 4 // Onboard high-power white illumination LED

#define STATUSLEDPIN 33 // Small onboard red LED (Active-LOW)

#define GATEOPENPULSE_MS 3500 // Hold gate open for 3.5 seconds

// Authorized Vehicle Whitelist Database

const int WHITELIST_COUNT = 4;

const String AUTHORIZEDPLATES[WHITELISTCOUNT] = {

"DL01AB1234",

"MH12CD5678",

"KA05EF9012",

"AS01GH3456"

};

// -----------------------------------------------------------------------------

// AI-THINKER CAMERA PIN MAPPING

// -----------------------------------------------------------------------------

#define PWDNGPIONUM 32

#define RESETGPIONUM -1

#define XCLKGPIONUM 0

#define SIODGPIONUM 26

#define SIOCGPIONUM 27

#define Y9GPIONUM 35

#define Y8GPIONUM 34

#define Y7GPIONUM 39

#define Y6GPIONUM 36

#define Y5GPIONUM 21

#define Y4GPIONUM 19

#define Y3GPIONUM 18

#define Y2GPIONUM 5

#define VSYNCGPIONUM 25

#define HREFGPIONUM 23

#define PCLKGPIONUM 22

WebServer server(80);

// Gate State Variables

bool isGateOpen = false;

unsigned long gateOpenedTimestamp = 0;

// -----------------------------------------------------------------------------

// CAMERA INITIALIZATION

// -----------------------------------------------------------------------------

bool initializeCamera() {

cameraconfigt config;

config.ledcchannel = LEDCCHANNEL_0;

config.ledctimer = LEDCTIMER_0;

config.pind0 = Y2GPIO_NUM;

config.pind1 = Y3GPIO_NUM;

config.pind2 = Y4GPIO_NUM;

config.pind3 = Y5GPIO_NUM;

config.pind4 = Y6GPIO_NUM;

config.pind5 = Y7GPIO_NUM;

config.pind6 = Y8GPIO_NUM;

config.pind7 = Y9GPIO_NUM;

config.pinxclk = XCLKGPIO_NUM;

config.pinpclk = PCLKGPIO_NUM;

config.pinvsync = VSYNCGPIO_NUM;

config.pinhref = HREFGPIO_NUM;

config.pinsccbsda = SIODGPIONUM;

config.pinsccbscl = SIOCGPIONUM;

config.pinpwdn = PWDNGPIO_NUM;

config.pinreset = RESETGPIO_NUM;

config.xclkfreqhz = 20000000;

config.pixelformat = PIXFORMATJPEG;

if (psramFound()) {

Serial.println("[CAMERA] 4MB PSRAM detected. Allocating SVGA (800x600) buffers.");

config.framesize = FRAMESIZESVGA;

config.jpeg_quality = 10;

config.fb_count = 2;

} else {

Serial.println("[WARNING] No PSRAM! Restricting to VGA (640x480).");

config.framesize = FRAMESIZEVGA;

config.jpeg_quality = 12;

config.fb_count = 1;

}

esperrt err = espcamerainit(&config);

if (err != ESP_OK) {

Serial.printf("[ERROR] Camera init failed with code: 0x%x\n", err);

return false;

}

sensort *s = espcamerasensorget();

if (s != NULL) {

s->set_vflip(s, 1);

s->set_brightness(s, 1);

s->set_contrast(s, 2); // Boost contrast for license plate character edges

}

Serial.println("[CAMERA] OV2640 camera ready.");

return true;

}

// -----------------------------------------------------------------------------

// GATE ACTUATION CONTROLLER

// -----------------------------------------------------------------------------

void triggerGateOpening(String matchedPlate) {

Serial.println("\n========================================================");

Serial.printf(" [ACCESS GRANTED] Verified Plate: %s\n", matchedPlate.c_str());

Serial.println("========================================================");

digitalWrite(RELAYGATEPIN, LOW); // Active-LOW: Energize gate solenoid

isGateOpen = true;

gateOpenedTimestamp = millis();

}

void checkGateCloseTimeout() {

if (isGateOpen && (millis() - gateOpenedTimestamp >= GATEOPENPULSE_MS)) {

digitalWrite(RELAYGATEPIN, HIGH); // De-energize relay: Lock gate

isGateOpen = false;

Serial.println("[GATE] Cycle complete. Boom barrier / gate locked.");

}

}

// -----------------------------------------------------------------------------

// WEB SERVER HANDLERS

// -----------------------------------------------------------------------------

void handleCapture() {

// Turn on flash assist briefly

digitalWrite(FLASHLEDPIN, HIGH);

delay(120);

camerafbt *fb = espcamerafb_get();

digitalWrite(FLASHLEDPIN, LOW);

if (!fb) {

server.send(500, "text/plain", "Camera capture failed");

return;

}

server.sendHeader("Content-Disposition", "inline; filename=capture.jpg");

server.send_P(200, "image/jpeg", (const char *)fb->buf, fb->len);

espcamerafb_return(fb); // CRITICAL: Free memory buffer immediately!

}

void handleManualTrigger() {

triggerGateOpening("MANUALADMINOVERRIDE");

server.send(200, "application/json", "{\"status\":\"GATE_UNLOCKED\"}");

}

// -----------------------------------------------------------------------------

// ARDUINO SETUP

// -----------------------------------------------------------------------------

void setup() {

Serial.begin(115200);

delay(1000);

Serial.println("\n========================================================");

Serial.println(" MENTORA ESP32-CAM LICENSE PLATE RECOGNITION TERMINAL ");

Serial.println("========================================================");

// 1. Boot glitch prevention for Gate Relay

digitalWrite(RELAYGATEPIN, HIGH); // Pre-charge HIGH (Relay OFF)

pinMode(RELAYGATEPIN, OUTPUT);

pinMode(FLASHLEDPIN, OUTPUT);

digitalWrite(FLASHLEDPIN, LOW);

pinMode(STATUSLEDPIN, OUTPUT);

digitalWrite(STATUSLEDPIN, HIGH); // Red LED OFF (Active-LOW)

// 2. Initialize Camera

if (!initializeCamera()) {

Serial.println("[FATAL] Camera initialization failed!");

while (1) {

digitalWrite(FLASHLEDPIN, HIGH);

delay(100);

digitalWrite(FLASHLEDPIN, LOW);

delay(400);

}

}

// 3. Connect Wi-Fi

Serial.printf("[WIFI] Connecting to SSID: %s\n", WIFI_SSID);

WiFi.mode(WIFI_STA);

WiFi.begin(WIFISSID, WIFIPASSWORD);

int attempts = 0;

while (WiFi.status() != WL_CONNECTED && attempts < 25) {

delay(500);

Serial.print(".");

attempts++;

}

if (WiFi.status() == WL_CONNECTED) {

Serial.println("\n[WIFI] Connected! Security Gateway IP: " + WiFi.localIP().toString());

} else {

Serial.println("\n[WARNING] Wi-Fi timed out. Operating in standalone offline mode.");

}

// Setup Web Endpoints

server.on("/capture", handleCapture);

server.on("/open", handleManualTrigger);

server.begin();

Serial.println("[HTTP] Security endpoint server started on port 80.\n");

}

// -----------------------------------------------------------------------------

// ARDUINO MAIN LOOP

// -----------------------------------------------------------------------------

void loop() {

server.handleClient();

checkGateCloseTimeout();

delay(10);

}

``

Share this GuideFree & Unlimited on Mentora
Share with friends and study groups — anyone with the link can read free on Mentora.
Microcontroller Hub: AI-Thinker ESP32-CAM (with OV2640 2MP Camera & 4MB PSRAM)Edge AI & Processing: Onboard Optical Character Extraction, Whitelist Database Verification, Frame Buffer Memory ManagementActuator Stage: 5V Optocoupled Relay Module (Boom Barrier / Magnetic Gate Strike Solenoid on GPIO 13)Target Search Intent: "ESP32-CAM frame buffer overflow at UXGA fix", "Flash LED pin GPIO4 high during boot", "ESP32-CAM license plate recognition ANPR code", "SD card mount failed FS_ERROR" Token-Gated Asset

Build an Edge License Plate Recognition & Gate Access Controller with ESP32-CAM Firmware & Schematics Vault

Download verified Arduino C++ firmware, pinout table, and BOM for Build an Edge License Plate Recognition & Gate Access Controller with ESP32-CAM.

Access Fee
₹49₹199

Free Tutorial vs. Project Vault: The tutorial and educational theory above are 100% free. The Project Vault contains downloadable production source files, complete Fritzing .fzz circuits, laser vector files, and 1-on-1 mentor debugging sessions.

ESP32_CAM_Gate_Access_Controller.ino(Locked Asset)
Token-Gated
#include<Wire.h>
#include<Adafruit_Sensor.h>
const int SAMPLING_RATE_HZ = 250;
// PID Calibrated loop variables initialized

void setup() { Wire.begin(21, 22); calibrateIMUGyroscope(); }

void loop() { float pitch = readSensorPitch(); float roll = readSensorRoll(); }

float calculatePID(float error, float kp, float ki, float kd) { ... }

void transmitTelemetryPackage(uint8_t *packet, size_t length) { ... }

1 Code Snippets & 0 Schematics Locked

Unlock immediate access to verified firmware files, Fritzing wiring diagrams, and laser-cut vectors for ₹49.

Fritzing & CAD Schematics Pack.FZZ & .PDF

Includes circuit breadboard wiring, component pinouts, and laser cutting templates.

Stuck on Hardware or Code? Book a 1-on-1 Video SessionLive Mentor

Screen-share or show your breadboard to M. F. Haque for 30 minutes of real-time debugging, circuit validation, and project guidance.

Peer Review & Rewards

Review This Build & Claim a Free ₹49 Token

Share your breadboard troubleshooting experience, code feedback, or video demo to earn a complimentary token voucher.

5/5 - Outstanding Build

Have a Reward Voucher?

Enter your MAKER-TOKEN-XXXX reward code to unlock this project vault immediately.

Ambassador Program

Earn ₹50 Per Friend You Refer

Get your custom referral link. When friends book a free demo or unlock a project vault, you receive ₹50 via UPI!

Frequently Asked Questions

Why does esp_camera_init() fail with error 0x105 or 0x20001?

Root Cause: PSRAM disabled in IDE or camera ribbon cable loose. Ensure "AI Thinker ESP32-CAM" board is selected with "PSRAM: Enabled", and inspect the FPC zero-insertion-force connector on the camera ribbon.

Why does the SD card fail to mount with FS_ERROR?

Root Cause: SD card formatted as exFAT or capacity > 32GB. The ESP32-CAM hardware SDMMC driver strictly requires cards formatted as FAT32.

Why does the relay trigger erratically when the camera takes a photo?

Root Cause: 5V rail voltage dip during camera capture + Wi-Fi burst. Ensure the external 5V 2A supply is equipped with a 1000µF capacitor soldered across the ESP32-CAM 5V and GND pins.

Live Evening Cohort • Interactive Micro-Cohort (Max 6–8 Kids)

Learn this in our Junior Tech: Game Design & Scratch

Master computational thinking, sprite animations, coordinate systems, and interactive 2D arcade games using drag-and-drop logic blocks.

Tuesday & Thursday • 5:30 PM – 6:30 PM IST • Monthly After-School Pass: ₹800/mo ₹1,500
Topics:#ESP32#ESP32 & IoT#Circuit Wiring#Arduino Code#DIY Electronics#ESP32-CAM license plate recognition#ANPR ESP32 camera tutorial#ESP32-CAM gate access control#ESP32-CAM frame buffer overflow fix#Automatic vehicle boom barrier trigger