diff --git a/code/components/jomjol_flowcontroll/ClassFlowAlignment.cpp b/code/components/jomjol_flowcontroll/ClassFlowAlignment.cpp index ef7af016..f7ff40d2 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowAlignment.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowAlignment.cpp @@ -190,10 +190,10 @@ bool ClassFlowAlignment::doFlow(string time) if (!ImageTMP) { - ImageTMP = new CImageBasis("ImageTMP", ImageBasis); + ImageTMP = new CImageBasis("tmpImage", ImageBasis); // Make sure the name does not get change, it is relevant for the PSRAM allocation! if (!ImageTMP) { - LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate ImageTMP -> Exec this round aborted!"); + LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate tmpImage -> Exec this round aborted!"); LogFile.WriteHeapInfo("ClassFlowAlignment-doFlow"); return false; } diff --git a/code/components/jomjol_flowcontroll/ClassFlowCNNGeneral.cpp b/code/components/jomjol_flowcontroll/ClassFlowCNNGeneral.cpp index fb3800a1..821fc89a 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowCNNGeneral.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowCNNGeneral.cpp @@ -374,8 +374,11 @@ bool ClassFlowCNNGeneral::ReadParameter(FILE* pfile, string& aktparamgraph) } } - if (!getNetworkParameter()) + if (!getNetworkParameter()) { + LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "An error occured on setting up the Network -> Disabling it!"); + disabled = true; // An error occured, disable this CNN! return false; + } for (int _ana = 0; _ana < GENERAL.size(); ++_ana) diff --git a/code/components/jomjol_flowcontroll/ClassFlowControll.cpp b/code/components/jomjol_flowcontroll/ClassFlowControll.cpp index 9e3ebebd..4068e9c4 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowControll.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowControll.cpp @@ -373,7 +373,7 @@ bool ClassFlowControll::doFlow(string time) zw_time = getCurrentTimeString("%H:%M:%S"); aktstatus = TranslateAktstatus(FlowControll[i]->name()); aktstatusWithTime = aktstatus + " (" + zw_time + ")"; - //LogFile.WriteToFile(ESP_LOG_INFO, TAG, aktstatusWithTime); + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Status: " + aktstatusWithTime); #ifdef ENABLE_MQTT MQTTPublish(mqttServer_getMainTopic() + "/" + "status", aktstatus, qos, false); #endif //ENABLE_MQTT diff --git a/code/components/jomjol_flowcontroll/ClassFlowTakeImage.cpp b/code/components/jomjol_flowcontroll/ClassFlowTakeImage.cpp index 5e0b2d5a..bafd53f7 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowTakeImage.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowTakeImage.cpp @@ -8,6 +8,7 @@ #include "esp_wifi.h" #include "esp_log.h" #include "../../include/defines.h" +#include "psram.h" #include @@ -183,6 +184,8 @@ string ClassFlowTakeImage::getHTMLSingleStep(string host) bool ClassFlowTakeImage::doFlow(string zwtime) { + psram_init_shared_memory_for_take_image_step(); + string logPath = CreateLogFolder(zwtime); int flash_duration = (int) (waitbeforepicture * 1000); diff --git a/code/components/jomjol_helper/psram.cpp b/code/components/jomjol_helper/psram.cpp index 8cbb64a5..8c7dcabb 100644 --- a/code/components/jomjol_helper/psram.cpp +++ b/code/components/jomjol_helper/psram.cpp @@ -1,11 +1,128 @@ #include "ClassLogFile.h" -#include "esp_heap_caps.h" +#include "../../include/defines.h" +#include "psram.h" static const char* TAG = "PSRAM"; using namespace std; +void *shared_region = NULL; +uint32_t allocatedBytesForSTBI = 0; + + +/** Reserve a large block in the PSRAM which will be shared between the different steps. + * Each step uses it differently but only wiuthin itself. */ +bool reserve_psram_shared_region(void) { + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Allocating shared PSRAM region (" + + std::to_string(TENSOR_ARENA_SIZE + MAX_MODEL_SIZE) + " bytes)..."); + shared_region = malloc_psram_heap("Shared PSRAM region", TENSOR_ARENA_SIZE + MAX_MODEL_SIZE, + MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + + if (shared_region == NULL) { + LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to allocating shared PSRAM region!"); + return false; + } + else { + return true; + } +} + + + +/******************************************************************* + * Memory used in Take Image (STBI) + *******************************************************************/ +void psram_init_shared_memory_for_take_image_step(void) { + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Init shared memory for step 'Take Image' (STBI buffers)"); + allocatedBytesForSTBI = 0; +} + + +void *psram_reserve_shared_stbi_memory(size_t size) { + /* Only large buffers should be placed in the shared PSRAM + * If we also place all smaller STBI buffers here, we get artefacts for some reasons. */ + if (size >= 100000) { + if ((allocatedBytesForSTBI + size) > TENSOR_ARENA_SIZE + MAX_MODEL_SIZE) { // Check if it still fits in the shared region + LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Shared memory in PSRAM too small (STBI) to fit additional " + + std::to_string(size) + "bytes! Available: " + std::to_string(TENSOR_ARENA_SIZE + MAX_MODEL_SIZE - allocatedBytesForSTBI) + " bytes!"); + return NULL; + } + + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Allocating memory (" + std::to_string(size) + " bytes) for STBI (use shared memory in PSRAM)..."); + allocatedBytesForSTBI += size; + return (uint8_t *)shared_region + allocatedBytesForSTBI - size; + } + else { // Normal PSRAM + return malloc_psram_heap("STBI", size, MALLOC_CAP_SPIRAM); + } +} + + +void *psram_reallocate_shared_stbi_memory(void *ptr, size_t newsize) { + char buf[20]; + sprintf(buf, "%p", ptr); + LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "STBI requested realloc for " + std::string(buf) + " but this is currently unsupported!"); + return NULL; +} + + +void psram_free_shared_stbi_memory(void *p) { + if ((p >= shared_region) && (p <= ((uint8_t *)shared_region + allocatedBytesForSTBI))) { // was allocated inside the shared memory + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Part of shared memory used for STBI (PSRAM, part of shared memory) is free again"); + } + else { // Normal PSRAM + free_psram_heap("STBI", p); + } +} + + + +/******************************************************************* + * Memory used in Aligning Step + * During this step we only use the shared part of the PSRAM + * for the tmpImage. + *******************************************************************/ +void *psram_reserve_shared_tmp_image_memory(void) { + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Allocating tmpImage (" + std::to_string(IMAGE_SIZE) + " bytes, use shared memory in PSRAM)..."); + return shared_region; // Use 1th part of the shared memory for the tmpImage (only user) +} + + +void psram_free_shared_temp_image_memory(void) { + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Shared memory used for tmpImage (PSRAM, part of shared memory) is free again"); +} + + + +/******************************************************************* + * Memory used in Digitalization Steps + * During this step we only use the shared part of the PSRAM for the + * Tensor Arena and one of the Models. + * The shared memory is large enough for the largest model and the + * Tensor Arena. Therefore we do not need to monitor the usage. + *******************************************************************/ +void *psram_get_shared_tensor_arena_memory(void) { + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Allocating Tensor Arena (" + std::to_string(TENSOR_ARENA_SIZE) + " bytes, use shared memory in PSRAM)..."); + return shared_region; // Use 1th part of the shared memory for Tensor +} + + +void *psram_get_shared_model_memory(void) { + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Allocating Model memory (" + std::to_string(MAX_MODEL_SIZE) + " bytes, use shared memory in PSRAM)..."); + return (uint8_t *)shared_region + TENSOR_ARENA_SIZE; // Use 2nd part of the shared memory (after Tensor Arena) for the model +} + + +void psram_free_shared_tensor_arena_and_model_memory(void) { + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Shared memory used for Tensor Arena and model (PSRAM, part of shared memory) is free again"); +} + + + +/******************************************************************* + * General + *******************************************************************/ void *malloc_psram_heap(std::string name, size_t size, uint32_t caps) { void *ptr; @@ -21,12 +138,25 @@ void *malloc_psram_heap(std::string name, size_t size, uint32_t caps) { } +void *realloc_psram_heap(std::string name, void *ptr, size_t size, uint32_t caps) { + ptr = heap_caps_realloc(ptr, size, caps); + if (ptr != NULL) { + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Reallocated " + to_string(size) + " bytes in PSRAM for '" + name + "'"); + } + else { + LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to reallocate " + to_string(size) + " bytes in PSRAM for '" + name + "'!"); + } + + return ptr; +} + + void *calloc_psram_heap(std::string name, size_t n, size_t size, uint32_t caps) { void *ptr; ptr = heap_caps_calloc(n, size, caps); if (ptr != NULL) { - LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Allocated " + to_string(size) + " bytes in PSRAM for '" + name + "'"); + LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Allocated " + to_string(size) + " bytes in PSRAM for '" + name + "'"); } else { LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to allocate " + to_string(size) + " bytes in PSRAM for '" + name + "'!"); @@ -39,4 +169,4 @@ void *calloc_psram_heap(std::string name, size_t n, size_t size, uint32_t caps) void free_psram_heap(std::string name, void *ptr) { LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Freeing memory in PSRAM used for '" + name + "'..."); heap_caps_free(ptr); -} \ No newline at end of file +} diff --git a/code/components/jomjol_helper/psram.h b/code/components/jomjol_helper/psram.h index fafd0c73..4c85bf26 100644 --- a/code/components/jomjol_helper/psram.h +++ b/code/components/jomjol_helper/psram.h @@ -1,7 +1,34 @@ +#pragma once +#ifndef PSRAM_h +#define PSRAM_h #include "esp_heap_caps.h" + +bool reserve_psram_shared_region(void); + + +/* Memory used in Take Image Step */ +void psram_init_shared_memory_for_take_image_step(void); +void *psram_reserve_shared_stbi_memory(size_t size); +void *psram_reallocate_shared_stbi_memory(void *ptr, size_t newsize); +void psram_free_shared_stbi_memory(void *p); + + +/* Memory used in Aligning Step */ +void *psram_reserve_shared_tmp_image_memory(void); +void psram_free_shared_temp_image_memory(void); + +/* Memory used in Digitalization Steps */ +void *psram_get_shared_tensor_arena_memory(void); +void *psram_get_shared_model_memory(void); +void psram_free_shared_tensor_arena_and_model_memory(void); + +/* General */ void *malloc_psram_heap(std::string name, size_t size, uint32_t caps); +void *realloc_psram_heap(std::string name, void *ptr, size_t size, uint32_t caps); void *calloc_psram_heap(std::string name, size_t n, size_t size, uint32_t caps); -void free_psram_heap(std::string name, void *ptr); \ No newline at end of file +void free_psram_heap(std::string name, void *ptr); + +#endif // PSRAM_h diff --git a/code/components/jomjol_image_proc/CImageBasis.cpp b/code/components/jomjol_image_proc/CImageBasis.cpp index ad6fee9d..a61ca7cd 100644 --- a/code/components/jomjol_image_proc/CImageBasis.cpp +++ b/code/components/jomjol_image_proc/CImageBasis.cpp @@ -477,7 +477,13 @@ CImageBasis::CImageBasis(string _name, CImageBasis *_copyfrom) memsize = width * height * channels; - rgb_image = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->CImageBasis (" + name + ")", memsize, MALLOC_CAP_SPIRAM); + + if (name == "tmpImage") { + rgb_image = (unsigned char*)psram_reserve_shared_tmp_image_memory(); + } + else { + rgb_image = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->CImageBasis (" + name + ")", memsize, MALLOC_CAP_SPIRAM); + } if (rgb_image == NULL) { @@ -618,9 +624,20 @@ CImageBasis::~CImageBasis() { RGBImageLock(); + if (!externalImage) { - //stbi_image_free(rgb_image); - free_psram_heap(std::string(TAG) + "->CImageBasis (" + name + ", " + to_string(memsize) + ")", rgb_image); + if (name == "tmpImage") { // This image should be placed in the shared part of PSRAM + psram_free_shared_temp_image_memory(); + } + else { // All other images are much smaller and can go into the normal PSRAM region + //stbi_image_free(rgb_image); + if (memsize == 0) { + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Not freeing (" + name + " as there was never PSRAM allocated for it)"); + } + else { + free_psram_heap(std::string(TAG) + "->CImageBasis (" + name + ", " + to_string(memsize) + ")", rgb_image); + } + } } RGBImageRelease(); diff --git a/code/components/jomjol_image_proc/make_stb.cpp b/code/components/jomjol_image_proc/make_stb.cpp index 1e24634b..59875fcb 100644 --- a/code/components/jomjol_image_proc/make_stb.cpp +++ b/code/components/jomjol_image_proc/make_stb.cpp @@ -1,8 +1,23 @@ #include #include +#include "psram.h" #include "../../include/defines.h" + +#define USE_SHARED_PSRAM_FOR_STBI + +#ifdef USE_SHARED_PSRAM_FOR_STBI +#define STBI_MALLOC(sz) psram_reserve_shared_stbi_memory(sz) +#define STBI_REALLOC(p,newsz) psram_reallocate_shared_stbi_memory(p, newsz) +#define STBI_FREE(p) psram_free_shared_stbi_memory(p) +#else // Use normal PSRAM +#define STBI_MALLOC(sz) malloc_psram_heap("STBI", sz, MALLOC_CAP_SPIRAM) +#define STBI_REALLOC(p,newsz) realloc_psram_heap("STBI", p, newsz, MALLOC_CAP_SPIRAM) +#define STBI_FREE(p) free_psram_heap("STBI", p) +#endif + + #define STB_IMAGE_IMPLEMENTATION #include "../stb/stb_image.h" diff --git a/code/components/jomjol_tfliteclass/CTfLiteClass.cpp b/code/components/jomjol_tfliteclass/CTfLiteClass.cpp index 6a2d4711..1f8d1daf 100644 --- a/code/components/jomjol_tfliteclass/CTfLiteClass.cpp +++ b/code/components/jomjol_tfliteclass/CTfLiteClass.cpp @@ -243,15 +243,22 @@ bool CTfLiteClass::ReadFileToModel(std::string _fn) if (size == -1) { - ESP_LOGE(TAG, "CTfLiteClass::ReadFileToModel: Model file doesn't exist: %s", _fn.c_str()); + LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Model file doesn't exist: " + _fn + "!"); return false; } + else if(size > MAX_MODEL_SIZE) { + LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Unable to load model '" + _fn + "'! It does not fit in the reserved shared memory in PSRAM!"); + return false; + } + + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Loading Model " + _fn + " /size: " + std::to_string(size) + " bytes..."); + #ifdef DEBUG_DETAIL_ON LogFile.WriteHeapInfo("CTLiteClass::Alloc modelfile start"); #endif - modelfile = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->modelfile", size, MALLOC_CAP_SPIRAM); + modelfile = (unsigned char*)psram_get_shared_model_memory(); if(modelfile != NULL) { @@ -304,9 +311,9 @@ CTfLiteClass::CTfLiteClass() this->modelfile = NULL; this->interpreter = nullptr; this->input = nullptr; - this->output = nullptr; - this->kTensorArenaSize = 800 * 1024; /// according to testfile: 108000 - so far 600;; 2021-09-11: 200 * 1024 - this->tensor_arena = (uint8_t*)malloc_psram_heap(std::string(TAG) + "->tensor_arena", kTensorArenaSize, MALLOC_CAP_SPIRAM); + this->output = nullptr; + this->kTensorArenaSize = TENSOR_ARENA_SIZE; + this->tensor_arena = (uint8_t*)psram_get_shared_tensor_arena_memory(); } @@ -315,8 +322,7 @@ CTfLiteClass::~CTfLiteClass() delete this->interpreter; delete this->error_reporter; - free_psram_heap(std::string(TAG) + "->modelfile", modelfile); - free_psram_heap(std::string(TAG) + "->tensor_arena", this->tensor_arena); + psram_free_shared_tensor_arena_and_model_memory(); } diff --git a/code/include/defines.h b/code/include/defines.h index f6df7a44..a289da66 100644 --- a/code/include/defines.h +++ b/code/include/defines.h @@ -208,6 +208,12 @@ //#define DEBUG_DETAIL_ON +///////////////////////////////////////////// +//// PSRAM Allocations //// +///////////////////////////////////////////// +#define MAX_MODEL_SIZE (unsigned int)(1.3 * 1024 * 1024) // Space for the currently largest model (1.1 MB) + some spare +#define TENSOR_ARENA_SIZE 800 * 1024 // Space for the Tensor Arena, (819200 Bytes) +#define IMAGE_SIZE 640 * 480 * 3 // Space for a extracted image (921600 Bytes) ///////////////////////////////////////////// //// Conditionnal definitions //// ///////////////////////////////////////////// diff --git a/code/main/main.cpp b/code/main/main.cpp index 8b77d446..b0b487ff 100644 --- a/code/main/main.cpp +++ b/code/main/main.cpp @@ -11,9 +11,13 @@ //#include "sdkconfig.h" #include "esp_psram.h" #include "esp_pm.h" + +#include "psram.h" + #include "esp_chip_info.h" + // SD-Card //////////////////// //#include "nvs_flash.h" #include "esp_vfs_fat.h" @@ -190,15 +194,6 @@ extern "C" void app_main(void) // ******************************************** ESP_LOGI(TAG, "\n\n\n\n================ Start app_main ================="); - // Init camera - // ******************************************** - PowerResetCamera(); - esp_err_t camStatus = Camera.InitCam(); - Camera.LightOnOff(false); - - xDelay = 2000 / portTICK_PERIOD_MS; - ESP_LOGD(TAG, "After camera initialization: sleep for: %ldms", (long) xDelay * CONFIG_FREERTOS_HZ/portTICK_PERIOD_MS); - vTaskDelay( xDelay ); // Init SD card // ******************************************** @@ -220,6 +215,105 @@ extern "C" void app_main(void) LogFile.WriteToFile(ESP_LOG_INFO, TAG, "==================== Start ======================"); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "================================================="); + + // Init external PSRAM + // ******************************************** + esp_err_t PSRAMStatus = esp_psram_init(); + if (PSRAMStatus != ESP_OK) { // ESP_FAIL -> Failed to init PSRAM + LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "PSRAM init failed (" + std::to_string(PSRAMStatus) + ")! PSRAM not found or defective"); + setSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD); + StatusLED(PSRAM_INIT, 1, true); + } + else { // ESP_OK -> PSRAM init OK --> continue to check PSRAM size + size_t psram_size = esp_psram_get_size(); // size_t psram_size = esp_psram_get_size(); // comming in IDF 5.0 + LogFile.WriteToFile(ESP_LOG_INFO, TAG, "PSRAM size: " + std::to_string(psram_size) + " byte (" + std::to_string(psram_size/1024/1024) + + "MB / " + std::to_string(psram_size/1024/1024*8) + "MBit)"); + + // Check PSRAM size + // ******************************************** + if (psram_size < (4*1024*1024)) { // PSRAM is below 4 MBytes (32Mbit) + LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "PSRAM size >= 4MB (32Mbit) is mandatory to run this application"); + setSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD); + StatusLED(PSRAM_INIT, 2, true); + } + else { // PSRAM size OK --> continue to check heap size + size_t _hsize = getESPHeapSize(); + LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Total heap: " + std::to_string(_hsize) + " byte"); + + // Check heap memory + // ******************************************** + if (_hsize < 4000000) { // Check available Heap memory for a bit less than 4 MB (a test on a good device showed 4187558 bytes to be available) + LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Total heap >= 4000000 byte is mandatory to run this application"); + setSystemStatusFlag(SYSTEM_STATUS_HEAP_TOO_SMALL); + StatusLED(PSRAM_INIT, 3, true); + } + else { // HEAP size OK --> continue to reserve shared memory block and check camera init + /* Allocate static PSRAM memory regions */ + if (! reserve_psram_shared_region()) { + setSystemStatusFlag(SYSTEM_STATUS_HEAP_TOO_SMALL); + StatusLED(PSRAM_INIT, 3, true); + } + else { // OK + // Init camera + // ******************************************** + PowerResetCamera(); + esp_err_t camStatus = Camera.InitCam(); + Camera.LightOnOff(false); + + xDelay = 2000 / portTICK_PERIOD_MS; + ESP_LOGD(TAG, "After camera initialization: sleep for: %ldms", (long) xDelay * CONFIG_FREERTOS_HZ/portTICK_PERIOD_MS); + vTaskDelay( xDelay ); + + + // Check camera init + // ******************************************** + if (camStatus != ESP_OK) { // Camera init failed, retry to init + char camStatusHex[33]; + sprintf(camStatusHex,"0x%02x", camStatus); + LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Camera init failed (" + std::string(camStatusHex) + "), retrying..."); + + PowerResetCamera(); + camStatus = Camera.InitCam(); + Camera.LightOnOff(false); + + xDelay = 2000 / portTICK_PERIOD_MS; + ESP_LOGD(TAG, "After camera initialization: sleep for: %ldms", (long) xDelay * CONFIG_FREERTOS_HZ/portTICK_PERIOD_MS); + vTaskDelay( xDelay ); + + if (camStatus != ESP_OK) { // Camera init failed again + sprintf(camStatusHex,"0x%02x", camStatus); + LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera init failed (" + std::string(camStatusHex) + + ")! Check camera module and/or proper electrical connection"); + setSystemStatusFlag(SYSTEM_STATUS_CAM_BAD); + StatusLED(CAM_INIT, 1, true); + } + } + else { // ESP_OK -> Camera init OK --> continue to perform camera framebuffer check + // Camera framebuffer check + // ******************************************** + if (!Camera.testCamera()) { + LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera framebuffer check failed"); + // Easiest would be to simply restart here and try again, + // how ever there seem to be systems where it fails at startup but still work correctly later. + // Therefore we treat it still as successed! */ + setSystemStatusFlag(SYSTEM_STATUS_CAM_FB_BAD); + StatusLED(CAM_INIT, 2, false); + } + Camera.LightOnOff(false); // make sure flashlight is off before start of flow + + // 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)); + } + } + } + } + } + + // SD card: basic R/W check // ******************************************** int iSDCardStatus = SDCardCheckRW(); @@ -374,84 +468,7 @@ extern "C" void app_main(void) #endif #endif - // Init external PSRAM - // ******************************************** - esp_err_t PSRAMStatus = esp_psram_init(); - if (PSRAMStatus == ESP_FAIL) { // ESP_FAIL -> Failed to init PSRAM - LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "PSRAM init failed (" + std::to_string(PSRAMStatus) + ")! PSRAM not found or defective"); - setSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD); - StatusLED(PSRAM_INIT, 1, true); - } - else { // ESP_OK -> PSRAM init OK --> continue to check PSRAM size - size_t psram_size = esp_psram_get_size(); // size_t psram_size = esp_psram_get_size(); // comming in IDF 5.0 - LogFile.WriteToFile(ESP_LOG_INFO, TAG, "PSRAM size: " + std::to_string(psram_size) + " byte (" + std::to_string(psram_size/1024/1024) + - "MB / " + std::to_string(psram_size/1024/1024*8) + "MBit)"); - // Check PSRAM size - // ******************************************** - if (psram_size < (4*1024*1024)) { // PSRAM is below 4 MBytes (32Mbit) - LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "PSRAM size >= 4MB (32Mbit) is mandatory to run this application"); - setSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD); - StatusLED(PSRAM_INIT, 2, true); - } - else { // PSRAM size OK --> continue to check heap size - size_t _hsize = getESPHeapSize(); - LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Total heap: " + std::to_string(_hsize) + " byte"); - - // Check heap memory - // ******************************************** - if (_hsize < 4000000) { // Check available Heap memory for a bit less than 4 MB (a test on a good device showed 4187558 bytes to be available) - LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Total heap >= 4000000 byte is mandatory to run this application"); - setSystemStatusFlag(SYSTEM_STATUS_HEAP_TOO_SMALL); - StatusLED(PSRAM_INIT, 3, true); - } - else { // HEAP size OK --> continue to check camera init - // Check camera init - // ******************************************** - if (camStatus != ESP_OK) { // Camera init failed, retry to init - char camStatusHex[33]; - sprintf(camStatusHex,"0x%02x", camStatus); - LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Camera init failed (" + std::string(camStatusHex) + "), retrying..."); - - PowerResetCamera(); - camStatus = Camera.InitCam(); - Camera.LightOnOff(false); - - xDelay = 2000 / portTICK_PERIOD_MS; - ESP_LOGD(TAG, "After camera initialization: sleep for: %ldms", (long) xDelay * CONFIG_FREERTOS_HZ/portTICK_PERIOD_MS); - vTaskDelay( xDelay ); - - if (camStatus != ESP_OK) { // Camera init failed again - sprintf(camStatusHex,"0x%02x", camStatus); - LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera init failed (" + std::string(camStatusHex) + - ")! Check camera module and/or proper electrical connection"); - setSystemStatusFlag(SYSTEM_STATUS_CAM_BAD); - StatusLED(CAM_INIT, 1, true); - } - } - else { // ESP_OK -> Camera init OK --> continue to perform camera framebuffer check - // Camera framebuffer check - // ******************************************** - if (!Camera.testCamera()) { - LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera framebuffer check failed"); - // Easiest would be to simply restart here and try again, - // how ever there seem to be systems where it fails at startup but still work correctly later. - // Therefore we treat it still as successed! */ - setSystemStatusFlag(SYSTEM_STATUS_CAM_FB_BAD); - StatusLED(CAM_INIT, 2, false); - } - Camera.LightOnOff(false); // make sure flashlight is off before start of flow - - // 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)); - } - } - } - } // Print Device info // ******************************************** diff --git a/code/sdkconfig.defaults b/code/sdkconfig.defaults index 1c8bec49..d7e142f3 100644 --- a/code/sdkconfig.defaults +++ b/code/sdkconfig.defaults @@ -101,8 +101,9 @@ CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384 CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=40960 CONFIG_SPIRAM_CACHE_WORKAROUND=y CONFIG_SPIRAM_IGNORE_NOTFOUND=y -#CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y => Leads to memory fragmentation, see https://github.com/jomjol/AI-on-the-edge-device/issues/2200 -#CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y => Leads to memory fragmentation, see https://github.com/jomjol/AI-on-the-edge-device/issues/2200 + +CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y +CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 @@ -124,7 +125,7 @@ CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED=y CONFIG_MQTT_USE_CORE_0=y CONFIG_MQTT_USE_CUSTOM_CONFIG=y #CONFIG_MQTT_OUTBOX_EXPIRED_TIMEOUT_MS=5000 -#CONFIG_MQTT_CUSTOM_OUTBOX=y # -> Use custom outbox in components/jomjol_mqtt/mqtt_outbox.h/cpp. If USE_PSRAM is enabled in there, it will save 10 kBytes of internal RAM. How ever it also leads to memory fragmentation, see https://github.com/jomjol/AI-on-the-edge-device/issues/2200 +CONFIG_MQTT_CUSTOM_OUTBOX=y CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=n