diff --git a/esp32cam-demo.ino b/esp32cam-demo.ino index c4668d6..30210a0 100644 --- a/esp32cam-demo.ino +++ b/esp32cam-demo.ino @@ -1,45 +1,46 @@ - /******************************************************************************************************************* - * - * ESP32Cam development board demo sketch using Arduino IDE or PlatformIO - * Github: https://github.com/alanesq/ESP32Cam-demo - * - * Tested with ESP32 board manager version 1.0.6 - * - * Starting point sketch for projects using the esp32cam development board with the following features - * web server with live video streaming and RGB data from camera demonstrated. - * sd card support using 1-bit mode (data pins are usually 2,4,12&13 but using 1bit mode only uses pin 2) - * flash led is still available for use (pin 4) and does not flash when accessing sd card - * Stores image in Spiffs if no sd card present - * PWM control of the illumination/flash LED - * - * GPIO: - * You can use io pins 13 and 12 for input or output (but 12 must not be high at boot) - * pin 16 is used for psram but you may get away with using it as input for a button etc. - * You could also use pins 1 & 3 if you do not use Serial (disable serialDebug in the settings below) - * Pins 14, 2 & 15 should be ok to use if you are not using an SD Card - * More info: https://randomnerdtutorials.com/esp32-cam-ai-thinker-pinout/ - * - * You can use a MCP23017 io expander chip to give 16 gpio lines by enabling 'useMCP23017' in the setup section and connecting - * the i2c pins to 12 and 13 on the esp32cam module. Note: this requires the adafruit MCP23017 library to be installed. - * - * Created using the Arduino IDE with ESP32 module installed, no additional libraries required - * ESP32 support for Arduino IDE: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json - * - * Info on the esp32cam board: https://randomnerdtutorials.com/esp32-cam-video-streaming-face-recognition-arduino-ide/ - * - * To see a more advanced sketch along the same format as this one have a look at https://github.com/alanesq/CameraWifiMotion - * which includes email support, FTP, OTA updates and motion detection - * - * Sending image to TFT display see: https://www.survivingwithandroid.com/esp32-cam-tft-display-picture-st7735/ - * - * esp32cam-demo is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * - *******************************************************************************************************************/ +/******************************************************************************************************************* +* +* ESP32Cam development board demo sketch using Arduino IDE or PlatformIO +* Github: https://github.com/alanesq/ESP32Cam-demo +* +* Tested with ESP32 board manager version 1.0.6 +* +* Starting point sketch for projects using the esp32cam development board with the following features +* web server with live video streaming and RGB data from camera demonstrated. +* sd card support using 1-bit mode (data pins are usually 2,4,12&13 but using 1bit mode only uses pin 2) +* flash led is still available for use (pin 4) and does not flash when accessing sd card +* Stores image in Spiffs if no sd card present +* PWM control of the illumination/flash LED +* +* GPIO: +* You can use io pins 13 and 12 for input or output (but 12 must not be high at boot) +* pin 16 is used for psram but you may get away with using it as input for a button etc. +* You could also use pins 1 & 3 if you do not use Serial (disable serialDebug in the settings below) +* Pins 14, 2 & 15 should be ok to use if you are not using an SD Card +* More info: https://randomnerdtutorials.com/esp32-cam-ai-thinker-pinout/ +* +* You can use a MCP23017 io expander chip to give 16 gpio lines by enabling 'useMCP23017' in the setup section and connecting +* the i2c pins to 12 and 13 on the esp32cam module. Note: this requires the adafruit MCP23017 library to be installed. +* +* Created using the Arduino IDE with ESP32 module installed, no additional libraries required +* ESP32 support for Arduino IDE: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json +* +* Info on the esp32cam board: https://randomnerdtutorials.com/esp32-cam-video-streaming-face-recognition-arduino-ide/ +* https://github.com/espressif/esp32-camera +* +* To see a more advanced sketch along the same format as this one have a look at https://github.com/alanesq/CameraWifiMotion +* which includes email support, FTP, OTA updates and motion detection +* +* Sending image to TFT display see: https://www.survivingwithandroid.com/esp32-cam-tft-display-picture-st7735/ +* +* esp32cam-demo is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the +* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* +* +*******************************************************************************************************************/ - #if !defined ESP32 - #error This sketch is only for an ESP32Cam module +#if !defined ESP32 + #error This sketch is only for an ESP32Cam module #endif @@ -57,107 +58,113 @@ // --------------------------------------------------------------------------------------------------------- -#include // required by PlatformIO +// Required by PlatformIO + + #include + + // forward declarations + bool initialiseCamera(); + bool cameraImageSettings(); + String localTime(); + void flashLED(int reps); + void showError(int errorNo); + byte storeImage(); + void handleRoot(); + void handlePhoto(); + bool handleImg(); + void handleNotFound(); + void readRGBImage(); + bool getNTPtime(int sec); + void handleStream(); + int requestWebPage(String*, String*, int); + void handleTest(); + void brightLed(byte ledBrightness); + //void MessageRGB(WiFiClient &client, String theText); + + +// --------------------------------------------------------------- + + #include "esp_camera.h" // https://github.com/espressif/esp32-camera // #include "camera_pins.h" #include #include -#include // used by requestWebPage() +#include #include "driver/ledc.h" // used to configure pwm on illumination led -// spiffs used to store images without an sd card - #include - #include // gives file access on spiffs - - -// forward declarations (required by PlatformIO) - bool initialiseCamera(); - bool cameraImageSettings(); - String localTime(); - void flashLED(int reps); - void showError(int errorNo); - byte storeImage(); - void handleRoot(); - void handlePhoto(); - bool handleImg(); - void handleNotFound(); - void readRGBImage(); - bool getNTPtime(int sec); - void handleStream(); - int requestWebPage(String*, String*, int); - void handleTest(); - void brightLed(byte ledBrightness); - void MessageRGB(WiFiClient &client, String theText); +// spiffs used to store images if no sd card present + #include + #include // gives file access on spiffs // --------------------------------------------------------------- // -SETTINGS // --------------------------------------------------------------- - const char* stitle = "ESP32Cam-demo"; // title of this sketch - const char* sversion = "29dec21"; // Sketch version + const char* stitle = "ESP32Cam-demo"; // title of this sketch + const char* sversion = "29Dec21"; // 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 some on a HTML page - const bool serialDebug = 1; // show debug info. on serial port (1=enabled, disable if using pins 1 and 3 as gpio) + const bool serialDebug = 1; // show debug info. on serial port (1=enabled, disable if using pins 1 and 3 as gpio) - #define useMCP23017 0 // if MCP23017 IO expander chip is being used (on pins 12 and 13) + #define useMCP23017 0 // if MCP23017 IO expander chip is being used (on pins 12 and 13) - // Camera related - const bool flashRequired = 1; // If flash to be used when capturing image (1 = yes) - const framesize_t FRAME_SIZE_IMAGE = FRAMESIZE_VGA; // Image resolution: - // default = "const framesize_t FRAME_SIZE_IMAGE = FRAMESIZE_VGA" - // 160x120 (QQVGA), 128x160 (QQVGA2), 176x144 (QCIF), 240x176 (HQVGA), - // 320x240 (QVGA), 400x296 (CIF), 640x480 (VGA, default), 800x600 (SVGA), - // 1024x768 (XGA), 1280x1024 (SXGA), 1600x1200 (UXGA) - #define PIXFORMAT PIXFORMAT_JPEG; // image format, Options = YUV422, GRAYSCALE, RGB565, JPEG, RGB888 - int cameraImageExposure = 0; // Camera exposure (0 - 1200) If gain and exposure both set to zero then auto adjust is enabled - int cameraImageGain = 0; // Image gain (0 - 30) + // Camera related + const bool flashRequired = 1; // If flash to be used when capturing image (1 = yes) + const framesize_t FRAME_SIZE_IMAGE = FRAMESIZE_VGA; // Image resolution: + // default = "const framesize_t FRAME_SIZE_IMAGE = FRAMESIZE_VGA" + // 160x120 (QQVGA), 128x160 (QQVGA2), 176x144 (QCIF), 240x176 (HQVGA), + // 320x240 (QVGA), 400x296 (CIF), 640x480 (VGA, default), 800x600 (SVGA), + // 1024x768 (XGA), 1280x1024 (SXGA), 1600x1200 (UXGA) + #define PIXFORMAT PIXFORMAT_JPEG; // image format, Options = YUV422, GRAYSCALE, RGB565, JPEG, RGB888 + int cameraImageExposure = 0; // Camera exposure (0 - 1200) If gain and exposure both set to zero then auto adjust is enabled + int cameraImageGain = 0; // Image gain (0 - 30) - const int TimeBetweenStatus = 600; // speed of flashing system running ok status light (milliseconds) + const int TimeBetweenStatus = 600; // speed of flashing system running ok status light (milliseconds) - const int indicatorLED = 33; // onboard small LED pin (33) + const int indicatorLED = 33; // onboard small LED pin (33) - // Bright LED - const int brightLED = 4; // onboard Illumination/flash LED pin (4) - int brightLEDbrightness = 0; // initial brightness (0 - 255) - const int ledFreq = 5000; // PWM settings - const int ledChannel = 15; // needs to be 14 or 15 with esp32cam (timer3?) - const int ledRresolution = 8; + // Bright LED + const int brightLED = 4; // onboard Illumination/flash LED pin (4) + int brightLEDbrightness = 0; // initial brightness (0 - 255) + const int ledFreq = 5000; // PWM settings + const int ledChannel = 15; // needs to be 14 or 15 with esp32cam (timer3?) + const int ledRresolution = 8; - const int iopinA = 13; // general io pin 13 - const int iopinB = 12; // general io pin 12 (must not be high at boot) - const int iopinC = 16; // input only pin 16 (used by PSRam but you may get away with using it for a button) + const int iopinA = 13; // general io pin 13 + const int iopinB = 12; // general io pin 12 (must not be high at boot) + const int iopinC = 16; // input only pin 16 (used by PSRam but you may get away with using it for a button) - const int serialSpeed = 115200; // Serial data speed to use + const int serialSpeed = 115200; // Serial data speed to use - // NTP - Internet time - const char* ntpServer = "pool.ntp.org"; - const char* TZ_INFO = "GMT+0BST-1,M3.5.0/01:00:00,M10.5.0/02:00:00"; // enter your time zone (https://remotemonitoringsystems.ca/time-zone-abbreviations.php) - long unsigned lastNTPtime; - tm timeinfo; - time_t now; + // NTP - Internet time + const char* ntpServer = "pool.ntp.org"; + const char* TZ_INFO = "GMT+0BST-1,M3.5.0/01:00:00,M10.5.0/02:00:00"; // enter your time zone (https://remotemonitoringsystems.ca/time-zone-abbreviations.php) + long unsigned lastNTPtime; + tm timeinfo; + time_t now; // camera settings (for the standard - OV2640 - CAMERA_MODEL_AI_THINKER) // see: https://randomnerdtutorials.com/esp32-cam-camera-pin-gpios/ // set camera resolution etc. in 'initialiseCamera()' and 'cameraImageSettings()' - #define CAMERA_MODEL_AI_THINKER - #define PWDN_GPIO_NUM 32 // power to camera (on/off) - #define RESET_GPIO_NUM -1 // -1 = not used - #define XCLK_GPIO_NUM 0 - #define SIOD_GPIO_NUM 26 // i2c sda - #define SIOC_GPIO_NUM 27 // i2c scl - #define Y9_GPIO_NUM 35 - #define Y8_GPIO_NUM 34 - #define Y7_GPIO_NUM 39 - #define Y6_GPIO_NUM 36 - #define Y5_GPIO_NUM 21 - #define Y4_GPIO_NUM 19 - #define Y3_GPIO_NUM 18 - #define Y2_GPIO_NUM 5 - #define VSYNC_GPIO_NUM 25 // vsync_pin - #define HREF_GPIO_NUM 23 // href_pin - #define PCLK_GPIO_NUM 22 // pixel_clock_pin + #define CAMERA_MODEL_AI_THINKER + #define PWDN_GPIO_NUM 32 // power to camera (on/off) + #define RESET_GPIO_NUM -1 // -1 = not used + #define XCLK_GPIO_NUM 0 + #define SIOD_GPIO_NUM 26 // i2c sda + #define SIOC_GPIO_NUM 27 // i2c scl + #define Y9_GPIO_NUM 35 + #define Y8_GPIO_NUM 34 + #define Y7_GPIO_NUM 39 + #define Y6_GPIO_NUM 36 + #define Y5_GPIO_NUM 21 + #define Y4_GPIO_NUM 19 + #define Y3_GPIO_NUM 18 + #define Y2_GPIO_NUM 5 + #define VSYNC_GPIO_NUM 25 // vsync_pin + #define HREF_GPIO_NUM 23 // href_pin + #define PCLK_GPIO_NUM 22 // pixel_clock_pin @@ -167,30 +174,30 @@ WebServer server(80); // serve web pages on port 80 // Used to disable brownout detection - #include "soc/soc.h" - #include "soc/rtc_cntl_reg.h" + #include "soc/soc.h" + #include "soc/rtc_cntl_reg.h" // sd-card - #include "SD_MMC.h" // sd card - see https://randomnerdtutorials.com/esp32-cam-take-photo-save-microsd-card/ - #include - #include // gives file access - #define SD_CS 5 // sd chip select pin = 5 + #include "SD_MMC.h" // sd card - see https://randomnerdtutorials.com/esp32-cam-take-photo-save-microsd-card/ + #include + #include // gives file access + #define SD_CS 5 // sd chip select pin = 5 // MCP23017 IO expander on pins 12 and 13 (optional) - #if useMCP23017 == 1 - #include - #include "Adafruit_MCP23017.h" - Adafruit_MCP23017 mcp; - // Wire.setClock(1700000); // set frequency to 1.7mhz - #endif + #if useMCP23017 == 1 + #include + #include "Adafruit_MCP23017.h" + Adafruit_MCP23017 mcp; + // Wire.setClock(1700000); // set frequency to 1.7mhz + #endif // Define some global variables: - uint32_t lastStatus = millis(); // last time status light changed status (to flash all ok led) - uint32_t lastCamera = millis(); // timer for periodic image capture - bool sdcardPresent; // flag if an sd card is detected - int imageCounter; // image file name on sd card counter - uint32_t illuminationLEDstatus; // current brightness setting of the illumination led - String spiffsFilename = "/image.jpg"; // image name to use when storing in spiffs + uint32_t lastStatus = millis(); // last time status light changed status (to flash all ok led) + uint32_t lastCamera = millis(); // timer for periodic image capture + bool sdcardPresent; // flag if an sd card is detected + int imageCounter; // image file name on sd card counter + uint32_t illuminationLEDstatus; // current brightness setting of the illumination led + String spiffsFilename = "/image.jpg"; // image name to use when storing in spiffs @@ -203,164 +210,164 @@ WebServer server(80); // serve web pages on port 80 void setup() { - if (serialDebug) { - Serial.begin(serialSpeed); // Start serial communication - // Serial.setDebugOutput(true); + if (serialDebug) { + Serial.begin(serialSpeed); // Start serial communication + // Serial.setDebugOutput(true); - Serial.println("\n\n\n"); // line feeds - Serial.println("-----------------------------------"); - Serial.printf("Starting - %s - %s \n", stitle, sversion); - Serial.println("-----------------------------------"); - // Serial.print("Reset reason: " + ESP.getResetReason()); - } + Serial.println("\n\n\n"); // line feeds + Serial.println("-----------------------------------"); + Serial.printf("Starting - %s - %s \n", stitle, sversion); + Serial.println("-----------------------------------"); + // Serial.print("Reset reason: " + ESP.getResetReason()); + } - WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // Turn-off the 'brownout detector' + WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // Turn-off the 'brownout detector' - // small indicator led on rear of esp32cam board - pinMode(indicatorLED, OUTPUT); - digitalWrite(indicatorLED,HIGH); + // small indicator led on rear of esp32cam board + pinMode(indicatorLED, OUTPUT); + digitalWrite(indicatorLED,HIGH); - // Connect to wifi - digitalWrite(indicatorLED,LOW); // small indicator led on - if (serialDebug) { - Serial.print("\nConnecting to "); - Serial.print(SSID); - Serial.print("\n "); - } - WiFi.begin(SSID, PWD); - while (WiFi.status() != WL_CONNECTED) { - delay(500); - if (serialDebug) Serial.print("."); - } - if (serialDebug) { - Serial.print("\nWiFi connected, "); - Serial.print("IP address: "); - Serial.println(WiFi.localIP()); - } - server.begin(); // start web server - digitalWrite(indicatorLED,HIGH); // small indicator led off + // Connect to wifi + digitalWrite(indicatorLED,LOW); // small indicator led on + if (serialDebug) { + Serial.print("\nConnecting to "); + Serial.print(SSID); + Serial.print("\n "); + } + WiFi.begin(SSID, PWD); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + if (serialDebug) Serial.print("."); + } + if (serialDebug) { + Serial.print("\nWiFi connected, "); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); + } + server.begin(); // start web server + digitalWrite(indicatorLED,HIGH); // small indicator led off - // define the web pages (i.e. call these procedures when url is requested) - server.on("/", handleRoot); // root page - server.on("/stream", handleStream); // stream live video - server.on("/photo", handlePhoto); // save image to sd card - server.on("/img", handleImg); // show image from sd card - server.on("/rgb", readRGBImage); // demo converting image to RGB - server.on("/test", handleTest); // Testing procedure - server.onNotFound(handleNotFound); // invalid url requested + // define the web pages (i.e. call these procedures when url is requested) + server.on("/", handleRoot); // root page + server.on("/stream", handleStream); // stream live video + server.on("/photo", handlePhoto); // save image to sd card + server.on("/img", handleImg); // show image from sd card + server.on("/rgb", readRGBImage); // demo converting image to RGB + server.on("/test", handleTest); // Testing procedure + server.onNotFound(handleNotFound); // invalid url requested - // NTP - internet time - if (serialDebug) Serial.println("\nGetting real time (NTP)"); - configTime(0, 0, ntpServer); - setenv("TZ", TZ_INFO, 1); - if (getNTPtime(10)) { // wait up to 10 sec to sync - } else { - if (serialDebug) Serial.println("Time not set"); - } - lastNTPtime = time(&now); + // NTP - internet time + if (serialDebug) Serial.println("\nGetting real time (NTP)"); + configTime(0, 0, ntpServer); + setenv("TZ", TZ_INFO, 1); + if (getNTPtime(10)) { // wait up to 10 sec to sync + } else { + if (serialDebug) Serial.println("Time not set"); + } + lastNTPtime = time(&now); - // set up camera - if (serialDebug) Serial.print(("\nInitialising camera: ")); - if (initialiseCamera()) { - if (serialDebug) Serial.println("OK"); - } - else { - if (serialDebug) Serial.println("Error!"); - showError(2); // critical error so stop and flash led - } + // set up camera + if (serialDebug) Serial.print(("\nInitialising camera: ")); + if (initialiseCamera()) { + if (serialDebug) Serial.println("OK"); + } + else { + if (serialDebug) Serial.println("Error!"); + showError(2); // critical error so stop and flash led + } - // Spiffs - for storing images without an sd card - // see: https://circuits4you.com/2018/01/31/example-of-esp8266-flash-file-system-spiffs/ - if (!SPIFFS.begin(true)) { - if (serialDebug) Serial.println(("An Error has occurred while mounting SPIFFS - restarting")); - delay(5000); - ESP.restart(); // restart and try again - delay(5000); - } else { - // SPIFFS.format(); // wipe spiffs - if (serialDebug) { - Serial.print(("SPIFFS mounted successfully: ")); - Serial.printf("total bytes: %d , used: %d \n", SPIFFS.totalBytes(), SPIFFS.usedBytes()); - } - } + // Spiffs - for storing images without an sd card + // see: https://circuits4you.com/2018/01/31/example-of-esp8266-flash-file-system-spiffs/ + if (!SPIFFS.begin(true)) { + if (serialDebug) Serial.println(("An Error has occurred while mounting SPIFFS - restarting")); + delay(5000); + ESP.restart(); // restart and try again + delay(5000); + } else { + // SPIFFS.format(); // wipe spiffs + if (serialDebug) { + Serial.print(("SPIFFS mounted successfully: ")); + Serial.printf("total bytes: %d , used: %d \n", SPIFFS.totalBytes(), SPIFFS.usedBytes()); + } + } - // SD Card - if one is detected set 'sdcardPresent' High - if (!SD_MMC.begin("/sdcard", true)) { // if loading sd card fails - // note: ('/sdcard", true)' = 1bit mode - see: https://www.reddit.com/r/esp32/comments/d71es9/a_breakdown_of_my_experience_trying_to_talk_to_an/ - if (serialDebug) Serial.println("No SD Card detected"); - sdcardPresent = 0; // flag no sd card available - } else { - uint8_t cardType = SD_MMC.cardType(); - if (cardType == CARD_NONE) { // if invalid card found - if (serialDebug) Serial.println("SD Card type detect failed"); - sdcardPresent = 0; // flag no sd card available - } else { - // valid sd card detected - uint16_t SDfreeSpace = (uint64_t)(SD_MMC.totalBytes() - SD_MMC.usedBytes()) / (1024 * 1024); - if (serialDebug) Serial.printf("SD Card found, free space = %dMB \n", SDfreeSpace); - sdcardPresent = 1; // flag sd card available - } - } - fs::FS &fs = SD_MMC; // sd card file system + // SD Card - if one is detected set 'sdcardPresent' High + if (!SD_MMC.begin("/sdcard", true)) { // if loading sd card fails + // note: ('/sdcard", true)' = 1bit mode - see: https://www.reddit.com/r/esp32/comments/d71es9/a_breakdown_of_my_experience_trying_to_talk_to_an/ + if (serialDebug) Serial.println("No SD Card detected"); + sdcardPresent = 0; // flag no sd card available + } else { + uint8_t cardType = SD_MMC.cardType(); + if (cardType == CARD_NONE) { // if invalid card found + if (serialDebug) Serial.println("SD Card type detect failed"); + sdcardPresent = 0; // flag no sd card available + } else { + // valid sd card detected + uint16_t SDfreeSpace = (uint64_t)(SD_MMC.totalBytes() - SD_MMC.usedBytes()) / (1024 * 1024); + if (serialDebug) Serial.printf("SD Card found, free space = %dMB \n", SDfreeSpace); + sdcardPresent = 1; // flag sd card available + } + } + fs::FS &fs = SD_MMC; // sd card file system - // discover the number of image files already stored in '/img' folder of the sd card and set image file counter accordingly - imageCounter = 0; - if (sdcardPresent) { - int tq=fs.mkdir("/img"); // create the '/img' folder on sd card (in case it is not already there) - if (!tq) { - if (serialDebug) Serial.println("Unable to create IMG folder on sd card"); - } + // discover the number of image files already stored in '/img' folder of the sd card and set image file counter accordingly + imageCounter = 0; + if (sdcardPresent) { + int tq=fs.mkdir("/img"); // create the '/img' folder on sd card (in case it is not already there) + if (!tq) { + if (serialDebug) Serial.println("Unable to create IMG folder on sd card"); + } - // open the image folder and step through all files in it - File root = fs.open("/img"); - while (true) - { - File entry = root.openNextFile(); // open next file in the folder - if (!entry) break; // if no more files in the folder - imageCounter ++; // increment image counter - entry.close(); - } - root.close(); - if (serialDebug) Serial.printf("Image file count = %d \n",imageCounter); - } + // open the image folder and step through all files in it + File root = fs.open("/img"); + while (true) + { + File entry = root.openNextFile(); // open next file in the folder + if (!entry) break; // if no more files in the folder + imageCounter ++; // increment image counter + entry.close(); + } + root.close(); + if (serialDebug) Serial.printf("Image file count = %d \n",imageCounter); + } - // define i/o pins - pinMode(indicatorLED, OUTPUT); // defined again as sd card config can reset it - digitalWrite(indicatorLED,HIGH); // led off = High - pinMode(iopinA, OUTPUT); // pin 13 - free io pin, can be used for input or output - pinMode(iopinB, OUTPUT); // pin 12 - free io pin, can be used for input or output (must not be high at boot) - pinMode(iopinC, INPUT); // pin 16 - free input only pin + // define i/o pins + pinMode(indicatorLED, OUTPUT); // defined again as sd card config can reset it + digitalWrite(indicatorLED,HIGH); // led off = High + pinMode(iopinA, OUTPUT); // pin 13 - free io pin, can be used for input or output + pinMode(iopinB, OUTPUT); // pin 12 - free io pin, can be used for input or output (must not be high at boot) + pinMode(iopinC, INPUT); // pin 16 - free input only pin - // MCP23017 io expander (requires adafruit MCP23017 library) - #if useMCP23017 == 1 - Wire.begin(12,13); // use pins 12 and 13 for i2c - mcp.begin(&Wire); // use default address 0 - mcp.pinMode(0, OUTPUT); // Define GPA0 (physical pin 21) as output pin - mcp.pinMode(8, INPUT); // Define GPB0 (physical pin 1) as input pin - mcp.pullUp(8, HIGH); // turn on a 100K pullup internally - // change pin state with mcp.digitalWrite(0, HIGH); - // read pin state with mcp.digitalRead(8) - #endif + // MCP23017 io expander (requires adafruit MCP23017 library) + #if useMCP23017 == 1 + Wire.begin(12,13); // use pins 12 and 13 for i2c + mcp.begin(&Wire); // use default address 0 + mcp.pinMode(0, OUTPUT); // Define GPA0 (physical pin 21) as output pin + mcp.pinMode(8, INPUT); // Define GPB0 (physical pin 1) as input pin + mcp.pullUp(8, HIGH); // turn on a 100K pullup internally + // change pin state with mcp.digitalWrite(0, HIGH); + // read pin state with mcp.digitalRead(8) + #endif - // set up bright LED (flash) - ledcSetup(ledChannel, ledFreq, ledRresolution); - ledcAttachPin(brightLED, ledChannel); - brightLed(0); // change bright LED + // set up bright LED (flash) + ledcSetup(ledChannel, ledFreq, ledRresolution); + ledcAttachPin(brightLED, ledChannel); + brightLed(0); // change bright LED - // startup complete - if (serialDebug) Serial.println("\nSetup complete..."); - brightLed(64); // change bright LED - delay(200); - brightLed(0); // change bright LED + // startup complete + if (serialDebug) Serial.println("\nSetup complete..."); + brightLed(64); // change bright LED + delay(200); + brightLed(0); // change bright LED } // setup // change bright LED illumination level - void brightLed(byte ledBrightness){ - brightLEDbrightness = ledBrightness; // store setting - ledcWrite(ledChannel, ledBrightness); // change LED brightness (0 - 255) - } + void brightLed(byte ledBrightness){ + brightLEDbrightness = ledBrightness; // store setting + ledcWrite(ledChannel, ledBrightness); // change LED brightness (0 - 255) + } // ****************************************************************************************************************** @@ -373,14 +380,14 @@ void setup() { void loop() { - server.handleClient(); // handle any incoming web page requests + server.handleClient(); // handle any incoming web page requests - // <<< YOUR CODE HERE >>> + // <<< YOUR CODE HERE >>> @@ -393,11 +400,11 @@ void loop() { // storeImage(); // save an image to sd card // } - // flash status LED to show sketch is running ok - if ((unsigned long)(millis() - lastStatus) >= TimeBetweenStatus) { - lastStatus = millis(); // reset timer - digitalWrite(indicatorLED,!digitalRead(indicatorLED)); // flip indicator led status - } + // flash status LED to show sketch is running ok + if ((unsigned long)(millis() - lastStatus) >= TimeBetweenStatus) { + lastStatus = millis(); // reset timer + digitalWrite(indicatorLED,!digitalRead(indicatorLED)); // flip indicator led status + } } // loop @@ -413,54 +420,54 @@ void loop() { bool initialiseCamera() { - camera_config_t config; + camera_config_t config; - config.ledc_channel = LEDC_CHANNEL_0; - config.ledc_timer = LEDC_TIMER_0; - config.pin_d0 = Y2_GPIO_NUM; - config.pin_d1 = Y3_GPIO_NUM; - config.pin_d2 = Y4_GPIO_NUM; - config.pin_d3 = Y5_GPIO_NUM; - config.pin_d4 = Y6_GPIO_NUM; - config.pin_d5 = Y7_GPIO_NUM; - config.pin_d6 = Y8_GPIO_NUM; - config.pin_d7 = Y9_GPIO_NUM; - config.pin_xclk = XCLK_GPIO_NUM; - 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_pwdn = PWDN_GPIO_NUM; - config.pin_reset = RESET_GPIO_NUM; - config.xclk_freq_hz = 20000000; // XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental) - config.pixel_format = PIXFORMAT; // Options = YUV422, GRAYSCALE, RGB565, JPEG, RGB888 - config.frame_size = FRAME_SIZE_IMAGE; // Image sizes: 160x120 (QQVGA), 128x160 (QQVGA2), 176x144 (QCIF), 240x176 (HQVGA), 320x240 (QVGA), - // 400x296 (CIF), 640x480 (VGA, default), 800x600 (SVGA), 1024x768 (XGA), 1280x1024 (SXGA), - // 1600x1200 (UXGA) - config.jpeg_quality = 10; // 0-63 lower number means higher quality - config.fb_count = 1; // if more than one, i2s runs in continuous mode. Use only with JPEG + config.ledc_channel = LEDC_CHANNEL_0; + config.ledc_timer = LEDC_TIMER_0; + config.pin_d0 = Y2_GPIO_NUM; + config.pin_d1 = Y3_GPIO_NUM; + config.pin_d2 = Y4_GPIO_NUM; + config.pin_d3 = Y5_GPIO_NUM; + config.pin_d4 = Y6_GPIO_NUM; + config.pin_d5 = Y7_GPIO_NUM; + config.pin_d6 = Y8_GPIO_NUM; + config.pin_d7 = Y9_GPIO_NUM; + config.pin_xclk = XCLK_GPIO_NUM; + 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_pwdn = PWDN_GPIO_NUM; + config.pin_reset = RESET_GPIO_NUM; + config.xclk_freq_hz = 20000000; // XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental) + config.pixel_format = PIXFORMAT; // Options = YUV422, GRAYSCALE, RGB565, JPEG, RGB888 + config.frame_size = FRAME_SIZE_IMAGE; // Image sizes: 160x120 (QQVGA), 128x160 (QQVGA2), 176x144 (QCIF), 240x176 (HQVGA), 320x240 (QVGA), + // 400x296 (CIF), 640x480 (VGA, default), 800x600 (SVGA), 1024x768 (XGA), 1280x1024 (SXGA), + // 1600x1200 (UXGA) + config.jpeg_quality = 10; // 0-63 lower number means higher quality + config.fb_count = 1; // if more than one, i2s runs in continuous mode. Use only with JPEG - // check the esp32cam board has a psram chip installed (extra memory used for storing captured images) - // Note: if not using "AI thinker esp32 cam" in the Arduino IDE, SPIFFS must be enabled - if (!psramFound()) { - if (serialDebug) Serial.println("Warning: No PSRam found so defaulting to image size 'CIF'"); - config.frame_size = FRAMESIZE_CIF; - } + // check the esp32cam board has a psram chip installed (extra memory used for storing captured images) + // Note: if not using "AI thinker esp32 cam" in the Arduino IDE, SPIFFS must be enabled + if (!psramFound()) { + if (serialDebug) Serial.println("Warning: No PSRam found so defaulting to image size 'CIF'"); + config.frame_size = FRAMESIZE_CIF; + } - //#if defined(CAMERA_MODEL_ESP_EYE) - // pinMode(13, INPUT_PULLUP); - // pinMode(14, INPUT_PULLUP); - //#endif + //#if defined(CAMERA_MODEL_ESP_EYE) + // pinMode(13, INPUT_PULLUP); + // pinMode(14, INPUT_PULLUP); + //#endif - esp_err_t camerr = esp_camera_init(&config); // initialise the camera - if (camerr != ESP_OK) { - if (serialDebug) Serial.printf("ERROR: Camera init failed with error 0x%x", camerr); - } + esp_err_t camerr = esp_camera_init(&config); // initialise the camera + if (camerr != ESP_OK) { + if (serialDebug) Serial.printf("ERROR: Camera init failed with error 0x%x", camerr); + } - cameraImageSettings(); // apply custom camera settings + cameraImageSettings(); // apply custom camera settings - return (camerr == ESP_OK); // return boolean result of camera initialisation + return (camerr == ESP_OK); // return boolean result of camera initialisation } @@ -477,29 +484,29 @@ bool initialiseCamera() { bool cameraImageSettings() { - sensor_t *s = esp_camera_sensor_get(); - // something to try?: if (s->id.PID == OV3660_PID) - if (s == NULL) { - if (serialDebug) Serial.println("Error: problem reading camera sensor settings"); - return 0; - } + sensor_t *s = esp_camera_sensor_get(); + // something to try?: if (s->id.PID == OV3660_PID) + if (s == NULL) { + if (serialDebug) Serial.println("Error: problem reading camera sensor settings"); + return 0; + } - // if both set to zero enable auto adjust - if (cameraImageExposure == 0 && cameraImageGain == 0) { - // enable auto adjust - s->set_gain_ctrl(s, 1); // auto gain on - s->set_exposure_ctrl(s, 1); // auto exposure on - s->set_awb_gain(s, 1); // Auto White Balance enable (0 or 1) - } else { - // Apply manual settings - s->set_gain_ctrl(s, 0); // auto gain off - s->set_awb_gain(s, 1); // Auto White Balance enable (0 or 1) - s->set_exposure_ctrl(s, 0); // auto exposure off - s->set_agc_gain(s, cameraImageGain); // set gain manually (0 - 30) - s->set_aec_value(s, cameraImageExposure); // set exposure manually (0-1200) - } + // if both set to zero enable auto adjust + if (cameraImageExposure == 0 && cameraImageGain == 0) { + // enable auto adjust + s->set_gain_ctrl(s, 1); // auto gain on + s->set_exposure_ctrl(s, 1); // auto exposure on + s->set_awb_gain(s, 1); // Auto White Balance enable (0 or 1) + } else { + // Apply manual settings + s->set_gain_ctrl(s, 0); // auto gain off + s->set_awb_gain(s, 1); // Auto White Balance enable (0 or 1) + s->set_exposure_ctrl(s, 0); // auto exposure off + s->set_agc_gain(s, cameraImageGain); // set gain manually (0 - 30) + s->set_aec_value(s, cameraImageExposure); // set exposure manually (0-1200) + } - return 1; + return 1; } // cameraImageSettings @@ -543,31 +550,31 @@ bool cameraImageSettings() { // returns the current real time as a String // see: https://randomnerdtutorials.com/esp32-date-time-ntp-client-server-arduino/ String localTime() { - struct tm timeinfo; - char ttime[40]; - if(!getLocalTime(&timeinfo)) return"Failed to obtain time"; - strftime(ttime,40, "%A, %B %d %Y %H:%M:%S", &timeinfo); - return ttime; + struct tm timeinfo; + char ttime[40]; + if(!getLocalTime(&timeinfo)) return"Failed to obtain time"; + strftime(ttime,40, "%A, %B %d %Y %H:%M:%S", &timeinfo); + return ttime; } // flash the indicator led 'reps' number of times void flashLED(int reps) { - for(int x=0; x < reps; x++) { - digitalWrite(indicatorLED,LOW); - delay(1000); - digitalWrite(indicatorLED,HIGH); - delay(500); - } + for(int x=0; x < reps; x++) { + digitalWrite(indicatorLED,LOW); + delay(1000); + digitalWrite(indicatorLED,HIGH); + delay(500); + } } // critical error - stop sketch and continually flash error code on indicator led void showError(int errorNo) { - while(1) { - flashLED(errorNo); - delay(4000); - } + while(1) { + flashLED(errorNo); + delay(4000); + } } @@ -581,78 +588,78 @@ void showError(int errorNo) { byte storeImage() { - fs::FS &fs = SD_MMC; // sd card file system + fs::FS &fs = SD_MMC; // sd card file system - // capture the image from camera - int currentBrightness = brightLEDbrightness; - if (flashRequired) brightLed(255); // change LED brightness (0 - 255) - camera_fb_t *fb = esp_camera_fb_get(); // capture image frame from camera - 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 - } + // capture the image from camera + int currentBrightness = brightLEDbrightness; + if (flashRequired) brightLed(255); // change LED brightness (0 - 255) + camera_fb_t *fb = esp_camera_fb_get(); // capture image frame from camera + 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 + } - // save image to Spiffs - if (!sdcardPresent) { - if (serialDebug) Serial.println("Storing image to spiffs only"); - SPIFFS.remove(spiffsFilename); // delete old image file if it exists - File file = SPIFFS.open(spiffsFilename, FILE_WRITE); - if (!file) { - if (serialDebug) Serial.println("Failed to create file in Spiffs"); - return 0; - } - else { - if (file.write(fb->buf, fb->len)) { - if (serialDebug) { - Serial.print("The picture has been saved as " + spiffsFilename); - Serial.print(" - Size: "); - Serial.print(file.size()); - Serial.println(" bytes"); - } - } else { - if (serialDebug) Serial.println("Error: writing image to spiffs...will format and try again"); - if (!SPIFFS.format()) { - if (serialDebug) Serial.println("Error: Unable to format Spiffs"); - return 0; - } - file = SPIFFS.open(spiffsFilename, FILE_WRITE); - if (!file.write(fb->buf, fb->len)) { - if (serialDebug) Serial.println("Error: Still unable to write image to Spiffs"); - return 0; - } - } - file.close(); - } - } + // save image to Spiffs + if (!sdcardPresent) { + if (serialDebug) Serial.println("Storing image to spiffs only"); + SPIFFS.remove(spiffsFilename); // delete old image file if it exists + File file = SPIFFS.open(spiffsFilename, FILE_WRITE); + if (!file) { + if (serialDebug) Serial.println("Failed to create file in Spiffs"); + return 0; + } + else { + if (file.write(fb->buf, fb->len)) { + if (serialDebug) { + Serial.print("The picture has been saved as " + spiffsFilename); + Serial.print(" - Size: "); + Serial.print(file.size()); + Serial.println(" bytes"); + } + } else { + if (serialDebug) Serial.println("Error: writing image to spiffs...will format and try again"); + if (!SPIFFS.format()) { + if (serialDebug) Serial.println("Error: Unable to format Spiffs"); + return 0; + } + file = SPIFFS.open(spiffsFilename, FILE_WRITE); + if (!file.write(fb->buf, fb->len)) { + if (serialDebug) Serial.println("Error: Still unable to write image to Spiffs"); + return 0; + } + } + file.close(); + } + } - // save the image to sd card - if (sdcardPresent) { - if (serialDebug) Serial.printf("Storing image #%d to sd card \n", imageCounter); - String SDfilename = "/img/" + String(imageCounter + 1) + ".jpg"; // build the image file name - 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 - } 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; - } - file.close(); // close image file on sd card - } - } + // save the image to sd card + if (sdcardPresent) { + if (serialDebug) Serial.printf("Storing image #%d to sd card \n", imageCounter); + String SDfilename = "/img/" + String(imageCounter + 1) + ".jpg"; // build the image file name + 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 + } 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; + } + file.close(); // close image file on sd card + } + } - esp_camera_fb_return(fb); // return frame so memory can be released + esp_camera_fb_return(fb); // return frame so memory can be released - if (sdcardPresent) return 2; // saved to sd card - else return 1; // saved in spiffs + if (sdcardPresent) return 2; // saved to sd card + else return 1; // saved in spiffs } // storeImage @@ -668,136 +675,136 @@ byte storeImage() { void handleRoot() { - getNTPtime(2); // refresh current time from NTP server + getNTPtime(2); // refresh current time from NTP server - WiFiClient client = server.client(); // open link with client + WiFiClient client = server.client(); // open link with client - // log the page request including clients IP address - if (serialDebug) { - IPAddress cip = client.remoteIP(); - Serial.printf("Root page requested from: %d.%d.%d.%d \n", cip[0], cip[1], cip[2], cip[3]); - } + // log the page request including clients IP address + if (serialDebug) { + IPAddress cip = client.remoteIP(); + Serial.printf("Root page requested from: %d.%d.%d.%d \n", cip[0], cip[1], cip[2], cip[3]); + } - // Action any button presses or settings entered on web page + // Action any button presses or settings entered on web page - // if button1 was pressed (toggle io pin A) - // Note: if using an input box etc. you would read the value with the command: String Bvalue = server.arg("demobutton1"); - if (server.hasArg("button1")) { - digitalWrite(iopinA,!digitalRead(iopinA)); // toggle output pin on/off - if (serialDebug) Serial.println("Button 1 pressed"); - } + // if button1 was pressed (toggle io pin A) + // Note: if using an input box etc. you would read the value with the command: String Bvalue = server.arg("demobutton1"); + if (server.hasArg("button1")) { + digitalWrite(iopinA,!digitalRead(iopinA)); // toggle output pin on/off + if (serialDebug) Serial.println("Button 1 pressed"); + } - // if button2 was pressed (toggle io pin B) - if (server.hasArg("button2")) { - digitalWrite(iopinB,!digitalRead(iopinB)); // toggle output pin on/off - if (serialDebug) Serial.println("Button 2 pressed"); - } + // if button2 was pressed (toggle io pin B) + if (server.hasArg("button2")) { + digitalWrite(iopinB,!digitalRead(iopinB)); // toggle output pin on/off + if (serialDebug) Serial.println("Button 2 pressed"); + } - // if button3 was pressed (toggle flash LED) - if (server.hasArg("button3")) { - if (brightLEDbrightness == 0) brightLed(10); // turn led on dim - else if (brightLEDbrightness == 10) brightLed(40); // turn led on medium - else if (brightLEDbrightness == 40) brightLed(255); // turn led on full - else brightLed(0); // turn led off - if (serialDebug) Serial.println("Button 3 pressed"); - } + // if button3 was pressed (toggle flash LED) + if (server.hasArg("button3")) { + if (brightLEDbrightness == 0) brightLed(10); // turn led on dim + else if (brightLEDbrightness == 10) brightLed(40); // turn led on medium + else if (brightLEDbrightness == 40) brightLed(255); // turn led on full + else brightLed(0); // turn led off + if (serialDebug) Serial.println("Button 3 pressed"); + } - // if exposure was adjusted - cameraImageExposure - if (server.hasArg("exp")) { - String Tvalue = server.arg("exp"); // read value - if (Tvalue != NULL) { - int val = Tvalue.toInt(); - if (val >= 0 && val <= 1200 && val != cameraImageExposure) { - if (serialDebug) Serial.printf("Exposure changed to %d\n", val); - cameraImageExposure = val; - cameraImageSettings(); // Apply camera image settings - } - } + // if exposure was adjusted - cameraImageExposure + if (server.hasArg("exp")) { + String Tvalue = server.arg("exp"); // read value + if (Tvalue != NULL) { + int val = Tvalue.toInt(); + if (val >= 0 && val <= 1200 && val != cameraImageExposure) { + if (serialDebug) Serial.printf("Exposure changed to %d\n", val); + cameraImageExposure = val; + cameraImageSettings(); // Apply camera image settings + } + } + } + + // if image gain was adjusted - cameraImageGain + if (server.hasArg("gain")) { + String Tvalue = server.arg("gain"); // read value + if (Tvalue != NULL) { + int val = Tvalue.toInt(); + if (val >= 0 && val <= 31 && val != cameraImageGain) { + if (serialDebug) Serial.printf("Gain changed to %d\n", val); + cameraImageGain = val; + cameraImageSettings(); // Apply camera image settings + } + } } - // if image gain was adjusted - cameraImageGain - if (server.hasArg("gain")) { - String Tvalue = server.arg("gain"); // read value - if (Tvalue != NULL) { - int val = Tvalue.toInt(); - if (val >= 0 && val <= 31 && val != cameraImageGain) { - if (serialDebug) Serial.printf("Gain changed to %d\n", val); - cameraImageGain = val; - cameraImageSettings(); // Apply camera image settings - } - } - } + + // html header + client.write(" root \n"); // basic html header + client.write("
\n"); // used by the buttons in the html (action = the web page to send it to - // html header - client.write(" root \n"); // basic html header - client.write("\n"); // used by the buttons in the html (action = the web page to send it to + // -------------------------------------------------------------------- - // -------------------------------------------------------------------- + // html main body + // Info on the arduino ethernet library: https://www.arduino.cc/en/Reference/Ethernet + // Info in HTML: https://www.w3schools.com/html/ + // Info on Javascript (can be inserted in to the HTML): https://www.w3schools.com/js/default.asp + // Verify your HTML is valid: https://validator.w3.org/ - // html main body - // Info on the arduino ethernet library: https://www.arduino.cc/en/Reference/Ethernet - // Info in HTML: https://www.w3schools.com/html/ - // Info on Javascript (can be inserted in to the HTML): https://www.w3schools.com/js/default.asp - // Verify your HTML is valid: https://validator.w3.org/ + client.write("

Hello from ESP32Cam

\n"); + // sd card details + if (sdcardPresent) client.printf("

SD Card detected - %d images stored

\n", imageCounter); + else client.write("

No SD Card detected

\n"); - client.write("

Hello from ESP32Cam

\n"); + // io pin details + if (digitalRead(iopinA) == LOW) client.write("

Output Pin 13 is Low

\n"); + else client.write("

Output Pin 13 is High

\n"); - // sd card details - if (sdcardPresent) client.printf("

SD Card detected - %d images stored

\n", imageCounter); - else client.write("

No SD Card detected

\n"); + if (digitalRead(iopinB) == LOW) client.write("

Output Pin 12 is Low

\n"); + else client.write("

Output Pin 12 is High

\n"); - // io pin details - if (digitalRead(iopinA) == LOW) client.write("

Output Pin 13 is Low

\n"); - else client.write("

Output Pin 13 is High

\n"); + if (digitalRead(iopinC) == LOW) client.write("

Input Pin 16 is Low

\n"); + else client.write("

Input Pin 16 is High

\n"); - if (digitalRead(iopinB) == LOW) client.write("

Output Pin 12 is Low

\n"); - else client.write("

Output Pin 12 is High

\n"); + // illumination led brightness + client.printf("

Illumination led set to %d

\n", illuminationLEDstatus); - if (digitalRead(iopinC) == LOW) client.write("

Input Pin 16 is Low

\n"); - else client.write("

Input Pin 16 is High

\n"); - - // illumination led brightness - client.printf("

Illumination led set to %d

\n", illuminationLEDstatus); - - // Current real time - client.print("

Current time: " + localTime() + "

\n"); + // Current real time + client.print("

Current time: " + localTime() + "

\n"); // // touch input on the two gpio pins // client.printf("

Touch on pin 12: %d

\n", touchRead(T5) ); // client.printf("

Touch on pin 13: %d

\n", touchRead(T4) ); - // Control bottons - client.write(" \n"); - client.write(" \n"); - client.write("
\n"); + // Control bottons + client.write(" \n"); + client.write(" \n"); + client.write("
\n"); - // Image setting controls - client.write("
CAMERA SETTINGS: \n"); - client.printf("Exposure: \n", cameraImageExposure); - client.printf("Gain: \n", cameraImageGain); - client.write(" - Set both to zero for auto adjust
\n"); + // Image setting controls + client.write("
CAMERA SETTINGS: \n"); + client.printf("Exposure: \n", cameraImageExposure); + client.printf("Gain: \n", cameraImageGain); + client.write(" - Set both to zero for auto adjust
\n"); - // links to the other pages available - client.write("
LINKS: \n"); - client.write("Capture an image - \n"); - client.write("View stored images - \n"); - client.write("Capture Image as raw RGB data - \n"); - client.write("Live stream
\n"); + // links to the other pages available + client.write("
LINKS: \n"); + client.write("Capture an image - \n"); + client.write("View stored images - \n"); + client.write("Capture Image as raw RGB data - \n"); + client.write("Live stream
\n"); - // -------------------------------------------------------------------- + // -------------------------------------------------------------------- - // end html - client.write("
\n"); - delay(3); - client.stop(); + // end html + client.write("\n"); + delay(3); + client.stop(); } // handleRoot @@ -812,35 +819,35 @@ void handleRoot() { void handlePhoto() { - WiFiClient client = server.client(); // open link with client + WiFiClient client = server.client(); // open link with client - // log page request including clients IP address - if (serialDebug) { - IPAddress cip = client.remoteIP(); - Serial.printf("Photo 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("Photo requested from: %d.%d.%d.%d \n", cip[0], cip[1], cip[2], cip[3]); + } - // save an image to sd card or spiffs - byte sRes = storeImage(); // save an image to sd card or spiffs (store sucess or failed flag - 0=fail, 1=spiffs only, 2=spiffs and sd card) + // save an image to sd card or spiffs + byte sRes = storeImage(); // save an image to sd card or spiffs (store sucess or failed flag - 0=fail, 1=spiffs only, 2=spiffs and sd card) - // html header - client.write(" photo \n"); // basic html header + // html header + client.write(" photo \n"); // basic html header - // html body - if (sRes == 2) { - client.printf("

Image saved to sd card as image number %d

\n", imageCounter); - client.write("View Image\n"); // link to the image - } else if (sRes == 1) { - client.write("

Image saved in Spiffs

\n"); - client.write("View Image\n"); // link to the image - } else { - client.write("

Error: Failed to save image to sd card

\n"); - } + // html body + if (sRes == 2) { + client.printf("

Image saved to sd card as image number %d

\n", imageCounter); + client.write("View Image\n"); // link to the image + } else if (sRes == 1) { + client.write("

Image saved in Spiffs

\n"); + client.write("View Image\n"); // link to the image + } else { + client.write("

Error: Failed to save image to sd card

\n"); + } - // end html - client.write("\n"); - delay(3); - client.stop(); + // end html + client.write("\n"); + delay(3); + client.stop(); } // handlePhoto @@ -854,64 +861,64 @@ void handlePhoto() { bool handleImg() { - WiFiClient client = server.client(); // open link with client - bool pRes = 0; + WiFiClient client = server.client(); // open link with client + bool pRes = 0; - // log page request including clients IP address - if (serialDebug) { - IPAddress cip = client.remoteIP(); - Serial.printf("Image display requested from: %d.%d.%d.%d \n", cip[0], cip[1], cip[2], cip[3]); - if (imageCounter == 0) Serial.println("Error: no images to display"); - } + // log page request including clients IP address + if (serialDebug) { + IPAddress cip = client.remoteIP(); + Serial.printf("Image display requested from: %d.%d.%d.%d \n", cip[0], cip[1], cip[2], cip[3]); + if (imageCounter == 0) Serial.println("Error: no images to display"); + } - int imgToShow = imageCounter; // default to showing most recent file + int imgToShow = imageCounter; // default to showing most recent file - // get image number from url parameter - if (server.hasArg("img")) { - String Tvalue = server.arg("img"); // read value - imgToShow = Tvalue.toInt(); // convert string to int - if (imgToShow < 1 || imgToShow > imageCounter) imgToShow = imageCounter; // validate image number - } + // get image number from url parameter + if (server.hasArg("img")) { + String Tvalue = server.arg("img"); // read value + imgToShow = Tvalue.toInt(); // convert string to int + if (imgToShow < 1 || imgToShow > imageCounter) imgToShow = imageCounter; // validate image number + } - // if stored on sd card - if (sdcardPresent) { - if (serialDebug) Serial.printf("Displaying image #%d from sd card", imgToShow); + // if stored on sd card + if (sdcardPresent) { + if (serialDebug) Serial.printf("Displaying image #%d from sd card", imgToShow); - String tFileName = "/img/" + String(imgToShow) + ".jpg"; - fs::FS &fs = SD_MMC; // sd card file system - File timg = fs.open(tFileName, "r"); - if (timg) { - size_t sent = server.streamFile(timg, "image/jpeg"); // send the image - timg.close(); - pRes = 1; // flag sucess - } else { - 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 found \n"); + client.write("

Error: Image not found\n"); + if (serialDebug || theText.indexOf("error") > 0) Serial.println(theText); +} + // ---------------------------------------------------------------- // -access image data as RGB - i.e. http://x.x.x.x/rgb // ---------------------------------------------------------------- @@ -967,105 +980,99 @@ void handleNotFound() { void readRGBImage() { - uint32_t tTimer; // used for timing operations - WiFiClient client = server.client(); // open link with client + uint32_t tTimer; // used for timing operations + WiFiClient client = server.client(); // open link with client - // log page request including clients IP address - if (serialDebug) { - IPAddress cip = client.remoteIP(); - Serial.printf("RGB 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("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 + // html header + if (!sendRGBfile) client.write(" photo \n"); // basic html header - MessageRGB(client,"LIVE IMAGE AS RGB DATA"); // 'MessageRGB' sends the String to both serial port and web page + MessageRGB(client,"LIVE IMAGE AS RGB DATA"); // 'MessageRGB' sends the String to both serial port and web page - // ****** the main code for converting an image to RGB data ***** + // ****** the main code for converting an image to RGB data ***** - // capture a live image from camera (as a jpg) - camera_fb_t * fb = NULL; - tTimer = millis(); // store time that image capture started - fb = esp_camera_fb_get(); - 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- "); - MessageRGB(client,"Image resolution=" + String(fb->width) + "x" + String(fb->height)); // display image resolution + // capture a live image from camera (as a jpg) + camera_fb_t * fb = NULL; + tTimer = millis(); // store time that image capture started + fb = esp_camera_fb_get(); + 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)); + } - // 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))); - 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- "); - 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))); + // 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))); + 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- "); + 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))); - // 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 + // 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 (sendRGBfile) client.write(rgb, ARRAY_LENGTH); // send the rgb data as a file + if (sendRGBfile) client.write(rgb, ARRAY_LENGTH); // send the rgb data as a file - // ****** examples of reading the resulting RGB data ***** + // ****** examples of reading the resulting RGB data ***** - // display some of the resulting data - uint32_t resultsToShow = 60; // how much data to display - MessageRGB(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 - // // 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); - } + // display some of the resulting data + uint32_t resultsToShow = 60; // how much data to display + MessageRGB(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 + // // 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); + } - // find the average values for each colour over entire image - uint32_t aRed = 0; - uint32_t aGreen = 0; - uint32_t aBlue = 0; - for (uint32_t i = 0; i < (ARRAY_LENGTH - 2); i+=3) { // go through all data and add up totals - aBlue+=rgb[i]; - aGreen+=rgb[i+1]; - aRed+=rgb[i+2]; - } - 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)); + // find the average values for each colour over entire image + uint32_t aRed = 0; + uint32_t aGreen = 0; + uint32_t aBlue = 0; + for (uint32_t i = 0; i < (ARRAY_LENGTH - 2); i+=3) { // go through all data and add up totals + aBlue+=rgb[i]; + aGreen+=rgb[i+1]; + aRed+=rgb[i+2]; + } + 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)); - // ******************************************************* + // ******************************************************* - // end html - if (!sendRGBfile) client.write("\n"); - delay(3); - client.stop(); + // end html + if (!sendRGBfile) client.write("\n"); + delay(3); + client.stop(); - // finished with the data so free up the memory space used in psram - esp_camera_fb_return(fb); // camera frame buffer - heap_caps_free(ptrVal); // rgb data + // finished with the data so free up the memory space used in psram + esp_camera_fb_return(fb); // camera frame buffer + heap_caps_free(ptrVal); // rgb data } // readRGBImage - -// send line of text to both serial port and web page -void MessageRGB(WiFiClient &client, String theText) { - if (!sendRGBfile) client.print(theText + "
\n"); - if (serialDebug || theText.indexOf("error") > 0) Serial.println(theText); -} - - - // ****************************************************************************************************************** @@ -1075,22 +1082,22 @@ void MessageRGB(WiFiClient &client, String theText) { bool getNTPtime(int sec) { - { - uint32_t start = millis(); - do { - time(&now); - localtime_r(&now, &timeinfo); - Serial.print("."); - delay(100); - } while (((millis() - start) <= (1000 * sec)) && (timeinfo.tm_year < (2016 - 1900))); - if (timeinfo.tm_year <= (2016 - 1900)) return false; // the NTP call was not successful - Serial.print("now "); Serial.println(now); - char time_output[30]; - strftime(time_output, 30, "%a %d-%m-%y %T", localtime(&now)); - Serial.println(time_output); - Serial.println(); - } - return true; + { + uint32_t start = millis(); + do { + time(&now); + localtime_r(&now, &timeinfo); + Serial.print("."); + delay(100); + } while (((millis() - start) <= (1000 * sec)) && (timeinfo.tm_year < (2016 - 1900))); + if (timeinfo.tm_year <= (2016 - 1900)) return false; // the NTP call was not successful + Serial.print("now "); Serial.println(now); + char time_output[30]; + strftime(time_output, 30, "%a %d-%m-%y %T", localtime(&now)); + Serial.println(time_output); + Serial.println(); + } + return true; } @@ -1104,50 +1111,50 @@ bool getNTPtime(int sec) { void handleStream(){ - WiFiClient client = server.client(); // open link with client + WiFiClient client = server.client(); // open link with client - // log page request including clients IP address - if (serialDebug) { - IPAddress cip = client.remoteIP(); - Serial.printf("Video stream 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("Video stream requested from: %d.%d.%d.%d \n", cip[0], cip[1], cip[2], cip[3]); + } - // HTML used in the web page - 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"; - const char BOUNDARY[] = "\r\n--123456789000000000000987654321\r\n"; // marks end of each image frame - const char CTNTTYPE[] = "Content-Type: image/jpeg\r\nContent-Length: "; // marks start of image data - 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); + // HTML used in the web page + 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"; + const char BOUNDARY[] = "\r\n--123456789000000000000987654321\r\n"; // marks end of each image frame + const char CTNTTYPE[] = "Content-Type: image/jpeg\r\nContent-Length: "; // marks start of image data + 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); - // temp stores - char buf[32]; - int s; - camera_fb_t * fb = NULL; + // temp stores + char buf[32]; + int s; + camera_fb_t * fb = NULL; - // send html header - client.write(HEADER, hdrLen); - client.write(BOUNDARY, bdrLen); + // send html header + client.write(HEADER, hdrLen); + client.write(BOUNDARY, bdrLen); - // send live images until client disconnects - while (true) - { - if (!client.connected()) break; - fb = esp_camera_fb_get(); // capture live 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' - client.write(buf, strlen(buf)); // send result (image size) - client.write((char *)fb->buf, s); // 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 - } + // send live images until client disconnects + while (true) + { + if (!client.connected()) break; + fb = esp_camera_fb_get(); // capture live 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' + client.write(buf, strlen(buf)); // send result (image size) + client.write((char *)fb->buf, s); // 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 + } - if (serialDebug) Serial.println("Video stream stopped"); - delay(3); - client.stop(); + if (serialDebug) Serial.println("Video stream stopped"); + delay(3); + client.stop(); } // handleStream @@ -1156,380 +1163,6 @@ void handleStream(){ // ****************************************************************************************************************** -// ---------------------------------------------------------------- -// -// -// ESP32 / ESp8266 very basic web server demo - 29Dec21 -// for Arduino IDE or PlatformIO -// -// shows use of AJAX to show updating info on the web page -// -// https://github.com/alanesq/BasicWebserver/blob/master/misc/VeryBasicWebserver.ino -// -// -// ---------------------------------------------------------------- - - -// --------------------------------------------------------------------------------------------------------- - -// Wifi Settings - -#include // delete this line, un-comment the below two lines and enter your wifi details - -//const char *SSID = "your_wifi_ssid"; - -//const char *PWD = "your_wifi_pwd"; - - -// --------------------------------------------------------------------------------------------------------- - - -#include // required by platformIO -bool serialDebug = 1; // enable debugging info on serial port - - -// forward declarations (required by PlatformIO) - //String requestWebPage(String ip, String page, int port, int maxChars, String cuttoffText = ""); - void handleRoot(); - void handleTest(); - void handleButton(); - void handleAJAX(); - void handleSendData(); - void handleLED(); - void handleNotFound(); - int requestWebPage(String*, String*, int); - - -// ---------------------------------------------------------------- - - -//#include // required by platformio? - -#if defined ESP32 - // esp32 - byte LEDpin = 2; - #include - #include - #include - WebServer server(80); -#elif defined ESP8266 - //Esp8266 - byte LEDpin = D4; - #include - #include - #include "ESP8266HTTPClient.h" - ESP8266WebServer server(80); -#else - #error "This sketch only works with the ESP8266 or ESP32" -#endif - - -// ---------------------------------------------------------------- - - -// this section runs once at startup - - -void setup() { - - Serial.begin(115200); // start serial comms at speed 115200 - delay(200); - Serial.println("\n\nWebserver demo sketch"); - //Serial.println("- Reset reason: " + ESP.getResetReason()); - - // onboard LEDs - pinMode(LEDpin, OUTPUT); - digitalWrite(LEDpin, HIGH); - - // Connect to Wifi - Serial.print("Connecting to "); - Serial.println(SSID); - WiFi.begin(SSID, PWD); - while (WiFi.status() != WL_CONNECTED) { - Serial.print("."); - delay(500); - } - Serial.print("\nConnected - IP: "); - Serial.println(WiFi.localIP()); - - // set up web server pages to serve - server.on("/", handleRoot); // root web page (i.e. when root page is requested run procedure 'handleroot') - server.on("/test", handleTest); // test web page - server.on("/button", handleButton); // demo simple use of buttons - server.on("/ajax", handleAJAX); // demo using AJAX to update information on the page (also javascript buttons) - server.on("/senddata", handleSendData); // requested by the AJAX web page to request current millis value - server.on("/setLED", handleLED); // action when a button is clicked on the AJAX page - server.onNotFound(handleNotFound); // if invalid url is requested - - // start web server - server.begin(); - - // stop the wifi being turned off if not used for a while - #if defined ESP32 - WiFi.setSleep(false); - #else - WiFi.setSleepMode(WIFI_NONE_SLEEP); - #endif - - WiFi.mode(WIFI_STA); // turn off access point - options are WIFI_AP, WIFI_STA, WIFI_AP_STA or WIFI_OFF - -} // setup - - - -// ---------------------------------------------------------------- - - -// this section runs repeatedly in a loop - - -void loop() { - - server.handleClient(); // service any web page requests - - //// flash onboard LED - //digitalWrite(LEDpin, !digitalRead(LEDpin)); // invert onboard LED status - //delay(200); // wait 200 milliseconds - - #if defined(ESP8266) - yield(); // allow esp8266 to carry out wifi tasks (may restart randomly without this) - #endif - -} // loop - - - -// ---------------------------------------------------------------- -// -test web page requested i.e. http://x.x.x.x/ -// ---------------------------------------------------------------- -// demonstrate sending a plain text reply - -void handleRoot(){ - - if (serialDebug) Serial.println("Root page requested"); - - String message = "root web page"; - - server.send(404, "text/plain", message); // send reply as plain text - -} // handleRoot - - - -// ---------------------------------------------------------------- -// -test web page requested i.e. http://x.x.x.x/test -// ---------------------------------------------------------------- -// demonstrate sending html reply - -void handleTest(){ - - if (serialDebug) Serial.println("Test page requested"); - - WiFiClient client = server.client(); // open link with client - - // html header - client.print(" Web Demo \n"); // basic html header - - // html body - client.print("

Test Page

\n"); - - // end html - client.print("\n"); - delay(3); - client.stop(); - -} // handleTest - - - -// ---------------------------------------------------------------- -// -button web page requested i.e. http://x.x.x.x/button -// ---------------------------------------------------------------- -// demonstrate simple use of a html buttons without using Javascript - -void handleButton(){ - - if (serialDebug) Serial.println("Button page requested"); - - // check if button1 has been pressed - if (server.hasArg("button1")) { - Serial.println("Button 1 was pressed"); - } - - // check if button2 has been pressed - if (server.hasArg("button2")) { - Serial.println("Button 2 was pressed"); - } - - - // send reply to client - - WiFiClient client = server.client(); // open link with client - - // html header - client.print(" Web Demo \n"); // basic html header - client.print("
\n"); // used by the buttons in the html (action = the web page to send it to - - // html body - client.print("

Button demo page

\n"); - if (server.hasArg("button1")) client.print("Button 1 has been pressed!"); - if (server.hasArg("button2")) client.print("Button 2 has been pressed!"); - client.print("

\n"); - client.print("

\n"); - - // end html - client.print("\n"); - delay(3); - client.stop(); - -} // handleButton - - -// ---------------------------------------------------------------- -// -ajax web page requested i.e. http://x.x.x.x/ajax -// ---------------------------------------------------------------- -// demonstrate use of AJAX to refresh info. on web page -// see: https://circuits4you.com/2018/02/04/esp8266-ajax-update-part-of-web-page-without-refreshing/ -// to store html in program memory to save ram use command: const char index_html[] PROGMEM = R"rawliteral( )rawliteral"; - -void handleAJAX() { - - WiFiClient client = server.client(); // open link with client - - // log page request including clients IP address - IPAddress cip = client.remoteIP(); - Serial.println("Ajax page requested from: " + String(cip[0]) +"." + String(cip[1]) + "." + String(cip[2]) + "." + String(cip[3]) ); - - - // ---------------------- html ---------------------- - - client.print (R"=====( - - - - - AJAX Demo - - - -
-

Update web page using AJAX

- -
-
-
- Current Millis : 0
- Received text : NA
- LED State is : NA
-
- - )====="); - - // ------------------- JavaScript ------------------- - - client.print (R"=====()====="); - // -------------------------------------------------- - - // close html page - client.print("\n"); // close HTML - delay(3); - client.stop(); - -} // handleAJAX - - -// send data to AJAX web page -// it replies with two items comma separated: the value in millis and some text -void handleSendData() { - String reply = String(millis()); // item 1 - reply += ","; - reply += "This text sent by handleSendtime()"; // item 2 - server.send(200, "text/plane", reply); //Send millis value only to client ajax request -} - - -// handle button clicks on AJAX web page -// it sets the onboard LED status and replies with it's status as plain text -void handleLED() { - String ledState = "OFF"; - String t_state = server.arg("LEDstate"); //Refer xhttp.open("GET", "setLED?LEDstate="+led, true); - Serial.println(t_state); - if(t_state == "1") { - digitalWrite(LEDpin,LOW); //LED ON - ledState = "ON"; //Feedback parameter - } else { - digitalWrite(LEDpin,HIGH); //LED OFF - ledState = "OFF"; //Feedback parameter - } - server.send(200, "text/plane", ledState); //Send web page -} - - -// ---------------------------------------------------------------- -// -invalid web page requested -// ---------------------------------------------------------------- -// send this reply to any invalid url requested - -void handleNotFound() { - - if (serialDebug) Serial.println("Invalid page requested"); - - String tReply; - - tReply = "File Not Found\n\n"; - tReply += "URI: "; - tReply += server.uri(); - tReply += "\nMethod: "; - tReply += ( server.method() == HTTP_GET ) ? "GET" : "POST"; - tReply += "\nArguments: "; - tReply += server.args(); - tReply += "\n"; - - for ( uint8_t i = 0; i < server.args(); i++ ) { - tReply += " " + server.argName ( i ) + ": " + server.arg ( i ) + "\n"; - } - - server.send ( 404, "text/plain", tReply ); - tReply = ""; // clear variable - -} // handleNotFound - - - -// ---------------------------------------------------------------------------------------------------------------- - - -// Not used in this sketch but provided as an example of how to request an external web page and receive the reply as a string - - // ---------------------------------------------------------------- // request a web page // ---------------------------------------------------------------- @@ -1566,12 +1199,6 @@ int requestWebPage(String* page, String* received, int maxWaitTime=5000){ } // requestWebPage -// ---------------------------------------------------------------- -// end - - - - // ****************************************************************************************************************** @@ -1581,30 +1208,30 @@ int requestWebPage(String* page, String* received, int maxWaitTime=5000){ void handleTest() { - WiFiClient client = server.client(); // open link with client + WiFiClient client = server.client(); // open link with client - // log page request including clients IP address - if (serialDebug) { - IPAddress cip = client.remoteIP(); - Serial.printf("Test 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("Test requested from: %d.%d.%d.%d \n", cip[0], cip[1], cip[2], cip[3]); + } - // html header - client.write(" photo \n"); // basic html header + // html header + client.write(" photo \n"); // basic html header - // html body - client.print("

Test Page

\n"); + // html body + client.print("

Test Page

\n"); - // ------------------------------------------------------------------- + // ------------------------------------------------------------------- - // < YOUR TEST CODE GOES HERE> + // < YOUR TEST CODE GOES HERE> @@ -1628,16 +1255,17 @@ void handleTest() { - // ------------------------------------------------------------------- + // ------------------------------------------------------------------- - // end html - client.write("\n"); - delay(3); - client.stop(); + // end html + client.write("\n"); + delay(3); + client.stop(); } // handleTest // ****************************************************************************************************************** // end +**Ñ¥