Introduction

The ESP32-cam is a tiny ESP32-S based board with a OV2640/OV7670 camera module.
Its tiny form factor makes it ideal for random placement. It can be used as a cheap low-resolution low-FPS security cam. More oftenly, it’s used for image recognition or object tracking.

The board usually includes a (very bright) LED for flash. A microSD-/TF-card slot is almost always present.

The ESP32-cam is not a replacement for security cams the likes of Reolink cameras.
The flash LED is pretty bright and doesn’t have a heatsink, so it can get really hot and shouldn’t be turned on for long periods of time. Running high-FPS can also heat up the chip, so it’s better to run low FPS when idle and do short periods of high(er) FPS when actively viewing the stream. The internal memory can be expanded using a microSD-/TF-card to allow for higher resolution recordings.

As much of the ESP32’s resources are dedicated for the camera and memory card, you won’t find much exposed I/O pins on the board.
The board also doesn’t provide a micro-USB port for power and flashing. You’ll need to use an FTDI adapter for flashing and you’ll need to use a breadboard or solder some wires for power.

Requirements (shopping list)

You can get everything you need from AliExpress.
Get it even cheaper using a welcome coupon.

ESP32-CAM Specifications

The ESP32-CAM has a ESP32-S chip, an OV2640 or OV7670 camera module and a tiny but powerful LED for flash. The board also features an external antenna (U.FL/IPEX MHF/MHF1) connector and a reset button.

Picture of ESP32-CAM
ESP32-CAM

The specifications for the ESP32-S are:

  • 802.11b/g/n Wi-Fi
  • Bluetooth 4.2 with BLE
  • UART, SPI, I2C and PWM interfaces
  • Clock speed up to 160 MHz
  • Computing power up to 600 DMIPS
  • 520 KB SRAM plus 4 MB PSRAM
  • Supports WiFi Image Upload
  • Multiple Sleep modes
  • Firmware Over the Air (FOTA) upgrades possible
  • 9 GPIO ports

The specifications for the OV2640 camera module are:

  • 2 Megapixel sensor
  • Array size UXGA 1622×1200
  • Output formats include YUV422, YUV420, RGB565, RGB555 and 8-bit compressed data
  • Image transfer rate of 15 to 60 fps

The ESP32-CAM board does not have a micro-USB connector, so programming the board won’t be plug-and-play. To flash the board, you’ll need an FTDI adapter and some female-female Dupont wires (or a breadboard and some male-male Dupont wires).

Programming our ESP32-CAM

We can start of with a basic ESPHome script, which we’ll flash using the FTDI adapter. Once the board has been flashed, we can use Over-the-Air (OTA) updates to modify our code.

Our basic script is about the same as the one we used for our temperature monitoring project. Note that we need to make sure we use the correct board in our config.

ESPHome - starter config

Open ESPHome and add a new device. It doesn’t really matter what you enter here, as we’ll be replacing the code afterwards.

Edit the device and replace the contents with the following code.

Note: I’m using a secrets.yaml file to store certain variables.

substitutions:
  esphome_name: espcam_sequr_example
  camera_name: Sequr example camera

esphome:
  name: "${esphome_name}"
  platform: ESP32
  board: node32s

wifi:
  ssid: !secret iot_wifi_ssid
  password: !secret iot_wifi_pass
  domain: .iot.local

api:
  reboot_timeout: 60min
  password: !secret esphome_api_pass

ota:
  password: !secret esphome_ota_pass

time:
  - platform: homeassistant
  
logger:

sensor:
  # General
  - platform: uptime
    name: "${esphome_name} - Uptime Sensor"
  - platform: wifi_signal
    name: "${esphome_name} - WiFi Signal"
    update_interval: 60s

Save this code and close the editor.

Press the 3 dots in the top-right of your device in the ESPHome dashboard and click Compile. This will compile our readable code into a binary file we can flash.

Once the compiling has finished, click Download and store the binary file on your device.

Flashing the ESP32

Connecting the FTDI

First we’ll need to connect the FTDI adapter to our ESP32-CAM board.

Picture of an FTDI Adapter
FTDI Adapter

As I said above, we can use some female-female Dupont wires to connect the correct pins, or plug our ESP32-cam board and FTDI in a breadboard and use some male-male Dupont wires.

Connect the following pins:

FTDI ESP32
VCC 3.3V
TX GPIO 3 (U0R)
RX GPIO 1 (U0T)
GND GND
GPIO 0 - GND

Note: the last connection connects two pins on the ESP32-CAM board.
This connection puts the board into flashing mode. Once we’re done with flashing, you can power the board down and remove this connection.

Annotated picture of ESP32-CAM
ESP32-CAM with pins annotated

Important: Make sure you set the jumper on the FTDI to output 3.3V!

Flashing

  1. Connect the FTDI with your computer using a mini-USB cabe and open ESPHome-Flasher
  2. Select the correct Serial Port (e.g. COM5)
  3. Browse to the location where you stored the ESPhome binary
  4. Click Flash ESP

The console should show that it auto-detected the board type, followed by the transfer of the firmware.
After a minute or so, you should see that the flashing has finished.

Some boards may require that you hold the RST button on the board when powering it on to put it in flashing mode.

Booting

Disconnect the FTDI from your computer and the ESP32-CAM.

The boards tend to run most stable when powered with a 5V supply.
The FTDI can in theory provide this, but most USB ports can’t provide enough power, unless you use a powered USB dock.

So grab a 5V supply capable of providing at least 1A and connect the positive wire to the 5V pin and negative to GND to power the board.
For long-term operation, I prefer to use a 2A supply so the power supply never runs warm.

Note: this breadboard kit includes a power module that can stepdown 6.5-12V to 5V (or 3.3V).

The board should connect to your WiFi network and the ESPHome dashboard should show a successful connection (green line).

Home Assistant will also show a Notification stating it discovered a new device.
If you do so, you’ll get access to the entities we added in our config (uptime and WiFi signal sensors) and those we’ll be adding in a minute.
When asked for a password, enter the OTA password.

ESPHome - OTA firmware update

Now that we booted our board and it connected to ESPHome, we can update our code to include the camera, and update our board Over-the-Air (OTA).

Edit your device in the ESPHome dashboard and append the following lines at the end of the config:

# Configuration for Ai-Thinker Camera
# https://esphome.io/components/esp32_camera.html#configuration-for-ai-thinker-camera
esp32_camera:
  name: "${camera_name}"
  external_clock:
    pin: GPIO0
    frequency: 20MHz
  i2c_pins:
    sda: GPIO26
    scl: GPIO27
  data_pins: [GPIO5, GPIO18, GPIO19, GPIO21, GPIO36, GPIO39, GPIO34, GPIO35]
  vsync_pin: GPIO25
  href_pin: GPIO23
  pixel_clock_pin: GPIO22
  power_down_pin: GPIO32
  # Image settings
  max_framerate: 5 fps    # default: 10 fps, max 60
  idle_framerate: 0.2 fps # default: 0.1 fps - framerate for 'picture' in HA dashboard
  resolution: 800x600     # default: 640x480 (VGA) - higher res requires more memory
  jpeg_quality: 10        # 10 (best) to 63 (worst)

switch:
  - platform: gpio
    name: "${camera_name} flash"
    pin: 4
    #inverted: True
  - platform: restart
    name: "${esphome_name} - Restart"
    id: restart_switch

Save the code, validate and Upload.

A console window will open and you’ll see a new binary file being compiled and uploaded to the board. After a minute or 2 the upload should have finished and new entities (camera, flash switch and reboot switch) will have been added to your ESPHome device in Home Assistant.

Installing the hardware

You can install the ESP32-CAM in a project box using some careful drilling, soldering and taping.
Use a 5V DC power supply and a DC power plug to provide power.
Grab your soldering station, some solder and heat shrink tubing to properly connect everything together.

Picture of ESP32-cam in waterproof box with antenna
ESP32-cam mounted

Direction

Do not be tempted to install the ESP32-cam board vertically (i.e. with the text in a readable way). If mounted like this, the captured footage will be 90° rotated.
Sadly enough, ESPHome doesn’t provide a method to rotate the video footage by 90°, only horizontal and vertical flip are supported.

To get the correct video orientation, mount the board with the flash LED at the top-right corner.
The text will be at the right side, the microSD card slot at the left.

If you mount the ESP32-cam upside down with the flash LED at the bottom-left, you can use vertical_flip and horizontal_mirror to correct the image.

External antenna

If you also bought the external WiFi antenna, you’ll need to do one extra step before you can use it.

Near the antenna connector, there’s a tiny SMD component (a resistor?) and 3 solder pads.
You’ll need to resolder the component and rotate it 90°. In other words: if currently pads A and B are linked, you need to link pads B and C.

Location of the antenna connector
Antenna connector and solder pads

Here’s how resoldering the component looks like:

Object Detection

Now that we have the camera, we can use it for various things. One example is Object Detection using DOODS.

Everything Smart Home has a good video on this topic.

Changelog

  • 2021-04-19
    • Added picture of mounted installation
  • 2021-04-06
    • Added remark about camera rotation
    • Added external antenna installation information