ESP32 Cam OV5640 Board

Setup

Getting Started

Arduino IDE (quick and dirty)

Install

  1. Follow the install instructions for Arduino.
  2. Add boards (File>Preferences>Boards URL) at https://espressif.github.io/arduino-esp32/package_esp32_index.json
  3. Selected ESP32 Dev Module
  4. Plug in USB-C to ESP32 Cam and do a journalctl -f to see what happens.
  5. Disable brltty which stuffs up USB.
  6. Ensure user is in the dialout group (check with groups command), and add with usermod if required.
  7. Should be able to see the board and port in Arduino IDE

Test Camera

  1. Install OV5640AF library
  2. Enable PSRAM (Ardino>Tool>PSRAM) in build flags
  3. Load the “Console Example.ino”
  4. Change pinout to suit (see pinout about and helpful hints)
  5. Compile, upload and run the code below to test basic operation:
# From OV5640AF library 

#include "esp_camera.h"
#include "ESP32_OV5640_AF.h"

# Custom PINOUT for ESP32 OV5640 Board
// ??
#defube  LED_GPIO_NUM 25
#define PWDN_GPIO_NUM 32
// maybe 5?
#define RESET_GPIO_NUM -1 
#define XCLK_GPIO_NUM 15 
#define SIOD_GPIO_NUM 22 
#define SIOC_GPIO_NUM 23 
#define Y9_GPIO_NUM 39 
#define Y8_GPIO_NUM 34 
#define Y7_GPIO_NUM 33 
#define Y6_GPIO_NUM 27 
#define Y5_GPIO_NUM 12 
#define Y4_GPIO_NUM 35 
#define Y3_GPIO_NUM 14 
#define Y2_GPIO_NUM 2 
#define VSYNC_GPIO_NUM 18 
#define HREF_GPIO_NUM 36 
#define PCLK_GPIO_NUM 26

OV5640 ov5640 = OV5640();

void setup() {
  Serial.begin(115200);

  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.xclk_freq_hz = 12000000;
  config.pixel_format = PIXFORMAT_JPEG;
  config.frame_size = FRAMESIZE_VGA;
  config.jpeg_quality = 10;
  config.fb_count = 2;

  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    return;
  } else {
    Serial.printf("Camera init OK");

  }

  sensor_t* sensor = esp_camera_sensor_get();
  ov5640.start(sensor);

  if (ov5640.focusInit() == 0) {
    Serial.println("OV5640_Focus_Init Successful!");
  }

  if (ov5640.autoFocusMode() == 0) {
    Serial.println("OV5640_Auto_Focus Successful!");
  }
  Serial.println("Exit setup");
  sleep(5);
}

void loop() {
Serial.println("enter loop");
  sleep(5);
  uint8_t rc = ov5640.getFWStatus();
  Serial.printf("FW_STATUS = 0x%x\n", rc);

  if (rc == -1) {
    Serial.println("Check your OV5640");
  } else if (rc == FW_STATUS_S_FOCUSED) {
    Serial.println("Focused!");
  } else if (rc == FW_STATUS_S_FOCUSING) {
    Serial.println("Focusing!");
  } else {
  }

  camera_fb_t* fb = esp_camera_fb_get();

  if (!fb) {
    Serial.println("Camera capture failed");
    esp_camera_fb_return(fb);
    return;
  }

  if (fb->format != PIXFORMAT_JPEG) {
    Serial.println("Non-JPEG data not implemented");
    esp_camera_fb_return(fb);
    return;
  }

  // Draw Image on the display or Send Image to the connected device!
  // With (fb->buf, fb->len);
  esp_camera_fb_return(fb);
}

ESP IDF with VSCode (recommended)

Then install ESP IDF toolchain and VSCode addin as per instructions. A summary below:

Prerequisites

sudo apt-get install git wget flex bison gperf python3 python3-pip python3-venv cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0

VSCode

  • Install ESP-IDF extension
  • Click express setup and use latest release version (v5.4). It will download toolchain.
  • I just used global python3 and defaults

USB Permissions

Disable brltty which stuffs up USB.

ESP-IDF extension asks for ‘OpenOCD’ permissions:

sudo cp /home/bbeeson/.espressif/tools/openocd-esp32/v0.12.0-esp32-20241016/openocd-esp32/share/openocd/contrib/60-openocd.rules /etc/udev/rules.d

Finish Install

cd ~/esp/v5.4/esp-idf
./install.sh
. ./export.sh # source this. maybe add to .bashrc?

Hello World

  • Plug in ESP32Cam to USB C and “Select Port” for /dev/ttyUSBXXXX
  • In the extension, load ‘hello world’ and command “build, flash and monitor”
  • My output is below

This is esp32 chip with 2 CPU core(s), WiFi/BTBLE, silicon revision v1.1, 2MB external flash

Try the Camera

Start here: https://github.com/espressif/esp-iot-solution/tree/master/examples/camera/basic

Use “New Project Wizard” in VSCode IDF Extension

Add the esp32 component (see “Finish Install” to get idf.py working)

idf.py add-dependency "espressif/esp32-camera"
idf.py menuconfig 

In menuconfig, there is now a “Camera Config” selection. Leave as defaults for now.

In menuconfig, enable PSRAM. Docs say “see to 80MHZ” but I don’t see how to do this.

Test the camera:

#include "esp_camera.h"

#include "ov5640.h"

#include <esp_log.h>
#include <esp_system.h>
//#include <nvs_flash.h>
#include <sys/param.h>
#include <string.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

// support IDF 5.x
#ifndef portTICK_RATE_MS
#define portTICK_RATE_MS portTICK_PERIOD_MS
#endif

static const char *TAG = "example:take_picture";

static camera_config_t camera_config = {
    .pin_pwdn = CAM_PIN_PWDN,
    .pin_reset = CAM_PIN_RESET,
    .pin_xclk = CAM_PIN_XCLK,
    .pin_sccb_sda = CAM_PIN_SIOD,
    .pin_sccb_scl = CAM_PIN_SIOC,

    .pin_d7 = CAM_PIN_D7,
    .pin_d6 = CAM_PIN_D6,
    .pin_d5 = CAM_PIN_D5,
    .pin_d4 = CAM_PIN_D4,
    .pin_d3 = CAM_PIN_D3,
    .pin_d2 = CAM_PIN_D2,
    .pin_d1 = CAM_PIN_D1,
    .pin_d0 = CAM_PIN_D0,
    .pin_vsync = CAM_PIN_VSYNC,
    .pin_href = CAM_PIN_HREF,
    .pin_pclk = CAM_PIN_PCLK,

    //XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental)
    .xclk_freq_hz = 20000000,
    .ledc_timer = LEDC_TIMER_0,
    .ledc_channel = LEDC_CHANNEL_0,

    .pixel_format = PIXFORMAT_RGB565, //YUV422,GRAYSCALE,RGB565,JPEG
    .frame_size = FRAMESIZE_QVGA,    //QQVGA-UXGA, For ESP32, do not use sizes above QVGA when not JPEG. The performance of the ESP32-S series has improved a lot, but JPEG mode always gives better frame rates.

    .jpeg_quality = 12, //0-63, for OV series camera sensors, lower number means higher quality
    .fb_count = 1,       //When jpeg mode is used, if fb_count more than one, the driver will work in continuous mode.
    .fb_location = CAMERA_FB_IN_PSRAM,
    .grab_mode = CAMERA_GRAB_WHEN_EMPTY,
};

static esp_err_t init_camera(void)
{
    //initialize the camera
    esp_err_t err = esp_camera_init(&camera_config);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "Camera Init Failed");
        return err;
    }

    return ESP_OK;
}

void app_main(void)
{
    if(ESP_OK != init_camera()) {
        return;
    }

    while (1)
    {
        ESP_LOGI(TAG, "Taking picture...");
        camera_fb_t *pic = esp_camera_fb_get();

        // use pic->buf to access the image
        ESP_LOGI(TAG, "Picture taken! Its size was: %zu bytes", pic->len);
        esp_camera_fb_return(pic);

        vTaskDelay(5000 / portTICK_RATE_MS);
    }
    
}

Seems to work, but we need to see the image!

Try the SD Card

Starting at https://github.com/espressif/esp-idf/tree/ad60568151ae3226375ddb05f33c067213048404/examples/storage/sd_card

Failed to get this working. See Stack Overflow question.

Leave a Reply

Your email address will not be published. Required fields are marked *