diff --git a/README.md b/README.md index e8c6229..8429cf8 100644 --- a/README.md +++ b/README.md @@ -30,15 +30,12 @@ This software supports the following ESP32-CAM (and alike) modules: - WROVER-KIT - M5STACK -![ESP32CAM module](assets/ESP32-CAM.jpg) - The software provides a **configuration web server**, that can be used to: - Provide information about the state of the device, wifi connection and camera, - Set the WiFi parameters, - Set the timeout for connecting to the access point, - Set an access password, -- Select the board type, - Select the image size, - Select the frame rate, - Select the JPEG quality @@ -77,25 +74,30 @@ It advertises HTTP (port 80) and RTSP (port 554) - USB to Serial (TTL level) converter, piggyback board ESP32-CAM-MB or other way to connect to the device, - [**PlatformIO**](https://platformio.org/) software (free download) +## Boards + +There are a lot of boards available that are all called ESP32-CAM. +However, there are differences in CPU (type/speed/cores), how the camera is connected, presence of PSRAM or not... +To select the right board use the table below and use the configuration that is listed below for your board: + +| Board | Configuration | Image | CPU | RAM | Camera | Site | +|--- |--- |--- |--- |--- |--- |--- | +| Espressif ESP32-Wropver CAM | | | ESP32 | 520KB SRAM 4MB PSRAM | OV2640 | | +| AI-Thinker ESP32-CAM | ai_thinker_esp32cam | | ESP32-S / 160Mhz | 520KB SRAM 4MB PSRAM | OV2640 | https://docs.ai-thinker.com/en/esp32-cam | +| Espressif ESP-EYE | | | ESP32 | 520KB SRAM 4MB PSRAM | OV2640 | | +| Espressif ESP-S3-EYE| | | ESP32-S3 | 520KB SRAM 4MB PSRAM | OV2640 | https://www.espressif.com/en/products/devkits/esp-eye/overview | +| LilyGo camera module| | | ESP32 Wrover | 520KB SRAM 4MB PSRAM | OV2640 / OV5640 +| LilyGo Simcam| | | | | OV2640 | | +| LilyGo TTGO-T Camera| | || | OV2640 | | +| M5 Stack Camera| | ||| OV2640 | | +| Seeed studio Xiao ESPS3 Sense| seeed_xiao_esp32s3_sense | | ESP32-S3 | 520KB SRAM 4MB PSRAM | OV2640 | | + ## Installing and running PlatformIO PlatformIO is available for all major operating systems: Windows, Linux and MacOS. It is also provided as a plugin to [Visual Studio Code](https://visualstudio.microsoft.com). More information can be found at: [https://docs.platformio.org/en/latest/installation.html](https://docs.platformio.org/en/latest/installation.html) below the basics. -### Debian based systems command-line install - -Install platformIO - -```sh - sudo apt-get install python-pip - sudo pip install platformio - pio upgrade -``` - -### Windows, Linux and MacOS - -Install [**Visual Studio code**](https://code.visualstudio.com) and install the PlatformIO plugin. -For command line usage Python and PlatformIO-Core is sufficient. +Install [**Visual Studio Code**](https://code.visualstudio.com) and install the PlatformIO plugin. ## Putting the ESP32-CAM in download mode @@ -284,7 +286,7 @@ Not all the boards are equipped with PSRAM: | ESP32CAM (USB-C) | No | | AI THINKER | Yes | | TTGO T-CAM | No | -| M5 STACK| | No | +| M5 STACK | No | | WROVER KIT | Yes | Depending on the image resolution, framerate and quality, the PSRAM must be enabled and/or the number of frame buffers increased to keep up with the data generated by the sensor. diff --git a/assets/ESP32-CAM-MB.jpg b/assets/ESP32-CAM-MB.jpg deleted file mode 100644 index 13226eb..0000000 Binary files a/assets/ESP32-CAM-MB.jpg and /dev/null differ diff --git a/assets/ESP32-CAM.jpg b/assets/ESP32-CAM.jpg deleted file mode 100644 index e69fe5f..0000000 Binary files a/assets/ESP32-CAM.jpg and /dev/null differ diff --git a/assets/boards/ai-thinker-esp32-cam-ipex.jpg b/assets/boards/ai-thinker-esp32-cam-ipex.jpg new file mode 100644 index 0000000..a819215 Binary files /dev/null and b/assets/boards/ai-thinker-esp32-cam-ipex.jpg differ diff --git a/assets/boards/ai-thinker-esp32-cam-mb.jpg b/assets/boards/ai-thinker-esp32-cam-mb.jpg new file mode 100644 index 0000000..027ad46 Binary files /dev/null and b/assets/boards/ai-thinker-esp32-cam-mb.jpg differ diff --git a/assets/boards/ai-thinker-esp32-cam.jpg b/assets/boards/ai-thinker-esp32-cam.jpg new file mode 100644 index 0000000..5cca775 Binary files /dev/null and b/assets/boards/ai-thinker-esp32-cam.jpg differ diff --git a/assets/boards/esp32-wrover-cam.jpg b/assets/boards/esp32-wrover-cam.jpg new file mode 100644 index 0000000..f58b5bb Binary files /dev/null and b/assets/boards/esp32-wrover-cam.jpg differ diff --git a/assets/boards/espressif-esp-eye.jpg b/assets/boards/espressif-esp-eye.jpg new file mode 100644 index 0000000..8276dd8 Binary files /dev/null and b/assets/boards/espressif-esp-eye.jpg differ diff --git a/assets/boards/espressif-esps3-eye.jpg b/assets/boards/espressif-esps3-eye.jpg new file mode 100644 index 0000000..79a072e Binary files /dev/null and b/assets/boards/espressif-esps3-eye.jpg differ diff --git a/assets/boards/lilygo-camera-module.jpg b/assets/boards/lilygo-camera-module.jpg new file mode 100644 index 0000000..63312e8 Binary files /dev/null and b/assets/boards/lilygo-camera-module.jpg differ diff --git a/assets/boards/lilygo-simcam.jpg b/assets/boards/lilygo-simcam.jpg new file mode 100644 index 0000000..357f56b Binary files /dev/null and b/assets/boards/lilygo-simcam.jpg differ diff --git a/assets/boards/lilygo-ttgo-t-camera.jpg b/assets/boards/lilygo-ttgo-t-camera.jpg new file mode 100644 index 0000000..4415c24 Binary files /dev/null and b/assets/boards/lilygo-ttgo-t-camera.jpg differ diff --git a/assets/boards/m5stack-esp32-camera.jpg b/assets/boards/m5stack-esp32-camera.jpg new file mode 100644 index 0000000..a240056 Binary files /dev/null and b/assets/boards/m5stack-esp32-camera.jpg differ diff --git a/assets/boards/seeed-studio-xiao-esp32s3-sense.jpg b/assets/boards/seeed-studio-xiao-esp32s3-sense.jpg new file mode 100644 index 0000000..c70122a Binary files /dev/null and b/assets/boards/seeed-studio-xiao-esp32s3-sense.jpg differ diff --git a/generate_html.ps1 b/generate_html.ps1 index 9474aa3..41885f2 100644 --- a/generate_html.ps1 +++ b/generate_html.ps1 @@ -1,5 +1,4 @@ . python3 -m pip install --upgrade pip setuptools wheel . python3 -m pip install minify-html -. python3 ./minify.py ./html/index.html ./html/index.min.html -. python3 ./minify.py ./html/restart.html ./html/restart.min.html \ No newline at end of file +. python3 ./minify.py ./html/index.html ./html/index.min.html \ No newline at end of file diff --git a/generate_html.sh b/generate_html.sh index 7920450..c313849 100755 --- a/generate_html.sh +++ b/generate_html.sh @@ -3,5 +3,4 @@ python3 -m pip install --upgrade pip setuptools wheel python3 -m pip install minify-html -python3 ./minify.py ./html/index.html ./html/index.min.html -python3 ./minify.py ./html/restart.html ./html/restart.min.html \ No newline at end of file +python3 ./minify.py ./html/index.html ./html/index.min.html \ No newline at end of file diff --git a/html/index.html b/html/index.html index cb98c25..4f70823 100644 --- a/html/index.html +++ b/html/index.html @@ -104,17 +104,11 @@ - {{#ConfigChanged}} -
-

- The configuration has been changed.
- It is recommended to restart the device.

- -

-
- {{/ConfigChanged}} +

ESP32

+
Board type:
+
{{BoardType}}
SDK Version:
{{SDKVersion}}
CPU model:
@@ -135,8 +129,6 @@
Uptime:
{{Uptime}}
-
Chip temperature:
-
{{Temperature}} °C
RTSP sessions:
{{NumRTSPSessions}}
Free heap:
@@ -145,14 +137,6 @@
{{MaxAllocHeap}}
-

Peripheral

-
-
Board type:
-
{{BoardType}}
-
LED intensity:
-
{{LedIntensity}} [0-100]
-
-

Network

Host name:
@@ -191,10 +175,6 @@
{{FrameSize}}
JPEG quality:
{{JpegQuality}} [1-100]
-
Enable PSRAM:
-
{{#EnablePSRAM}}Enabled{{/EnablePSRAM}}{{^EnablePSRAM}}Disabled{{/EnablePSRAM}}
-
Number of frame buffers:
-
{{FrameBuffers}}
Brightness:
{{Brightness}} [-2,2]
Contrast:
@@ -262,13 +242,9 @@
RTSP camera stream:
rtsp://{{IpV4}}:{{RtspPort}}/mjpeg/1
JPEG Motion stream:
-
http://{{IpV4}}/stream
+
http://{{IpV4}}/stream
Snapshot of the camera:
-
http://{{IpV4}}/snapshot
-
Intensity of the flash led (0-255):
-
http://{{IpV4}}/flash?v=0 (Authentication required)
-
Restart the camera:
-
http://{{IpV4}}/restart (Authentication required)
+
http://{{IpV4}}/snapshot
diff --git a/html/index.min.html b/html/index.min.html index dca1e1b..b84ac80 100644 --- a/html/index.min.html +++ b/html/index.min.html @@ -1 +1 @@ -{{AppTitle}} v{{AppVersion}}

{{ThingName}}


Press on the button below to change the settings

{{#ConfigChanged}}

The configuration has been changed.
It is recommended to restart the device.

{{/ConfigChanged}}

ESP32

SDK Version:
{{SDKVersion}}
CPU model:
{{ChipModel}} rev. {{ChipRevision}}
CPU speed:
{{CpuFreqMHz}} Mhz
CPU cores:
{{CpuCores}}
RAM size:
{{HeapSize}}
PSRAM size:
{{PsRamSize}}
Flash size:
{{FlashSize}}

Diagnostics

Uptime:
{{Uptime}}
Chip temperature:
{{Temperature}} °C
RTSP sessions:
{{NumRTSPSessions}}
Free heap:
{{FreeHeap}}
Max free block:
{{MaxAllocHeap}}

Peripheral

Board type:
{{BoardType}}
LED intensity:
{{LedIntensity}} [0-100]

Network

Host name:
{{HostName}}
Mac address:
{{MacAddress}}
Wifi mode:
{{WifiMode}}
Access point:
{{AccessPoint}}
Signal strength:
{{SignalStrength}} dbm
IPv4 address:
{{IpV4}}
IPv6 address:
{{IpV6}}
{{#NetworkState.ApMode}}

Not connected to an access point.
Consider configuring the access point.

{{/NetworkState.ApMode}} {{#NetworkState.OnLine}}

Connected to the access point

{{/NetworkState.OnLine}}

Camera

Frame rate:
{{FrameDuration}} ms ({{FrameFrequency}} f/s)
Frame size:
{{FrameSize}}
JPEG quality:
{{JpegQuality}} [1-100]
Enable PSRAM:
{{#EnablePSRAM}}Enabled{{/EnablePSRAM}}{{^EnablePSRAM}}Disabled{{/EnablePSRAM}}
Number of frame buffers:
{{FrameBuffers}}
Brightness:
{{Brightness}} [-2,2]
Contrast:
{{Contrast}} [-2,2]
Saturation:
{{Saturation}} [-2,2]
Special effect:
{{SpecialEffect}}
White balance:
{{#WhiteBal}}Auto{{/WhiteBal}}{{^WhiteBal}}Manual{{/WhiteBal}}
AWB gain:
{{#AwbGain}}Auto{{/AwbGain}}{{^AwbGain}}Manual{{/AwbGain}}
WB mode:
{{WbMode}}
Exposure control:
{{#ExposureCtrl}}Auto{{/ExposureCtrl}}{{^ExposureCtrl}}Manual{{/ExposureCtrl}}
Auto exposure control (dsp):
{{#Aec2}}Enabled{{/Aec2}}{{^Aec2}}Disabled{{/Aec2}}
Auto Exposure level:
{{AeLevel}}
Manual exposure value:
{{AecValue}}
Gain control:
{{#GainCtrl}}Auto{{/GainCtrl}}{{^GainCtrl}}Manual{{/GainCtrl}}
AGC gain:
{{AgcGain}}
Gain ceiling:
{{GainCeiling}}
Black pixel correct:
{{#Bpc}}Auto{{/Bpc}}{{^Bpc}}Manual{{/Bpc}}
White pixel correct:
{{#Wpc}}Auto{{/Wpc}}{{^Wpc}}Manual{{/Wpc}}
Gamma correct:
{{#RawGma}}Enabled{{/RawGma}}{{^RawGma}}Disabled{{/RawGma}}
Lens correction:
{{#Lenc}}Enabled{{/Lenc}}{{^Lenc}}Disabled{{/Lenc}}
Horizontal mirror:
{{#HMirror}}Mirrored{{/HMirror}}{{^HMirror}}Normal{{/HMirror}}
Vertical flip:
{{#VFlip}}Flipped{{/VFlip}}{{^VFlip}}Normal{{/VFlip}}
Downsize enable:
{{#Dcw}}Enabled{{/Dcw}}{{^Dcw}}Disabled{{/Dcw}}
Color bar:
{{#ColorBar}}Enabled{{/ColorBar}}{{^ColorBar}}Camera{{/ColorBar}}
{{#CameraInitialized}}

Camera was initialized successfully!

{{/CameraInitialized}} {{^CameraInitialized}}

Failed to initialize the camera!
Result: {{CameraInitResult}} ({{CameraInitResultText}})
Please check hardware or correct the camera settings and restart.

{{/CameraInitialized}}

Special URLs / API

RTSP camera stream:
rtsp://{{IpV4}}:{{RtspPort}}/mjpeg/1
JPEG Motion stream:
http://{{IpV4}}/stream
Snapshot of the camera:
http://{{IpV4}}/snapshot
Intensity of the flash led (0-255):
http://{{IpV4}}/flash?v=0 (Authentication required)
Restart the camera:
http://{{IpV4}}/restart (Authentication required)
\ No newline at end of file +{{AppTitle}} v{{AppVersion}}

{{ThingName}}


Press on the button below to change the settings

ESP32

Board type:
{{BoardType}}
SDK Version:
{{SDKVersion}}
CPU model:
{{ChipModel}} rev. {{ChipRevision}}
CPU speed:
{{CpuFreqMHz}} Mhz
CPU cores:
{{CpuCores}}
RAM size:
{{HeapSize}}
PSRAM size:
{{PsRamSize}}
Flash size:
{{FlashSize}}

Diagnostics

Uptime:
{{Uptime}}
RTSP sessions:
{{NumRTSPSessions}}
Free heap:
{{FreeHeap}}
Max free block:
{{MaxAllocHeap}}

Network

Host name:
{{HostName}}
Mac address:
{{MacAddress}}
Wifi mode:
{{WifiMode}}
Access point:
{{AccessPoint}}
Signal strength:
{{SignalStrength}} dbm
IPv4 address:
{{IpV4}}
IPv6 address:
{{IpV6}}
{{#NetworkState.ApMode}}

Not connected to an access point.
Consider configuring the access point.

{{/NetworkState.ApMode}} {{#NetworkState.OnLine}}

Connected to the access point

{{/NetworkState.OnLine}}

Camera

Frame rate:
{{FrameDuration}} ms ({{FrameFrequency}} f/s)
Frame size:
{{FrameSize}}
JPEG quality:
{{JpegQuality}} [1-100]
Brightness:
{{Brightness}} [-2,2]
Contrast:
{{Contrast}} [-2,2]
Saturation:
{{Saturation}} [-2,2]
Special effect:
{{SpecialEffect}}
White balance:
{{#WhiteBal}}Auto{{/WhiteBal}}{{^WhiteBal}}Manual{{/WhiteBal}}
AWB gain:
{{#AwbGain}}Auto{{/AwbGain}}{{^AwbGain}}Manual{{/AwbGain}}
WB mode:
{{WbMode}}
Exposure control:
{{#ExposureCtrl}}Auto{{/ExposureCtrl}}{{^ExposureCtrl}}Manual{{/ExposureCtrl}}
Auto exposure control (dsp):
{{#Aec2}}Enabled{{/Aec2}}{{^Aec2}}Disabled{{/Aec2}}
Auto Exposure level:
{{AeLevel}}
Manual exposure value:
{{AecValue}}
Gain control:
{{#GainCtrl}}Auto{{/GainCtrl}}{{^GainCtrl}}Manual{{/GainCtrl}}
AGC gain:
{{AgcGain}}
Gain ceiling:
{{GainCeiling}}
Black pixel correct:
{{#Bpc}}Auto{{/Bpc}}{{^Bpc}}Manual{{/Bpc}}
White pixel correct:
{{#Wpc}}Auto{{/Wpc}}{{^Wpc}}Manual{{/Wpc}}
Gamma correct:
{{#RawGma}}Enabled{{/RawGma}}{{^RawGma}}Disabled{{/RawGma}}
Lens correction:
{{#Lenc}}Enabled{{/Lenc}}{{^Lenc}}Disabled{{/Lenc}}
Horizontal mirror:
{{#HMirror}}Mirrored{{/HMirror}}{{^HMirror}}Normal{{/HMirror}}
Vertical flip:
{{#VFlip}}Flipped{{/VFlip}}{{^VFlip}}Normal{{/VFlip}}
Downsize enable:
{{#Dcw}}Enabled{{/Dcw}}{{^Dcw}}Disabled{{/Dcw}}
Color bar:
{{#ColorBar}}Enabled{{/ColorBar}}{{^ColorBar}}Camera{{/ColorBar}}
{{#CameraInitialized}}

Camera was initialized successfully!

{{/CameraInitialized}} {{^CameraInitialized}}

Failed to initialize the camera!
Result: {{CameraInitResult}} ({{CameraInitResultText}})
Please check hardware or correct the camera settings and restart.

{{/CameraInitialized}}

Special URLs / API

RTSP camera stream:
rtsp://{{IpV4}}:{{RtspPort}}/mjpeg/1
JPEG Motion stream:
http://{{IpV4}}/stream
Snapshot of the camera:
http://{{IpV4}}/snapshot
\ No newline at end of file diff --git a/html/restart.html b/html/restart.html deleted file mode 100644 index 1d5c738..0000000 --- a/html/restart.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - {{AppTitle}} v{{AppVersion}} - - - -

{{ThingName}}

-
- -
-

Restarting

-

- The device is restarting...

- If this page takes longer than a minute, consider performing a power cycle. -

-
- - - - \ No newline at end of file diff --git a/html/restart.min.html b/html/restart.min.html deleted file mode 100644 index 5bf2225..0000000 --- a/html/restart.min.html +++ /dev/null @@ -1 +0,0 @@ -{{AppTitle}} v{{AppVersion}}

{{ThingName}}


Restarting

The device is restarting...

If this page takes longer than a minute, consider performing a power cycle.

\ No newline at end of file diff --git a/include/lookup_camera_config.h b/include/camera_config.h similarity index 68% rename from include/lookup_camera_config.h rename to include/camera_config.h index 65159b0..518756a 100644 --- a/include/lookup_camera_config.h +++ b/include/camera_config.h @@ -1,15 +1,8 @@ #pragma once -#include #include -typedef struct -{ - const char name[17]; - const camera_config_t config; -} camera_config_entry_t; - -constexpr camera_config_t esp32cam_settings = { +constexpr camera_config_t esp32cam_camera_settings = { .pin_pwdn = -1, .pin_reset = 15, .pin_xclk = 27, @@ -32,10 +25,38 @@ constexpr camera_config_t esp32cam_settings = { .pixel_format = PIXFORMAT_JPEG, .frame_size = FRAMESIZE_SVGA, .jpeg_quality = 12, - .fb_count = 2, - .grab_mode = CAMERA_GRAB_WHEN_EMPTY}; + .fb_count = 1, + .fb_location = CAMERA_FB_IN_DRAM, + .grab_mode = CAMERA_GRAB_LATEST}; -constexpr camera_config_t esp32cam_aithinker_settings = { +constexpr camera_config_t esp_eye_camera_settings = { + .pin_pwdn = -1, + .pin_reset = -1, + .pin_xclk = 4, + .pin_sscb_sda = 18, + .pin_sscb_scl = 23, + .pin_d7 = 36, + .pin_d6 = 37, + .pin_d5 = 38, + .pin_d4 = 39, + .pin_d3 = 35, + .pin_d2 = 14, + .pin_d1 = 13, + .pin_d0 = 34, + .pin_vsync = 5, + .pin_href = 27, + .pin_pclk = 25, + .xclk_freq_hz = 20000000, + .ledc_timer = LEDC_TIMER_0, + .ledc_channel = LEDC_CHANNEL_0, + .pixel_format = PIXFORMAT_JPEG, + .frame_size = FRAMESIZE_SVGA, + .jpeg_quality = 12, + .fb_count = 1, + .fb_location = CAMERA_FB_IN_DRAM, + .grab_mode = CAMERA_GRAB_LATEST}; + +constexpr camera_config_t aithinker_camera_settings = { .pin_pwdn = 32, .pin_reset = -1, .pin_xclk = 0, @@ -59,9 +80,10 @@ constexpr camera_config_t esp32cam_aithinker_settings = { .frame_size = FRAMESIZE_SVGA, .jpeg_quality = 12, .fb_count = 2, - .grab_mode = CAMERA_GRAB_WHEN_EMPTY}; + .fb_location = CAMERA_FB_IN_PSRAM, + .grab_mode = CAMERA_GRAB_LATEST}; -constexpr camera_config_t esp32cam_ttgo_t_settings = { +constexpr camera_config_t ttgo_t_camera_settings = { .pin_pwdn = 26, .pin_reset = -1, .pin_xclk = 32, @@ -84,10 +106,11 @@ constexpr camera_config_t esp32cam_ttgo_t_settings = { .pixel_format = PIXFORMAT_JPEG, .frame_size = FRAMESIZE_SVGA, .jpeg_quality = 12, - .fb_count = 2, - .grab_mode = CAMERA_GRAB_WHEN_EMPTY}; + .fb_count = 1, + .fb_location = CAMERA_FB_IN_DRAM, + .grab_mode = CAMERA_GRAB_LATEST}; -constexpr camera_config_t esp32cam_m5stack_settings = { +constexpr camera_config_t m5stack_camera_settings = { .pin_pwdn = -1, .pin_reset = 15, .pin_xclk = 27, @@ -110,10 +133,11 @@ constexpr camera_config_t esp32cam_m5stack_settings = { .pixel_format = PIXFORMAT_JPEG, .frame_size = FRAMESIZE_SVGA, .jpeg_quality = 12, - .fb_count = 2, - .grab_mode = CAMERA_GRAB_WHEN_EMPTY}; + .fb_count = 1, + .fb_location = CAMERA_FB_IN_DRAM, + .grab_mode = CAMERA_GRAB_LATEST}; -constexpr camera_config_t esp32cam_wrover_kit_settings = { +constexpr camera_config_t wrover_kit_camera_settings = { .pin_pwdn = -1, .pin_reset = -1, .pin_xclk = 21, @@ -137,9 +161,10 @@ constexpr camera_config_t esp32cam_wrover_kit_settings = { .frame_size = FRAMESIZE_SVGA, .jpeg_quality = 12, .fb_count = 2, - .grab_mode = CAMERA_GRAB_WHEN_EMPTY}; + .fb_location = CAMERA_FB_IN_PSRAM, + .grab_mode = CAMERA_GRAB_LATEST}; -constexpr camera_config_t esp32cam_xiaoesp32s3_settings = { +constexpr camera_config_t xiao_esp32s3_camera_settings = { .pin_pwdn = -1, .pin_reset = -1, .pin_xclk = 10, @@ -162,23 +187,6 @@ constexpr camera_config_t esp32cam_xiaoesp32s3_settings = { .pixel_format = PIXFORMAT_JPEG, // for streaming .frame_size = FRAMESIZE_UXGA, .jpeg_quality = 12, - .fb_count = 1, - .grab_mode = CAMERA_GRAB_WHEN_EMPTY}; - -constexpr const camera_config_entry_t camera_configs[] = { - {"ESP32CAM", esp32cam_settings}, - {"ESP32CAM_XIAO_S3", esp32cam_xiaoesp32s3_settings}, - {"AI THINKER", esp32cam_aithinker_settings}, - {"TTGO T-CAM", esp32cam_ttgo_t_settings}, - {"M5 STACK", esp32cam_m5stack_settings}, - {"WROVER KIT", esp32cam_wrover_kit_settings}}; - -const camera_config_t lookup_camera_config(const char *name) -{ - // Lookup table for the frame name to framesize_t - for (const auto &entry : camera_configs) - if (strncmp(entry.name, name, sizeof(entry.name)) == 0) - return entry.config; - - return camera_config_t{}; -} + .fb_count = 2, + .fb_location = CAMERA_FB_IN_PSRAM, + .grab_mode = CAMERA_GRAB_LATEST}; \ No newline at end of file diff --git a/include/settings.h b/include/settings.h index 98bc9e2..9678284 100644 --- a/include/settings.h +++ b/include/settings.h @@ -5,23 +5,45 @@ #define WIFI_SSID "ESP32CAM-RTSP" #define WIFI_PASSWORD nullptr -#define CONFIG_VERSION "1.5" +#define CONFIG_VERSION "1.6" #define OTA_PASSWORD "ESP32CAM-RTSP" #define RTSP_PORT 554 -#define DEFAULT_CAMERA_CONFIG "AI THINKER" -#define DEFAULT_ENABLE_PSRAM psramFound() -#define DEFAULT_BUFFERS (psramFound() ? 2 : 1) +#if defined(BOARD_ESP32CAM) +constexpr const char *board_name = "ESP32CAM"; +constexpr camera_config_t default_camera_config = esp32cam_camera_settings; +#elif defined(BOARD_AITHINKER_ESP32CAM) +constexpr const char *board_name = "AI-Thinker ESP32CAM"; +constexpr camera_config_t default_camera_config = aithinker_camera_settings; +#elif defined(BOARD_ESP_EYE) +constexpr const char *board_name = "ESP-EYE"; +constexpr camera_config_t default_camera_config = exp_eye_camera_settings; +#elif defined(BOARD_TTGO_T_CAMERA) +constexpr const char *board_name = "TTGO-T-CAMERA"; +constexpr camera_config_t default_camera_config = ttgo_t_camera_settings; +#elif defined(BOARD_M5STACK_ESP32CAM) +constexpr const char *board_name = "M5STACK-CAMERA"; +constexpr camera_config_t default_camera_config = m5stack_camera_settings; +#elif defined(BOARD_ESP32_WROVER_CAM) +constexpr const char *board_name = "WROVER-KIT"; +constexpr camera_config_t default_camera_config = wrover_kit_camera_settings; +#elif defined(BOARD_SEEED_XIAO_ESP32S3_SENSE) +constexpr const char *board_name = "Seed Xiao ESP32S3 Sense"; +constexpr camera_config_t default_camera_config = xiao_esp32s3_camera_settings; +#elif +#error No board defined +#endif + #define DEFAULT_FRAME_DURATION 200 #define DEFAULT_FRAME_SIZE "VGA (640x480)" #define DEFAULT_JPEG_QUALITY (psramFound() ? 12 : 14) -#define DEFAULT_BRIGHTNESS 0 -#define DEFAULT_CONTRAST 0 -#define DEFAULT_SATURATION 0 -#define DEFAULT_EFFECT "Normal" +#define DEFAULT_BRIGHTNESS 0 +#define DEFAULT_CONTRAST 0 +#define DEFAULT_SATURATION 0 +#define DEFAULT_EFFECT "Normal" #define DEFAULT_WHITE_BALANCE true #define DEFAULT_WHITE_BALANCE_GAIN true #define DEFAULT_WHITE_BALANCE_MODE "Auto" diff --git a/lib/rtsp_server/rtsp_server.h b/lib/rtsp_server/rtsp_server.h index a49a98b..63e207a 100644 --- a/lib/rtsp_server/rtsp_server.h +++ b/lib/rtsp_server/rtsp_server.h @@ -29,7 +29,7 @@ private: std::shared_ptr session; }; - OV2640 cam_; + OV2640 cam_; std::list> clients_; uintptr_t task_; Timer<> timer_; diff --git a/platformio.ini b/platformio.ini index ced4507..1d349c4 100644 --- a/platformio.ini +++ b/platformio.ini @@ -8,15 +8,15 @@ ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html +############################################################################### [env:esp32cam] platform = espressif32 board = esp32cam framework = arduino #upload_protocol = espota -#upload_port = 192.168.50.222 -#upload_flags = -# --auth='ESP32CAM-RTSP' +#upload_port = 192.168.178.223 +#upload_flags = --auth='ESP32CAM-RTSP' # Partition scheme for OTA board_build.partitions = min_spiffs.csv @@ -28,28 +28,30 @@ monitor_filters = log2file, time, default, esp32_exception_decoder build_flags = -O2 + -D BOARD_ESP32CAM -D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE - -D LED_FLASH=4 -D LED_BUILTIN=33 - -D BOARD_HAS_PSRAM - -D TEMPRATURE_SENS_READ -mfix-esp32-psram-cache-issue -D IOTWEBCONF_PASSWORD_LEN=64 board_build.embed_txtfiles = html/index.min.html - html/restart.min.html lib_deps = prampec/IotWebConf @ ^3.2.1 geeksville/Micro-RTSP @ ^0.1.6 rzeldent/micro-moustache@^1.0.1 -[env:seeed_xiao_esp32s3] +############################################################################### +[env:ai_thinker_esp32cam] platform = espressif32 -board = esp32s3box +board = esp32cam framework = arduino +#upload_protocol = espota +#upload_port = 192.168.178.223 +#upload_flags = --auth='ESP32CAM-RTSP' + # Partition scheme for OTA board_build.partitions = min_spiffs.csv @@ -60,16 +62,183 @@ monitor_filters = log2file, time, default, esp32_exception_decoder build_flags = -O2 + -D BOARD_AITHINKER_ESP32CAM + -D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE + -D LED_BUILTIN=33 + -mfix-esp32-psram-cache-issue + -D IOTWEBCONF_PASSWORD_LEN=64 + +board_build.embed_txtfiles = + html/index.min.html + +lib_deps = + prampec/IotWebConf @ ^3.2.1 + geeksville/Micro-RTSP @ ^0.1.6 + rzeldent/micro-moustache@^1.0.1 + +############################################################################### +[env:esp_eye] +platform = espressif32 +board = esp32cam +framework = arduino + +#upload_protocol = espota +#upload_port = 192.168.178.223 +#upload_flags = --auth='ESP32CAM-RTSP' + +# Partition scheme for OTA +board_build.partitions = min_spiffs.csv + +monitor_speed = 115200 +monitor_rts = 0 +monitor_dtr = 0 +monitor_filters = log2file, time, default, esp32_exception_decoder + +build_flags = + -O2 + -D BOARD_ESP_EYE + -D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE + -D LED_BUILTIN=33 + -mfix-esp32-psram-cache-issue + -D IOTWEBCONF_PASSWORD_LEN=64 + +board_build.embed_txtfiles = + html/index.min.html + +lib_deps = + prampec/IotWebConf @ ^3.2.1 + geeksville/Micro-RTSP @ ^0.1.6 + rzeldent/micro-moustache@^1.0.1 + +############################################################################### +[env:ttgo_t_camers] +platform = espressif32 +board = ttgo-t-beam +framework = arduino + +#upload_protocol = espota +#upload_port = 192.168.178.223 +#upload_flags = --auth='ESP32CAM-RTSP' + +# Partition scheme for OTA +board_build.partitions = min_spiffs.csv + +monitor_speed = 115200 +monitor_rts = 0 +monitor_dtr = 0 +monitor_filters = log2file, time, default, esp32_exception_decoder + +build_flags = + -O2 + -D BOARD_TTGO_T_CAMERA + -D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE + -D LED_BUILTIN=33 + -mfix-esp32-psram-cache-issue + -D IOTWEBCONF_PASSWORD_LEN=64 + +board_build.embed_txtfiles = + html/index.min.html + +lib_deps = + prampec/IotWebConf @ ^3.2.1 + geeksville/Micro-RTSP @ ^0.1.6 + rzeldent/micro-moustache@^1.0.1 + +############################################################################### +[env:m5stack_esp32cam] +platform = espressif32 +board = m5stack-core-esp32 +framework = arduino + +#upload_protocol = espota +#upload_port = 192.168.178.223 +#upload_flags = --auth='ESP32CAM-RTSP' + +# Partition scheme for OTA +board_build.partitions = min_spiffs.csv + +monitor_speed = 115200 +monitor_rts = 0 +monitor_dtr = 0 +monitor_filters = log2file, time, default, esp32_exception_decoder + +build_flags = + -O2 + -D BOARD_M5STACK_ESP32CAM + -D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE + -D LED_BUILTIN=33 + -mfix-esp32-psram-cache-issue + -D IOTWEBCONF_PASSWORD_LEN=64 + +board_build.embed_txtfiles = + html/index.min.html + +lib_deps = + prampec/IotWebConf @ ^3.2.1 + geeksville/Micro-RTSP @ ^0.1.6 + rzeldent/micro-moustache@^1.0.1 + +############################################################################### +[env:esp32_wrover_cam] +platform = espressif32 +board = esp-wrover-kit +framework = arduino + +#upload_protocol = espota +#upload_port = 192.168.178.223 +#upload_flags = --auth='ESP32CAM-RTSP' + +# Partition scheme for OTA +board_build.partitions = min_spiffs.csv + +monitor_speed = 115200 +monitor_rts = 0 +monitor_dtr = 0 +monitor_filters = log2file, time, default, esp32_exception_decoder + +build_flags = + -O2 + -D BOARD_ESP32_WROVER_CAM + -D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE + -D LED_BUILTIN=2 + -mfix-esp32-psram-cache-issue + -D IOTWEBCONF_PASSWORD_LEN=64 + +board_build.embed_txtfiles = + html/index.min.html + +lib_deps = + prampec/IotWebConf @ ^3.2.1 + geeksville/Micro-RTSP @ ^0.1.6 + rzeldent/micro-moustache@^1.0.1 + +############################################################################### +[env:seeed_xiao_esp32s3_sense] +platform = espressif32 +board = seeed_xiao_esp32s3 +framework = arduino + +# Partition scheme for OTA +board_build.partitions = min_spiffs.csv + +#upload_protocol = espota +#upload_port = 192.168.178.223 +#upload_flags = --auth='ESP32CAM-RTSP' + +monitor_speed = 115200 +monitor_rts = 0 +monitor_dtr = 0 +monitor_filters = log2file, time, default, esp32_exception_decoder + +build_flags = + -O2 + -D BOARD_SEEED_XIAO_ESP32S3_SENSE -D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE - -D LED_FLASH=8 - -D LED_BUILTIN=21 - -D BOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -D IOTWEBCONF_PASSWORD_LEN=64 board_build.embed_txtfiles = html/index.min.html - html/restart.min.html lib_deps = prampec/IotWebConf @ ^3.2.1 diff --git a/src/main.cpp b/src/main.cpp index bb302e3..b0d17b7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include @@ -17,21 +17,13 @@ #include #include -extern "C" uint8_t temprature_sens_read(); - // HTML files extern const char index_html_min_start[] asm("_binary_html_index_min_html_start"); -extern const char restart_html_min_start[] asm("_binary_html_restart_min_html_start"); - -auto param_group_board = iotwebconf::ParameterGroup("board", "Board settings"); -auto param_board = iotwebconf::Builder>("bt").label("Board").optionValues((const char *)&camera_configs).optionNames((const char *)&camera_configs).optionCount(sizeof(camera_configs) / sizeof(camera_configs[0])).nameLength(sizeof(camera_configs[0])).defaultValue(DEFAULT_CAMERA_CONFIG).build(); auto param_group_camera = iotwebconf::ParameterGroup("camera", "Camera settings"); auto param_frame_duration = iotwebconf::Builder>("fd").label("Frame duration (ms)").defaultValue(DEFAULT_FRAME_DURATION).min(10).build(); auto param_frame_size = iotwebconf::Builder>("fs").label("Frame size").optionValues((const char *)&frame_sizes).optionNames((const char *)&frame_sizes).optionCount(sizeof(frame_sizes) / sizeof(frame_sizes[0])).nameLength(sizeof(frame_sizes[0])).defaultValue(DEFAULT_FRAME_SIZE).build(); auto param_jpg_quality = iotwebconf::Builder>("q").label("JPG quality").defaultValue(DEFAULT_JPEG_QUALITY).min(1).max(100).build(); -auto param_enable_psram = iotwebconf::Builder("eps").label("Enable PSRAM if available").defaultValue(DEFAULT_ENABLE_PSRAM).build(); -auto param_frame_buffers = iotwebconf::Builder>("fb").label("Buffers").defaultValue(DEFAULT_BUFFERS).min(1).max(4).build(); auto param_brightness = iotwebconf::Builder>("b").label("Brightness").defaultValue(DEFAULT_BRIGHTNESS).min(-2).max(2).build(); auto param_contrast = iotwebconf::Builder>("c").label("Contrast").defaultValue(DEFAULT_CONTRAST).min(-2).max(2).build(); auto param_saturation = iotwebconf::Builder>("s").label("Saturation").defaultValue(DEFAULT_SATURATION).min(-2).max(2).build(); @@ -55,9 +47,6 @@ auto param_vflip = iotwebconf::Builder("vm").lab auto param_dcw = iotwebconf::Builder("dcw").label("Downsize enable").defaultValue(DEFAULT_DCW).build(); auto param_colorbar = iotwebconf::Builder("cb").label("Colorbar").defaultValue(DEFAULT_COLORBAR).build(); -auto param_group_peripheral = iotwebconf::ParameterGroup("io", "peripheral settings"); -auto param_led_intensity = iotwebconf::Builder>("li").label("LED intensity").defaultValue(DEFAULT_LED_INTENSITY).min(0).max(100).build(); - // Camera OV2640 cam; // DNS Server @@ -70,8 +59,6 @@ WebServer web_server(80); auto thingName = String(WIFI_SSID) + "-" + String(ESP.getEfuseMac(), 16); IotWebConf iotWebConf(thingName.c_str(), &dnsServer, &web_server, WIFI_PASSWORD, CONFIG_VERSION); -// Keep track of config changes. This will allow a reset of the device -bool config_changed = false; // Camera initialization result esp_err_t camera_init_result; @@ -103,11 +90,10 @@ void handle_root() auto ipv6 = WiFi.getMode() == WIFI_MODE_AP ? WiFi.softAPIPv6() : WiFi.localIPv6(); moustache_variable_t substitutions[] = { - // Config Changed? - {"ConfigChanged", String(config_changed)}, // Version / CPU {"AppTitle", APP_TITLE}, {"AppVersion", APP_VERSION}, + {"BoardType", board_name}, {"ThingName", iotWebConf.getThingName()}, {"SDKVersion", ESP.getSdkVersion()}, {"ChipModel", ESP.getChipModel()}, @@ -119,11 +105,6 @@ void handle_root() {"PsRamSize", format_memory(ESP.getPsramSize(), 0)}, // Diagnostics {"Uptime", String(format_duration(millis() / 1000))}, -#ifdef TEMPRATURE_SENS_READ - {"Temperature", String((temprature_sens_read() - 32) / 1.8)}, -#else - {"Temperature", "N/A"}, -#endif {"FreeHeap", format_memory(ESP.getFreeHeap())}, {"MaxAllocHeap", format_memory(ESP.getMaxAllocHeap())}, {"NumRTSPSessions", camera_server != nullptr ? String(camera_server->num_connected()) : "RTSP server disabled"}, @@ -138,13 +119,10 @@ void handle_root() {"NetworkState.ApMode", String(iotWebConf.getState() == iotwebconf::NetworkState::ApMode)}, {"NetworkState.OnLine", String(iotWebConf.getState() == iotwebconf::NetworkState::OnLine)}, // Camera - {"BoardType", String(param_board.value())}, {"FrameSize", String(param_frame_size.value())}, {"FrameDuration", String(param_frame_duration.value())}, {"FrameFrequency", String(1000.0 / param_frame_duration.value(), 1)}, {"JpegQuality", String(param_jpg_quality.value())}, - {"EnablePSRAM", String(param_enable_psram.value())}, - {"FrameBuffers", String(param_frame_buffers.value())}, {"CameraInitialized", String(camera_init_result == ESP_OK)}, {"CameraInitResult", String(camera_init_result)}, {"CameraInitResultText", esp_err_to_name(camera_init_result)}, @@ -171,8 +149,6 @@ void handle_root() {"VFlip", String(param_vflip.value())}, {"Dcw", String(param_dcw.value())}, {"ColorBar", String(param_colorbar.value())}, - // LED - {"LedIntensity", String(param_led_intensity.value())}, // RTSP {"RtspPort", String(RTSP_PORT)}}; @@ -181,28 +157,6 @@ void handle_root() web_server.send(200, "text/html", html); } -void handle_restart() -{ - log_v("Handle restart"); - - if (!web_server.authenticate("admin", iotWebConf.getApPasswordParameter()->valueBuffer)) - { - web_server.requestAuthentication(BASIC_AUTH, APP_TITLE, "401 Unauthorized

The password is incorrect."); - return; - } - - moustache_variable_t substitutions[] = { - {"AppTitle", APP_TITLE}, - {"AppVersion", APP_VERSION}, - {"ThingName", iotWebConf.getThingName()}}; - - auto html = moustache_render(restart_html_min_start, substitutions); - web_server.send(200, "text/html", html); - log_v("Restarting... Press refresh to connect again"); - sleep(100); - ESP.restart(); -} - void handle_snapshot() { log_v("handle_snapshot"); @@ -213,7 +167,7 @@ void handle_snapshot() } // Remove old images stored in the frame buffer - auto frame_buffers = param_frame_buffers.value(); + auto frame_buffers = default_camera_config.fb_count; while (frame_buffers--) cam.run(); @@ -261,64 +215,19 @@ void handle_stream() client.stop(); log_v("stopped streaming"); } - -void handle_flash() -{ - log_v("handle_flash"); - - if (!web_server.authenticate("admin", iotWebConf.getApPasswordParameter()->valueBuffer)) - { - web_server.requestAuthentication(BASIC_AUTH, APP_TITLE, "401 Unauthorized

The password is incorrect."); - return; - } - - // If no value present, use value from config - if (web_server.hasArg("v")) - { - auto v = (uint8_t)min(web_server.arg("v").toInt(), 255L); - // If conversion fails, v = 0 - analogWrite(LED_FLASH, v); - } - else - { - analogWrite(LED_FLASH, param_led_intensity.value()); - } - - web_server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); - web_server.send(200); -} - esp_err_t initialize_camera() { log_v("initialize_camera"); - log_i("Camera config: %s", param_board.value()); - auto camera_config_template = lookup_camera_config(param_board.value()); // Copy the settings camera_config_t camera_config; memset(&camera_config, 0, sizeof(camera_config_t)); - memcpy(&camera_config, &camera_config_template, sizeof(camera_config_t)); + memcpy(&camera_config, &default_camera_config, sizeof(camera_config_t)); log_i("Frame size: %s", param_frame_size.value()); auto frame_size = lookup_frame_size(param_frame_size.value()); log_i("JPEG quality: %d", param_jpg_quality.value()); log_i("Frame duration: %d ms", param_frame_duration.value()); camera_config.frame_size = frame_size; camera_config.jpeg_quality = param_jpg_quality.value(); - camera_config.grab_mode = CAMERA_GRAB_LATEST; - log_i("Enable PSRAM: %d", param_enable_psram.value()); - log_i("Frame buffers: %d", param_frame_buffers.value()); - camera_config.fb_count = param_frame_buffers.value(); - - if (param_enable_psram.value() && psramFound()) - { - camera_config.fb_location = CAMERA_FB_IN_PSRAM; - log_i("PSRAM enabled!"); - } - else - { - camera_config.fb_location = CAMERA_FB_IN_DRAM; - log_i("PSRAM disabled"); - } - return cam.init(camera_config); } @@ -379,26 +288,17 @@ void on_connected() void on_config_saved() { log_v("on_config_saved"); - // Set flash led intensity - analogWrite(LED_FLASH, param_led_intensity.value()); - // Update camera setting update_camera_settings(); - config_changed = true; } void setup() { // Disable brownout WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); - // LED_BUILTIN (GPIO33) has inverted logic false => LED on pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, false); - pinMode(LED_FLASH, OUTPUT); - // Turn flash led off - analogWrite(LED_FLASH, 0); - #ifdef CORE_DEBUG_LEVEL Serial.begin(115200); Serial.setDebugOutput(true); @@ -407,22 +307,19 @@ void setup() log_i("CPU Freq: %d Mhz, %d core(s)", getCpuFrequencyMhz(), ESP.getChipCores()); log_i("Free heap: %d bytes", ESP.getFreeHeap()); log_i("SDK version: %s", ESP.getSdkVersion()); + log_i("Board: %s", board_name); log_i("Starting " APP_TITLE "..."); - if (psramFound()) - { - psramInit(); - log_v("PSRAM found and initialized"); - } - param_group_board.addItem(¶m_board); - iotWebConf.addParameterGroup(¶m_group_board); + if (default_camera_config.fb_location == CAMERA_FB_IN_PSRAM) + { + if (!psramInit()) + log_e("Failed to initialize PSRAM"); + } param_group_camera.addItem(¶m_frame_duration); param_group_camera.addItem(¶m_frame_size); param_group_camera.addItem(¶m_jpg_quality); - param_group_camera.addItem(¶m_enable_psram); - param_group_camera.addItem(¶m_frame_buffers); param_group_camera.addItem(¶m_brightness); param_group_camera.addItem(¶m_contrast); param_group_camera.addItem(¶m_saturation); @@ -447,9 +344,6 @@ void setup() param_group_camera.addItem(¶m_colorbar); iotWebConf.addParameterGroup(¶m_group_camera); - param_group_peripheral.addItem(¶m_led_intensity); - iotWebConf.addParameterGroup(¶m_group_peripheral); - iotWebConf.getApTimeoutParameter()->visible = true; iotWebConf.setConfigSavedCallback(on_config_saved); iotWebConf.setWifiConnectionCallback(on_connected); @@ -460,19 +354,16 @@ void setup() if (camera_init_result == ESP_OK) update_camera_settings(); else - log_e("Failed to initialize camera: 0x%0x. Type: %s, frame size: %s, frame rate: %d ms, jpeg quality: %d", camera_init_result, param_board.value(), param_frame_size.value(), param_frame_duration.value(), param_jpg_quality.value()); + log_e("Failed to initialize camera: 0x%0x. Frame size: %s, frame rate: %d ms, jpeg quality: %d", camera_init_result, param_frame_size.value(), param_frame_duration.value(), param_jpg_quality.value()); // Set up required URL handlers on the web server web_server.on("/", HTTP_GET, handle_root); web_server.on("/config", [] { iotWebConf.handleConfig(); }); - web_server.on("/restart", HTTP_GET, handle_restart); // Camera snapshot web_server.on("/snapshot", HTTP_GET, handle_snapshot); // Camera stream web_server.on("/stream", HTTP_GET, handle_stream); - // Camera flash light - web_server.on("/flash", HTTP_GET, handle_flash); web_server.onNotFound([]() { iotWebConf.handleNotFound(); }); @@ -496,9 +387,6 @@ void setup() case OTA_END_ERROR: log_e("OTA: End Failed"); break; default: log_e("OTA error: %u", error); } }); - - // Set flash led intensity - analogWrite(LED_FLASH, param_led_intensity.value()); } void loop()