From 6e29483d7fc07b701dc59806f591b39f9e7ce18c Mon Sep 17 00:00:00 2001 From: Alan <60433566+alanesq@users.noreply.github.com> Date: Wed, 5 Jan 2022 08:15:21 +0000 Subject: [PATCH] Update esp32cam-demo.ino --- esp32cam-demo.ino | 174 ++++++++++++++++++++-------------------------- 1 file changed, 77 insertions(+), 97 deletions(-) diff --git a/esp32cam-demo.ino b/esp32cam-demo.ino index a6265fe..5806a8a 100644 --- a/esp32cam-demo.ino +++ b/esp32cam-demo.ino @@ -65,7 +65,6 @@ bool cameraImageSettings(); String localTime(); void flashLED(int reps); - void showError(int errorNo); byte storeImage(); void handleRoot(); void handlePhoto(); @@ -73,12 +72,12 @@ void handleNotFound(); void readRGBImage(); bool getNTPtime(int sec); - void handleJPG(); + bool handleJPG(); void handleStream(); int requestWebPage(String*, String*, int); void handleTest(); void brightLed(byte ledBrightness); - //void MessageRGB(WiFiClient &client, String theText); + //void sendText(WiFiClient &client, String theText); // --------------------------------------------------------------- @@ -101,9 +100,9 @@ // --------------------------------------------------------------- const char* stitle = "ESP32Cam-demo"; // title of this sketch - const char* sversion = "04Jan22"; // Sketch version + const char* sversion = "05Jan22"; // Sketch version - bool sendRGBfile = 0; // if set '/rgb' will send the rgb data as a file rather than display some on a HTML page + bool sendRGBfile = 0; // if set '/rgb' will send the rgb data as a file rather than display a HTML page const bool serialDebug = 1; // show debug info. on serial port (1=enabled, disable if using pins 1 and 3 as gpio) @@ -271,8 +270,7 @@ void setup() { if (serialDebug) Serial.println("OK"); } else { - if (serialDebug) Serial.println("Error!"); - showError(2); // critical error so stop and flash led + if (serialDebug) Serial.println("failed"); } // Spiffs - for storing images without an sd card @@ -355,6 +353,7 @@ void setup() { // startup complete if (serialDebug) Serial.println("\nStarted..."); + flashLED(2); // flash the onboard indicator led brightLed(64); // change bright LED delay(200); brightLed(0); // change bright LED @@ -572,16 +571,6 @@ void flashLED(int reps) { } -// critical error - stop sketch and continually flash error code on indicator led -void showError(int errorNo) { - if (serialDebug) Serial.println("Critical Error: " + String(errorNo) ); - while(1) { // repeat forever - flashLED(errorNo); - delay(4000); - } -} - - // ****************************************************************************************************************** @@ -601,8 +590,7 @@ byte storeImage() { if (flashRequired) brightLed(currentBrightness); // change LED brightness back to previous state if (!fb) { if (serialDebug) Serial.println("Error: Camera capture failed"); - flashLED(3); // stop and display error code on LED - // return 0 + return 0; } // save image to Spiffs @@ -613,8 +601,7 @@ byte storeImage() { if (!file) { if (serialDebug) Serial.println("Failed to create file in Spiffs"); return 0; - } - else { + } else { if (file.write(fb->buf, fb->len)) { if (serialDebug) { Serial.print("The picture has been saved as " + spiffsFilename); @@ -645,16 +632,14 @@ byte storeImage() { File file = fs.open(SDfilename, FILE_WRITE); // create file on sd card if (!file) { if (serialDebug) Serial.println("Error: Failed to create file on sd-card: " + SDfilename); - flashLED(4); // stop and display error code on LED - // return 0 + return 0; } else { if (file.write(fb->buf, fb->len)) { // File created ok so save image to it if (serialDebug) Serial.println("Image saved to sd card"); imageCounter ++; // increment image counter } else { if (serialDebug) Serial.println("Error: failed to save image to sd card"); - flashLED(4); // stop and display error code on LED - // return 0; + return 0; } file.close(); // close image file on sd card } @@ -915,7 +900,7 @@ bool handleImg() { if (serialDebug) Serial.println("Error: image file not found"); WiFiClient client = server.client(); // open link with client client.write(" \n"); - client.write("

Error: Image not foundError: Image not found

\n"); delay(3); client.stop(); } @@ -979,7 +964,7 @@ void handleNotFound() { // send line of text to both serial port and web page -void MessageRGB(WiFiClient &client, String theText) { +void sendText(WiFiClient &client, String theText) { if (!sendRGBfile) client.print(theText + "
\n"); if (serialDebug || theText.indexOf("error") > 0) Serial.println(theText); // if text contains "error" } @@ -999,9 +984,9 @@ void MessageRGB(WiFiClient &client, String theText) { // I learned how to read the RGB data from: https://github.com/Makerfabs/Project_Touch-Screen-Camera/blob/master/Camera_v2/Camera_v2.ino void readRGBImage() { - - uint32_t tTimer; // used for timing operations - WiFiClient client = server.client(); // open link with client + // used for timing operations + WiFiClient client = server.client(); + uint32_t tTimer; // used to time tasks // open link with client // log page request including clients IP address if (serialDebug) { @@ -1009,10 +994,10 @@ void readRGBImage() { Serial.printf("RGB requested from: %d.%d.%d.%d \n", cip[0], cip[1], cip[2], cip[3]); } - // html header - if (!sendRGBfile) client.write(" photo \n"); // basic html header + // basic html header + if (!sendRGBfile) client.write(" Show RGB data \n"); // basic html header - MessageRGB(client,"LIVE IMAGE AS RGB DATA"); // 'MessageRGB' sends the String to both serial port and web page + sendText(client,"LIVE IMAGE AS RGB DATA"); // 'sendText' sends the String to both serial port and web page // ****** the main code for converting an image to RGB data ***** @@ -1020,41 +1005,41 @@ void readRGBImage() { camera_fb_t * fb = NULL; tTimer = millis(); // store time that image capture started fb = esp_camera_fb_get(); - if (!fb) MessageRGB(client,"error: failed to capture image"); - MessageRGB(client, "-Image capture took " + String(millis() - tTimer) + " milliseconds"); // report time it took to capture an image - if (!fb) MessageRGB(client," -error capturing image from camera- "); - else { - MessageRGB(client,"-Image resolution=" + String(fb->width) + "x" + String(fb->height)); - //MessageRGB(client,"-Image size=" + String(pic->len)); + if (!fb) { + sendText(client,"error: failed to capture image"); + } else { + sendText(client, "-JPG image capture took " + String(millis() - tTimer) + " milliseconds"); // report time it took to capture an image + sendText(client,"-Image resolution=" + String(fb->width) + "x" + String(fb->height)); + sendText(client,"-Image size=" + String(fb->len) + " bytes"); } // allocate memory to store the rgb data (in psram, 3 bytes per pixel) - if (!psramFound()) MessageRGB(client," -error no psram found- "); - MessageRGB(client,"Free psram before rgb data stored = " + String(heap_caps_get_free_size(MALLOC_CAP_SPIRAM))); + if (!psramFound()) sendText(client," -error no psram found- "); + sendText(client,"Free psram before rgb data allocated = " + String(heap_caps_get_free_size(MALLOC_CAP_SPIRAM) / 1024) + "K"); void *ptrVal = NULL; // create a pointer for memory location to store the data uint32_t ARRAY_LENGTH = fb->width * fb->height * 3; // calculate memory required to store the RGB data (i.e. number of pixels in the jpg image x 3) - if (heap_caps_get_free_size( MALLOC_CAP_SPIRAM) < ARRAY_LENGTH) MessageRGB(client," -error: not enough free psram to store the rgb data- "); + if (heap_caps_get_free_size( MALLOC_CAP_SPIRAM) < ARRAY_LENGTH) sendText(client," -error: not enough free psram to store the rgb data- "); ptrVal = heap_caps_malloc(ARRAY_LENGTH, MALLOC_CAP_SPIRAM); // allocate memory space for the rgb data uint8_t *rgb = (uint8_t *)ptrVal; // create the 'rgb' array pointer to the allocated memory space - MessageRGB(client,"Free psram after rgb data stored = " + String(heap_caps_get_free_size(MALLOC_CAP_SPIRAM))); + sendText(client,"Free psram after rgb data allocated = " + String(heap_caps_get_free_size(MALLOC_CAP_SPIRAM) / 1024) + "K"); // convert the captured jpg image (fb) to rgb data (store in 'rgb' array) tTimer = millis(); // store time that image conversion process started bool jpeg_converted = fmt2rgb888(fb->buf, fb->len, PIXFORMAT_JPEG, rgb); - if (!jpeg_converted) MessageRGB(client," -error converting image to RGB- "); - MessageRGB(client, "Conversion from jpg to RGB took " + String(millis() - tTimer) + " milliseconds");// report how long the conversion took + if (!jpeg_converted) sendText(client," -error: failed to convert image to RGB- "); + sendText(client, "Conversion from jpg to RGB took " + String(millis() - tTimer) + " milliseconds");// report how long the conversion took - if (sendRGBfile) client.write(rgb, ARRAY_LENGTH); // send the rgb data as a file + if (sendRGBfile) client.write(rgb, ARRAY_LENGTH); // send the raw rgb data - // ****** examples of reading the resulting RGB data ***** + // ****** examples of using the resulting RGB data ***** // display some of the resulting data uint32_t resultsToShow = 60; // how much data to display - MessageRGB(client,"R , G , B"); + sendText(client,"
R , G , B"); for (uint32_t i = 0; i < resultsToShow-2; i+=3) { - MessageRGB(client,String(rgb[i+2]) + "," + String(rgb[i+1]) + "," + String(rgb[i+0])); // Red , Green , Blue + sendText(client,String(rgb[i+2]) + "," + String(rgb[i+1]) + "," + String(rgb[i+0])); // Red , Green , Blue // // calculate the x and y coordinate of the current pixel // uint16_t x = (i / 3) % fb->width; // uint16_t y = floor( (i / 3) / fb->width); @@ -1072,9 +1057,9 @@ void readRGBImage() { aRed = aRed / (fb->width * fb->height); // divide total by number of pixels to give the average value aGreen = aGreen / (fb->width * fb->height); aBlue = aBlue / (fb->width * fb->height); - MessageRGB(client,"Average Blue = " + String(aBlue)); - MessageRGB(client,"Average Green = " + String(aGreen)); - MessageRGB(client,"Average Red = " + String(aRed)); + sendText(client,"Average Blue = " + String(aBlue)); + sendText(client,"Average Green = " + String(aGreen)); + sendText(client,"Average Red = " + String(aRed)); // ******************************************************* @@ -1128,48 +1113,49 @@ bool getNTPtime(int sec) { // ---------------------------------------------------------------- -// -capture image and send as jpg i.e. http://x.x.x.x/jpg +// -capture jpg image and send i.e. http://x.x.x.x/jpg // ---------------------------------------------------------------- -void handleJPG() { +bool handleJPG() { - WiFiClient client = server.client(); // open link with client - char buf[32]; - camera_fb_t * fb = NULL; + WiFiClient client = server.client(); // open link with client + char buf[32]; + camera_fb_t * fb = NULL; // pointer for image frame buffer - // log page request including clients IP address - if (serialDebug) { - IPAddress cip = client.remoteIP(); - Serial.printf("jpg requested from: %d.%d.%d.%d \n", cip[0], cip[1], cip[2], cip[3]); - } + // log page request including clients IP address + if (serialDebug) { + IPAddress cip = client.remoteIP(); + Serial.printf("jpg requested from: %d.%d.%d.%d \n", cip[0], cip[1], cip[2], cip[3]); + } - // build and send html + // capture the jpg image from camera + fb = esp_camera_fb_get(); + if (!fb) { + if (serialDebug) Serial.println("Error: failed to capture image"); + return 0; + } + + // html to send a jpg const char HEADER[] = "HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\n"; const char CTNTTYPE[] = "Content-Type: image/jpeg\r\nContent-Length: "; - const int hdrLen = strlen(HEADER); // length of the stored text, used when sending to web page + const int hdrLen = strlen(HEADER); const int cntLen = strlen(CTNTTYPE); client.write(HEADER, hdrLen); client.write(CTNTTYPE, cntLen); + sprintf( buf, "%d\r\n\r\n", fb->len); // put text size in to 'buf' char array and send + client.write(buf, strlen(buf)); - // capture and send image - fb = esp_camera_fb_get(); - if (!fb) { - if (serialDebug) Serial.println("Error: failed to capture image"); - return; - } + // send the captured jpg data + client.write((char *)fb->buf, fb->len); - // put text in to 'buf' char array and send - sprintf( buf, "%d\r\n\r\n", fb->len); - client.write(buf, strlen(buf)); + // close client connection + delay(3); + client.stop(); - // send the jpg data - client.write((char *)fb->buf, fb->len); + // return image frame so memory can be released + esp_camera_fb_return(fb); - // close client connection - delay(3); - client.stop(); - - esp_camera_fb_return(fb); // return image so memory can be released + return 1; } // handleJPG @@ -1182,7 +1168,9 @@ void handleJPG() { void handleStream(){ - WiFiClient client = server.client(); // open link with client + WiFiClient client = server.client(); // open link with client + char buf[32]; + camera_fb_t * fb = NULL; // log page request including clients IP address if (serialDebug) { @@ -1190,7 +1178,7 @@ void handleStream(){ Serial.printf("Video stream requested from: %d.%d.%d.%d \n", cip[0], cip[1], cip[2], cip[3]); } - // HTML used in the web page + // html const char HEADER[] = "HTTP/1.1 200 OK\r\n" \ "Access-Control-Allow-Origin: *\r\n" \ "Content-Type: multipart/x-mixed-replace; boundary=123456789000000000000987654321\r\n"; @@ -1199,29 +1187,21 @@ void handleStream(){ const int hdrLen = strlen(HEADER); // length of the stored text, used when sending to web page const int bdrLen = strlen(BOUNDARY); const int cntLen = strlen(CTNTTYPE); + client.write(HEADER, hdrLen); + client.write(BOUNDARY, bdrLen); - // temp stores - char buf[32]; - int s; - camera_fb_t * fb = NULL; - - // send html header - client.write(HEADER, hdrLen); - client.write(BOUNDARY, bdrLen); - - // send live images until client disconnects + // send live jpg images until client disconnects while (true) { if (!client.connected()) break; - fb = esp_camera_fb_get(); // capture live image + fb = esp_camera_fb_get(); // capture live image as jpg if (!fb) { - if (serialDebug) Serial.println("Error: failed to capture image"); + if (serialDebug) Serial.println("Error: failed to capture jpg image"); } - s = fb->len; // store size of image (i.e. buffer length) client.write(CTNTTYPE, cntLen); // send content type html (i.e. jpg image) - sprintf( buf, "%d\r\n\r\n", s ); // format the image's size as html and put in to 'buf' + sprintf( buf, "%d\r\n\r\n", fb->len); // format the image's size as html and put in to 'buf' client.write(buf, strlen(buf)); // send result (image size) - client.write((char *)fb->buf, s); // send the image data + client.write((char *)fb->buf, fb->len); // send the image data client.write(BOUNDARY, bdrLen); // send html boundary see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type esp_camera_fb_return(fb); // return image so memory can be released }