From 68ca8e59cdce4d0d6d90ec40f48c69b5f0de6613 Mon Sep 17 00:00:00 2001 From: Toby Vincent Date: Sun, 7 Jan 2024 18:42:09 -0600 Subject: Enable OTA --- esp32cam_partitions.csv | 6 ++++ platformio.ini | 4 ++- src/main.cpp | 85 ++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 79 insertions(+), 16 deletions(-) create mode 100644 esp32cam_partitions.csv diff --git a/esp32cam_partitions.csv b/esp32cam_partitions.csv new file mode 100644 index 0000000..a179a89 --- /dev/null +++ b/esp32cam_partitions.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, ota_0, 0x10000, 0x180000, +app1, app, ota_1, 0x190000,0x180000, +spiffs, data, spiffs, 0x310000,0xF0000, diff --git a/platformio.ini b/platformio.ini index 23e577c..46a70cc 100644 --- a/platformio.ini +++ b/platformio.ini @@ -11,8 +11,10 @@ [env:esp32cam] platform = espressif32 board = esp32cam +board_build.partitions = esp32cam_partitions.csv framework = arduino extra_scripts = pre:extra_script.py +upload_protocol = espota +upload_port = 10.42.0.189 monitor_speed = 115200 -upload_speed = 921600 lib_deps = espressif/esp32-camera@^2.0.4 diff --git a/src/main.cpp b/src/main.cpp index e15bffa..7555b1f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,7 @@ #define APP_CPU 1 #define PRO_CPU 0 +#include #include #include #include @@ -29,6 +30,8 @@ #define HREF_GPIO_NUM 23 #define PCLK_GPIO_NUM 22 +#define LED_GPIO_NUM 4 + OV2640 cam; WebServer server(80); @@ -39,6 +42,7 @@ TaskHandle_t tMjpeg; // handles client connections to the webserver TaskHandle_t tCam; // handles getting picture frames from the camera and storing // them locally TaskHandle_t tStream; // actually streaming frames to all connected clients +TaskHandle_t tOTA; // frameSync semaphore is used to prevent streaming buffer as it is replaced // with the next frame @@ -113,7 +117,6 @@ void camCB(void *pvParameters) { xLastWakeTime = xTaskGetTickCount(); for (;;) { - // Grab a frame from the camera and query its size cam.run(); size_t s = cam.getSize(); @@ -222,6 +225,9 @@ void streamCB(void *pvParameters) { // Only bother to send anything if there is someone watching UBaseType_t activeClients = uxQueueMessagesWaiting(streamingClients); if (activeClients) { + // Enable LED while client connected + digitalWrite(LED_GPIO_NUM, HIGH); + // Adjust the period to the number of connected clients xFrequency /= activeClients; @@ -244,7 +250,7 @@ void streamCB(void *pvParameters) { xSemaphoreTake(frameSync, portMAX_DELAY); client->write(CTNTTYPE, cntLen); - sprintf(buf, "%d\r\n\r\n", camSize); + sprintf(buf, "%zu\r\n\r\n", camSize); client->write(buf, strlen(buf)); client->write((char *)camBuf, (size_t)camSize); client->write(BOUNDARY, bdrLen); @@ -262,6 +268,7 @@ void streamCB(void *pvParameters) { } else { // Since there are no connected clients, there is no reason to waste // battery running + digitalWrite(LED_GPIO_NUM, LOW); vTaskSuspend(NULL); } // Let other tasks run after serving every client @@ -281,9 +288,21 @@ void handleJPG(void) { if (!client.connected()) return; + + int prev_led_state = digitalRead(LED_GPIO_NUM); + if (prev_led_state == LOW) { + digitalWrite(LED_GPIO_NUM, HIGH); + // Delay capture to prevent partial illumination + delay(200); + } + cam.run(); client.write(JHEADER, jhdLen); client.write((char *)cam.getfb(), cam.getSize()); + + if (prev_led_state == LOW) { + digitalWrite(LED_GPIO_NUM, LOW); + } } // ==== Handle invalid URL requests ============================================ @@ -347,6 +366,13 @@ void mjpegCB(void *pvParameters) { } } +void ota_handle(void *optionalArgs) { + for (;;) { + ArduinoOTA.handle(); + delay(3500); + } +} + // ==== SETUP method // ================================================================== void setup() { @@ -355,6 +381,8 @@ void setup() { Serial.begin(115200); delay(1000); // wait for a second to let Serial connect + pinMode(LED_GPIO_NUM, OUTPUT); + // Configure the camera camera_config_t config; config.ledc_channel = LEDC_CHANNEL_0; @@ -371,26 +399,16 @@ void setup() { config.pin_pclk = PCLK_GPIO_NUM; config.pin_vsync = VSYNC_GPIO_NUM; config.pin_href = HREF_GPIO_NUM; - config.pin_sscb_sda = SIOD_GPIO_NUM; - config.pin_sscb_scl = SIOC_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 = 20000000; config.pixel_format = PIXFORMAT_JPEG; - - // Frame parameters: pick one - // config.frame_size = FRAMESIZE_UXGA; - // config.frame_size = FRAMESIZE_SVGA; - // config.frame_size = FRAMESIZE_QVGA; - config.frame_size = FRAMESIZE_VGA; + config.frame_size = FRAMESIZE_SVGA; config.jpeg_quality = 12; config.fb_count = 2; -#if defined(CAMERA_MODEL_ESP_EYE) - pinMode(13, INPUT_PULLUP); - pinMode(14, INPUT_PULLUP); -#endif - if (cam.init(config) != ESP_OK) { Serial.println("Error initializing the camera"); delay(10000); @@ -415,6 +433,43 @@ void setup() { Serial.print(ip); Serial.println("/mjpeg/1"); + ArduinoOTA + .onStart([]() { + String type; + if (ArduinoOTA.getCommand() == U_FLASH) + type = "sketch"; + else // U_SPIFFS + type = "filesystem"; + + // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS + // using SPIFFS.end() + Serial.println("Start updating " + type); + }) + .onEnd([]() { Serial.println("\nEnd"); }) + .onProgress([](unsigned int progress, unsigned int total) { + Serial.printf("Progress: %u%%\r", (progress / (total / 100))); + }) + .onError([](ota_error_t error) { + Serial.printf("Error[%u]: ", error); + if (error == OTA_AUTH_ERROR) + Serial.println("Auth Failed"); + else if (error == OTA_BEGIN_ERROR) + Serial.println("Begin Failed"); + else if (error == OTA_CONNECT_ERROR) + Serial.println("Connect Failed"); + else if (error == OTA_RECEIVE_ERROR) + Serial.println("Receive Failed"); + else if (error == OTA_END_ERROR) + Serial.println("End Failed"); + }); + + ArduinoOTA.begin(); + + // Start Android OTA RTOS task + xTaskCreatePinnedToCore(ota_handle, "TaskAutoConnect", 10000, NULL, 1, &tOTA, + 0); + // xTaskCreate(ota_handle, "ota", 8 * 1024, NULL, 1, NULL); + // Start mainstreaming RTOS task xTaskCreatePinnedToCore(mjpegCB, "mjpeg", 4 * 1024, NULL, 2, &tMjpeg, APP_CPU); -- cgit v1.2.3-70-g09d2