Skip to content

Commit

Permalink
Add a post process event handler to perform error/debug handling (#59)
Browse files Browse the repository at this point in the history
* Add more error handling to flow states + debuging options

* Debug logs: Split logs by date folders

* Allow more post process events + some renaming

* Set failed alingment to error + save failed alignment results

* Align file retention functions

* Reset process error at process start

* OTA update: Fully allow firmware.bin

* Adapt camera init + continue at any cam error to regular interface

* Continue to regular interface at any cam error

* Adapt cam deinit + update demo mode

* Modify doInit to prepare for reloading cam driver

* Add SPIRAM coverage info block

* Reload cam driver after error detected during processing
  • Loading branch information
Slider0007 authored Aug 20, 2023
1 parent 3505044 commit 932d538
Show file tree
Hide file tree
Showing 43 changed files with 916 additions and 471 deletions.
126 changes: 86 additions & 40 deletions code/components/jomjol_controlcamera/ClassControllCamera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,17 @@ CCamera::CCamera()
isFixedExposure = false;
flashduration = 5000;
led_intensity = 4095;
demoImage = NULL;
demoMode = false;
CameraInitSuccessful = false;

#ifdef USE_PWM_LEDFLASH
ledc_init();
#endif
}


void CCamera::PowerResetCamera(){
void CCamera::PowerResetCamera()
{

ESP_LOGD(TAG, "Resetting camera by power down line");
gpio_config_t conf;
Expand All @@ -160,40 +162,72 @@ void CCamera::PowerResetCamera(){

esp_err_t CCamera::InitCam()
{
ESP_LOGD(TAG, "Init Camera");
ActualQuality = camera_config.jpeg_quality;
ActualResolution = camera_config.frame_size;
//initialize the camera
esp_camera_deinit(); // De-init in case it was already initialized
if (CameraInitSuccessful)
DeinitCam(); // De-init in case it was already initialized

esp_err_t err = esp_camera_init(&camera_config);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Camera Init Failed");
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera init failed: " + intToHexString(err));

if (err == ESP_ERR_NOT_FOUND)
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera module not found, check camera module and electrical connection");
else if (err == ESP_ERR_NOT_SUPPORTED)
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera module or feature not supported");

return err;
}

ActualQuality = camera_config.jpeg_quality;
ActualResolution = camera_config.frame_size;

CameraInitSuccessful = true;
return ESP_OK;
}


esp_err_t CCamera::DeinitCam()
{
CameraInitSuccessful = false;
esp_camera_deinit(); // De-init in case it was already initialized (returns ESP_FAIL if deinit is already done)
PowerResetCamera();

return ESP_OK;
}


bool CCamera::testCamera(void)
{
bool success;
camera_fb_t *fb = esp_camera_fb_get();
if (fb) {
if (fb) {
success = true;
}
else {
success = false;
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera framebuffer check failed");
}
esp_camera_fb_return(fb);

return success;
}


void CCamera::printCamInfo(void)
{
// Print camera infos
// ********************************************
char caminfo[50];
sensor_t * s = esp_camera_sensor_get();
sprintf(caminfo, "PID: 0x%02x, VER: 0x%02x, MIDL: 0x%02x, MIDH: 0x%02x", s->id.PID, s->id.VER, s->id.MIDH, s->id.MIDL);
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Camera info: " + std::string(caminfo));
}


bool CCamera::SetBrightnessContrastSaturation(int _brightness, int _contrast, int _saturation)
{
if (!getCameraInitSuccessful())
return false;

_brightness = std::min(2, std::max(-2, _brightness));
_contrast = std::min(2, std::max(-2, _contrast));
_saturation = std::min(2, std::max(-2, _saturation));
Expand Down Expand Up @@ -254,6 +288,9 @@ bool CCamera::SetBrightnessContrastSaturation(int _brightness, int _contrast, in

void CCamera::SetQualitySize(int qual, framesize_t resol)
{
if (!getCameraInitSuccessful())
return;

qual = std::min(63, std::max(8, qual)); // Limit quality from 8..63 (values lower than 8 tent to be unstable)

sensor_t * s = esp_camera_sensor_get();
Expand Down Expand Up @@ -292,6 +329,9 @@ void CCamera::SetLEDIntensity(int _intensity)

bool CCamera::EnableAutoExposure(int _flashduration)
{
if (!getCameraInitSuccessful())
return false;

flashduration = _flashduration; // save last flashduration internally
ESP_LOGD(TAG, "EnableAutoExposure");

Expand Down Expand Up @@ -338,6 +378,9 @@ esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int _flashduration)
LogFile.WriteHeapInfo("CaptureToBasisImage - Start");
#endif

if (!getCameraInitSuccessful())
return ESP_FAIL;

flashduration = _flashduration; // save last flashduration internally

if (flashduration > 0) { // Switch on for defined time if a flashduration is set
Expand Down Expand Up @@ -392,6 +435,9 @@ esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int _flashduration)

esp_err_t CCamera::CaptureToFile(std::string nm, int _flashduration)
{
if (!getCameraInitSuccessful())
return ESP_FAIL;

std::string ftype;
flashduration = _flashduration; // save last flashduration internally

Expand Down Expand Up @@ -492,6 +538,9 @@ static size_t jpg_encode_stream(void * arg, size_t index, const void* data, size

esp_err_t CCamera::CaptureToHTTP(httpd_req_t *req, int _flashduration)
{
if (!getCameraInitSuccessful())
return ESP_FAIL;

esp_err_t res = ESP_OK;
size_t fb_len = 0;
int64_t fr_start = esp_timer_get_time();
Expand Down Expand Up @@ -519,11 +568,11 @@ esp_err_t CCamera::CaptureToHTTP(httpd_req_t *req, int _flashduration)
}

res = httpd_resp_set_type(req, "image/jpeg");
if(res == ESP_OK){
if(res == ESP_OK) {
res = httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=raw.jpg");
}

if(res == ESP_OK){
if(res == ESP_OK) {
if (demoMode) { // Use images stored on SD-Card instead of camera image
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Demo mode active");
/* Replace Framebuffer with image from SD-Card */
Expand All @@ -532,10 +581,11 @@ esp_err_t CCamera::CaptureToHTTP(httpd_req_t *req, int _flashduration)
res = httpd_resp_send(req, (const char *)fb->buf, fb->len);
}
else {
if(fb->format == PIXFORMAT_JPEG){
if(fb->format == PIXFORMAT_JPEG) {
fb_len = fb->len;
res = httpd_resp_send(req, (const char *)fb->buf, fb->len);
} else {
}
else {
jpg_chunking_t jchunk = {req, 0};
res = frame2jpg_cb(fb, 80, jpg_encode_stream, &jchunk)?ESP_OK:ESP_FAIL;
httpd_resp_send_chunk(req, NULL, 0);
Expand All @@ -554,6 +604,9 @@ esp_err_t CCamera::CaptureToHTTP(httpd_req_t *req, int _flashduration)

esp_err_t CCamera::CaptureToStream(httpd_req_t *req, bool FlashlightOn)
{
if (!getCameraInitSuccessful())
return ESP_FAIL;

esp_err_t res = ESP_OK;
size_t fb_len = 0;
int64_t fr_start;
Expand Down Expand Up @@ -583,14 +636,14 @@ esp_err_t CCamera::CaptureToStream(httpd_req_t *req, bool FlashlightOn)
}
fb_len = fb->len;

if (res == ESP_OK){
if (res == ESP_OK) {
size_t hlen = snprintf((char *)part_buf, sizeof(part_buf), _STREAM_PART, fb_len);
res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen);
}
if (res == ESP_OK){
if (res == ESP_OK) {
res = httpd_resp_send_chunk(req, (const char *)fb->buf, fb_len);
}
if (res == ESP_OK){
if (res == ESP_OK) {
res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));
}

Expand Down Expand Up @@ -743,12 +796,9 @@ bool CCamera::getCameraInitSuccessful()
}


std::vector<std::string> demoFiles;

void CCamera::EnableDemoMode()
{
demoFiles.clear();
free(demoImage);

char line[50];

Expand All @@ -759,12 +809,6 @@ void CCamera::EnableDemoMode()
return;
}

demoImage = (uint8_t*)malloc(DEMO_IMAGE_SIZE);
if (demoImage == NULL) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Unable to acquire required memory for demo image");
return;
}

while (fgets(line, sizeof(line), fd) != NULL) {
line[strlen(line) - 1] = '\0';
demoFiles.push_back(line);
Expand All @@ -787,13 +831,11 @@ void CCamera::DisableDemoMode()
{
demoMode = false;
demoFiles.clear();
free(demoImage);
}


bool CCamera::loadNextDemoImage(camera_fb_t *fb) {
char filename[50];
int readBytes;
long fileSize;

snprintf(filename, sizeof(filename), "/sdcard/demo/%s", demoFiles[getCountFlowRounds() % demoFiles.size()].c_str());
Expand All @@ -802,35 +844,39 @@ bool CCamera::loadNextDemoImage(camera_fb_t *fb) {

/* Inject saved image */

FILE * fp = fopen(filename, "rb");
if (!fp) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to read file: " + std::string(filename));
return false;
}

fileSize = getFileSize(filename);
if (fileSize > DEMO_IMAGE_SIZE) {
char buf[100];
snprintf(buf, sizeof(buf), "Demo Image (%d bytes) is larger than provided buffer (%d bytes)",
snprintf(buf, sizeof(buf), "Demo image (%d bytes) is larger than provided buffer (%d bytes)",
(int)fileSize, DEMO_IMAGE_SIZE);
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, std::string(buf));
return false;
}

readBytes = fread(demoImage, 1, DEMO_IMAGE_SIZE, fp);
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "read " + std::to_string(readBytes) + " bytes");
FILE * fp = fopen(filename, "rb");
if (!fp) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to read file: " + std::string(filename));
return false;
}

fb->len = fread(fb->buf, 1, fileSize, fp);
fclose(fp);

fb->buf = demoImage; // Update pointer
fb->len = readBytes;
// ToDo do we also need to set height, width, format and timestamp?
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "read " + std::to_string(fb->len) + " bytes");

return true;
}


/* Free only user allocated memory without deinit of cam driver */
void CCamera::FreeMemoryOnly()
{
demoFiles.clear();
}


CCamera::~CCamera()
{
DeinitCam();
demoFiles.clear();
free(demoImage);
}
30 changes: 17 additions & 13 deletions code/components/jomjol_controlcamera/ClassControllCamera.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#define CLASSCONTROLLCAMERA_H

#include <string>
#include <vector>
//#include "freertos/FreeRTOS.h"
//#include "freertos/task.h"

Expand All @@ -29,40 +30,43 @@ class CCamera {
int flashduration;
int led_intensity;

bool CameraInitSuccessful = false;
bool demoMode = false;
bool CameraInitSuccessful;
bool demoMode;
std::vector<std::string> demoFiles;

void LEDOnOff(bool status);
bool loadNextDemoImage(camera_fb_t *fb);
long GetFileSize(std::string filename);

public:
int image_height, image_width;

CCamera();
~CCamera();
void FreeMemoryOnly();
void PowerResetCamera();
esp_err_t InitCam();
esp_err_t DeinitCam();
bool testCamera(void);
void printCamInfo(void);

void LightOnOff(bool status);
void LEDOnOff(bool status);
esp_err_t CaptureToBasisImage(CImageBasis *_Image, int delay = 0);
esp_err_t CaptureToFile(std::string nm, int delay = 0);
esp_err_t CaptureToHTTP(httpd_req_t *req, int delay = 0);
esp_err_t CaptureToStream(httpd_req_t *req, bool FlashlightOn);

void ledc_init(void);
void SetQualitySize(int qual, framesize_t resol);
framesize_t TextToFramesize(const char * text);
bool SetBrightnessContrastSaturation(int _brightness, int _contrast, int _saturation);
void GetCameraParameter(httpd_req_t *req, int &qual, framesize_t &resol);
void SetLEDIntensity(int _intrel);
bool testCamera(void);

bool EnableAutoExposure(int flash_duration);
bool getCameraInitSuccessful();
void LightOnOff(bool status);

void EnableDemoMode(void);
void DisableDemoMode(void);
void ledc_init(void);


framesize_t TextToFramesize(const char * text);

esp_err_t CaptureToFile(std::string nm, int delay = 0);
esp_err_t CaptureToBasisImage(CImageBasis *_Image, int delay = 0);
};


Expand Down
2 changes: 1 addition & 1 deletion code/components/jomjol_fileserver_ota/server_ota.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ void doRebootOTA()

Camera.LightOnOff(false);
StatusLEDOff();
esp_camera_deinit();
Camera.DeinitCam();

vTaskDelay(5000 / portTICK_PERIOD_MS);
esp_restart(); // Reset type: CPU reset (Reset both CPUs)
Expand Down
Loading

0 comments on commit 932d538

Please sign in to comment.