Setup
- board is V1.2.1 with the OV5640AF (autofocus)
- pin out of this board
- ubuntu linux
Getting Started
Arduino IDE (quick and dirty)
Install
- Follow the install instructions for Arduino.
- Add boards (File>Preferences>Boards URL) at
https://espressif.github.io/arduino-esp32/package_esp32_index.json
- Selected ESP32 Dev Module
- Plug in USB-C to ESP32 Cam and do a
journalctl -f
to see what happens. - Disable
brltty
which stuffs up USB. - Ensure user is in the
dialout
group (check withgroups
command), and add withusermod
if required. - Should be able to see the board and port in Arduino IDE
Test Camera
- Install OV5640AF library
- Enable PSRAM (Ardino>Tool>PSRAM) in build flags
- Load the “Console Example.ino”
- Change pinout to suit (see pinout about and helpful hints)
- 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.