feat(camera): supported camera related example using sc2336 and ek79007

Closes https://github.com/espressif/esp-idf/issues/14517
This commit is contained in:
Armando
2024-09-13 16:51:21 +08:00
parent 01613ca01d
commit c48a47c341
24 changed files with 357 additions and 213 deletions

View File

@@ -6,21 +6,28 @@
## Overview
This example demonstrates how to use the ISP (image signal processor) to work with esp_driver_cam component. This example will capture camera sensor signals via CSI interface and display it via DSI interface. This example also enables the ISP AF (auto-focus) feature and ISP BF (bayer denoise) feature.
This example demonstrates how to use the ISP (image signal processor) to work with esp_driver_cam component. This example will auto-detect camera sensors via [ESP camera sensor driver](https://components.espressif.com/components/espressif/esp_cam_sensor/versions/0.5.3) and capture camera sensor signals via CSI interface and display it via DSI interface. This example also enables the ISP AF (auto-focus) feature and ISP BF (bayer denoise) feature.
## Usage
The subsections below give only absolutely necessary information. For full steps to configure ESP-IDF and use it to build and run projects, see [ESP-IDF Getting Started](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html#get-started).
### Hardware Required
This example requires:
- OV5647 camera sensor with VCM (Voice Coil Motor). The VCM used in this example is DW9714.
- ILI9881C LCD screen
- OV5647 or SC2336 camera sensor, or other camera sensors
- EK79007 or ILI9881C LCD screen
- ESP32P4 devkit
**Note:** OV5647 has its own ISP functions, whereas SC2336 is a camera sensor without ISP functions. You can use the ESP on-chip ISP functions to tune the image together with the sensor ISP functions, if the image quality is not as expected.
**Note:** For EK79007 you will need to connect following pins:
- 5V - 5V
- GND - GND
- RST_LCD - 3V3
You can also connect camera sensors and LCD screens from other vendors to the ESP chip, you can find corresponding camera or LCD drivers from [ESP Component Registry](https://components.espressif.com), or design your own customized drivers.
GND GND
┌────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────┐
@@ -40,7 +47,7 @@ This example requires:
│ ├──────────────────────┤ │ DSI DATA 1N │ │
│ │ │ ├───────────────────────────┤ │
│ │ CSI DATA 1N │ ESP32-P4 │ │ │
OV5647 ├──────────────────────┤ │ DSI CLK N │ ILI9881C
Camera ├──────────────────────┤ │ DSI CLK N │ LCD Screen
│ │ │ ├───────────────────────────┤ │
│ │ CSI CLK N │ │ │ │
│ ├──────────────────────┤ │ DSI CLK P │ │
@@ -97,6 +104,7 @@ idf.py menuconfig
```
Set CONFIG_CAMERA_OV5647 to y
Set CONFIG_CAMERA_SC2336 to y
```

View File

@@ -1,4 +1,4 @@
idf_component_register(SRCS "isp_af_dsi_main.c"
INCLUDE_DIRS "."
REQUIRES esp_mm esp_driver_isp esp_driver_cam esp_driver_i2c esp_lcd dsi_init
REQUIRES esp_mm esp_driver_isp esp_driver_cam esp_driver_i2c esp_lcd dsi_init sensor_init
)

View File

@@ -14,20 +14,25 @@ menu "Example Configuration"
choice EXAMPLE_MIPI_CSI_DISP_HRES
bool "Set MIPI CSI horizontal resolution"
default EXAMPLE_MIPI_CSI_HRES_800
default EXAMPLE_MIPI_CSI_HRES_1024
config EXAMPLE_MIPI_CSI_HRES_800
bool "800"
config EXAMPLE_MIPI_CSI_HRES_1024
bool "1024"
endchoice
config EXAMPLE_MIPI_CSI_DISP_HRES
int
default 800 if EXAMPLE_MIPI_CSI_HRES_800
default 1024 if EXAMPLE_MIPI_CSI_HRES_1024
choice EXAMPLE_MIPI_CSI_DISP_VRES
bool "Set MIPI CSI vertical resolution"
default EXAMPLE_MIPI_CSI_VRES_640
default EXAMPLE_MIPI_CSI_VRES_600
config EXAMPLE_MIPI_CSI_VRES_600
bool "600"
config EXAMPLE_MIPI_CSI_VRES_640
bool "640"
config EXAMPLE_MIPI_CSI_VRES_1280
@@ -36,6 +41,7 @@ menu "Example Configuration"
config EXAMPLE_MIPI_CSI_DISP_VRES
int
default 600 if EXAMPLE_MIPI_CSI_VRES_600
default 640 if EXAMPLE_MIPI_CSI_VRES_640
default 1280 if EXAMPLE_MIPI_CSI_VRES_1280
endmenu

View File

@@ -12,12 +12,8 @@ extern "C" {
#define EXAMPLE_RGB565_BITS_PER_PIXEL 16
#define EXAMPLE_MIPI_SCCB_FREQ (100000)
#define EXAMPLE_MIPI_SCCB_SCL_IO (8)
#define EXAMPLE_MIPI_SCCB_SDA_IO (7)
#define EXAMPLE_MIPI_IDI_CLOCK_RATE (50000000)
#define EXAMPLE_MIPI_CSI_LANE_BITRATE_MBPS 200 //line_rate = pclk * 4
#define EXAMPLE_OV5647_DEV_ADDR 0x36
#define EXAMPLE_DW9714_DEV_ADDR 0xC
#ifdef __cplusplus
}

View File

@@ -1,9 +1,10 @@
dependencies:
espressif/esp_cam_sensor: "^0.5.*"
espressif/esp_lcd_ili9881c: "~0.2.0"
idf:
version: ">=5.3.0"
isp_af_schemes:
path: ${IDF_PATH}/examples/peripherals/isp/auto_focus/components/isp_af_schemes
dsi_init:
path: ${IDF_PATH}/examples/peripherals/camera/camera_dsi/components/dsi_init
sensor_init:
path: ${IDF_PATH}/examples/peripherals/camera/camera_dsi/components/sensor_init

View File

@@ -6,26 +6,26 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "esp_log.h"
#include "esp_heap_caps.h"
#include "esp_lcd_mipi_dsi.h"
#include "esp_lcd_panel_ops.h"
#include "esp_lcd_ili9881c.h"
#include "esp_ldo_regulator.h"
#include "esp_cache.h"
#include "driver/i2c_master.h"
#include "driver/isp.h"
#include "driver/isp_bf.h"
#include "isp_af_scheme_sa.h"
#include "esp_cam_ctlr_csi.h"
#include "esp_cam_ctlr.h"
#include "esp_sccb_intf.h"
#include "esp_sccb_i2c.h"
#include "esp_cam_sensor.h"
#include "ov5647.h"
#include "example_dsi_init.h"
#include "example_dsi_init_config.h"
#include "example_sensor_init.h"
#include "example_config.h"
static const char *TAG = "isp_dsi";
@@ -33,6 +33,9 @@ static const char *TAG = "isp_dsi";
static bool s_camera_get_new_vb(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data);
static bool s_camera_get_finished_trans(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data);
/*---------------------------------------------------------------
AF
---------------------------------------------------------------*/
typedef union {
struct {
uint16_t s : 4;
@@ -47,7 +50,7 @@ typedef union {
uint16_t val;
} dw9714_reg_t;
static bool IRAM_ATTR s_env_change_cb(isp_af_ctlr_t af_ctrlr, const esp_isp_af_env_detector_evt_data_t *edata, void *user_data)
static bool IRAM_ATTR s_af_env_change_cb(isp_af_ctlr_t af_ctrlr, const esp_isp_af_env_detector_evt_data_t *edata, void *user_data)
{
BaseType_t mustYield = pdFALSE;
TaskHandle_t task_handle = (TaskHandle_t)user_data;
@@ -141,7 +144,7 @@ static void af_task(void *arg)
ESP_ERROR_CHECK(esp_isp_af_controller_set_env_detector(af_ctrlr, &env_config));
esp_isp_af_env_detector_evt_cbs_t cbs = {
.on_env_change = s_env_change_cb,
.on_env_change = s_af_env_change_cb,
};
ESP_ERROR_CHECK(esp_isp_af_env_detector_register_event_callbacks(af_ctrlr, &cbs, task_handle));
@@ -176,7 +179,8 @@ static void af_task(void *arg)
void app_main(void)
{
esp_err_t ret = ESP_FAIL;
esp_lcd_panel_handle_t ili9881c_ctrl_panel = NULL;
esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL;
esp_lcd_panel_io_handle_t mipi_dbi_io = NULL;
esp_lcd_panel_handle_t mipi_dpi_panel = NULL;
void *frame_buffer = NULL;
size_t frame_buffer_size = 0;
@@ -195,7 +199,7 @@ void app_main(void)
* ISP convert to RGB565
*/
//---------------DSI Init------------------//
example_dsi_resource_alloc(&ili9881c_ctrl_panel, &mipi_dpi_panel, &frame_buffer);
example_dsi_resource_alloc(&mipi_dsi_bus, &mipi_dbi_io, &mipi_dpi_panel, &frame_buffer);
//---------------Necessary variable config------------------//
frame_buffer_size = CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES * CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES * EXAMPLE_RGB565_BITS_PER_PIXEL / 8;
@@ -209,29 +213,18 @@ void app_main(void)
.buflen = frame_buffer_size,
};
//---------------I2C Init------------------//
i2c_master_bus_config_t i2c_bus_conf = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.sda_io_num = EXAMPLE_MIPI_SCCB_SDA_IO,
.scl_io_num = EXAMPLE_MIPI_SCCB_SCL_IO,
.i2c_port = I2C_NUM_0,
.flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t bus_handle = NULL;
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_conf, &bus_handle));
//--------Camera Sensor and SCCB Init-----------//
i2c_master_bus_handle_t i2c_bus_handle = NULL;
example_sensor_init(I2C_NUM_0, &i2c_bus_handle);
//---------------SCCB Init------------------//
esp_sccb_io_handle_t ov5647_io_handle = NULL;
//---------------VCM SCCB Init------------------//
esp_sccb_io_handle_t dw9714_io_handle = NULL;
sccb_i2c_config_t i2c_config = {
.scl_speed_hz = EXAMPLE_MIPI_SCCB_FREQ,
.device_address = EXAMPLE_OV5647_DEV_ADDR,
.device_address = EXAMPLE_DW9714_DEV_ADDR,
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
};
ESP_ERROR_CHECK(sccb_new_i2c_io(bus_handle, &i2c_config, &ov5647_io_handle));
esp_sccb_io_handle_t dw9714_io_handle = NULL;
i2c_config.device_address = EXAMPLE_DW9714_DEV_ADDR;
ESP_ERROR_CHECK(sccb_new_i2c_io(bus_handle, &i2c_config, &dw9714_io_handle));
ESP_ERROR_CHECK(sccb_new_i2c_io(i2c_bus_handle, &i2c_config, &dw9714_io_handle));
//---------------CSI Init------------------//
esp_cam_ctlr_csi_config_t csi_config = {
@@ -302,8 +295,8 @@ void app_main(void)
};
xTaskCreatePinnedToCore(af_task, "af_task", 8192, &af_task_param, 5, NULL, 0);
//---------------DSI Panel Init------------------//
example_dsi_ili9881c_panel_init(ili9881c_ctrl_panel);
//---------------DPI Reset------------------//
example_dpi_panel_reset(mipi_dpi_panel);
//init to all white
memset(frame_buffer, 0xFF, frame_buffer_size);
@@ -314,55 +307,6 @@ void app_main(void)
return;
}
esp_cam_sensor_config_t cam_config = {
.sccb_handle = ov5647_io_handle,
.reset_pin = -1,
.pwdn_pin = -1,
.xclk_pin = -1,
.sensor_port = ESP_CAM_SENSOR_MIPI_CSI,
};
esp_cam_sensor_device_t *cam = ov5647_detect(&cam_config);
if (!cam) {
ESP_LOGE(TAG, "failed to detect 5647");
return;
}
esp_cam_sensor_format_array_t cam_fmt_array = {0};
esp_cam_sensor_query_format(cam, &cam_fmt_array);
const esp_cam_sensor_format_t *parray = cam_fmt_array.format_array;
for (int i = 0; i < cam_fmt_array.count; i++) {
ESP_LOGI(TAG, "fmt[%d].name:%s", i, parray[i].name);
}
esp_cam_sensor_format_t *cam_cur_fmt = NULL;
for (int i = 0; i < cam_fmt_array.count; i++) {
#if CONFIG_EXAMPLE_MIPI_CSI_VRES_640
if (!strcmp(parray[i].name, "MIPI_2lane_24Minput_RAW8_800x640_50fps")) {
cam_cur_fmt = (esp_cam_sensor_format_t *) & (parray[i].name);
break;
}
#else
if (!strcmp(parray[i].name, "MIPI_2lane_24Minput_RAW8_800x1280_50fps")) {
cam_cur_fmt = (esp_cam_sensor_format_t *) & (parray[i].name);
break;
}
#endif
}
ret = esp_cam_sensor_set_format(cam, (const esp_cam_sensor_format_t *) cam_cur_fmt);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Format set fail");
} else {
ESP_LOGI(TAG, "Format in use:%s", cam_cur_fmt->name);
}
int enable_flag = 1;
// Set sensor output stream
ret = esp_cam_sensor_ioctl(cam, ESP_CAM_SENSOR_IOC_S_STREAM, &enable_flag);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Start stream fail");
}
example_dpi_panel_init(mipi_dpi_panel);
while (1) {

View File

@@ -1,4 +1,5 @@
CONFIG_SPIRAM=y
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
CONFIG_SPIRAM_SPEED_200M=y
CONFIG_CAMERA_SC2336=y
CONFIG_CAMERA_OV5647=y