From cf0b395fd9e37eb53d7e4b61218f55661d965a55 Mon Sep 17 00:00:00 2001 From: lorow Date: Thu, 23 Mar 2023 00:33:27 +0100 Subject: [PATCH 1/6] Initial implementation of API/user config controlled auto exposure and gain settings --- ESP/ini/dev_config.ini | 10 ++++-- ESP/ini/user_config.ini | 11 +++++++ ESP/lib/src/data/config/project_config.cpp | 35 ++++++++++++++++++--- ESP/lib/src/data/config/project_config.hpp | 10 ++++++ ESP/lib/src/io/camera/cameraHandler.cpp | 20 ++++-------- ESP/lib/src/network/api/baseAPI/baseAPI.cpp | 23 +++++++++++++- 6 files changed, 88 insertions(+), 21 deletions(-) diff --git a/ESP/ini/dev_config.ini b/ESP/ini/dev_config.ini index ad99ae0b..f33a07ae 100644 --- a/ESP/ini/dev_config.ini +++ b/ESP/ini/dev_config.ini @@ -30,8 +30,14 @@ build_flags = -DADHOC_CHANNEL=${wifi.adhocchannel} -DWIFI_CHANNEL=${wifi.channel} -DDEBUG_ESP_PORT=Serial - '-DVERSION=""' ; set the debug port - '-DMDNS_HOSTNAME=${wifi.mdnsname}' ; Set the OTA password + '-DVERSION=""' + '-DMDNS_HOSTNAME=${wifi.mdnsname}' + -DSIMPLE_AUTO_EXPOSURE_ON=${autoexposure.simple_auto_exposure_on} + -DFANCY_AUTO_EXPOSURE_ON=${autoexposure.fancy_auto_exposure_on} + -DAE_LEVEL=${autoexposure.ae_level} + -DAEC_VALUE=${autoexposure.aec_value} + -DAUTO_GAIN_ON=${autoexposure.auto_gain_on} + -DBRIGHTNESS=${autoexposure.brightness} '-DWIFI_SSID=${wifi.ssid}' '-DWIFI_PASSWORD=${wifi.password}' '-DWIFI_AP_SSID=${wifi.ap_ssid}' diff --git a/ESP/ini/user_config.ini b/ESP/ini/user_config.ini index 6302c5f4..397e2251 100644 --- a/ESP/ini/user_config.ini +++ b/ESP/ini/user_config.ini @@ -17,3 +17,14 @@ otaserverip = "openiristracker.local" otalogin = "openiris" otapassword = "12345678" otaserverport = 3232 + +[autoexposure] +simple_auto_exposure_on = 0 ; should the auto exposure be enabled, 0 - off, 1 - on +fancy_auto_exposure_on = 0 ; should the more advanced auto exposure be enabled, 0 - on, 1 - off + +ae_level = 0 ; auto exposure level, -2 to 2, 0 is the default +aec_value = 300 ; auto exposure control, a sort of brightness, 0 - 1200 + +auto_gain_on = 0 ; should the auto gain be enabled, 0 - off, 1 - on + +brightness = 2 ; controls the brightness, -2 to 2, to is the default \ No newline at end of file diff --git a/ESP/lib/src/data/config/project_config.cpp b/ESP/lib/src/data/config/project_config.cpp index 0ad5bd52..8944b96f 100644 --- a/ESP/lib/src/data/config/project_config.cpp +++ b/ESP/lib/src/data/config/project_config.cpp @@ -55,7 +55,12 @@ void ProjectConfig::initConfig() { .href = 0, .framesize = 4, .quality = 7, - .brightness = 2, + .brightness = BRIGHTNESS, + .simple_auto_exposure_on = SIMPLE_AUTO_EXPOSURE_ON, + .fancy_auto_exposure_on = FANCY_AUTO_EXPOSURE_ON, + .ae_level = AE_LEVEL, + .aec_value = AEC_VALUE, + .auto_gain_on = AUTO_GAIN_ON, }; } @@ -132,6 +137,12 @@ void ProjectConfig::cameraConfigSave() { putInt("framesize", this->config.camera.framesize); putInt("quality", this->config.camera.quality); putInt("brightness", this->config.camera.brightness); + putInt("brightness", this->config.camera.brightness); + putInt("simple_auto_exposure_on", this->config.camera.fancy_auto_exposure_on); + putInt("fancy_auto_exposure_on", this->config.camera.fancy_auto_exposure_on); + putInt("ae_level", this->config.camera.ae_level); + putInt("aec_value", this->config.camera.aec_value); + putInt("auto_gain_on ", this->config.camera.auto_gain_on); } bool ProjectConfig::reset() { @@ -198,7 +209,12 @@ void ProjectConfig::load() { this->config.camera.href = getInt("href", 0); this->config.camera.framesize = getInt("framesize", 4); this->config.camera.quality = getInt("quality", 7); - this->config.camera.brightness = getInt("brightness", 2); + this->config.camera.brightness = getInt("brightness", BRIGHTNESS); + this->config.camera.fancy_auto_exposure_on = getInt("simple_auto_exposure_on", SIMPLE_AUTO_EXPOSURE_ON); + this->config.camera.fancy_auto_exposure_on = getInt("fancy_auto_exposure_on", FANCY_AUTO_EXPOSURE_ON); + this->config.camera.ae_level = getInt("ae_level", AE_LEVEL); + this->config.camera.aec_value = getInt("aec_value", AEC_VALUE); + this->config.camera.auto_gain_on = getInt("auto_gain_on ", AUTO_GAIN_ON); this->_already_loaded = true; this->notifyAll(ConfigState_e::configLoaded); @@ -238,6 +254,11 @@ void ProjectConfig::setCameraConfig(uint8_t vflip, uint8_t href, uint8_t quality, uint8_t brightness, + bool simple_auto_exposure_on, + bool fancy_auto_exposure_on, + int ae_level, + unsigned int aec_value, + bool auto_gain_on, bool shouldNotify) { log_d("Updating camera config"); this->config.camera.vflip = vflip; @@ -245,6 +266,11 @@ void ProjectConfig::setCameraConfig(uint8_t vflip, this->config.camera.framesize = framesize; this->config.camera.quality = quality; this->config.camera.brightness = brightness; + this->config.camera.simple_auto_exposure_on = simple_auto_exposure_on; + this->config.camera.fancy_auto_exposure_on = fancy_auto_exposure_on; + this->config.camera.ae_level = ae_level; + this->config.camera.aec_value = aec_value; + this->config.camera.auto_gain_on = auto_gain_on; log_d("Updating Camera config"); if (shouldNotify) @@ -384,9 +410,10 @@ std::string ProjectConfig::MDNSConfig_t::toRepresentation() { std::string ProjectConfig::CameraConfig_t::toRepresentation() { std::string json = Helpers::format_string( "\"camera_config\": {\"vflip\": %d,\"framesize\": %d,\"href\": " - "%d,\"quality\": %d,\"brightness\": %d}", + "%d,\"quality\": %d,\"brightness\": %d, \"simple_auto_exposure_on\": %d, \"fancy_auto_exposure_on\": %d,\"ae_level\": %d, \"aec_value\": %d, \"auto_gain_on\": %d }", this->vflip, this->framesize, this->href, this->quality, - this->brightness); + this->brightness, this->simple_auto_exposure_on, this->fancy_auto_exposure_on, + this->aec_value, this->ae_level, this->auto_gain_on); return json; } diff --git a/ESP/lib/src/data/config/project_config.hpp b/ESP/lib/src/data/config/project_config.hpp index a2a5c99a..7ab97a93 100644 --- a/ESP/lib/src/data/config/project_config.hpp +++ b/ESP/lib/src/data/config/project_config.hpp @@ -47,6 +47,11 @@ class ProjectConfig : public Preferences, public ISubject { uint8_t framesize; uint8_t quality; uint8_t brightness; + bool simple_auto_exposure_on; + bool fancy_auto_exposure_on; + int ae_level; + int aec_value; + bool auto_gain_on; std::string toRepresentation(); }; @@ -116,6 +121,11 @@ class ProjectConfig : public Preferences, public ISubject { uint8_t href, uint8_t quality, uint8_t brightness, + bool simple_auto_exposure_on, + bool fancy_auto_exposure_on, + int ae_level, + unsigned int aec_value, + bool auto_gain_on, bool shouldNotify); void setWifiConfig(const std::string& networkName, const std::string& ssid, diff --git a/ESP/lib/src/io/camera/cameraHandler.cpp b/ESP/lib/src/io/camera/cameraHandler.cpp index eb1b78a1..0b0eb727 100644 --- a/ESP/lib/src/io/camera/cameraHandler.cpp +++ b/ESP/lib/src/io/camera/cameraHandler.cpp @@ -89,7 +89,7 @@ void CameraHandler::setupCameraSensor() { 0x00); // banksel, here we're directly writing to the registers. // 0xFF==0x00 is the first bank, there's also 0xFF==0x01 camera_sensor->set_reg(camera_sensor, 0xd3, 0xff, 5); // clock - camera_sensor->set_brightness(camera_sensor, 2); // -2 to 2 + camera_sensor->set_brightness(camera_sensor, cameraConfig->brightness); // -2 to 2 camera_sensor->set_contrast(camera_sensor, 2); // -2 to 2 camera_sensor->set_saturation(camera_sensor, -2); // -2 to 2 @@ -101,14 +101,13 @@ void CameraHandler::setupCameraSensor() { // Sunny, 2 - Cloudy, 3 - Office, 4 - Home) // controls the exposure - camera_sensor->set_exposure_ctrl(camera_sensor, - 0); // 0 = disable , 1 = enable - camera_sensor->set_aec2(camera_sensor, 0); // 0 = disable , 1 = enable - camera_sensor->set_ae_level(camera_sensor, 0); // -2 to 2 - camera_sensor->set_aec_value(camera_sensor, 300); // 0 to 1200 + camera_sensor->set_exposure_ctrl(camera_sensor, cameraConfig->simple_auto_exposure_on); // 0 = disable , 1 = enable + camera_sensor->set_aec2(camera_sensor, cameraConfig->fancy_auto_exposure_on); // 0 = disable , 1 = enable + camera_sensor->set_ae_level(camera_sensor, cameraConfig->ae_level); // -2 to 2 + camera_sensor->set_aec_value(camera_sensor, cameraConfig->aec_value); // 0 to 1200 // controls the gain - camera_sensor->set_gain_ctrl(camera_sensor, 0); // 0 = disable , 1 = enable + camera_sensor->set_gain_ctrl(camera_sensor, cameraConfig->auto_gain_on); // 0 = disable , 1 = enable // automatic gain control gain, controls by how much the resulting image // should be amplified @@ -186,13 +185,6 @@ int CameraHandler::setHFlip(int direction) { return camera_sensor->set_hmirror(camera_sensor, direction); } -int CameraHandler::setVieWindow(int offsetX, - int offsetY, - int outputX, - int outputY) { - return 0; -} - //! either hardware(1) or software(0) void CameraHandler::resetCamera(bool type) { if (type) { diff --git a/ESP/lib/src/network/api/baseAPI/baseAPI.cpp b/ESP/lib/src/network/api/baseAPI/baseAPI.cpp index a55ea2df..84d9c4d9 100644 --- a/ESP/lib/src/network/api/baseAPI/baseAPI.cpp +++ b/ESP/lib/src/network/api/baseAPI/baseAPI.cpp @@ -286,8 +286,17 @@ void BaseAPI::setCamera(AsyncWebServerRequest* request) { uint8_t temp_camera_hflip = 0; uint8_t temp_camera_quality = 0; uint8_t temp_camera_brightness = 0; + uint8_t temp_simple_auto_exposure_on = SIMPLE_AUTO_EXPOSURE_ON; + uint8_t temp_fancy_auto_exposure_on = FANCY_AUTO_EXPOSURE_ON; + int temp_ae_level = AE_LEVEL; + unsigned int temp_aec_value = AEC_VALUE; + uint8_t temp_auto_gain_on = AUTO_GAIN_ON; + int params = request->params(); + // TODO we probably should refactor this at some point, maybe some serialization of sorts, or direct mapping of + // TODO get parameters? Can we even do that? + //! Using the else if statements to ensure that the values do not need to //! be set in a specific order This means the order of the URL params does //! not matter @@ -303,13 +312,25 @@ void BaseAPI::setCamera(AsyncWebServerRequest* request) { temp_camera_quality = (uint8_t)param->value().toInt(); } else if (param->name() == "brightness") { temp_camera_brightness = (uint8_t)param->value().toInt(); + } else if (param->name() == "simple_auto_exposure_on") { + temp_simple_auto_exposure_on = (uint8_t)param->value().toInt(); + } else if (param->name() == "fancy_auto_exposure_on") { + temp_fancy_auto_exposure_on = (uint8_t)param->value().toInt(); + } else if (param->name() == "ae_level") { + temp_ae_level = param->value().toInt(); + } else if (param->name() == "aec_value") { + temp_aec_value = (uint8_t)param->value().toInt(); + } else if (param->name() == "auto_gain_on") { + temp_auto_gain_on = (uint8_t)param->value().toInt(); } } // note: We're passing empty params by design, this is done to reset // specific fields projectConfig.setCameraConfig(temp_camera_vflip, temp_camera_framesize, temp_camera_hflip, temp_camera_quality, - temp_camera_brightness, true); + temp_camera_brightness, temp_simple_auto_exposure_on, + temp_fancy_auto_exposure_on, temp_ae_level, + temp_aec_value, temp_auto_gain_on, true); request->send(200, MIMETYPE_JSON, "{\"msg\":\"Done. Camera Settings have been set.\"}"); From 63e6c96aae1cad18547d8d3fa8b94f07edcedc42 Mon Sep 17 00:00:00 2001 From: lorow Date: Wed, 3 May 2023 16:27:38 +0200 Subject: [PATCH 2/6] Fixes after rebase --- ESP/lib/src/io/camera/cameraHandler.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/ESP/lib/src/io/camera/cameraHandler.cpp b/ESP/lib/src/io/camera/cameraHandler.cpp index 0b0eb727..a4196f7e 100644 --- a/ESP/lib/src/io/camera/cameraHandler.cpp +++ b/ESP/lib/src/io/camera/cameraHandler.cpp @@ -76,11 +76,12 @@ void CameraHandler::setupBasicResolution() { log_d("Found psram, setting the higher image quality"); config.jpeg_quality = 7; // 0-63 lower number = higher quality, more latency - // and less fps 7 for most fps, 5 for best quality + // and fewer fps 7 for most fps, 5 for best quality config.fb_count = 3; } void CameraHandler::setupCameraSensor() { + ProjectConfig::CameraConfig_t cameraConfig = configManager.getCameraConfig(); camera_sensor = esp_camera_sensor_get(); // fixes corrupted jpegs, https://github.com/espressif/esp32-camera/issues/203 // documentation https://www.uctronics.com/download/cam_module/OV2640DS.pdf @@ -89,7 +90,7 @@ void CameraHandler::setupCameraSensor() { 0x00); // banksel, here we're directly writing to the registers. // 0xFF==0x00 is the first bank, there's also 0xFF==0x01 camera_sensor->set_reg(camera_sensor, 0xd3, 0xff, 5); // clock - camera_sensor->set_brightness(camera_sensor, cameraConfig->brightness); // -2 to 2 + camera_sensor->set_brightness(camera_sensor, cameraConfig.brightness); // -2 to 2 camera_sensor->set_contrast(camera_sensor, 2); // -2 to 2 camera_sensor->set_saturation(camera_sensor, -2); // -2 to 2 @@ -101,13 +102,13 @@ void CameraHandler::setupCameraSensor() { // Sunny, 2 - Cloudy, 3 - Office, 4 - Home) // controls the exposure - camera_sensor->set_exposure_ctrl(camera_sensor, cameraConfig->simple_auto_exposure_on); // 0 = disable , 1 = enable - camera_sensor->set_aec2(camera_sensor, cameraConfig->fancy_auto_exposure_on); // 0 = disable , 1 = enable - camera_sensor->set_ae_level(camera_sensor, cameraConfig->ae_level); // -2 to 2 - camera_sensor->set_aec_value(camera_sensor, cameraConfig->aec_value); // 0 to 1200 + camera_sensor->set_exposure_ctrl(camera_sensor, cameraConfig.simple_auto_exposure_on); // 0 = disable , 1 = enable + camera_sensor->set_aec2(camera_sensor, cameraConfig.fancy_auto_exposure_on); // 0 = disable , 1 = enable + camera_sensor->set_ae_level(camera_sensor, cameraConfig.ae_level); // -2 to 2 + camera_sensor->set_aec_value(camera_sensor, cameraConfig.aec_value); // 0 to 1200 // controls the gain - camera_sensor->set_gain_ctrl(camera_sensor, cameraConfig->auto_gain_on); // 0 = disable , 1 = enable + camera_sensor->set_gain_ctrl(camera_sensor, cameraConfig.auto_gain_on); // 0 = disable , 1 = enable // automatic gain control gain, controls by how much the resulting image // should be amplified From ca70b88639c9a079132d05870503058c1bc2fd98 Mon Sep 17 00:00:00 2001 From: lorow Date: Thu, 4 May 2023 01:56:22 +0200 Subject: [PATCH 3/6] Refactor camera handler to actually make use of events related to config - needs more testing --- ESP/lib/src/io/camera/cameraHandler.cpp | 370 ++++++++++++------------ ESP/lib/src/io/camera/cameraHandler.hpp | 11 +- 2 files changed, 188 insertions(+), 193 deletions(-) diff --git a/ESP/lib/src/io/camera/cameraHandler.cpp b/ESP/lib/src/io/camera/cameraHandler.cpp index a4196f7e..2390ef1d 100644 --- a/ESP/lib/src/io/camera/cameraHandler.cpp +++ b/ESP/lib/src/io/camera/cameraHandler.cpp @@ -1,223 +1,221 @@ #include "cameraHandler.hpp" -CameraHandler::CameraHandler(ProjectConfig& configManager) - : configManager(configManager) {} +CameraHandler::CameraHandler(ProjectConfig &configManager) + : configManager(configManager) {} + +void CameraHandler::update(ConfigState_e event) { + switch (event) { + case ConfigState_e::configLoaded: + // we're just starting out, set up the sensor and do the initial config, then load the on-the-fly-config + // and init the sensor + this->setupCamera(); + break; + case ConfigState_e::cameraConfigUpdated: + this->loadChangeableConfig(); + break; + default: + break; + } +} void CameraHandler::setupCameraPinout() { - // Workaround for espM5SStack not having a defined camera + // Workaround for espM5SStack not having a defined camera #ifdef CAMERA_MODULE_NAME - log_i("Camera module is %s", CAMERA_MODULE_NAME); + log_i("Camera module is %s", CAMERA_MODULE_NAME); #else - log_i("Camera module is undefined"); + log_i("Camera module is undefined"); #endif - // camera external clock signal frequencies - // 10000000 stable - // 16500000 optimal freq on ESP32-CAM (default) - // 20000000 max freq on ESP32-CAM - // 24000000 optimal freq on ESP32-S3 - int xclk_freq_hz = 16500000; + // camera external clock signal frequencies + // 10000000 stable + // 16500000 optimal freq on ESP32-CAM (default) + // 20000000 max freq on ESP32-CAM + // 24000000 optimal freq on ESP32-S3 + int xclk_freq_hz = 16500000; #if CONFIG_CAMERA_MODULE_ESP_EYE - /* IO13, IO14 is designed for JTAG by default, - * to use it as generalized input, - * firstly declare it as pullup input - **/ - pinMode(13, INPUT_PULLUP); - pinMode(14, INPUT_PULLUP); - log_i("ESP_EYE"); + /* IO13, IO14 is designed for JTAG by default, + * to use it as generalized input, + * firstly declare it as pullup input + **/ + pinMode(13, INPUT_PULLUP); + pinMode(14, INPUT_PULLUP); + log_i("ESP_EYE"); #elif CONFIG_CAMERA_MODULE_CAM_BOARD - /* IO13, IO14 is designed for JTAG by default, - * to use it as generalized input, - * firstly declare it as pullup input - **/ - pinMode(13, INPUT_PULLUP); - pinMode(14, INPUT_PULLUP); - log_i("CAM_BOARD"); + /* IO13, IO14 is designed for JTAG by default, + * to use it as generalized input, + * firstly declare it as pullup input + **/ + pinMode(13, INPUT_PULLUP); + pinMode(14, INPUT_PULLUP); + log_i("CAM_BOARD"); #endif #if ETVR_EYE_TRACKER_USB_API - /* ESP32-S3 is capable of using higher freqs */ - xclk_freq_hz = 24000000; + /* ESP32-S3 is capable of using higher freqs */ + xclk_freq_hz = 24000000; #endif - config.ledc_channel = LEDC_CHANNEL_0; - config.ledc_timer = LEDC_TIMER_0; - config.grab_mode = CAMERA_GRAB_LATEST; - 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_sccb_sda = SIOD_GPIO_NUM; - config.pin_sccb_scl = SIOC_GPIO_NUM; - config.pin_pwdn = PWDN_GPIO_NUM; - config.pin_reset = RESET_GPIO_NUM; - config.xclk_freq_hz = xclk_freq_hz; + config.ledc_channel = LEDC_CHANNEL_0; + config.ledc_timer = LEDC_TIMER_0; + config.grab_mode = CAMERA_GRAB_LATEST; + 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_sccb_sda = SIOD_GPIO_NUM; + config.pin_sccb_scl = SIOC_GPIO_NUM; + config.pin_pwdn = PWDN_GPIO_NUM; + config.pin_reset = RESET_GPIO_NUM; + config.xclk_freq_hz = xclk_freq_hz; } -void CameraHandler::setupBasicResolution() { - config.pixel_format = PIXFORMAT_JPEG; - config.frame_size = FRAMESIZE_240X240; - - if (!psramFound()) { - log_e("Did not find psram, setting lower image quality"); - config.fb_location = CAMERA_FB_IN_DRAM; - config.jpeg_quality = 9; - config.fb_count = 2; - return; - } - - log_d("Found psram, setting the higher image quality"); - config.jpeg_quality = 7; // 0-63 lower number = higher quality, more latency - // and fewer fps 7 for most fps, 5 for best quality - config.fb_count = 3; +void CameraHandler::setupCameraMemoryStorage() { + config.pixel_format = PIXFORMAT_JPEG; + // set here only for initialization purposes, proper framesize will be loaded from config + config.frame_size = FRAMESIZE_240X240; + + if (!psramFound()) { + log_e("Did not find psram, setting lower image quality"); + config.fb_location = CAMERA_FB_IN_DRAM; + config.jpeg_quality = 9; + config.fb_count = 2; + return; + } + + log_d("Found psram, setting the higher image quality"); + config.jpeg_quality = 7; // 0-63 lower number = higher quality, more latency + // and fewer fps 7 for most fps, 5 for best quality + config.fb_count = 3; } void CameraHandler::setupCameraSensor() { - ProjectConfig::CameraConfig_t cameraConfig = configManager.getCameraConfig(); - camera_sensor = esp_camera_sensor_get(); - // fixes corrupted jpegs, https://github.com/espressif/esp32-camera/issues/203 - // documentation https://www.uctronics.com/download/cam_module/OV2640DS.pdf - camera_sensor->set_reg( - camera_sensor, 0xff, 0xff, - 0x00); // banksel, here we're directly writing to the registers. - // 0xFF==0x00 is the first bank, there's also 0xFF==0x01 - camera_sensor->set_reg(camera_sensor, 0xd3, 0xff, 5); // clock - camera_sensor->set_brightness(camera_sensor, cameraConfig.brightness); // -2 to 2 - camera_sensor->set_contrast(camera_sensor, 2); // -2 to 2 - camera_sensor->set_saturation(camera_sensor, -2); // -2 to 2 - - // white balance control - camera_sensor->set_whitebal(camera_sensor, 1); // 0 = disable , 1 = enable - camera_sensor->set_awb_gain(camera_sensor, 0); // 0 = disable , 1 = enable - camera_sensor->set_wb_mode(camera_sensor, - 0); // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - - // Sunny, 2 - Cloudy, 3 - Office, 4 - Home) - - // controls the exposure - camera_sensor->set_exposure_ctrl(camera_sensor, cameraConfig.simple_auto_exposure_on); // 0 = disable , 1 = enable - camera_sensor->set_aec2(camera_sensor, cameraConfig.fancy_auto_exposure_on); // 0 = disable , 1 = enable - camera_sensor->set_ae_level(camera_sensor, cameraConfig.ae_level); // -2 to 2 - camera_sensor->set_aec_value(camera_sensor, cameraConfig.aec_value); // 0 to 1200 - - // controls the gain - camera_sensor->set_gain_ctrl(camera_sensor, cameraConfig.auto_gain_on); // 0 = disable , 1 = enable - - // automatic gain control gain, controls by how much the resulting image - // should be amplified - camera_sensor->set_agc_gain(camera_sensor, 2); // 0 to 30 - camera_sensor->set_gainceiling(camera_sensor, (gainceiling_t)6); // 0 to 6 - - // black and white pixel correction, averages the white and black spots - camera_sensor->set_bpc(camera_sensor, 1); // 0 = disable , 1 = enable - camera_sensor->set_wpc(camera_sensor, 1); // 0 = disable , 1 = enable - // digital clamp white balance - camera_sensor->set_dcw(camera_sensor, 0); // 0 = disable , 1 = enable - - // gamma correction - camera_sensor->set_raw_gma( - camera_sensor, - 1); // 0 = disable , 1 = enable (makes much lighter and noisy) - - camera_sensor->set_lenc(camera_sensor, 0); // 0 = disable , 1 = enable // 0 = - // disable , 1 = enable - - camera_sensor->set_colorbar(camera_sensor, 0); // 0 = disable , 1 = enable - - camera_sensor->set_special_effect( - camera_sensor, - 2); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, - // 4 - Green Tint, 5 - Blue Tint, 6 - Sepia) + // this should be split into two methods + // fixes corrupted jpegs, https://github.com/espressif/esp32-camera/issues/203 + // documentation https://www.uctronics.com/download/cam_module/OV2640DS.pdf + camera_sensor->set_reg( + camera_sensor, 0xff, 0xff, + 0x00); // banksel, here we're directly writing to the registers. + // 0xFF==0x00 is the first bank, there's also 0xFF==0x01 + camera_sensor->set_reg(camera_sensor, 0xd3, 0xff, 5); // clock + camera_sensor->set_contrast(camera_sensor, 2); // -2 to 2 + camera_sensor->set_saturation(camera_sensor, -2); // -2 to 2 + + // white balance control + camera_sensor->set_whitebal(camera_sensor, 1); // 0 = disable , 1 = enable + camera_sensor->set_awb_gain(camera_sensor, 0); // 0 = disable , 1 = enable + camera_sensor->set_wb_mode(camera_sensor, + 0); // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - + // Sunny, 2 - Cloudy, 3 - Office, 4 - Home) + + // automatic gain control gain, controls by how much the resulting image + // should be amplified + camera_sensor->set_agc_gain(camera_sensor, 2); // 0 to 30 + camera_sensor->set_gainceiling(camera_sensor, (gainceiling_t) 6); // 0 to 6 + + // black and white pixel correction, averages the white and black spots + camera_sensor->set_bpc(camera_sensor, 1); // 0 = disable , 1 = enable + camera_sensor->set_wpc(camera_sensor, 1); // 0 = disable , 1 = enable + // digital clamp white balance + camera_sensor->set_dcw(camera_sensor, 0); // 0 = disable , 1 = enable + + // gamma correction + camera_sensor->set_raw_gma( + camera_sensor, + 1); // 0 = disable , 1 = enable (makes much lighter and noisy) + + camera_sensor->set_lenc(camera_sensor, 0); // 0 = disable , 1 = enable // 0 = + // disable , 1 = enable + + camera_sensor->set_colorbar(camera_sensor, 0); // 0 = disable , 1 = enable + + camera_sensor->set_special_effect( + camera_sensor, + 2); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, + // 4 - Green Tint, 5 - Blue Tint, 6 - Sepia) } -bool CameraHandler::setupCamera() { - this->setupCameraPinout(); - this->setupBasicResolution(); - esp_err_t hasCameraBeenInitialized = esp_camera_init(&config); - - if (hasCameraBeenInitialized != ESP_OK) { - log_e("Camera initialization failed with error: 0x%x \r\n", - hasCameraBeenInitialized); - log_e( - "Camera most likely not seated properly in the socket. Please fix the " - "camera and reboot the device.\r\n"); - ledStateManager.setState(LEDStates_e::_Camera_Error); - return false; - } - - this->setupCameraSensor(); - return true; -} +void CameraHandler::loadChangeableConfig() { + ProjectConfig::CameraConfig_t cameraConfig = configManager.getCameraConfig(); + + // controls the exposure + camera_sensor->set_brightness(camera_sensor, cameraConfig.brightness); // -2 to 2 + camera_sensor->set_exposure_ctrl(camera_sensor, + cameraConfig.simple_auto_exposure_on); // 0 = disable , 1 = enable + camera_sensor->set_aec2(camera_sensor, cameraConfig.fancy_auto_exposure_on); // 0 = disable , 1 = enable + camera_sensor->set_ae_level(camera_sensor, cameraConfig.ae_level); // -2 to 2 + camera_sensor->set_aec_value(camera_sensor, cameraConfig.aec_value); // 0 to 1200 + + camera_sensor->set_quality(camera_sensor, cameraConfig.quality); + camera_sensor->set_agc_gain(camera_sensor, cameraConfig.brightness); + + // controls the gain + camera_sensor->set_gain_ctrl(camera_sensor, cameraConfig.auto_gain_on); // 0 = disable , 1 = enable -void CameraHandler::loadConfigData() { - ProjectConfig::CameraConfig_t cameraConfig = configManager.getCameraConfig(); - this->setHFlip(cameraConfig.href); - this->setVFlip(cameraConfig.vflip); - this->setCameraResolution((framesize_t)cameraConfig.framesize); - camera_sensor->set_quality(camera_sensor, cameraConfig.quality); - camera_sensor->set_agc_gain(camera_sensor, cameraConfig.brightness); + camera_sensor->set_hmirror(camera_sensor, cameraConfig.href); + camera_sensor->set_vflip(camera_sensor, cameraConfig.vflip); + + this->setCameraResolution(FRAMESIZE_240X240); //(framesize_t) cameraConfig.framesize } -int CameraHandler::setCameraResolution(framesize_t frameSize) { - if (camera_sensor->pixformat == PIXFORMAT_JPEG) { - try { - return camera_sensor->set_framesize(camera_sensor, frameSize); - } catch (...) { - // they sent us a malformed or unsupported frameSize - rather than crash - - // tell them about it - return -1; +bool CameraHandler::setupCamera() { + this->setupCameraPinout(); + this->setupCameraMemoryStorage(); + esp_err_t hasCameraBeenInitialized = esp_camera_init(&config); + + if (hasCameraBeenInitialized != ESP_OK) { + log_e("Camera initialization failed with error: 0x%x \r\n", hasCameraBeenInitialized); + log_e("Camera most likely not seated properly in the socket. Please fix the camera and reboot the device.\r\n"); + ledStateManager.setState(LEDStates_e::_Camera_Error); + return false; } - } - return -1; -} -int CameraHandler::setVFlip(int direction) { - return camera_sensor->set_vflip(camera_sensor, direction); + this->camera_sensor = esp_camera_sensor_get(); + this->loadChangeableConfig(); + this->setupCameraSensor(); + return true; } -int CameraHandler::setHFlip(int direction) { - return camera_sensor->set_hmirror(camera_sensor, direction); + +int CameraHandler::setCameraResolution(framesize_t frameSize) { + if (camera_sensor->pixformat == PIXFORMAT_JPEG) { + try { + int result = camera_sensor->set_framesize(camera_sensor, frameSize); + return result; + } catch (...) { + // they sent us a malformed or unsupported frameSize - rather than crash - + // tell them about it + return -1; + } + } + return -1; } //! either hardware(1) or software(0) void CameraHandler::resetCamera(bool type) { - if (type) { - // power cycle the camera module (handy if camera stops responding) - digitalWrite(PWDN_GPIO_NUM, HIGH); // turn power off to camera module - Network_Utilities::my_delay(0.3); // a for loop with a delay of 300ms - digitalWrite(PWDN_GPIO_NUM, LOW); - Network_Utilities::my_delay(0.3); - setupCamera(); - } else { - // reset via software (handy if you wish to change resolution or image type - // etc. - see test procedure) - esp_camera_deinit(); - Network_Utilities::my_delay(0.05); - setupCamera(); - } -} - -void CameraHandler::update(ConfigState_e event) { - switch (event) { - case ConfigState_e::configLoaded: - this->setupCamera(); - this->loadConfigData(); - break; - case ConfigState_e::cameraConfigUpdated: - this->loadConfigData(); - break; - default: - break; - } + if (type) { + // power cycle the camera module (handy if camera stops responding) + digitalWrite(PWDN_GPIO_NUM, HIGH); // turn power off to camera module + Network_Utilities::my_delay(0.3); // a for loop with a delay of 300ms + digitalWrite(PWDN_GPIO_NUM, LOW); + Network_Utilities::my_delay(0.3); + setupCamera(); + } else { + // reset via software (handy if you wish to change resolution or image type + // etc. - see test procedure) + esp_camera_deinit(); + Network_Utilities::my_delay(0.05); + setupCamera(); + } } std::string CameraHandler::getName() { - return "CameraHandler"; + return "CameraHandler"; } diff --git a/ESP/lib/src/io/camera/cameraHandler.hpp b/ESP/lib/src/io/camera/cameraHandler.hpp index 93250fb6..9c1e9216 100644 --- a/ESP/lib/src/io/camera/cameraHandler.hpp +++ b/ESP/lib/src/io/camera/cameraHandler.hpp @@ -15,17 +15,14 @@ class CameraHandler : public IObserver { public: CameraHandler(ProjectConfig& configManager); int setCameraResolution(framesize_t frameSize); - int setVFlip(int direction); - int setHFlip(int direction); - int setVieWindow(int offsetX, int offsetY, int outputX, int outputY); - void update(ConfigState_e event); - std::string getName(); + void update(ConfigState_e event) override; + std::string getName() override; void resetCamera(bool type = 0); private: - void loadConfigData(); + void loadChangeableConfig(); bool setupCamera(); void setupCameraPinout(); - void setupBasicResolution(); + void setupCameraMemoryStorage(); void setupCameraSensor(); }; From d0c2aa76226b7795f46fd27d77520ab4a485f161 Mon Sep 17 00:00:00 2001 From: lorow Date: Wed, 17 May 2023 22:58:53 +0200 Subject: [PATCH 4/6] WIP refactoring camera --- ESP/lib/src/io/camera/cameraHandler.cpp | 161 +++++++++++++++++++- ESP/lib/src/network/stream/streamServer.cpp | 2 + 2 files changed, 157 insertions(+), 6 deletions(-) diff --git a/ESP/lib/src/io/camera/cameraHandler.cpp b/ESP/lib/src/io/camera/cameraHandler.cpp index 2390ef1d..80b9f724 100644 --- a/ESP/lib/src/io/camera/cameraHandler.cpp +++ b/ESP/lib/src/io/camera/cameraHandler.cpp @@ -80,7 +80,7 @@ void CameraHandler::setupCameraPinout() { void CameraHandler::setupCameraMemoryStorage() { config.pixel_format = PIXFORMAT_JPEG; // set here only for initialization purposes, proper framesize will be loaded from config - config.frame_size = FRAMESIZE_240X240; + config.frame_size = FRAMESIZE_96X96; if (!psramFound()) { log_e("Did not find psram, setting lower image quality"); @@ -162,12 +162,97 @@ void CameraHandler::loadChangeableConfig() { camera_sensor->set_hmirror(camera_sensor, cameraConfig.href); camera_sensor->set_vflip(camera_sensor, cameraConfig.vflip); + config.pixel_format = PIXFORMAT_JPEG; + // set here only for initialization purposes, proper framesize will be loaded from config + config.frame_size = FRAMESIZE_96X96; + + if (!psramFound()) { + log_e("Did not find psram, setting lower image quality"); + config.fb_location = CAMERA_FB_IN_DRAM; + config.jpeg_quality = 9; + config.fb_count = 2; + return; + } + + log_d("Found psram, setting the higher image quality"); + config.jpeg_quality = 7; // 0-63 lower number = higher quality, more latency + // and fewer fps 7 for most fps, 5 for best quality + config.fb_location = CAMERA_FB_IN_PSRAM; + config.fb_count = 3; + + // this somehow gets set to FRAMESIZE_CIF, what in the absolute fuck this->setCameraResolution(FRAMESIZE_240X240); //(framesize_t) cameraConfig.framesize } bool CameraHandler::setupCamera() { - this->setupCameraPinout(); - this->setupCameraMemoryStorage(); + // Workaround for espM5SStack not having a defined camera +#ifdef CAMERA_MODULE_NAME + log_i("Camera module is %s", CAMERA_MODULE_NAME); +#else + log_i("Camera module is undefined"); +#endif + + // camera external clock signal frequencies + // 10000000 stable + // 16500000 optimal freq on ESP32-CAM (default) + // 20000000 max freq on ESP32-CAM + // 24000000 optimal freq on ESP32-S3 + int xclk_freq_hz = 16500000; + +#if CONFIG_CAMERA_MODULE_ESP_EYE + /* IO13, IO14 is designed for JTAG by default, + * to use it as generalized input, + * firstly declare it as pullup input + **/ + pinMode(13, INPUT_PULLUP); + pinMode(14, INPUT_PULLUP); + log_i("ESP_EYE"); +#elif CONFIG_CAMERA_MODULE_CAM_BOARD + /* IO13, IO14 is designed for JTAG by default, + * to use it as generalized input, + * firstly declare it as pullup input + **/ + pinMode(13, INPUT_PULLUP); + pinMode(14, INPUT_PULLUP); + log_i("CAM_BOARD"); +#endif +#if ETVR_EYE_TRACKER_USB_API + /* ESP32-S3 is capable of using higher freqs */ + xclk_freq_hz = 24000000; +#endif + config.ledc_channel = LEDC_CHANNEL_0; + config.ledc_timer = LEDC_TIMER_0; + config.grab_mode = CAMERA_GRAB_LATEST; + 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_sccb_sda = SIOD_GPIO_NUM; + config.pin_sccb_scl = SIOC_GPIO_NUM; + config.pin_pwdn = PWDN_GPIO_NUM; + config.pin_reset = RESET_GPIO_NUM; + config.xclk_freq_hz = xclk_freq_hz; + config.pixel_format = PIXFORMAT_JPEG; + config.frame_size = FRAMESIZE_240X240; + + if(psramFound()){ + config.jpeg_quality = 10; + config.fb_count = 3; + } else { + log_e("Did not find psram, setting lower image quality"); + config.fb_location = CAMERA_FB_IN_DRAM; + config.jpeg_quality = 9; + config.fb_count = 2; + } + esp_err_t hasCameraBeenInitialized = esp_camera_init(&config); if (hasCameraBeenInitialized != ESP_OK) { @@ -178,8 +263,71 @@ bool CameraHandler::setupCamera() { } this->camera_sensor = esp_camera_sensor_get(); - this->loadChangeableConfig(); - this->setupCameraSensor(); + +//// this->loadChangeableConfig(); +//// this->setupCameraSensor(); + + // fixes corrupted jpegs, https://github.com/espressif/esp32-camera/issues/203 + // documentation https://www.uctronics.com/download/cam_module/OV2640DS.pdf + camera_sensor->set_reg( + camera_sensor, 0xff, 0xff, + 0x00); // banksel, here we're directly writing to the registers. + + // 0xFF==0x00 is the first bank, there's also 0xFF==0x01 + camera_sensor->set_reg(camera_sensor, 0xd3, 0xff, 5); // clock + camera_sensor->set_contrast(camera_sensor, 2); // -2 to 2 + camera_sensor->set_saturation(camera_sensor, -2); // -2 to 2 +// +// // white balance control + camera_sensor->set_whitebal(camera_sensor, 1); // 0 = disable , 1 = enable + camera_sensor->set_awb_gain(camera_sensor, 0); // 0 = disable , 1 = enable + // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home) + + camera_sensor->set_wb_mode(camera_sensor, 0); +// +// // automatic gain control gain, controls by how much the resulting image +// // should be amplified + camera_sensor->set_agc_gain(camera_sensor, 2); // 0 to 30 + camera_sensor->set_gainceiling(camera_sensor, (gainceiling_t) 6); // 0 to 6 +// +// // black and white pixel correction, averages the white and black spots + camera_sensor->set_bpc(camera_sensor, 1); // 0 = disable , 1 = enable + camera_sensor->set_wpc(camera_sensor, 1); // 0 = disable , 1 = enable + // digital clamp white balance + + // this breaks things for some reason + camera_sensor->set_dcw(camera_sensor, 1); // 0 = disable , 1 = enable +// +// // gamma correction + camera_sensor->set_raw_gma(camera_sensor, 1); // 0 = disable , 1 = enable (makes much lighter and noisy) + + camera_sensor->set_lenc(camera_sensor, 0); // 0 = disable , 1 = enable // 0 = + // disable , 1 = enable + + camera_sensor->set_colorbar(camera_sensor, 0); // 0 = disable , 1 = enable + + camera_sensor->set_special_effect(camera_sensor, 1); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, +// // 4 - Green Tint, 5 - Blue Tint, 6 - Sepia) + + + ProjectConfig::CameraConfig_t cameraConfig = configManager.getCameraConfig(); + // controls the exposure + camera_sensor->set_brightness(camera_sensor, cameraConfig.brightness); // -2 to 2 + camera_sensor->set_exposure_ctrl(camera_sensor, + cameraConfig.simple_auto_exposure_on); // 0 = disable , 1 = enable + camera_sensor->set_aec2(camera_sensor, cameraConfig.fancy_auto_exposure_on); // 0 = disable , 1 = enable + camera_sensor->set_ae_level(camera_sensor, cameraConfig.ae_level); // -2 to 2 + camera_sensor->set_aec_value(camera_sensor, cameraConfig.aec_value); // 0 to 1200 + + camera_sensor->set_quality(camera_sensor, cameraConfig.quality); + camera_sensor->set_agc_gain(camera_sensor, cameraConfig.brightness); + + // controls the gain + camera_sensor->set_gain_ctrl(camera_sensor, cameraConfig.auto_gain_on); // 0 = disable , 1 = enable + + camera_sensor->set_hmirror(camera_sensor, cameraConfig.href); + camera_sensor->set_vflip(camera_sensor, cameraConfig.vflip); + return true; } @@ -190,6 +338,7 @@ int CameraHandler::setCameraResolution(framesize_t frameSize) { int result = camera_sensor->set_framesize(camera_sensor, frameSize); return result; } catch (...) { + log_d("[ERROR] Unsupported resolution %d", frameSize); // they sent us a malformed or unsupported frameSize - rather than crash - // tell them about it return -1; @@ -206,7 +355,7 @@ void CameraHandler::resetCamera(bool type) { Network_Utilities::my_delay(0.3); // a for loop with a delay of 300ms digitalWrite(PWDN_GPIO_NUM, LOW); Network_Utilities::my_delay(0.3); - setupCamera(); + loadChangeableConfig(); } else { // reset via software (handy if you wish to change resolution or image type // etc. - see test procedure) diff --git a/ESP/lib/src/network/stream/streamServer.cpp b/ESP/lib/src/network/stream/streamServer.cpp index 951379bd..0006672c 100644 --- a/ESP/lib/src/network/stream/streamServer.cpp +++ b/ESP/lib/src/network/stream/streamServer.cpp @@ -69,6 +69,8 @@ esp_err_t StreamHelpers::stream(httpd_req_t *req) long latency = (request_end - last_request_time); last_request_time = request_end; log_d("Size: %uKB, Time: %ums (%ifps)\n", _jpg_buf_len / 1024, latency, 1000 / latency); + auto sensor = esp_camera_sensor_get(); + log_d(" ----current framesize is %d ", sensor->status.framesize); } last_frame = 0; return res; From 1cb2632d23c8af269d189bceb67a503425e2065a Mon Sep 17 00:00:00 2001 From: lorow Date: Wed, 17 May 2023 23:55:46 +0200 Subject: [PATCH 5/6] FIX the camera handler resolution and brightness bugs --- ESP/lib/src/io/camera/cameraHandler.cpp | 195 +++--------------------- 1 file changed, 23 insertions(+), 172 deletions(-) diff --git a/ESP/lib/src/io/camera/cameraHandler.cpp b/ESP/lib/src/io/camera/cameraHandler.cpp index 80b9f724..f2692cda 100644 --- a/ESP/lib/src/io/camera/cameraHandler.cpp +++ b/ESP/lib/src/io/camera/cameraHandler.cpp @@ -18,6 +18,24 @@ void CameraHandler::update(ConfigState_e event) { } } +bool CameraHandler::setupCamera() { + this->setupCameraPinout(); + this->setupCameraMemoryStorage(); + + esp_err_t hasCameraBeenInitialized = esp_camera_init(&config); + if (hasCameraBeenInitialized != ESP_OK) { + log_e("Camera initialization failed with error: 0x%x \r\n", hasCameraBeenInitialized); + log_e("Camera most likely not seated properly in the socket. Please fix the camera and reboot the device.\r\n"); + ledStateManager.setState(LEDStates_e::_Camera_Error); + return false; + } + + this->camera_sensor = esp_camera_sensor_get(); + this->setupCameraSensor(); + this->loadChangeableConfig(); + return true; +} + void CameraHandler::setupCameraPinout() { // Workaround for espM5SStack not having a defined camera #ifdef CAMERA_MODULE_NAME @@ -79,8 +97,7 @@ void CameraHandler::setupCameraPinout() { void CameraHandler::setupCameraMemoryStorage() { config.pixel_format = PIXFORMAT_JPEG; - // set here only for initialization purposes, proper framesize will be loaded from config - config.frame_size = FRAMESIZE_96X96; + config.frame_size = FRAMESIZE_240X240; // initial, the proper one will be loaded later if (!psramFound()) { log_e("Did not find psram, setting lower image quality"); @@ -145,8 +162,8 @@ void CameraHandler::setupCameraSensor() { void CameraHandler::loadChangeableConfig() { ProjectConfig::CameraConfig_t cameraConfig = configManager.getCameraConfig(); - // controls the exposure - camera_sensor->set_brightness(camera_sensor, cameraConfig.brightness); // -2 to 2 + // controls the exposure [TODO] figure out why it makes the image bright af + // camera_sensor->set_brightness(camera_sensor, cameraConfig.brightness); // -2 to 2 camera_sensor->set_exposure_ctrl(camera_sensor, cameraConfig.simple_auto_exposure_on); // 0 = disable , 1 = enable camera_sensor->set_aec2(camera_sensor, cameraConfig.fancy_auto_exposure_on); // 0 = disable , 1 = enable @@ -162,177 +179,11 @@ void CameraHandler::loadChangeableConfig() { camera_sensor->set_hmirror(camera_sensor, cameraConfig.href); camera_sensor->set_vflip(camera_sensor, cameraConfig.vflip); - config.pixel_format = PIXFORMAT_JPEG; - // set here only for initialization purposes, proper framesize will be loaded from config - config.frame_size = FRAMESIZE_96X96; - - if (!psramFound()) { - log_e("Did not find psram, setting lower image quality"); - config.fb_location = CAMERA_FB_IN_DRAM; - config.jpeg_quality = 9; - config.fb_count = 2; - return; - } - - log_d("Found psram, setting the higher image quality"); - config.jpeg_quality = 7; // 0-63 lower number = higher quality, more latency - // and fewer fps 7 for most fps, 5 for best quality - config.fb_location = CAMERA_FB_IN_PSRAM; - config.fb_count = 3; - - // this somehow gets set to FRAMESIZE_CIF, what in the absolute fuck this->setCameraResolution(FRAMESIZE_240X240); //(framesize_t) cameraConfig.framesize } -bool CameraHandler::setupCamera() { - // Workaround for espM5SStack not having a defined camera -#ifdef CAMERA_MODULE_NAME - log_i("Camera module is %s", CAMERA_MODULE_NAME); -#else - log_i("Camera module is undefined"); -#endif - - // camera external clock signal frequencies - // 10000000 stable - // 16500000 optimal freq on ESP32-CAM (default) - // 20000000 max freq on ESP32-CAM - // 24000000 optimal freq on ESP32-S3 - int xclk_freq_hz = 16500000; - -#if CONFIG_CAMERA_MODULE_ESP_EYE - /* IO13, IO14 is designed for JTAG by default, - * to use it as generalized input, - * firstly declare it as pullup input - **/ - pinMode(13, INPUT_PULLUP); - pinMode(14, INPUT_PULLUP); - log_i("ESP_EYE"); -#elif CONFIG_CAMERA_MODULE_CAM_BOARD - /* IO13, IO14 is designed for JTAG by default, - * to use it as generalized input, - * firstly declare it as pullup input - **/ - pinMode(13, INPUT_PULLUP); - pinMode(14, INPUT_PULLUP); - log_i("CAM_BOARD"); -#endif -#if ETVR_EYE_TRACKER_USB_API - /* ESP32-S3 is capable of using higher freqs */ - xclk_freq_hz = 24000000; -#endif - config.ledc_channel = LEDC_CHANNEL_0; - config.ledc_timer = LEDC_TIMER_0; - config.grab_mode = CAMERA_GRAB_LATEST; - 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_sccb_sda = SIOD_GPIO_NUM; - config.pin_sccb_scl = SIOC_GPIO_NUM; - config.pin_pwdn = PWDN_GPIO_NUM; - config.pin_reset = RESET_GPIO_NUM; - config.xclk_freq_hz = xclk_freq_hz; - config.pixel_format = PIXFORMAT_JPEG; - config.frame_size = FRAMESIZE_240X240; - - if(psramFound()){ - config.jpeg_quality = 10; - config.fb_count = 3; - } else { - log_e("Did not find psram, setting lower image quality"); - config.fb_location = CAMERA_FB_IN_DRAM; - config.jpeg_quality = 9; - config.fb_count = 2; - } - - esp_err_t hasCameraBeenInitialized = esp_camera_init(&config); - - if (hasCameraBeenInitialized != ESP_OK) { - log_e("Camera initialization failed with error: 0x%x \r\n", hasCameraBeenInitialized); - log_e("Camera most likely not seated properly in the socket. Please fix the camera and reboot the device.\r\n"); - ledStateManager.setState(LEDStates_e::_Camera_Error); - return false; - } - - this->camera_sensor = esp_camera_sensor_get(); - -//// this->loadChangeableConfig(); -//// this->setupCameraSensor(); - - // fixes corrupted jpegs, https://github.com/espressif/esp32-camera/issues/203 - // documentation https://www.uctronics.com/download/cam_module/OV2640DS.pdf - camera_sensor->set_reg( - camera_sensor, 0xff, 0xff, - 0x00); // banksel, here we're directly writing to the registers. - - // 0xFF==0x00 is the first bank, there's also 0xFF==0x01 - camera_sensor->set_reg(camera_sensor, 0xd3, 0xff, 5); // clock - camera_sensor->set_contrast(camera_sensor, 2); // -2 to 2 - camera_sensor->set_saturation(camera_sensor, -2); // -2 to 2 -// -// // white balance control - camera_sensor->set_whitebal(camera_sensor, 1); // 0 = disable , 1 = enable - camera_sensor->set_awb_gain(camera_sensor, 0); // 0 = disable , 1 = enable - // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home) - - camera_sensor->set_wb_mode(camera_sensor, 0); -// -// // automatic gain control gain, controls by how much the resulting image -// // should be amplified - camera_sensor->set_agc_gain(camera_sensor, 2); // 0 to 30 - camera_sensor->set_gainceiling(camera_sensor, (gainceiling_t) 6); // 0 to 6 -// -// // black and white pixel correction, averages the white and black spots - camera_sensor->set_bpc(camera_sensor, 1); // 0 = disable , 1 = enable - camera_sensor->set_wpc(camera_sensor, 1); // 0 = disable , 1 = enable - // digital clamp white balance - - // this breaks things for some reason - camera_sensor->set_dcw(camera_sensor, 1); // 0 = disable , 1 = enable -// -// // gamma correction - camera_sensor->set_raw_gma(camera_sensor, 1); // 0 = disable , 1 = enable (makes much lighter and noisy) - - camera_sensor->set_lenc(camera_sensor, 0); // 0 = disable , 1 = enable // 0 = - // disable , 1 = enable - - camera_sensor->set_colorbar(camera_sensor, 0); // 0 = disable , 1 = enable - - camera_sensor->set_special_effect(camera_sensor, 1); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, -// // 4 - Green Tint, 5 - Blue Tint, 6 - Sepia) - - - ProjectConfig::CameraConfig_t cameraConfig = configManager.getCameraConfig(); - // controls the exposure - camera_sensor->set_brightness(camera_sensor, cameraConfig.brightness); // -2 to 2 - camera_sensor->set_exposure_ctrl(camera_sensor, - cameraConfig.simple_auto_exposure_on); // 0 = disable , 1 = enable - camera_sensor->set_aec2(camera_sensor, cameraConfig.fancy_auto_exposure_on); // 0 = disable , 1 = enable - camera_sensor->set_ae_level(camera_sensor, cameraConfig.ae_level); // -2 to 2 - camera_sensor->set_aec_value(camera_sensor, cameraConfig.aec_value); // 0 to 1200 - - camera_sensor->set_quality(camera_sensor, cameraConfig.quality); - camera_sensor->set_agc_gain(camera_sensor, cameraConfig.brightness); - - // controls the gain - camera_sensor->set_gain_ctrl(camera_sensor, cameraConfig.auto_gain_on); // 0 = disable , 1 = enable - - camera_sensor->set_hmirror(camera_sensor, cameraConfig.href); - camera_sensor->set_vflip(camera_sensor, cameraConfig.vflip); - - return true; -} - - int CameraHandler::setCameraResolution(framesize_t frameSize) { + log_d("[CAMERA] trying to set resolution of %d", frameSize); if (camera_sensor->pixformat == PIXFORMAT_JPEG) { try { int result = camera_sensor->set_framesize(camera_sensor, frameSize); @@ -367,4 +218,4 @@ void CameraHandler::resetCamera(bool type) { std::string CameraHandler::getName() { return "CameraHandler"; -} +} \ No newline at end of file From 77eca1fd8deb64f79fdbb4de23dc5614127a55cb Mon Sep 17 00:00:00 2001 From: lorow Date: Fri, 19 May 2023 00:30:00 +0200 Subject: [PATCH 6/6] Code cleanup, fix bug making the camera feed yellow-ish --- ESP/lib/src/data/config/project_config.hpp | 4 +-- ESP/lib/src/io/camera/cameraHandler.cpp | 35 ++++++---------------- ESP/lib/src/io/camera/cameraHandler.hpp | 1 - 3 files changed, 11 insertions(+), 29 deletions(-) diff --git a/ESP/lib/src/data/config/project_config.hpp b/ESP/lib/src/data/config/project_config.hpp index 7ab97a93..8ee0309a 100644 --- a/ESP/lib/src/data/config/project_config.hpp +++ b/ESP/lib/src/data/config/project_config.hpp @@ -44,9 +44,9 @@ class ProjectConfig : public Preferences, public ISubject { struct CameraConfig_t { uint8_t vflip; uint8_t href; - uint8_t framesize; + int framesize; uint8_t quality; - uint8_t brightness; + int brightness; bool simple_auto_exposure_on; bool fancy_auto_exposure_on; int ae_level; diff --git a/ESP/lib/src/io/camera/cameraHandler.cpp b/ESP/lib/src/io/camera/cameraHandler.cpp index f2692cda..13e4bf2e 100644 --- a/ESP/lib/src/io/camera/cameraHandler.cpp +++ b/ESP/lib/src/io/camera/cameraHandler.cpp @@ -153,25 +153,19 @@ void CameraHandler::setupCameraSensor() { camera_sensor->set_colorbar(camera_sensor, 0); // 0 = disable , 1 = enable - camera_sensor->set_special_effect( - camera_sensor, - 2); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, - // 4 - Green Tint, 5 - Blue Tint, 6 - Sepia) + camera_sensor->set_agc_gain(camera_sensor, 2); } void CameraHandler::loadChangeableConfig() { ProjectConfig::CameraConfig_t cameraConfig = configManager.getCameraConfig(); - // controls the exposure [TODO] figure out why it makes the image bright af - // camera_sensor->set_brightness(camera_sensor, cameraConfig.brightness); // -2 to 2 - camera_sensor->set_exposure_ctrl(camera_sensor, - cameraConfig.simple_auto_exposure_on); // 0 = disable , 1 = enable + camera_sensor->set_brightness(camera_sensor, cameraConfig.brightness); // -2 to 2 + camera_sensor->set_exposure_ctrl(camera_sensor,cameraConfig.simple_auto_exposure_on); // 0 = disable , 1 = enable camera_sensor->set_aec2(camera_sensor, cameraConfig.fancy_auto_exposure_on); // 0 = disable , 1 = enable camera_sensor->set_ae_level(camera_sensor, cameraConfig.ae_level); // -2 to 2 camera_sensor->set_aec_value(camera_sensor, cameraConfig.aec_value); // 0 to 1200 camera_sensor->set_quality(camera_sensor, cameraConfig.quality); - camera_sensor->set_agc_gain(camera_sensor, cameraConfig.brightness); // controls the gain camera_sensor->set_gain_ctrl(camera_sensor, cameraConfig.auto_gain_on); // 0 = disable , 1 = enable @@ -179,23 +173,12 @@ void CameraHandler::loadChangeableConfig() { camera_sensor->set_hmirror(camera_sensor, cameraConfig.href); camera_sensor->set_vflip(camera_sensor, cameraConfig.vflip); - this->setCameraResolution(FRAMESIZE_240X240); //(framesize_t) cameraConfig.framesize -} - -int CameraHandler::setCameraResolution(framesize_t frameSize) { - log_d("[CAMERA] trying to set resolution of %d", frameSize); - if (camera_sensor->pixformat == PIXFORMAT_JPEG) { - try { - int result = camera_sensor->set_framesize(camera_sensor, frameSize); - return result; - } catch (...) { - log_d("[ERROR] Unsupported resolution %d", frameSize); - // they sent us a malformed or unsupported frameSize - rather than crash - - // tell them about it - return -1; - } - } - return -1; + // being set here because modification of brightness somehow disables this effect + // so, we first load the whole config, and then we tell the camera to go noir-style + camera_sensor->set_special_effect( + camera_sensor, + 2); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint + camera_sensor->set_framesize(camera_sensor, (framesize_t)cameraConfig.framesize); } //! either hardware(1) or software(0) diff --git a/ESP/lib/src/io/camera/cameraHandler.hpp b/ESP/lib/src/io/camera/cameraHandler.hpp index 9c1e9216..f62ae3a4 100644 --- a/ESP/lib/src/io/camera/cameraHandler.hpp +++ b/ESP/lib/src/io/camera/cameraHandler.hpp @@ -14,7 +14,6 @@ class CameraHandler : public IObserver { public: CameraHandler(ProjectConfig& configManager); - int setCameraResolution(framesize_t frameSize); void update(ConfigState_e event) override; std::string getName() override; void resetCamera(bool type = 0);