Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3.x #270

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open

3.x #270

42 changes: 0 additions & 42 deletions .travis.yml

This file was deleted.

2 changes: 1 addition & 1 deletion API.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ reboot - Reboots the camera
* `http://<IP-ADDRESS>/control?var=lamp&val=50`
* `http://<IP-ADDRESS>/control?var=lamp&val=0`
* Set resolution to VGA
* `http://<IP-ADDRESS>/control?var=framesize&val=6`
* `http://<IP-ADDRESS>/control?var=framesize&val=8`
* Show camera details and settings
* All settings are returned via single `status` call in [JSON](https://www.json.org/) format.
* `http://<IP-ADDRESS>/status`
Expand Down
Binary file added Docs/v3x-select-106-ide-core.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
43 changes: 24 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
# ESP32-CAM example revisited. &nbsp;&nbsp;&nbsp; <span title="Master branch build status">[![CI Status](https://travis-ci.org/easytarget/esp32-cam-webserver.svg?branch=master)](https://travis-ci.org/github/easytarget/esp32-cam-webserver)</span> &nbsp;&nbsp; <span title="ESP EYE">![ESP-EYE logo](Docs/logo.svg)</span>
# ESP32-CAM example revisited.

# V3.x - Legacy Branch
### This is the *old* 3.x branch of the project, with Face Recognition, but no Over The Air updates
I will continue to fix bugs as needed on this branch for the forseeable future, but will not be adding any new features

You need to **downgrade** the esp32 board definition in the Arduino IDE to an old version (v1.0.6) to use this, instructions are below but please understand that this is not really recommended, the only reason you should be using this branch is to investigate the (very limited!) Face Recognition features of the camera module.

See the [master](https://github.com/easytarget/esp32-cam-webserver/tree/master/) branch for the current (v4+) version which has lost the basic Face Recognition features, but gained Over The Air updates and other new features.

## Taken from the ESP examples, and expanded
This sketch is a extension/expansion/rework of the 'official' ESP32 Camera example sketch from Espressif:
Expand Down Expand Up @@ -49,6 +57,16 @@ The existing [issues list](https://github.com/easytarget/esp32-cam-webserver/iss

* For programming you will need a suitable development environment, I use the Arduino IDE, but this code should work in the Espressif development environment too.
* Make sure you are using the [latest version](https://www.arduino.cc/en/main/software#download) of the IDE and then follow [This Guide](https://github.com/espressif/arduino-esp32/blob/master/docs/arduino-ide/boards_manager.md) to set up the Espressif Arduino core for the IDE.

### Downgrade the ESP arduino core to v1.0.6

* This (3.x) branch only compiles with, *and is only supported on*, the old [v1.0.6](https://github.com/espressif/arduino-esp32/releases/tag/1.0.6) version of the expressif arduino core.
* Before compiling you must select this version in the Boards manager of the IDE:
![Selecting the correct IDE core version](Docs/v3x-select-106-ide-core.png)
* If you later upgrade back to the latest camera version or want to program other esp32 based boards do not forget to revert this when done programming.

## Programming:

* If you have a development board (anything that can be programmed via a standard USB cable/jack on the board itself) you are in luck. Just plug it in and skip ahead to the [config](#config) section. Remember to set your board model.
* The AI-THINKER board requires use of an external **3.3v** serial adapter to program; I use a `FTDI Friend` adapter, for more about this read AdaFruits excellent [FTDI Friend guide](https://learn.adafruit.com/ftdi-friend).
* Be careful not to use a 5v serial adapter since this will damage the ESP32.
Expand All @@ -63,10 +81,9 @@ Is pretty simple, You just need jumper wires, no soldering really required, see
* You must supply 5v to the ESP32 in order to power it during programming, the FTDI board can supply this.

### Download the Sketch, Unpack and Rename
Download the latest release of the sketch from https://github.com/easytarget/esp32-cam-webserver/releases/latest
- You can get the latest stable development release by cloning / downloading the `master` branch of the repo.
Download the latest 3.X release of the sketch from https://github.com/easytarget/esp32-cam-webserver/releases?q=v3.&expanded=true

This will give you an archive file with the Version number in it, eg.`esp32-cam-webserver-3.0.zip`. Tou need to unpack this into your Arduino sketch folder, and then you need to rename the folder you just extracted to remove the version number, eg.`esp32-cam-webserver-3.0` becomes `esp32-cam-webserver`.
This will give you an archive file with the Version number in it, eg.`esp32-cam-webserver-3.5.zip`. Tou need to unpack this into your Arduino sketch folder, and then you need to rename the folder you just extracted to remove the version number, eg.`esp32-cam-webserver-3.0` becomes `esp32-cam-webserver`.

Once you have done that you can open the sketch in the IDE by going to the `esp32-cam-webserver` sketch folder and selecting `esp32-cam-webserver.ino`.

Expand All @@ -81,6 +98,8 @@ To make a permanent config with your home wifi settings, different defaults or a
Assuming you are using the latest Espressif Arduino core the `AI-THINKER` board (or whatever board you select for programming) will appear in the ESP32 Arduino section of the boards list.
![IDE board config](Docs/board-selection-small.png)

If you have a different board and are using a generic ESP32 DEV board select `Huge APP (3MB No OTA/1MB SPIFFS` for the partition scheme, and make sure PSRAM is enabled (it defaults to off!)

Compile and upload the code from the IDE, when the `Connecting...` appears in the console reboot the ESP32 module while keeping **GPIO0** grounded. You can release GPO0 once the sketch is uploading, most boards have a 'boot' button to trigger a reboot.

Once the upload completes (be patient, it can be a bit slow) open the serial monitor in the IDE and reboot the board again without GPIO0 grounded. In the serial monitor you should see the board start, connect to the wifi and then report the IP address it has been assigned.
Expand Down Expand Up @@ -119,18 +138,4 @@ I would also like to shoutout to @jmfloyd; who suggested rotating the image in t

## Contributing

Contributions are welcome; please see the [Contribution guidelines](CONTRIBUTING.md).

## Plans

Time allowing; my Current plan is:

V4 Remove face recognition entirely;
* Dont try to make it optional, this is a code and maintenance nightmare. V3 can be maintained on a branch for those who need it.
* Investigate using SD card to capture images
* implement OTA and a better network stack for remembering multiple AP's, auto-config etc.
* UI Skinning/Theming
* OSD
* Temperature/humidity/pressure sensor suport (bme20,dht11)
You can check the [enhancement list](https://github.com/easytarget/esp32-cam-webserver/issues?q=is%3Aissue+label%3Aenhancement) (past and present), and add any thoghts you may have there.

Contributions for the main branch are welcome; please see the [Contribution guidelines](CONTRIBUTING.md).
77 changes: 61 additions & 16 deletions app_httpd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ extern int sketchSpace;
extern String sketchMD5;
extern char knownFaceText[];
extern char unknownFaceText[];
extern unsigned long xclkFreqHz;



#include "fb_gfx.h"
Expand Down Expand Up @@ -104,6 +106,14 @@ static ra_filter_t ra_filter;
httpd_handle_t stream_httpd = NULL;
httpd_handle_t camera_httpd = NULL;

#ifdef __cplusplus
extern "C" {
#endif
uint8_t temprature_sens_read();
#ifdef __cplusplus
}
#endif

static mtmn_config_t mtmn_config = {0};
static int8_t is_enrolling = 0;
static face_id_list id_list = {0};
Expand Down Expand Up @@ -252,11 +262,7 @@ static int run_face_recognition(dl_matrix3du_t *image_matrix, box_array_t *net_b
}

void serialDump() {
Serial.println("\r\nPreferences file: ");
dumpPrefs(SPIFFS);
if (critERR.length() > 0) {
Serial.printf("\r\n\r\nA critical error has occurred when initialising Camera Hardware, see startup megssages\r\n");
}
Serial.println();
// Module
Serial.printf("Name: %s\r\n", myName);
Serial.printf("Firmware: %s (base: %s)\r\n", myVer, baseVersion);
Expand Down Expand Up @@ -295,15 +301,33 @@ void serialDump() {
int upHours = int64_t(floor(sec/3600)) % 24;
int upMin = int64_t(floor(sec/60)) % 60;
int upSec = sec % 60;
int McuTc = (temprature_sens_read() - 32) / 1.8; // celsius
int McuTf = temprature_sens_read(); // fahrenheit
float xclk = xclkFreqHz/1000000;
Serial.printf("System up: %" PRId64 ":%02i:%02i:%02i (d:h:m:s)\r\n", upDays, upHours, upMin, upSec);
Serial.printf("Active streams: %i, Previous streams: %lu, Images captured: %lu\r\n", streamCount, streamsServed, imagesServed);
Serial.printf("Freq: %i MHz\r\n", ESP.getCpuFreqMHz());
Serial.printf("CPU Freq: %i MHz, Xclk Freq: %.1f MHz\r\n", ESP.getCpuFreqMHz(), xclk);
Serial.printf("MCU temperature : %i C, %i F (approximate)\r\n", McuTc, McuTf);
Serial.printf("Heap: %i, free: %i, min free: %i, max block: %i\r\n", ESP.getHeapSize(), ESP.getFreeHeap(), ESP.getMinFreeHeap(), ESP.getMaxAllocHeap());
Serial.printf("Psram: %i, free: %i, min free: %i, max block: %i\r\n", ESP.getPsramSize(), ESP.getFreePsram(), ESP.getMinFreePsram(), ESP.getMaxAllocPsram());
if (filesystem) {
if(psramFound()) {
Serial.printf("Psram: %i, free: %i, min free: %i, max block: %i\r\n", ESP.getPsramSize(), ESP.getFreePsram(), ESP.getMinFreePsram(), ESP.getMaxAllocPsram());
} else {
Serial.printf("Psram: Not found; please check your board configuration.\r\n");
Serial.printf("- High resolution/quality settings will show incomplete frames due to low memory.\r\n");
}
// Filesystems
if (filesystem && (SPIFFS.totalBytes() > 0)) {
Serial.printf("Spiffs: %i, used: %i\r\n", SPIFFS.totalBytes(), SPIFFS.usedBytes());
} else {
Serial.printf("Spiffs: No filesystem found, please check your board configuration.\r\n");
Serial.printf("- Saving and restoring camera settings will not function without this.\r\n");
}
Serial.printf("Enrolled faces: %i (max %i)\r\n", id_list.count, id_list.size);
Serial.println("Preferences file: ");
dumpPrefs(SPIFFS);
if (critERR.length() > 0) {
Serial.printf("\r\n\r\nA critical error has occurred when initialising Camera Hardware, see startup megssages\r\n");
}
Serial.println();
return;
}
Expand All @@ -325,7 +349,10 @@ static esp_err_t capture_handler(httpd_req_t *req){
esp_err_t res = ESP_OK;

Serial.println("Capture Requested");
if (autoLamp && (lampVal != -1)) setLamp(lampVal);
if (autoLamp && (lampVal != -1)) {
setLamp(lampVal);
delay(75); // coupled with the status led flash this gives ~150ms for lamp to settle.
}
flashLED(75); // little flash of status LED

int64_t fr_start = esp_timer_get_time();
Expand Down Expand Up @@ -384,7 +411,8 @@ static esp_err_t capture_handler(httpd_req_t *req){

s = fmt2rgb888(fb->buf, fb->len, fb->format, out_buf);
esp_camera_fb_return(fb);
if(!s){
fb = NULL;
if(!s){
dl_matrix3du_free(image_matrix);
Serial.println("CAPTURE: frame convert to rgb888 failed");
httpd_resp_send_500(req);
Expand Down Expand Up @@ -421,7 +449,9 @@ static esp_err_t capture_handler(httpd_req_t *req){
}

imagesServed++;
if (autoLamp && (lampVal != -1)) setLamp(0);
if (autoLamp && (lampVal != -1)) {
setLamp(0);
}
return res;
}

Expand Down Expand Up @@ -601,6 +631,7 @@ static esp_err_t cmd_handler(httpd_req_t *req){
size_t buf_len;
char variable[32] = {0,};
char value[32] = {0,};

flashLED(75);

buf_len = httpd_req_get_url_query_len(req) + 1;
Expand Down Expand Up @@ -827,8 +858,8 @@ static esp_err_t dump_handler(httpd_req_t *req){
d+= sprintf(d,"<body>\n");
d+= sprintf(d,"<img src=\"/logo.svg\" style=\"position: relative; float: right;\">\n");
if (critERR.length() > 0) {
d+= sprintf(d,"Hardware Error Detected!\n(the serial log may give more information)\n");
d+= sprintf(d,"%s<hr>\n", critERR.c_str());
d+= sprintf(d,"<span style=\"color:red;\">%s<hr></span>\n", critERR.c_str());
d+= sprintf(d,"<h2 style=\"color:red;\">(the serial log may give more information)</h2><br>\n");
}
d+= sprintf(d,"<h1>ESP32 Cam Webserver</h1>\n");
// Module
Expand Down Expand Up @@ -872,13 +903,27 @@ static esp_err_t dump_handler(httpd_req_t *req){
int upHours = int64_t(floor(sec/3600)) % 24;
int upMin = int64_t(floor(sec/60)) % 60;
int upSec = sec % 60;
int McuTc = (temprature_sens_read() - 32) / 1.8; // celsius
int McuTf = temprature_sens_read(); // fahrenheit
float xclk = xclkFreqHz/1000000;

d+= sprintf(d,"Up: %" PRId64 ":%02i:%02i:%02i (d:h:m:s)<br>\n", upDays, upHours, upMin, upSec);
d+= sprintf(d,"Active streams: %i, Previous streams: %lu, Images captured: %lu<br>\n", streamCount, streamsServed, imagesServed);
d+= sprintf(d,"Freq: %i MHz<br>\n", ESP.getCpuFreqMHz());
d+= sprintf(d,"CPU Freq: %i MHz, Xclk Freq: %.1f MHz<br>\n", ESP.getCpuFreqMHz(), xclk);
d+= sprintf(d,"<span title=\"NOTE: Internal temperature sensor readings can be innacurate on the ESP32-c1 chipset, and may vary significantly between devices!\">");
d+= sprintf(d,"MCU temperature : %i &deg;C, %i &deg;F</span>\n<br>", McuTc, McuTf);
d+= sprintf(d,"Heap: %i, free: %i, min free: %i, max block: %i<br>\n", ESP.getHeapSize(), ESP.getFreeHeap(), ESP.getMinFreeHeap(), ESP.getMaxAllocHeap());
d+= sprintf(d,"Psram: %i, free: %i, min free: %i, max block: %i<br>\n", ESP.getPsramSize(), ESP.getFreePsram(), ESP.getMinFreePsram(), ESP.getMaxAllocPsram());
if (filesystem) {
if (psramFound()) {
d+= sprintf(d,"Psram: %i, free: %i, min free: %i, max block: %i<br>\n", ESP.getPsramSize(), ESP.getFreePsram(), ESP.getMinFreePsram(), ESP.getMaxAllocPsram());
} else {
d+= sprintf(d,"Psram: <span style=\"color:red;\">Not found</span>, please check your board configuration.<br>\n");
d+= sprintf(d,"- High resolution/quality images & streams will show incomplete frames due to low memory.<br>\n");
}
if (filesystem && (SPIFFS.totalBytes() > 0)) {
d+= sprintf(d,"Spiffs: %i, used: %i<br>\n", SPIFFS.totalBytes(), SPIFFS.usedBytes());
} else {
d+= sprintf(d,"Spiffs: <span style=\"color:red;\">No filesystem found</span>, please check your board configuration.<br>\n");
d+= sprintf(d,"- saving and restoring camera settings will not function without this.<br>\n");
}
d+= sprintf(d,"Enrolled faces: %i (max %i)<br>\n", id_list.count, id_list.size);

Expand Down
79 changes: 52 additions & 27 deletions camera_pins.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,33 @@
* Defaults to AI-THINKER CAM module
*
*/
#if defined(CAMERA_MODEL_WROVER_KIT)
#if defined(CAMERA_MODEL_AI_THINKER)
//
// AI Thinker
// https://github.com/SeeedDocument/forum_doc/raw/master/reg/ESP32_CAM_V1.6.pdf
//
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#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
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
#define LED_PIN 33 // Status led
#define LED_ON LOW // - Pin is inverted.
#define LED_OFF HIGH //
#define LAMP_PIN 4 // LED FloodLamp.

#elif defined(CAMERA_MODEL_WROVER_KIT)
//
// ESP WROVER
// https://dl.espressif.com/dl/schematics/ESP-WROVER-KIT_SCH-2.pdf
Expand Down Expand Up @@ -161,32 +187,6 @@
// #define LED_OFF LOW //
// #define LAMP_PIN x // LED FloodLamp.

#elif defined(CAMERA_MODEL_AI_THINKER)
//
// AI Thinker
// https://github.com/SeeedDocument/forum_doc/raw/master/reg/ESP32_CAM_V1.6.pdf
//
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#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
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
#define LED_PIN 33 // Status led
#define LED_ON LOW // - Pin is inverted.
#define LED_OFF HIGH //
#define LAMP_PIN 4 // LED FloodLamp.

#elif defined(CAMERA_MODEL_TTGO_T_JOURNAL)
//
// LilyGO TTGO T-Journal ESP32; with OLED! but not used here.. :-(
Expand All @@ -212,6 +212,31 @@
// #define LED_OFF HIGH //
// #define LAMP_PIN 4 // LED FloodLamp.

#elif defined(CAMERA_MODEL_ARDUCAM_ESP32S_UNO)
// Pins from user @rdragonrydr
// https://github.com/ArduCAM/ArduCAM_ESP32S_UNO/
// Based on AI-THINKER definitions
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#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
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
#define LED_PIN 2 // Status led
#define LED_ON HIGH // - Pin is not inverted.
#define LED_OFF LOW //
//#define LAMP_PIN x // No LED FloodLamp.

#else
// Well.
// that went badly...
Expand Down
Loading