diff --git a/PlatformIO/esp32-cam-rtos-pio/include/definitions.h b/PlatformIO/esp32-cam-rtos-pio/include/definitions.h index a3cfe81..4daff85 100644 --- a/PlatformIO/esp32-cam-rtos-pio/include/definitions.h +++ b/PlatformIO/esp32-cam-rtos-pio/include/definitions.h @@ -1,5 +1,9 @@ #pragma once // ESP32 has two cores: APPlication core and PROcess core (the one that runs ESP32 SDK stack) -#define APP_CPU 1 -#define PRO_CPU 0 +#define APP_CPU 1 +#define PRO_CPU 0 + +#define KILOBYTE 1024 + +#define SERIAL_RATE 115200 diff --git a/PlatformIO/esp32-cam-rtos-pio/include/references.h b/PlatformIO/esp32-cam-rtos-pio/include/references.h index 658e484..2842cd1 100644 --- a/PlatformIO/esp32-cam-rtos-pio/include/references.h +++ b/PlatformIO/esp32-cam-rtos-pio/include/references.h @@ -2,6 +2,18 @@ #include #include #include +#include "logging.h" + +#include "esp_camera.h" +#include "ov2640.h" +#include +#include +#include +#include + +#include +#include +#include extern SemaphoreHandle_t frameSync; extern WebServer server; @@ -10,4 +22,4 @@ extern TaskHandle_t tCam; // handles getting picture frames from the camera extern TaskHandle_t tStream; extern uint8_t noActiveClients; // number of active clients -void handleNotFound(); \ No newline at end of file +extern const char* STREAMING_URL; diff --git a/PlatformIO/esp32-cam-rtos-pio/include/streaming.h b/PlatformIO/esp32-cam-rtos-pio/include/streaming.h index 507448b..0a0c708 100644 --- a/PlatformIO/esp32-cam-rtos-pio/include/streaming.h +++ b/PlatformIO/esp32-cam-rtos-pio/include/streaming.h @@ -2,8 +2,6 @@ #include "definitions.h" #include "references.h" -#include "esp_camera.h" - typedef struct { uint32_t frame; WiFiClient *client; @@ -23,6 +21,7 @@ typedef struct { void camCB(void* pvParameters); void handleJPGSstream(void); +void handleNotFound(void); void streamCB(void * pvParameters); void mjpegCB(void * pvParameters); diff --git a/PlatformIO/esp32-cam-rtos-pio/platformio.ini b/PlatformIO/esp32-cam-rtos-pio/platformio.ini index 209ae43..4651554 100644 --- a/PlatformIO/esp32-cam-rtos-pio/platformio.ini +++ b/PlatformIO/esp32-cam-rtos-pio/platformio.ini @@ -22,9 +22,9 @@ build_flags = -D ARDUINO_ARCH_ESP32 ; pick one of the three - -D CAMERA_MULTICLIENT_QUEUE - ; -D CAMERA_MULTICLIENT_TASK - ; -D CAMERA_ALL_FRAMES + -D CAMERA_MULTICLIENT_QUEUE ; current frames served by a single task + ; -D CAMERA_MULTICLIENT_TASK ; current frames served by dedicated tasks + ; -D CAMERA_ALL_FRAMES ; all frames served by dedicated tasks ; Includes for the ESP-camera components -I components/esp32-camera/sensors -I components/esp32-camera/sensors/private_include @@ -74,15 +74,16 @@ build_flags = ${env.build_flags} - -D CAMERA_MODEL_AI_THINKER - -D FRAME_SIZE=FRAMESIZE_VGA - -D FPS=10 - -D WSINTERVAL=100 - -D MAX_CLIENTS=10 - -D JPEG_QUALITY=16 ; 0-63 lower means higher quality - -D LOG_LEVEL=0 - -D DISABLE_LOGGING - -D WM_NODEBUG + -D CAMERA_MODEL_AI_THINKER ; camera model + -D FRAME_SIZE=FRAMESIZE_VGA ; frame size + -D XCLK_FREQ=20000000 ; frame acquisition rate clock + -D FPS=10 ; desired FPS, not to exceed (may be lower) + -D WSINTERVAL=100 ; webserver processing rate + -D MAX_CLIENTS=10 ; max number of streaming clients + -D JPEG_QUALITY=16 ; JPEG picture quality - 0-63 lower means higher quality + -D LOG_LEVEL=0 ; LOG level for ArduinoLog + -D DISABLE_LOGGING ; Disable logging completely + -D WM_NODEBUG ; Disable logging completely for WiFi Manager as well [env:ai-thinker-cam-debug] @@ -106,14 +107,15 @@ build_flags = ${env.build_flags} - -D CAMERA_MODEL_AI_THINKER - -D FRAME_SIZE=FRAMESIZE_VGA - -D FPS=10 - -D WSINTERVAL=100 - -D MAX_CLIENTS=10 - -D JPEG_QUALITY=16 ; 0-63 lower means higher quality - -D LOG_LEVEL=6 - -D BENCHMARK + -D CAMERA_MODEL_AI_THINKER ; camera model + -D FRAME_SIZE=FRAMESIZE_VGA ; frame size + -D XCLK_FREQ=20000000 ; frame acquisition rate clock + -D FPS=10 ; desired FPS, not to exceed (may be lower) + -D WSINTERVAL=100 ; webserver processing rate + -D MAX_CLIENTS=10 ; max number of streaming clients + -D JPEG_QUALITY=16 ; JPEG picture quality - 0-63 lower means higher quality + -D LOG_LEVEL=6 ; LOG level for ArduinoLog + -D BENCHMARK ; Print streaming benchmarking information [env:esp-eye] @@ -137,16 +139,17 @@ build_flags = ${env.build_flags} - -D CAMERA_MODEL_ESP_EYE - ; -D FLIP_VERTICALLY - -D FRAME_SIZE=FRAMESIZE_VGA - -D FPS=10 - -D WSINTERVAL=100 - -D MAX_CLIENTS=10 - -D JPEG_QUALITY=24 ; 0-63 lower means higher quality - -D LOG_LEVEL=0 - -D DISABLE_LOGGING - -D WM_NODEBUG + -D CAMERA_MODEL_ESP_EYE ; camera model + ; -D FLIP_VERTICALLY ; flip picture vertically after capture + -D FRAME_SIZE=FRAMESIZE_VGA ; frame size + -D XCLK_FREQ=20000000 ; frame acquisition rate clock + -D FPS=10 ; desired FPS, not to exceed (may be lower) + -D WSINTERVAL=100 ; webserver processing rate + -D MAX_CLIENTS=10 ; max number of streaming clients + -D JPEG_QUALITY=24 ; JPEG picture quality - 0-63 lower means higher quality + -D LOG_LEVEL=0 ; LOG level for ArduinoLog + -D DISABLE_LOGGING ; Disable logging completely + -D WM_NODEBUG ; Disable logging completely for WiFi Manager as well [env:esp-eye-debug] @@ -170,16 +173,17 @@ build_flags = ${env.build_flags} - -D CAMERA_MODEL_ESP_EYE - -D FLIP_VERTICALLY - -D FRAME_SIZE=FRAMESIZE_SVGA - -D FPS=10 - -D WSINTERVAL=100 - -D MAX_CLIENTS=10 - -D JPEG_QUALITY=32 ; 0-63 lower means higher quality - -D LOG_LEVEL=6 - -D WM_DEBUG_LEVEL=WM_DEBUG_VERBOSE - -D BENCHMARK + -D CAMERA_MODEL_ESP_EYE ; camera model + -D FLIP_VERTICALLY ; flip picture vertically after capture + -D FRAME_SIZE=FRAMESIZE_SVGA ; frame size + -D XCLK_FREQ=20000000 ; frame acquisition rate clock + -D FPS=10 ; desired FPS, not to exceed (may be lower) + -D WSINTERVAL=100 ; webserver processing rate + -D MAX_CLIENTS=10 ; max number of streaming clients + -D JPEG_QUALITY=32 ; JPEG picture quality - 0-63 lower means higher qualityr means higher quality + -D LOG_LEVEL=6 ; LOG level for ArduinoLog + -D WM_DEBUG_LEVEL=WM_DEBUG_VERBOSE ; LOG level for WiFi Manager + -D BENCHMARK ; Print streaming benchmarking information ; EXAMPLE of the additional board configuration @@ -207,12 +211,14 @@ build_flags = ${env.build_flags} - -D CAMERA_MODEL_WROVER_KIT - ; -D FLIP_VERTICALLY - -D FRAME_SIZE=FRAMESIZE_HVGA - -D FPS=5 - -D WSINTERVAL=100 - -D MAX_CLIENTS=10 - -D JPEG_QUALITY=24 ; 0-63 lower means higher quality - -D LOG_LEVEL=0 - -D DISABLE_LOGGING \ No newline at end of file + -D CAMERA_MODEL_WROVER_KIT ; camera model + ; -D FLIP_VERTICALLY ; flip picture vertically after capture + -D FRAME_SIZE=FRAMESIZE_HVGA ; frame size + -D XCLK_FREQ=20000000 ; frame acquisition rate clock + -D FPS=10 ; desired FPS, not to exceed (may be lower) + -D WSINTERVAL=100 ; webserver processing rate + -D MAX_CLIENTS=10 ; max number of streaming clients + -D JPEG_QUALITY=24 ; JPEG picture quality - 0-63 lower means higher quality + -D LOG_LEVEL=0 ; LOG level for ArduinoLog + -D DISABLE_LOGGING ; Disable logging completely + -D WM_NODEBUG ; Disable logging completely for WiFi Manager as well diff --git a/PlatformIO/esp32-cam-rtos-pio/src/main.cpp b/PlatformIO/esp32-cam-rtos-pio/src/main.cpp index 77c0647..5624aa4 100644 --- a/PlatformIO/esp32-cam-rtos-pio/src/main.cpp +++ b/PlatformIO/esp32-cam-rtos-pio/src/main.cpp @@ -13,18 +13,7 @@ #include "definitions.h" #include "references.h" -#include "logging.h" -#include "esp_camera.h" -#include "ov2640.h" -#include -#include -#include -#include - -#include -#include -#include #include "credentials.h" #include "streaming.h" @@ -51,40 +40,21 @@ uint8_t noActiveClients; // number of active clients // frameSync semaphore is used to prevent streaming buffer as it is replaced with the next frame SemaphoreHandle_t frameSync = NULL; -void handleNotFound(); - - -// ==== Handle invalid URL requests ============================================ -void handleNotFound() -{ - String message = "Server is running!\n\n"; - message += "URI: "; - message += server.uri(); - message += "\nMethod: "; - message += (server.method() == HTTP_GET) ? "GET" : "POST"; - message += "\nArguments: "; - message += server.args(); - message += "\n"; - server.send(200, "text / plain", message); -} - - // ==== SETUP method ================================================================== -void setup() -{ +void setup() { // Setup Serial connection: - Serial.begin(115200); + Serial.begin(SERIAL_RATE); delay(500); // wait for a bit to let Serial connect setupLogging(); Log.trace("\n\nMulti-client MJPEG Server\n"); - Log.trace("setup: total heap : %d\n", ESP.getHeapSize()); - Log.trace("setup: free heap : %d\n", ESP.getFreeHeap()); - Log.trace("setup: free psram : %d\n", ESP.getPsramSize()); - Log.trace("setup: free psram : %d\n", ESP.getFreePsram()); + Log.trace("setup: total heap : %d\n", ESP.getHeapSize()); + Log.trace("setup: free heap : %d\n", ESP.getFreeHeap()); + Log.trace("setup: total psram : %d\n", ESP.getPsramSize()); + Log.trace("setup: free psram : %d\n", ESP.getFreePsram()); static camera_config_t camera_config = { .pin_pwdn = PWDN_GPIO_NUM, @@ -104,8 +74,7 @@ void setup() .pin_href = HREF_GPIO_NUM, .pin_pclk = PCLK_GPIO_NUM, - // .xclk_freq_hz = 16000000, - .xclk_freq_hz = 20000000, + .xclk_freq_hz = XCLK_FREQ, .ledc_timer = LEDC_TIMER_0, .ledc_channel = LEDC_CHANNEL_0, .pixel_format = PIXFORMAT_JPEG, @@ -160,15 +129,15 @@ void setup() ip = WiFi.localIP(); Log.verbose(F("setup: WiFi connected\n")); // Log.verbose("Stream Link: http://%S/mjpeg/1\n\n", ip.toString()); - Serial.printf("Stream Link: http://%s/mjpeg/1\n\n", ip.toString().c_str()); + Serial.printf("Stream Link: http://%s%s\n\n", ip.toString().c_str(), STREAMING_URL); // Start main streaming RTOS task xTaskCreatePinnedToCore( mjpegCB, "mjpeg", - 3 * 1024, + 3 * KILOBYTE, NULL, - 2, + tskIDLE_PRIORITY + 2, &tMjpeg, PRO_CPU); diff --git a/PlatformIO/esp32-cam-rtos-pio/src/streaming.cpp b/PlatformIO/esp32-cam-rtos-pio/src/streaming.cpp index d33caaa..7cfcfc8 100644 --- a/PlatformIO/esp32-cam-rtos-pio/src/streaming.cpp +++ b/PlatformIO/esp32-cam-rtos-pio/src/streaming.cpp @@ -13,6 +13,8 @@ volatile uint32_t frameNumber; frameChunck_t* fstFrame = NULL; // first frame frameChunck_t* curFrame = NULL; // current frame being captured by the camera +const char* STREAMING_URL = "/mjpeg/1"; + void mjpegCB(void* pvParameters) { TickType_t xLastWakeTime; const TickType_t xFrequency = pdMS_TO_TICKS(WSINTERVAL); @@ -24,16 +26,16 @@ void mjpegCB(void* pvParameters) { // Creating RTOS task for grabbing frames from the camera xTaskCreatePinnedToCore( - camCB, // callback - "cam", // name - 4096, // stacj size - NULL, // parameters - 2, // priority - &tCam, // RTOS task handle - APP_CPU); // core + camCB, // callback + "cam", // name + 4 * KILOBYTE, // stack size + NULL, // parameters + tskIDLE_PRIORITY + 2, // priority + &tCam, // RTOS task handle + APP_CPU); // core // Registering webserver handling routines - server.on("/mjpeg/1", HTTP_GET, handleJPGSstream); + server.on(STREAMING_URL, HTTP_GET, handleJPGSstream); server.onNotFound(handleNotFound); // Starting webserver @@ -54,6 +56,13 @@ void mjpegCB(void* pvParameters) { // ==== Memory allocator that takes advantage of PSRAM if present ======================= +char* allocatePSRAM(size_t aSize) { + if ( psramFound() && ESP.getFreePsram() > aSize ) { + return (char*) ps_malloc(aSize); + } + return NULL; +} + char* allocateMemory(char* aPtr, size_t aSize, bool fail, bool psramOnly) { // Since current buffer is too smal, free it @@ -65,25 +74,19 @@ char* allocateMemory(char* aPtr, size_t aSize, bool fail, bool psramOnly) { char* ptr = NULL; if ( psramOnly ) { - if ( psramFound() && ESP.getFreePsram() > aSize ) { - ptr = (char*) ps_malloc(aSize); - } + ptr = allocatePSRAM(aSize); } else { // If memory requested is more than 2/3 of the currently free heap, try PSRAM immediately if ( aSize > ESP.getFreeHeap() * 2 / 3 ) { - if ( psramFound() && ESP.getFreePsram() > aSize ) { - ptr = (char*) ps_malloc(aSize); - } + ptr = allocatePSRAM(aSize); } else { // Enough free heap - let's try allocating fast RAM as a buffer ptr = (char*) malloc(aSize); // If allocation on the heap failed, let's give PSRAM one more chance: - if ( ptr == NULL && psramFound() && ESP.getFreePsram() > aSize) { - ptr = (char*) ps_malloc(aSize); - } + if ( ptr == NULL ) ptr = allocatePSRAM(aSize); } } // Finally, if the memory pointer is NULL, we were not able to allocate any memory, and that is a terminal condition. @@ -95,3 +98,17 @@ char* allocateMemory(char* aPtr, size_t aSize, bool fail, bool psramOnly) { return ptr; } + +// ==== Handle invalid URL requests ============================================ +void handleNotFound() { + String message = "Server is running!\n\n"; + message += "URI: "; + message += server.uri(); + message += "\nMethod: "; + message += (server.method() == HTTP_GET) ? "GET" : "POST"; + message += "\nArguments: "; + message += server.args(); + message += "\n"; + server.send(200, "text / plain", message); +} + diff --git a/PlatformIO/esp32-cam-rtos-pio/src/streaming_all_frames.cpp b/PlatformIO/esp32-cam-rtos-pio/src/streaming_all_frames.cpp index f499245..ee97b1f 100644 --- a/PlatformIO/esp32-cam-rtos-pio/src/streaming_all_frames.cpp +++ b/PlatformIO/esp32-cam-rtos-pio/src/streaming_all_frames.cpp @@ -140,9 +140,9 @@ void handleJPGSstream(void) int rc = xTaskCreatePinnedToCore( streamCB, "streamCB", - 3 * 1024, + 3 * KILOBYTE, (void*) info, - 2, + tskIDLE_PRIORITY + 2, &info->task, APP_CPU); if ( rc != pdPASS ) { diff --git a/PlatformIO/esp32-cam-rtos-pio/src/streaming_multiclient_queue.cpp b/PlatformIO/esp32-cam-rtos-pio/src/streaming_multiclient_queue.cpp index 9575518..179428f 100644 --- a/PlatformIO/esp32-cam-rtos-pio/src/streaming_multiclient_queue.cpp +++ b/PlatformIO/esp32-cam-rtos-pio/src/streaming_multiclient_queue.cpp @@ -29,10 +29,10 @@ void camCB(void* pvParameters) { // Creating task to push the stream to all connected clients xTaskCreatePinnedToCore( streamCB, - "strmCB", - 4096, + "streamCB", + 4 * KILOBYTE, NULL, //(void*) handler, - 2, + tskIDLE_PRIORITY + 2, &tStream, APP_CPU); // PRO_CPU); diff --git a/PlatformIO/esp32-cam-rtos-pio/src/streaming_multiclient_task.cpp b/PlatformIO/esp32-cam-rtos-pio/src/streaming_multiclient_task.cpp index b74a298..6020e55 100644 --- a/PlatformIO/esp32-cam-rtos-pio/src/streaming_multiclient_task.cpp +++ b/PlatformIO/esp32-cam-rtos-pio/src/streaming_multiclient_task.cpp @@ -133,10 +133,10 @@ void handleJPGSstream(void) // Creating task to push the stream to all connected clients int rc = xTaskCreatePinnedToCore( streamCB, - "strmCB", - 3 * 1024, + "streamCB", + 3 * KILOBYTE, (void*) info, - 2, + tskIDLE_PRIORITY + 2, &info->task, APP_CPU); if ( rc != pdPASS ) {