Compare commits

..

56 Commits

Author SHA1 Message Date
Miroslav Pivovarsky db0112e9c2
Update README.md 2025-01-02 21:28:35 +01:00
Miroslav Pivovarsky 9a70b1c31b update picture 2025-01-02 21:27:35 +01:00
Miroslav Pivovarsky d42ba99511 added picture 2025-01-02 21:19:43 +01:00
Miroslav Pivovarsky 0b1f3b75cd
Merge pull request #67 from devsfan3/patch-1
Update README
2025-01-02 21:01:26 +01:00
Miroslav Pivovarsky 8dd9cf66e9 fix typo 2025-01-02 20:18:19 +01:00
Miroslav Pivovarsky 10cb00fdcd update build script 2025-01-02 20:17:04 +01:00
Miroslav Pivovarsky 5608b4c4c4 added ESP32-S3 WROOM Freenove board 2025-01-02 20:16:52 +01:00
Miroslav Pivovarsky df58d5d5cb update libs 2025-01-02 20:16:06 +01:00
Miroslav Pivovarsky 80711f9722
Update mcu_cfg.h 2025-01-02 20:12:03 +01:00
Miroslav Pivovarsky d7e39a1a4d
Merge pull request #92 from muesli/bump-version
Bump to v1.1.1
2025-01-02 20:08:52 +01:00
Miroslav Pivovarsky 5888e42c9d
Update README.md 2024-12-28 13:05:06 +01:00
Miroslav Pivovarsky 1770b0bc62
Update README.md 2024-12-28 13:03:55 +01:00
Miroslav Pivovarsky 734fe6325b Updated documentation for ESP32-S3 WROOM Freenove 2024-12-28 12:58:21 +01:00
Miroslav Pivovarsky e93f7ee0e4 update pinout for ESP32-S3 wroom Freenove 2024-12-28 12:55:25 +01:00
Miroslav Pivovarsky 999968ef94 Added support for ESP32-S3 Wroom Freenove 2024-12-27 23:34:48 +01:00
Miroslav Pivovarsky 8180aa84c0 update libs 2024-12-27 23:33:40 +01:00
Christian Muehlhaeuser 7a90f47a1e Bump to v1.1.1 2024-12-03 00:08:31 +01:00
Miroslav Pivovarsky aebd048651 Merge branch 'master' of https://github.com/prusa3d/Prusa-Firmware-ESP32-Cam 2024-11-26 21:58:37 +01:00
Miroslav Pivovarsky 607c768832 update jquery lib to 3.7.1 2024-11-26 21:58:18 +01:00
Miroslav Pivovarsky 41fad4bcd3 change stack size 2024-11-26 21:57:49 +01:00
Miroslav Pivovarsky 5d0527e7a2
Merge pull request #89 from muesli/readme-link
Fix Freenove ESP32-S3 link
2024-11-25 16:59:27 +01:00
Christian Muehlhaeuser bc8d613edb Fix Freenove ESP32-S3 link 2024-11-22 02:44:43 +01:00
Miroslav Pivovarsky 78ed136785 update readme 2024-11-20 21:15:35 +01:00
Miroslav Pivovarsky 1e22640cdf update tasks stack size 2024-11-20 21:15:18 +01:00
Miroslav Pivovarsky d55035b31a Added FW version in the info message for the Prusa Connect 2024-11-20 21:14:27 +01:00
Miroslav Pivovarsky d9394e4c6b Update libs. arduino-esp32, ESPAsyncWebServer, AsyncTCP, ArduinoJson, DHTnew 2024-11-20 21:13:53 +01:00
Miroslav Pivovarsky cf6af3958f regenerate WebPage.h 2024-11-20 21:13:00 +01:00
Miroslav Pivovarsky cd63bcb8ad init freenove esp32-s3-wroom cam docu 2024-11-20 21:09:24 +01:00
Miroslav Pivovarsky 7148425bd6
Merge pull request #88 from muesli/readme-cleanup
Typo and rewording of the central README
2024-11-20 20:46:55 +01:00
Christian Muehlhaeuser e5814de1ad Typo and rewording of the central README 2024-11-19 10:52:56 +01:00
Miroslav Pivovarsky 6f787e3f9d
Merge pull request #87 from muesli/typo-readme
Fix various typos in READMEs
2024-11-19 07:26:07 +01:00
Christian Muehlhaeuser fab36176f7 Fix various typos in READMEs 2024-11-19 06:13:28 +01:00
Miroslav Pivovarsky 08a3f076ab
Merge pull request #77 from ZevEisenberg/master
Fix typos and add .gitignore
2024-11-18 20:58:55 +01:00
Miroslav Pivovarsky 1394cc891f
Merge pull request #80 from muesli/typo-erase
Fix "erase" typo in docs
2024-11-18 20:58:04 +01:00
Miroslav Pivovarsky 09fce11834
Merge pull request #83 from ZevEisenberg/patch-1
Indicate that the printer must be powered on
2024-11-18 20:57:40 +01:00
Miroslav Pivovarsky e73241d68b
Merge pull request #86 from BNoiZe/patch-1
Update README.md
2024-11-18 20:57:13 +01:00
Roman Schmerold 948ebdbd4d
Update README.md
Fixed a typo (--erase-all)
2024-11-17 21:37:39 +01:00
Zev Eisenberg 4b2fde2a21
Indicate that the printer must be powered on. 2024-10-30 22:49:11 -04:00
Christian Muehlhaeuser ba3d4660c7 Fix typo in docs 2024-10-26 00:47:55 +02:00
Zev Eisenberg 4edd60f1c3 Clarify comments. 2024-10-21 22:52:59 -04:00
Zev Eisenberg 39f10d23df Fix copypasta action comment. 2024-10-21 22:51:15 -04:00
Zev Eisenberg b29b541eb3 Add newline at end of file. 2024-10-21 22:31:03 -04:00
Zev Eisenberg a80b349576 Wording. 2024-10-21 22:30:56 -04:00
Zev Eisenberg 9b9fc6cf8a Add .gitignore. 2024-10-21 22:27:53 -04:00
Zev Eisenberg 49c4bb80fe Pluralize seconds. 2024-10-21 22:23:28 -04:00
devsfan3 8e87eaca88
Add files via upload 2024-09-12 17:12:45 -05:00
devsfan3 b29945df10
Update README.md 2024-09-12 17:12:13 -05:00
devsfan3 009ff6741c
Update README.md
Added a how-to on how to use ESP Tool on Chrome to flash boards.
2024-09-12 17:06:02 -05:00
Miroslav Pivovarsky 6d13443061
Update README.md 2024-08-30 22:41:02 +02:00
Miroslav Pivovarsky 5a78bc6df3
Update README.md 2024-08-30 22:39:37 +02:00
Miroslav Pivovarsky 65383926d7
Update README.md 2024-08-30 22:39:18 +02:00
Miroslav Pivovarsky 92a8ccfe75
Update README.md 2024-08-30 22:38:53 +02:00
Miroslav Pivovarsky 24e71d5ade
Update README.md 2024-08-30 22:37:34 +02:00
Miroslav Pivovarsky fa57491e22
Merge pull request #60 from OniriCorpe/patch-1
set wifi password input field as a "password" type
2024-08-22 22:06:59 +02:00
OniriCorpe 496fd111af
set wifi password input field as a "password" type
else the autocorrection is enabled on smartphone and it's really annoying af
2024-08-13 13:38:53 +02:00
Miroslav Pivovarsky 5c420e384c
Update README.md 2024-08-05 21:36:30 +02:00
113 changed files with 12066 additions and 136 deletions

70
.gitignore vendored Normal file
View File

@ -0,0 +1,70 @@
# Created by https://www.toptal.com/developers/gitignore/api/c++,macos
# Edit at https://www.toptal.com/developers/gitignore?templates=c++,macos
### C++ ###
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.out
*.app
### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### macOS Patch ###
# iCloud generated files
*.icloud
# End of https://www.toptal.com/developers/gitignore/api/c++,macos

View File

@ -8,12 +8,12 @@
This project uses other libraries. It is necessary to install them in the arduino IDE.
- Library - License - Version - Link
- ESPAsyncWebServer - LGPL 3.0 - 3.0.6 - https://github.com/mathieucarbou/ESPAsyncWebServer
- AsyncTCP - LGPL 3.0 - 3.1.4 - https://github.com/mathieucarbou/AsyncTCP
- ArduinoJson - MIT - 7.1.0 - https://github.com/bblanchon/ArduinoJson
- ESPAsyncWebServer - LGPL 3.0 - 3.4.5 - https://github.com/mathieucarbou/ESPAsyncWebServer
- AsyncTCP - LGPL 3.0 - 3.3.1 - https://github.com/mathieucarbou/AsyncTCP
- ArduinoJson - MIT - 7.3.0 - https://github.com/bblanchon/ArduinoJson
- ArduinoUniqueID - MIT - 1.3.0 - https://github.com/ricaun/ArduinoUniqueID
- arduino-esp32 - LGPL 2.1 - 3.0.4 - https://github.com/espressif/arduino-esp32
- DHTnew - MIT - 0.4.20 - https://github.com/RobTillaart/DHTNew
- arduino-esp32 - LGPL 2.1 - 3.1.0 - https://github.com/espressif/arduino-esp32
- DHTnew - MIT - 0.5.2 - https://github.com/RobTillaart/DHTNew
Arduino IDE configuration for the MCU are stored in the module_XXX.h file.
@ -113,7 +113,7 @@ void setup() {
/* init tasks */
SystemLog.AddEvent(LogLevel_Info, F("Start tasks"));
xTaskCreatePinnedToCore(System_TaskMain, "SystemNtpOtaUpdate", 5000, NULL, 1, &Task_SystemMain, 0); /*function, description, stack size, parameters, priority, task handle, core*/
xTaskCreatePinnedToCore(System_TaskMain, "SystemNtpOtaUpdate", 5200, NULL, 1, &Task_SystemMain, 0); /*function, description, stack size, parameters, priority, task handle, core*/
ESP_ERROR_CHECK(esp_task_wdt_add(Task_SystemMain));
xTaskCreatePinnedToCore(System_TaskCaptureAndSendPhoto, "CaptureAndSendPhoto", 4400, NULL, 2, &Task_CapturePhotoAndSend, 0); /*function, description, stack size, parameters, priority, task handle, core*/
ESP_ERROR_CHECK(esp_task_wdt_add(Task_CapturePhotoAndSend));
@ -123,11 +123,11 @@ void setup() {
xTaskCreatePinnedToCore(System_TaskSdCardCheck, "CheckMicroSdCard", 3000, NULL, 4, &Task_SdCardCheck, 0); /*function, description, stack size, parameters, priority, task handle, core*/
ESP_ERROR_CHECK(esp_task_wdt_add(Task_SdCardCheck));
#endif
xTaskCreatePinnedToCore(System_TaskSerialCfg, "CheckSerialConfiguration", 2400, NULL, 5, &Task_SerialCfg, 0); /*function, description, stack size, parameters, priority, task handle, core*/
xTaskCreatePinnedToCore(System_TaskSerialCfg, "CheckSerialConfiguration", 2300, NULL, 5, &Task_SerialCfg, 0); /*function, description, stack size, parameters, priority, task handle, core*/
ESP_ERROR_CHECK(esp_task_wdt_add(Task_SerialCfg));
xTaskCreatePinnedToCore(System_TaskSystemTelemetry, "PrintSystemTelemetry", 2200, NULL, 6, &Task_SystemTelemetry, 0); /*function, description, stack size, parameters, priority, task handle, core*/
ESP_ERROR_CHECK(esp_task_wdt_add(Task_SystemTelemetry));
xTaskCreatePinnedToCore(System_TaskSysLed, "SystemLed", 2100, NULL, 7, &Task_SysLed, 0); /*function, description, stack size, parameters, priority, task handle, core*/
xTaskCreatePinnedToCore(System_TaskSysLed, "SystemLed", 2000, NULL, 7, &Task_SysLed, 0); /*function, description, stack size, parameters, priority, task handle, core*/
ESP_ERROR_CHECK(esp_task_wdt_add(Task_SysLed));
xTaskCreatePinnedToCore(System_TaskWiFiWatchdog, "WiFiWatchdog", 2200, NULL, 8, &Task_WiFiWatchdog, 0); /*function, description, stack size, parameters, priority, task handle, core*/
ESP_ERROR_CHECK(esp_task_wdt_add(Task_WiFiWatchdog));

View File

@ -29,7 +29,7 @@ const char index_html[] PROGMEM = R"rawliteral(
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="stylesheet" type="text/css" href="styles.css?v=1.0.0">
<script src="jquery-3.7.0.min.js"></script>
<script src="/jquery-3.7.0.min.js"></script>
<script>
$(document).ready(function () {
$("a").click(function (e) {
@ -98,13 +98,13 @@ const char index_html[] PROGMEM = R"rawliteral(
<td><a href="https://github.com/Prusa-Development/Prusa-Firmware-ESP32-Cam/" id="github-link"><svg height="25"><image href="github-icon.svg"></svg></a></td>
</tr></table>
</body>
<script src="scripts.js"></script>
<script>
sliderCheck();
get_data();
addClickListener('github-link');
addClickListener('forum-link');
</script>
<script src="scripts.js"></script>
<script>
sliderCheck();
get_data();
addClickListener('github-link');
addClickListener('forum-link');
</script>
</html>
)rawliteral";
@ -176,7 +176,7 @@ const char page_wifi_html[] PROGMEM = R"rawliteral(
<table>
<tr><td class="w1">Connect to Wi-Fi network</td></tr>
<tr><td class="w2" align="right">Wi-Fi network name (SSID) </td><td><input type="text" name="wifi_ssid" id=wifi_ssid_id ></td></tr>
<tr><td class="w2" align="right">Password </td><td><input type="text" name="wifi_pass" id=wifi_pass_id></td></tr>
<tr><td class="w2" align="right">Password </td><td><input type="password" name="wifi_pass" id=wifi_pass_id></td></tr>
<tr><td></td><td align="center"><button class="btn_save_w" onclick="setWifi(document.getElementById('wifi_ssid_id').value, document.getElementById('wifi_pass_id').value)">Save & Connect</button></td></tr>
</table>
</td><td></td></tr>
@ -210,7 +210,7 @@ const char page_wifi_html[] PROGMEM = R"rawliteral(
setTimeout(function(){GetDataAndPrintTableWiFi();}, 500);
get_data("wifi");
setupCollapsibleButtonsWiFi();
</script>
</script>
)rawliteral";
/* ------------------------------------------------------------------------------------------------------------ */
@ -1342,7 +1342,7 @@ function updateProgress() {
function checkUpdate() {
var xmlHttp = new XMLHttpRequest();
alert("Connecting to server... Please wait several second");
alert("Connecting to server... Please wait several seconds");
xmlHttp.open("GET", "/check_web_ota_update", false);
xmlHttp.send(null);
alert(xmlHttp.responseText);

View File

@ -52,10 +52,19 @@ void Server_InitWebServer() {
/* send photo with exif data */
SystemLog.AddEvent(LogLevel_Verbose, F("Send photo with EXIF data"));
size_t total_len = SystemCamera.GetPhotoExifData()->len + SystemCamera.GetPhotoFb()->len - SystemCamera.GetPhotoExifData()->offset;
auto response = request->beginResponseStream("image/jpg");
auto response = request->beginChunkedResponse("image/jpg", [total_len](uint8_t *buffer, size_t maxLen, size_t index) -> size_t {
size_t len = 0;
if (index < SystemCamera.GetPhotoExifData()->len) {
len = min(maxLen, SystemCamera.GetPhotoExifData()->len - index);
memcpy(buffer, SystemCamera.GetPhotoExifData()->header + index, len);
} else {
size_t offset = index - SystemCamera.GetPhotoExifData()->len + SystemCamera.GetPhotoExifData()->offset;
len = min(maxLen, SystemCamera.GetPhotoFb()->len - offset);
memcpy(buffer, SystemCamera.GetPhotoFb()->buf + offset, len);
}
return len;
});
response->addHeader("Content-Length", String(total_len));
response->write(SystemCamera.GetPhotoExifData()->header, SystemCamera.GetPhotoExifData()->len);
response->write(&SystemCamera.GetPhotoFb()->buf[SystemCamera.GetPhotoExifData()->offset], SystemCamera.GetPhotoFb()->len - SystemCamera.GetPhotoExifData()->offset);
request->send(response);
} else {

View File

@ -254,12 +254,12 @@ void Camera::SetFlashStatus(bool i_data) {
}
#endif
/* Neopixel control of the FLASH */
/* rgbLedWrite control of the FLASH */
#if (true == CAMERA_FLASH_NEOPIXEL)
if (true == i_data) {
neopixelWrite(FLASH_NEOPIXEL_LED_PIN, RGB_BRIGHTNESS, RGB_BRIGHTNESS, RGB_BRIGHTNESS);
rgbLedWrite(FLASH_NEOPIXEL_LED_PIN, RGB_BRIGHTNESS, RGB_BRIGHTNESS, RGB_BRIGHTNESS);
} else if (false == i_data) {
neopixelWrite(FLASH_NEOPIXEL_LED_PIN, 0, 0, 0);
rgbLedWrite(FLASH_NEOPIXEL_LED_PIN, 0, 0, 0);
}
#endif
#endif

View File

@ -269,6 +269,9 @@ void PrusaConnect::SendInfoToBackend() {
JsonObject config = json_data["config"].to<JsonObject>();
config["name"] = wifi->GetMdns();
config["firmware"] = SW_VERSION;
config["manufacturer"] = F("Prusa");
config["model"] = BOARD_NAME;
JsonObject resolution = config["resolution"].to<JsonObject>();
resolution["width"] = SystemCamera.GetFrameSizeWidth();

File diff suppressed because one or more lines are too long

View File

@ -7,22 +7,22 @@
Contact: miroslav.pivovarsky@gmail.com
@bug: no know bug
*/
#ifndef _MCU_CFG_H_
#define _MCU_CFG_H_
/* ----------------- CAMERA TYPE ---------------*/
#define AI_THINKER_ESP32_CAM true
#define ESP32_WROVER_DEV false
#define CAMERA_MODEL_ESP32_S3_DEV_CAM false
#define CAMERA_MODEL_ESP32_S3_EYE_2_2 false
#define CAMERA_MODEL_XIAO_ESP32_S3_CAM false
#define CAMERA_MODEL_ESP32_S3_CAM false
#define AI_THINKER_ESP32_CAM true
#define ESP32_WROVER_DEV false
#define CAMERA_MODEL_ESP32_S3_DEV_CAM false
#define CAMERA_MODEL_ESP32_S3_EYE_2_2 false
#define CAMERA_MODEL_XIAO_ESP32_S3_CAM false
#define CAMERA_MODEL_ESP32_S3_CAM false
#define ESP32_S3_WROOM_FREENOVE false
/* ---------------- BASIC MCU CFG --------------*/
#define SW_VERSION "1.1.0" ///< SW version
#define SW_VERSION "1.1.2" ///< SW version
#define SW_BUILD __DATE__ " " __TIME__ ///< build number
#define CONSOLE_VERBOSE_DEBUG false ///< enable/disable verbose debug log level for console
#define DEVICE_HOSTNAME "Prusa-ESP32cam" ///< device hostname
@ -90,7 +90,7 @@
/* ----------------- WiFi CFG -------------------*/
#define WIFI_STA_WDG_TIMEOUT 60000 ///< STA watchdog timeout [ms]
#define WIFI_DISABLE_UNENCRYPTED_STA_PASS_CHECK false ///< enable/disable WEP/WPA/WPA2/... encryption for STA mode . for the wifi network without encryption set to false
#define WIFI_DISABLE_UNENCRYPTED_STA_PASS_CHECK false ///< enable/disable WEP/WPA/WPA2/... encryption for STA mode . for the wifi network without encryption set to false
/* ----------------- NTP CFG --------------------*/
#define NTP_SERVER_1 "pool.ntp.org" ///< NTP server

View File

@ -0,0 +1,103 @@
/**
@file module_ESP32-S3_Wroom_Freenove.h
@brief Definition of the ESP32-S3 Wroom FreeNove board
@author Miroslav Pivovarsky
Contact: miroslav.pivovarsky@gmail.com
Board configuration in the arduino IDE 2.3.2
Tools -> Board -> ESP32 Arduino -> ESP32S3 Dev Module
Tools -> USB CDC on BOOT -> Disabled
Tools -> CPU Frequency -> 240MHz (WiFi/BT)
Tools -> Core debug level -> None
Tools -> USB DFU on BOOT -> Disable
Tools -> Erase all Flash Before Sketch Upload -> Disable (first flash, new board = enable. otherwise = disable)
Tools -> Events Run On -> Core 0
Tools -> Flash Mode -> QIO 80MHz
Tools -> Flash Size -> 8MB
Tools -> Jtag Adapter -> Disable
Tools -> Arduino Runs On -> Core 0
Tools -> USB Firmware MSC On Boot -> Disable
Tools -> Partition scheme -> Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS)
Tools -> PSRAM -> OPI PSRAM
Tools -> Upload Mode -> UART0 / Hardware CDC
Tools -> Upload Speed -> 921600
Tools -> USB Mode -> Hardware CDC and JTAG
Tools -> Zigbee mode -> Disable
https://freenove.com/fnk0085
@bug: no know bug
*/
#pragma once
#include "mcu_cfg.h"
#ifdef ESP32_S3_WROOM_FREENOVE
/* --------------- CAMERA CFG -------------------*/
#define PWDN_GPIO_NUM -1 ///< Power down control pin
#define RESET_GPIO_NUM -1 ///< Reset control pin
#define SIOD_GPIO_NUM 4 ///< SCCB: SI/O data pin
#define SIOC_GPIO_NUM 5 ///< SCCB: SI/O control pin
#define Y2_GPIO_NUM 11 ///< SCCB: Y2 pin
#define Y3_GPIO_NUM 9 ///< SCCB: Y3 pin
#define Y4_GPIO_NUM 8 ///< SCCB: Y4 pin
#define Y5_GPIO_NUM 10 ///< SCCB: Y5 pin
#define Y6_GPIO_NUM 12 ///< SCCB: Y6 pin
#define Y7_GPIO_NUM 18 ///< SCCB: Y7 pin
#define Y8_GPIO_NUM 17 ///< SCCB: Y8 pin
#define Y9_GPIO_NUM 16 ///< SCCB: Y9 pin
#define VSYNC_GPIO_NUM 6 ///< Vertical sync pin
#define HREF_GPIO_NUM 7 ///< Line sync pin
#define PCLK_GPIO_NUM 13 ///< Pixel clock pin
#define XCLK_GPIO_NUM 15 ///< External clock pin
/* ------------------ MCU CFG ------------------*/
#define BOARD_NAME F("ESP32-S3 WROOM Freenove") ///< Board name
#define ENABLE_BROWN_OUT_DETECTION false ///< Enable brown out detection
#define ENABLE_PSRAM true ///< Enable PSRAM
/* --------------- OTA UPDATE CFG --------------*/
#define OTA_UPDATE_FW_FILE PSTR("ESP32-S3-WROOM_FREENOVE.bin") ///< OTA update firmware file name
#define FW_STATUS_LED_PIN 2 ///< GPIO pin for status FW update LED
#define FW_STATUS_LED_LEVEL_ON LOW ///< GPIO pin level for status LED ON
/* --------------- FLASH LED CFG ---------------*/
#define ENABLE_CAMERA_FLASH true ///< Enable camera flash function
#define CAMERA_FLASH_DIGITAL_CTRL true ///< Enable camera flash digital control
#define CAMERA_FLASH_PWM_CTRL false ///< Enable camera flash PWM control
#define CAMERA_FLASH_NEOPIXEL true ///< Enable camera flash NeoPixel control
#define FLASH_GPIO_NUM 14 ///< Flash control pin
#define FLASH_NEOPIXEL_LED_PIN 48 ///< External flash control pin. RGB LED NeoPixel
#define FLASH_OFF_STATUS 0 ///< PWM intensity LED for OFF. 0-2^FLASH_PWM_RESOLUTION = 0-255
#define FLASH_ON_STATUS 205 ///< PWM intensity LED for ON. limitation to 80%. 2^FLASH_PWM_RESOLUTION * 0.8% = 204
#define FLASH_PWM_FREQ 2000 ///< frequency of pwm [240MHz / (100 prescale * pwm cycles)] = frequency
#define FLASH_PWM_CHANNEL 0 ///< channel 0
#define FLASH_PWM_RESOLUTION 8 ///< range 1-20bit. 8bit = 0-255 range
/* --------------- SD CARD CFG ---------------*/
#define ENABLE_SD_CARD true ///< Enable SD card function
#define SD_PIN_CLK 39 ///< GPIO pin for SD card clock
#define SD_PIN_CMD 38 ///< GPIO pin for SD card command
#define SD_PIN_DATA0 40 ///< GPIO pin for SD card data 0
/* ---------- RESET CFG CONFIGURATION ----------*/
#define CFG_RESET_PIN 21 ///< GPIO 12 is for reset CFG to default
#define CFG_RESET_LED_PIN 2 ///< GPIO for indication of reset CFG
#define CFG_RESET_LED_LEVEL_ON HIGH ///< GPIO pin level for status LED ON
/* -------------- STATUS LED CFG ----------------*/
#define STATUS_LED_ENABLE false ///< enable/disable status LED
#define STATUS_LED_GPIO_NUM 2 ///< GPIO pin for status LED
#define STATUS_LED_OFF_PIN_LEVEL LOW ///< GPIO pin level for status LED ON
/* -------------- DHT SENSOR CFG ----------------*/
#define DHT_SENSOR_ENABLE false ///< enable/disable DHT sensor
#define DHT_SENSOR_PIN 47 ///< GPIO pin for DHT sensor
#endif // AI_THINKER_ESP32_CAM
/* EOF */

View File

@ -14,7 +14,7 @@
#include "mcu_cfg.h"
#if ((AI_THINKER_ESP32_CAM + ESP32_WROVER_DEV + CAMERA_MODEL_ESP32_S3_DEV_CAM + CAMERA_MODEL_ESP32_S3_EYE_2_2 + CAMERA_MODEL_XIAO_ESP32_S3_CAM + CAMERA_MODEL_ESP32_S3_CAM) != 1)
#if ((AI_THINKER_ESP32_CAM + ESP32_WROVER_DEV + CAMERA_MODEL_ESP32_S3_DEV_CAM + CAMERA_MODEL_ESP32_S3_EYE_2_2 + CAMERA_MODEL_XIAO_ESP32_S3_CAM + CAMERA_MODEL_ESP32_S3_CAM + ESP32_S3_WROOM_FREENOVE) != 1)
#error "Exactly one camera model must be defined as true."
#endif
@ -36,6 +36,9 @@
#elif (true == CAMERA_MODEL_ESP32_S3_CAM)
#include "module_ESP32-S3-CAM.h"
#elif (true == ESP32_S3_WROOM_FREENOVE)
#include "module_ESP32-S3_Wroom_Freenove.h"
#else
#error "No module selected"

145
README.md
View File

@ -1,21 +1,22 @@
# PrusaConnect ESP32-CAM
This repository includes source code and firmware releases for the **ESP32-cam** module programmed in the **Arduino IDE**. Currently, several versions of boards built on **ESP32/ESP32S3** processors with a camera chip are supported. Below is the list supported boards. Additionally, for each supported board, there is a guide on how to upload the firmware, how to compile code for it, and a basic data informations/issues for the board.
This repository includes source code and firmware releases for the **ESP32-cam** module programmed in the **Arduino IDE**. Currently, several versions of boards built on **ESP32/ESP32S3** processors with a camera chip are supported. You can find a list of supported boards below. Additionally, for each supported board, there is a guide on how to upload the firmware, how to compile code for it, some basic information and a list of known issues for this particular board.
This project uses other libraries. It is necessary to install them in the Arduino IDE.
- App [Arduino IDE 2.3.2](https://www.arduino.cc/en/software)
- MCU support [arduino-ESP32 3.0.2](https://github.com/espressif/arduino-esp32)
This project uses other libraries. It is necessary to install them in the Arduino IDE:
- App [Arduino IDE 2.3.4](https://www.arduino.cc/en/software)
- MCU support [arduino-ESP32 3.1.0](https://github.com/espressif/arduino-esp32)
- ~~Library [ESPAsyncWebSrv 1.2.7](https://github.com/dvarrel/ESPAsyncWebSrv)~~ To version **1.0.3-rc1**
- ~~Library [AsyncTCP 1.1.4](https://github.com/dvarrel/AsyncTCP)~~ To version **1.0.3-rc1**
- Library [AsyncTCP 3.1.4](https://github.com/mathieucarbou/AsyncTCP)
- Library [ESPAsyncWebServer 3.0.6](https://github.com/mathieucarbou/ESPAsyncWebServer)
- Library [ArduinoJson 7.1.0](https://github.com/bblanchon/ArduinoJson)
- Library [AsyncTCP 3.3.1](https://github.com/mathieucarbou/AsyncTCP)
- Library [ESPAsyncWebServer 3.4.5](https://github.com/mathieucarbou/ESPAsyncWebServer)
- Library [ArduinoJson 7.3.0](https://github.com/bblanchon/ArduinoJson)
- Library [UniqueID 1.3.0](https://github.com/ricaun/ArduinoUniqueID)
- Library [DHTnew 0.4.20](https://github.com/RobTillaart/DHTNew)
- Library [DHTnew 0.5.2](https://github.com/RobTillaart/DHTNew)
What we need for functionality
What we need for functionality:
- Supported versions of boards built on **ESP32/ESP32-S3** processors with a camera [here](#supported_boards)
- How to flash binary files to ESP32-cam board from Linux/MAC/Windows [ here ](#flash_fw)
- How to flash using Chrome [here](#browser_flash)
- How to compile software in the Arduino IDE [here](#arduino_lib)
- How to connect camera board to Prusa Connect [here](#prusa_connect)
- Service AP [here](#service_ap)
@ -32,15 +33,15 @@ What we need for functionality
<a name="supported_boards"></a>
## Supported boards
| Board name | Support | Stream | Micro SD | FLASH LED | FW update | DHT22/DHT11 | Documentation |
|---------------------------|-------------|--------|----------|-----------|-----------|-------------|----------------------------------------------|
| Ai-Thinker ESP32-cam | Full | Yes | Yes | Board/Ext | Yes | Yes | [ here ](doc/AI_Thinker-ESP32-cam/README.md) |
| ESP32-S3-EYE 2.2 | Full | Yes | Yes | External | Yes | Yes | [ here ](doc/ESP32-S3-EYE-22/README.md) |
| Freenove ESP32-Wrover cam | Full | Yes | No | External | Yes | Yes | [ here ](doc/ESP32-Wrover-dev/README.md) |
| Freenove ESP32-S3-Wroom | in Progress | | | | | | |
| ESP32-S3-DEV-CAM | in Progress | | | External | | | [ here ](doc/ESP32-S3-DEV-CAM/README.md) |
| Seeed Studio XIAO ESP32S3 | Full | Yes | Yes | External | Yes | Yes | [ here ](doc/XIAO_ESP32S3/README.md) |
| ESP32-S3-CAM | Full | Yes | Yes | Board/Ext | Yes | Yes | [ here ](doc/ESP32-S3-CAM/README.md) |
| Board name | Support | Stream | Micro SD | FLASH LED | FW update | DHT22/DHT11 | Documentation |
|---------------------------|-------------|--------|----------|-----------|-----------|-------------|---------------------------------------------------|
| Ai-Thinker ESP32-cam | Full | Yes | Yes | Board/Ext | Yes | Yes | [ here ](doc/AI_Thinker-ESP32-cam/README.md) |
| ESP32-S3-EYE 2.2 | Full | Yes | Yes | External | Yes | Yes | [ here ](doc/ESP32-S3-EYE-22/README.md) |
| Freenove ESP32-Wrover cam | Full | Yes | No | External | Yes | Yes | [ here ](doc/ESP32-Wrover-dev/README.md) |
| Freenove ESP32-S3-Wroom | Full | Yes | Yes | Board/Ext | Yes | Yes | [ here ](doc/Freenove%20ESP32-S3-Wroom/README.md) |
| ESP32-S3-DEV-CAM | in Progress | | | External | | | [ here ](doc/ESP32-S3-DEV-CAM/README.md) |
| Seeed Studio XIAO ESP32S3 | Full | Yes | Yes | External | Yes | Yes | [ here ](doc/XIAO_ESP32S3/README.md) |
| ESP32-S3-CAM | Full | Yes | Yes | Board/Ext | Yes | Yes | [ here ](doc/ESP32-S3-CAM/README.md) |
The compiled firmware for each supported board is published with every release.
@ -49,12 +50,26 @@ The compiled firmware for each supported board is published with every release.
Uploading a precompiled version of the firmware to the MCU is possible from either Linux or Windows OS. Since different boards use various processors and modules, it is not possible to create a single universal guide. Therefore, it is necessary to select the board you are using and then refer to the documentation on how to upload the firmware to it. Here is list with currently [supported boards](#supported_boards).
<a name="browser_flash"></a>
## How to flash using Chrome
It is also possible to flash firmware using ESP Tool on a WEB browser https://espressif.github.io/esptool-js/
**This option is currently not supported on the Ai Thinker ESP32-cam board version.**
Ensure that you set the correct baud rate from the documentation for the board you are using (921600). Select the serial port your board is connected to. You can then click "Add File" and select each .bin file for your board. Make sure that you input the **correct Flash Address** from the documentation from your board. For the initial flash, click "Erase Flash", and when that is complete, click "Program." See below for a screenshot of how to configure ESP Tool for the Freenove Wrover board.
<img src="doc/ESPToolConnect.jpg" width=50% height=50%>
<img src="doc/ESPTool.png" width=50% height=50%>
<img src="doc/ESPToolFinish.jpg" width=50% height=50%>
<a name="arduino_lib"></a>
## How to compile software in the Arduino IDE
The software can be compiled and uploaded to the MCU. Software compilation was done in Arduino IDE. To ensure proper functionality, it is necessary to install support for ESP32 boards into Arduino IDE, as well as several other libraries
The software can be compiled and uploaded to the MCU. Software compilation was done in Arduino IDE. To ensure proper functionality, it is necessary to install support for ESP32 boards into Arduino IDE, as well as several other libraries.
At the first step we need to install support for **ESP32 board**.
As a first step we need to install support for **ESP32 boards**.
**File** -> **Preferences** -> **Additional boards managers URLs**
@ -62,15 +77,15 @@ At the first step we need to install support for **ESP32 board**.
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
```
then go to **Tools** -> **Board** -> **Boards Manager...** and install module **ESP32** by **Espressif Systems**
then go to **Tools** -> **Board** -> **Boards Manager...** and install module **ESP32** by **Espressif Systems**.
The next step is to install the necessary libraries. Go to **Sketch** -> **Include Library** -> **Manage Libraries...** or you can use **Ctrl+Shift+I**. Then you can search for the necessary libraries and install them.
The next step is to install the necessary libraries. Go to **Sketch** -> **Include Library** -> **Manage Libraries...** or you can use **Ctrl+Shift+I**. Here you can search for the necessary libraries and install them.
For the installation of the **ESPAsyncWebServer** and **AsyncTCP** libraries, it is necessary to download the **ZIP** archive from the official **GIT** repository, and then import it using **Sketch** -> **Include Library** -> **Add .ZIP Library ...**
For the installation of the **ESPAsyncWebServer** and **AsyncTCP** libraries, it is necessary to download the **ZIP** archive from the official **GIT** repository, and then import it using **Sketch** -> **Include Library** -> **Add .ZIP Library ...**.
Then it is possible build and upload the firmware to the board. Each board requires a different Arduino IDE configuration. Therefore, it is necessary to select the board from the [supported boards](#supported_boards) and read the documentation on how to build and upload the firmware.
You should now be able to build the firmware and upload it to the board. Each board requires a different Arduino IDE configuration. Therefore, it is necessary to select the board from the [supported boards](#supported_boards) and read the documentation on how to build and upload the firmware.
**For each specific the board type, it's neccerasy** in the file **mcu_cfg.h**, after **line 16** is definitions specify the version of the board for which the software will be compiled. It is necessary to enable the version of the board that will be used.
**For each specific board type, it's necessary** to update the file called **mcu_cfg.h**. Below **line 16** you can find several definitions that specify the version of the board for which the software will be compiled. It is necessary to enable the version of the board that will be used:
```c
#define AI_THINKER_ESP32_CAM false
@ -84,44 +99,44 @@ Then it is possible build and upload the firmware to the board. Each board requi
<a name="prusa_connect"></a>
## How to connect camera board to Prusa Connect
- Open up the **Prusa Connect** webpage [connect.prusa3D.com](https://connect.prusa3D.com)
- Log in
- Go to the **Prusa Connect** webpage [https://connect.prusa3D.com](https://connect.prusa3D.com).
- Log in.
- Select a printer you wish to use the camera for.
- Navigate to the **Camera** tab.
- Click **Add new other camera**
- Click **Add new other camera**.
- **A new camera will appear** in the list. Here, you can give the camera a name.
- This is the most important part: Copy the **TOKEN** for the given camera and save it for later use.
<img src="doc/connect_1.jpg" width=50% height=50%>
<img src="doc/connect_2.jpg" width=50% height=50%>
- Connect the Cam to the **USB Power supply**
- After a brief moment, the camera will start in a **Wi-Fi AP mode**. Essentially, it starts it's own Wi-Fi network. The network name (SSID) is **ESP32_camera_UID**, where **UID** is the first three numbers from the **MCU ID**.
- Connect the Cam to the **USB Power supply**.
- After a brief moment, the camera will start in a **Wi-Fi AP mode**. Essentially, it starts its own Wi-Fi network. The network name (SSID) is **ESP32_camera_UID**, where **UID** is the first three numbers from the **MCU ID**.
- Find the camera in the Wi-Fi list on your computer.
- Enter the default password: **12345678** and connect to it. After establishing a successful connection, your computer might complain about having "No Internet" on the given network. That is OK.
- Open up a new web browser.
- Open up the **192.168.0.1** IP Address as a webpage. Alternatively, you can also use the http://prusa-esp32cam.local hostname (mDNS) instead of the IP Address.
- Enter [http://192.168.0.1](http://192.168.0.1) as the URL. Alternatively, you can also try to use the http://prusa-esp32cam.local hostname (mDNS) instead of the IP address.
- The camera's configuration interface should appear.
- In the **Wi-Fi configuration tab** It's necessary to set the SSID of the WiFi network and the password of the WiFi network to which the camera should connect in order to be able to upload images to Prusa Connect. And click to **Save & Connect** button
- In the **Wi-Fi configuration tab** it's necessary to set the SSID of the WiFi network and the password of the WiFi network to which the camera should connect in order to be able to upload images to Prusa Connect. Make sure to click the **Save & Connect** button when you're done.
<img src="doc/connect_4.jpg" width=50% height=50%>
- In the **Camera configuration tab**, insert the **Token** into the marked field. Click **Save**. **This is the Prusa Connect camera token we have obtained in an earlier step.** Wait until the token has been save successfully.
- In the **Camera configuration tab**, insert the **Token** you have obtained earlier into the marked field. Click **Save**. Wait until the token has been saved successfully.
<img src="doc/connect_3.jpg" width=50% height=50%>
- Since we're in the camera configuration tab already, we can set up the image options:
In this same tab you should also configure a few image settings:
- Set up the **resolution**. This will improve the image quality significantly, as the resolution is set to the lowest possible by default.
- Set up the **Trigger interval** and click **Save**.
- Clicking **Refresh snapshot** will refresh the image you see on the page.
- We should now have completed setting up the camera.
While we are on the ESP camera's configuration page, let's take a quick look at the other options it offers.
- Camera configuration tab contain
While we are on the ESP camera's configuration page, let's take a quick look at the other options it offers:
- Camera configuration tab contains
- Camera cip settings
- Authentication token setting
- Camera flash settings
- Wi-Fi configuration tab contain
- Wi-Fi configuration tab contains
- Setting the wifi network to which the camera can connect
- The possibility of turning off the service AP
- Option to set static IP addresses for WiFi networks to which the camera connects
@ -131,7 +146,7 @@ While we are on the ESP camera's configuration page, let's take a quick look at
- For a manual firmware update, select the firmware file **ESP32_PrusaConnectCam.ino.bin** and click **Upload file & Update**. Afterwards, reboot the camera.
- Update from cloud. To check for firmware updates, select **Check Update from cloud**. If a newer version is available, click **Update from cloud**. Note that the camera has to be connected to the Internet, before using these functions.
- Setting **log level** and getting logs from the camera. To get the logs, it is necessary to have a micro SD card formatted to **FAT32** inserted in the camera!
- Check the status of uploading the image to Prusa Connect using the **PrusaConnect Status:** variable
- Check the status of uploading the image to Prusa Connect using the **PrusaConnect Status:** variable.
**Interesting improvements.** There is a protective film on the camera module. The protective film needs to be removed from the lens.
@ -144,38 +159,37 @@ The second problem is that the camera module is not usually attached to the micr
<a name="service_ap"></a>
## Service AP
After powering on and booting up the camera, it enters **AP mode**, which serves as a configuration mode for the camera. Essentially, it starts its own Wi-Fi network. The network name (SSID) is **ESP32_camera_UID**, where **UID** is the first three numbers from the **MCU ID**, serving as a unique identifier for the camera. The password for connecting to the AP is **12345678**. The camera's IP address is **192.168.0.1**. To configure the camera via **AP mode**, you need to connect to this IP address using a web browser: **http://192.168.0.1**. Alternatively, you can also use the **http://prusa-esp32cam.local** hostname (**mDNS**) instead of the IP Address.
After powering on and booting up the camera, it enters **AP mode**, which serves as a configuration mode for the camera. Essentially, it starts its own Wi-Fi network. The network name (SSID) is **ESP32_camera_UID**, where **UID** is the first three numbers from the **MCU ID**, serving as a unique identifier for the camera. The password for connecting to the AP is **12345678**. The camera's IP address is **192.168.0.1**. To configure the camera via **AP mode**, you need to connect to this IP address using a web browser: **http://192.168.0.1**. Alternatively, you can also use the **http://prusa-esp32cam.local** hostname (**mDNS**) instead of the IP address.
After establishing a successful connection, your computer might display a "**No Internet**" warning for the given network. **This is normal**.
If you have set up a Wi-Fi network name (SSID) and password in the camera for it to connect to, then upon powering on, the camera will automatically connect to the configured Wi-Fi network and simultaneously activate AP mode for **5 minutes**. AP mode is always enabled after powering on and booting up the camera for **5 minutes**. The service Wi-Fi AP is **automatically deactivates** itself after **5 minutes** following each camera startup if no device is connected to the camera.
If you have set up a Wi-Fi network name (SSID) and password in the camera for it to connect to, then upon powering on, the camera will automatically connect to the configured Wi-Fi network and simultaneously activate AP mode for **5 minutes**. AP mode is always enabled after powering on and booting up the camera for **5 minutes**. The service Wi-Fi AP **automatically deactivates** itself after **5 minutes** following each camera startup if no device is connected to the camera.
Service AP is for for the first camera configuration. If the camera is connected to a WiFi network, it is possible to configure it from the local network.
Service AP is for the first camera configuration. If the camera is connected to a WiFi network, it is possible to configure it from the local network.
<a name="factory_cfg"></a>
## How to reset configuration to factory settings
Each version of the [supported board](#supported_boards) uses a different pin for camera reset. Therefore, it is necessary to refer to the documentation for the specific board to determine which pin is used for reset camera configuration to factory configuration.
Each version of the [supported boards](#supported_boards) uses a different pin for camera reset. Therefore, it is necessary to refer to the documentation of the specific board to determine which pin is used to reset the camera configuration to factory defaults.
The procedure is always the same:
The procedure is the same for each board:
- Ground the pin for camera reset configuration.
- Connect the power supply.
- Wait for 10 seconds.
- An LED will start blinking (refer to the board's documentation).
- Disconnect the ground from the camera reset configuration pin.
- The LED will stop blinking.
- The camera configuration will be restored to factory settings.
- The camera configuration will be reset to factory defaults.
<a name="status_led"></a>
## Status LED
On the board, there is a status LED that provides a visual indicator of the module's current status
through blinking at defined intervals. Each [supported board](#supported_boards) has the STATUS LED located in a different place. It is necessary to refer to the documentation to locate the STATUS LED on the board.
On the board, there is a status LED that provides a visual indicator of the module's current status through blinking at defined intervals. Each [supported board](#supported_boards) has the STATUS LED located in a different place. It is necessary to refer to the documentation to locate the STATUS LED on the board.
Upon module activation, the LED illuminates. After processor initialization, the LED exhibits different blinking intervals based on the current mode of the module
Upon module activation, the LED illuminates. After processor initialization, the LED exhibits different blinking intervals based on the current mode of the module:
- **Service AP Mode only:** The LED blinks every **400 ms**, indicating the module's availability in service AP mode.
- **Connecting to WiFi AP:** While connecting to a WiFi Access Point, the LED blinks at intervals of **800 ms**.
- **Connected to WiFi Network:** Upon successful connection to a WiFi network, the LED blinks at intervals of **4000 ms**, signaling a stable connection.
- **Connecting to WiFi AP:** While connecting to a WiFi Access Point, the LED blinks at an interval of **800 ms**.
- **Connected to WiFi Network:** Upon successful connection to a WiFi network, the LED blinks at an interval of **4000 ms**, signaling a stable connection.
- **Problematic State:** If an issue or error occurs, the LED accelerates its blinking to every **100 ms**.
The approximate boot time of the device is 15-20 seconds.
@ -183,14 +197,14 @@ The approximate boot time of the device is 15-20 seconds.
<a name="logs"></a>
## Debug logs
It is possible to save debug logs to a microSD card, but the card must be formatted to FAT32. Currently, the maximum tested capacity for a microSD card is 16GB. If a microSD card is inserted into the camera, it is necessary to reboot the camera. When a microSD card is inserted into the camera before boot, logging to the microSD card is automatically enabled. If no microSD card is inserted, the saving of debug logs to the microSD card is automatically disabled. Enabling the saving of debug logs to a microSD card is only possible during camera boot, so it is necessary to restart the camera after inserting the microSD card. Debug logs are saved as plain text in the file Syslog.log
It is possible to save debug logs to a microSD card, but the card must be formatted to FAT32. Currently, the maximum tested capacity for a microSD card is 16GB. If a microSD card is inserted into the camera, it is necessary to reboot the camera. When a microSD card is inserted into the camera before boot, logging to the microSD card is automatically enabled. If no microSD card is inserted, logging to the microSD card is automatically disabled. Enabling the saving of debug logs to a microSD card is only possible during camera boot, so it is necessary to restart the camera after inserting the microSD card. Debug logs are saved as plain text in the file `SysLog.log`.
<a name="serial_cfg"></a>
## Serial console configuration
Currently, it is possible to set the basic camera configuration using the serial console. Baud speed for communication with MCU is **115200 8N1**
It is possible to set the basic camera configuration using the serial console. Serial port settings for communication with the MCU need to be set to **115200 8N1**.
Commands for configuration have simple syntax
Commands for configuration have a simple syntax:
| command | separator | variable | termination | line terminator |
|--------------|-----------|-----------|-------------|--------------------------|
@ -206,16 +220,16 @@ Currently, available commands are listed in the table below:
| mcureboot | Rebooting the MCU |
| commandslist | Listing currently supported commands via serial console |
| getwifimode | Print current WiFi mode. STA/AP/AP+STA |
| getwifistastatus | Print WiFi STA status. Connected/Disconnected/Connecting.... |
| getwifistastatus | Print WiFi STA status. Connected/Disconnected/Connecting... |
| getwifistaip | Print IP address for WiFi STA |
| getserviceapssid | Print service AP SSID name |
| setauthtoken | Set authentication token for Prusa Connect |
| otaupdate | Start OTA update process |
| resolution | Set photo resolution |
| photoquality | Set photo quality |
| setflash | enable/disable LED flash |
| setlight | enable/disable LED light |
| loglevel | set log level. 0=Error, 1=Warning, 2=Info, 3=Verbose |
| setflash | Enable/disable LED flash |
| setlight | Enable/disable LED light |
| loglevel | Set log level. 0=Error, 1=Warning, 2=Info, 3=Verbose |
The standard command sequence for camera basic settings is
@ -228,7 +242,7 @@ The standard command sequence for camera basic settings is
<a name="rest"></a>
## WEB API
The camera have a WEB API, allowing several operations to be performed through the web interface.
The camera offers a web API, allowing several operations to be performed through the web interface:
| Command | Description |
|---------------------------|--------------------------------------------------|
@ -247,12 +261,12 @@ The camera have a WEB API, allowing several operations to be performed through t
<a name="stream"></a>
## Video stream
The video stream is available on the WEB page **http://IP/stream.mjpg**
The video stream is available at **http://IP/stream.mjpg**.
<a name="man_focus"></a>
## Manual camera focus
Usually, the camera module is properly focused. However, the camera module can be manually focused. There are several types of lenses for camera modules. I have created several [Tools](https://www.printables.com/cs/model/877739-esp32-cam-ov2640-focus-adjustment-wrench) for manually focusing the camera module.
Usually, the camera module is properly focused. However, the camera module can be manually focused. There are several types of lenses for camera modules. I have created several [tools](https://www.printables.com/cs/model/877739-esp32-cam-ov2640-focus-adjustment-wrench) for manually focusing the camera module.
<img src="doc/focus_2.jpg" width=40% height=40%>
@ -263,11 +277,11 @@ First, it is necessary to hold the camera with a holder and then put the wrench
<a name="ext_temp"></a>
## External temperature sensor
The software supports an external temperature sensor **DHT22** or **DHT11**. The sensor needs to be connected according to the manual for the specific version of the board. The temperature and humidity are automatically read every 30 seconds after the enable sensor.
The software supports an external temperature sensor **DHT22** or **DHT11**. The sensor needs to be connected according to the manual for the specific version of the board. The temperature and humidity are automatically read every 30 seconds once the sensor has been enabled.
<img src="doc/Sensori-DHT11-e-DHT22.jpg" width=40% height=40%>
Information about sensor
Information about sensors:
| | DHT11 | DHT22 |
|-------------------|--------------|------------------|
@ -277,15 +291,16 @@ Information about sensor
| Humidity range | 20-80% / 5% | 0-100% / 2-5% |
| Sampling rate | 1Hz | 0.5Hz |
It is necessary to use the **module**, **not the sensor**! The module with the sensor has a **4.7Kohm** resistor soldered onto the PCB, which is necessary for the proper functioning of the **one-wire bus**. If you use the sensor, it is necessary to connect a 4.7K ohm resistor to the one-wire bus as shown in the schematic below. **The module must be powered with 3.3V VCC, otherwise, it may damage the camera board.**
It is necessary to use the **module**, **not the sensor**! The module with the sensor has a **4.7kOhm** resistor soldered onto the PCB, which is necessary for the **one-wire bus** to operate properly. If you use the sensor, it is necessary to connect a 4.7kOhm resistor to the one-wire bus as shown in the schematic below. **The module must be powered with 3.3V VCC, otherwise it may damage the camera board**.
Here is a typical schematic for the DHT22 or DHT11 sensor:
<img src="doc/DHT22-Schematic.png" width=40% height=40%>
<a name="issue"></a>
## Potential issue
## Troubleshooting
- A potential issue may arise with connecting to the service AP. If the connection fails and an authentication error occurs, it is necessary to clear the FLASH memory of the processor, and FLASH FW again. This can be done either through the Arduino IDE or using official software.
- After the initial firmware upload to the new camera, there may be an issue when connecting to the IP address, where the camera prompts for a username and password to access the web page. Even when entering the username "admin" and the password "admin", the login still doesn't work. In such cases, it's necessary to reset the camera configuration to factory settings. The procedure is outlined in the readme file [here](#factory_cfg)
- If you are getting a 400 return code from Prusa Connect, then you need to create a new other camera in Prusa Connect and enter a new token into the ESP32 camera.
- After the initial firmware upload to a new camera, there may be an issue when connecting to the IP address, where the camera prompts for a username and password to access the web page. Even when entering the username "admin" and the password "admin", the login still doesn't work. In such cases, it's necessary to reset the camera configuration to factory settings. The procedure is outlined in the readme file [here](#factory_cfg).
- If you are getting a 400 return code from Prusa Connect, then you need to create another camera in Prusa Connect and enter a new token into the ESP32 camera.
- If you are getting a 404 return code from Prusa Connect, it may indicate that the printer is powered off. The printer must be powered on in order for images to be uploaded.

View File

@ -18,7 +18,7 @@ What we need for functionality
<a name="esp32"></a>
## ESP32-CAM AI-thinker board
Basic informations:
Basic information:
- Low cost version
- FLASH LED on the board
- Option connecting external FLASH LED
@ -32,7 +32,7 @@ It's a few dollars board with **ESP32** MCU and Camera. It's necessary to buy a
<img src="esp32-cam.jpg" width=30% height=30%>
In the following picture, we can see the **ESP32-CAM** board and the programator for the board.
In the following picture, we can see the **ESP32-CAM** board and the programmer for the board.
<img src="esp32_and_prog.jpg" width=30% height=30%>
@ -117,7 +117,7 @@ And command for FLASH FW is here, where **/dev/ttya0** is your serial interface
./esptool -p /dev/ttya0 -b 460800 --before default_reset --after hard_reset --chip esp32 write_flash --erase-all --flash_mode dio --flash_size 4MB --flash_freq 80m 0x1000 ESP32_PrusaConnectCam.ino.bootloader.bin 0x8000 ESP32_PrusaConnectCam.ino.partitions.bin 0x10000 ESP32_PrusaConnectCam.ino.bin
```
This command contains the parameter **--eras-all**, which erases the entire flash in the MCU. So, for just updating the firmware, it is necessary to remove the parameter **--eras-all**; otherwise, the MCU configuration will also be deleted. The basic command list can be found [here](https://docs.espressif.com/projects/esptool/en/latest/esp32s3/esptool/basic-commands.html)
This command contains the parameter **--erase-all**, which erases the entire flash in the MCU. So, for just updating the firmware, it is necessary to remove the parameter **--erase-all**; otherwise, the MCU configuration will also be deleted. The basic command list can be found [here](https://docs.espressif.com/projects/esptool/en/latest/esp32s3/esptool/basic-commands.html)
Here is the command for updating the firmware in the MCU without erasing the MCU configuration
@ -129,7 +129,7 @@ Launching the esptool application may be different in different operating system
#### Windows
Driver for CH340 USB to UART convert for Windows is for example [here](https://www.wch-ic.com/search?q=CH340&t=downloads) . An older version of the driver is for example [here](https://blog.laskakit.cz/wp-content/uploads/2020/03/CH341SER.zip)
Driver for CH340 USB to UART convert for Windows is for example [here](https://www.wch-ic.com/search?q=CH340&t=downloads) . An older version of the driver is for example [here](https://blog.laskakit.cz/wp-content/uploads/2020/03/CH341SER.zip). SW for FW flash (Flash Download Tools) is [here](https://www.espressif.com/en/support/download/other-tools)
<img src="how to flash chip select.jpg" width=25% height=25%>

View File

@ -17,11 +17,11 @@ What we need for functionality
<a name="esp32"></a>
## ESP32-S3-CAM
Basic informations:
Basic information:
- Onboard RGB LED (most likely ws2812b)
- Option connecting external FLASH LED
- Micro SD card slot
- Internal or External WiFi antena
- Internal or External WiFi antenna
- 16MB FLASH and 8MB external PSRAM
- 520 KB SRAM
- Excellent WiFi signal
@ -70,7 +70,7 @@ And command for FLASH FW is here, where **/dev/ttya0** is your serial interface
./esptool --chip esp32s3 -p /dev/ttya0 -b 921600 --before default_reset --after hard_reset write_flash --erase-all --flash_mode dio --flash_size 16MB --flash_freq 80m 0x0 ESP32_PrusaConnectCam.ino.bootloader.bin 0x8000 ESP32_PrusaConnectCam.ino.partitions.bin 0x10000 ESP32_PrusaConnectCam.ino.bin
```
This command contains the parameter **--eras-all**, which erases the entire flash in the MCU. So, for just updating the firmware, it is necessary to remove the parameter **--eras-all**; otherwise, the MCU configuration will also be deleted. The basic command list can be found [here](https://docs.espressif.com/projects/esptool/en/latest/esp32s3/esptool/basic-commands.html)
This command contains the parameter **--erase-all**, which erases the entire flash in the MCU. So, for just updating the firmware, it is necessary to remove the parameter **--erase-all**; otherwise, the MCU configuration will also be deleted. The basic command list can be found [here](https://docs.espressif.com/projects/esptool/en/latest/esp32s3/esptool/basic-commands.html)
Here is the command for updating the firmware in the MCU without erasing the MCU configuration
@ -82,7 +82,7 @@ Launching the esptool application may be different in different operating system
#### Windows
The driver should be installed automatically by Windows
The driver should be installed automatically by Windows. SW for FW flash (Flash Download Tools) is [here](https://www.espressif.com/en/support/download/other-tools)
In the first step, you need to open the application **flash download tool**, and select MCU version

View File

@ -16,7 +16,7 @@ What we need for functionality
<a name="esp32"></a>
## ESP32-S3-EYE 2.2
Basic informations:
Basic information:
- On the board missing LED for flash
- Option connecting external FLASH LED
- Micro SD card slot
@ -24,6 +24,7 @@ Basic informations:
- no additional HW is needed for programming
- 8MB FLASH and 8MB external PSRAM
- Excellent WiFi signal
- 1.27mm Pitch 2x5Pin Double Row Female Pin Header external LCD connector
This is a more expensive version with a more powerful ESP32-S3 processor. The board is sold with an OV2640 camera module. No additional hardware is required for programming. The ESP32-S3 processor is programmed via the processor's USB interface.
@ -70,7 +71,7 @@ And command for FLASH FW is here, where **/dev/ttya0** is your serial interface
./esptool --chip esp32s3 -p /dev/ttya0 -b 921600 --before default_reset --after hard_reset write_flash --erase-all --flash_mode dio --flash_size 8MB --flash_freq 80m 0x0 ESP32_PrusaConnectCam.ino.bootloader.bin 0x8000 ESP32_PrusaConnectCam.ino.partitions.bin 0x10000 ESP32_PrusaConnectCam.ino.bin
```
This command contains the parameter **--eras-all**, which erases the entire flash in the MCU. So, for just updating the firmware, it is necessary to remove the parameter **--eras-all**; otherwise, the MCU configuration will also be deleted. The basic command list can be found [here](https://docs.espressif.com/projects/esptool/en/latest/esp32s3/esptool/basic-commands.html)
This command contains the parameter **--erase-all**, which erases the entire flash in the MCU. So, for just updating the firmware, it is necessary to remove the parameter **--erase-all**; otherwise, the MCU configuration will also be deleted. The basic command list can be found [here](https://docs.espressif.com/projects/esptool/en/latest/esp32s3/esptool/basic-commands.html)
Here is the command for updating the firmware in the MCU without erasing the MCU configuration
@ -82,7 +83,7 @@ Launching the esptool application may be different in different operating system
#### Windows
The driver should be installed automatically by Windows
The driver should be installed automatically by Windows. SW for FW flash (Flash Download Tools) is [here](https://www.espressif.com/en/support/download/other-tools)
In the first step, you need to open the application **flash download tool**, and select MCU version

View File

@ -17,7 +17,7 @@ What we need for functionality
<a name="esp32"></a>
## Freenove ESP32-Wrover-CAM
Basic informations:
Basic information:
- On the board missing LED for flash
- Option connecting external FLASH LED
- Missing micro SD card slot
@ -90,7 +90,7 @@ And command for FLASH FW is here, where **/dev/ttya0** is your serial interface
./esptool -p /dev/ttya0 -b 460800 --before default_reset --after hard_reset --chip esp32 write_flash --erase-all --flash_mode dio --flash_size 4MB --flash_freq 80m 0x1000 ESP32_PrusaConnectCam.ino.bootloader.bin 0x8000 ESP32_PrusaConnectCam.ino.partitions.bin 0x10000 ESP32_PrusaConnectCam.ino.bin
```
This command contains the parameter **--eras-all**, which erases the entire flash in the MCU. So, for just updating the firmware, it is necessary to remove the parameter **--eras-all**; otherwise, the MCU configuration will also be deleted. The basic command list can be found [here](https://docs.espressif.com/projects/esptool/en/latest/esp32s3/esptool/basic-commands.html)
This command contains the parameter **--erase-all**, which erases the entire flash in the MCU. So, for just updating the firmware, it is necessary to remove the parameter **--erase-all**; otherwise, the MCU configuration will also be deleted. The basic command list can be found [here](https://docs.espressif.com/projects/esptool/en/latest/esp32s3/esptool/basic-commands.html)
Here is the command for updating the firmware in the MCU without erasing the MCU configuration
@ -102,7 +102,7 @@ Launching the esptool application may be different in different operating system
#### Windows
Driver for CH340 USB to UART convert for Windows is for example [here](https://www.wch-ic.com/search?q=CH340&t=downloads) . An older version of the driver is for example [here](https://blog.laskakit.cz/wp-content/uploads/2020/03/CH341SER.zip)
Driver for CH340 USB to UART convert for Windows is for example [here](https://www.wch-ic.com/search?q=CH340&t=downloads) . An older version of the driver is for example [here](https://blog.laskakit.cz/wp-content/uploads/2020/03/CH341SER.zip) . SW for FW flash (Flash Download Tools) is [here](https://www.espressif.com/en/support/download/other-tools)
<img src="how to flash chip select.jpg" width=25% height=25%>

BIN
doc/ESPTool.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

BIN
doc/ESPToolConnect.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
doc/ESPToolFinish.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

BIN
doc/ESPToolPort.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 KiB

Binary file not shown.

View File

@ -0,0 +1,20 @@
/**********************************************************************
* Filename : Blink
* Description : Make an led blinking.
* Auther : www.freenove.com
* Modification: 2022/10/19
**********************************************************************/
#define LED_BUILTIN 2
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}

View File

@ -0,0 +1,16 @@
/**********************************************************************
Filename : SerialPrinter
Description : Use UART send some data to PC, and show them on serial monitor.
Auther : www.freenove.com
Modification: 2022/10/20
**********************************************************************/
void setup() {
Serial.begin(115200);
Serial.println("ESP32S3 initialization completed!");
}
void loop() {
Serial.printf("Running time : %.1f s\r\n", millis() / 1000.0f);
delay(1000);
}

View File

@ -0,0 +1,30 @@
/**********************************************************************
Filename : SerialRW
Description : Use UART read and write data between ESP32 and PC.
Auther : www.freenove.com
Modification: 2022/10/20
**********************************************************************/
String inputString = ""; //a String to hold incoming data
bool stringComplete = false; // whether the string is complete
void setup() {
Serial.begin(115200);
Serial.println(String("\nESP32S3 initialization completed!\r\n")
+ String("Please input some characters,\r\n")
+ String("select \"Newline\" below and Ctrl + Enter to send message to ESP32S3. \r\n"));
}
void loop() {
if (Serial.available()) { // judge whether data has been received
char inChar = Serial.read(); // read one character
inputString += inChar;
if (inChar == '\n') {
stringComplete = true;
}
}
if (stringComplete) {
Serial.printf("inputString: %s \r\n", inputString);
inputString = "";
stringComplete = false;
}
}

View File

@ -0,0 +1,79 @@
/**********************************************************************
Filename : BLE_USART
Description : Esp32 communicates with the phone by BLE and sends incoming data via a serial port
Auther : www.freenove.com
Modification: 2024/07/01
**********************************************************************/
#include "BLEDevice.h"
#include "BLEServer.h"
#include "BLEUtils.h"
#include "BLE2902.h"
BLECharacteristic *pCharacteristic;
bool deviceConnected = false;
uint8_t txValue = 0;
long lastMsg = 0;
String rxload="Test\n";
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
//pServer->getAdvertising()->start(); //Reopen the pServer and wait for the connection.
}
};
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
String rxValue = pCharacteristic->getValue();
if (rxValue.length() > 0) {
rxload="";
for (int i = 0; i < rxValue.length(); i++){
rxload +=(char)rxValue[i];
}
}
}
};
void setupBLE(String BLEName){
const char *ble_name=BLEName.c_str();
BLEDevice::init(ble_name);
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
BLEService *pService = pServer->createService(SERVICE_UUID);
pCharacteristic= pService->createCharacteristic(CHARACTERISTIC_UUID_TX,BLECharacteristic::PROPERTY_NOTIFY);
pCharacteristic->addDescriptor(new BLE2902());
BLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RX,BLECharacteristic::PROPERTY_WRITE);
pCharacteristic->setCallbacks(new MyCallbacks());
pService->start();
pServer->getAdvertising()->start();
Serial.println("Waiting a client connection to notify...");
}
void setup() {
Serial.begin(115200);
setupBLE("ESP32S3_Bluetooth");
}
void loop() {
long now = millis();
if (now - lastMsg > 100) {
if (deviceConnected&&rxload.length()>0) {
Serial.println(rxload);
rxload="";
}
if(Serial.available()>0){
String str=Serial.readString();
const char *newValue=str.c_str();
pCharacteristic->setValue(newValue);
pCharacteristic->notify();
}
lastMsg = now;
}
}

View File

@ -0,0 +1,65 @@
/**********************************************************************
Filename : SDMMC Test
Description : The SD card is accessed using the SDMMC one-bit bus
Auther : www.freenove.com
Modification: 2022/10/28
**********************************************************************/
#include "sd_read_write.h"
#include "SD_MMC.h"
#define SD_MMC_CMD 38 //Please do not modify it.
#define SD_MMC_CLK 39 //Please do not modify it.
#define SD_MMC_D0 40 //Please do not modify it.
void setup(){
Serial.begin(115200);
SD_MMC.setPins(SD_MMC_CLK, SD_MMC_CMD, SD_MMC_D0);
if (!SD_MMC.begin("/sdcard", true, true, SDMMC_FREQ_DEFAULT, 5)) {
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD_MMC.cardType();
if(cardType == CARD_NONE){
Serial.println("No SD_MMC card attached");
return;
}
Serial.print("SD_MMC Card Type: ");
if(cardType == CARD_MMC){
Serial.println("MMC");
} else if(cardType == CARD_SD){
Serial.println("SDSC");
} else if(cardType == CARD_SDHC){
Serial.println("SDHC");
} else {
Serial.println("UNKNOWN");
}
uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);
Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize);
listDir(SD_MMC, "/", 0);
createDir(SD_MMC, "/mydir");
listDir(SD_MMC, "/", 0);
removeDir(SD_MMC, "/mydir");
listDir(SD_MMC, "/", 2);
writeFile(SD_MMC, "/hello.txt", "Hello ");
appendFile(SD_MMC, "/hello.txt", "World!\n");
readFile(SD_MMC, "/hello.txt");
deleteFile(SD_MMC, "/foo.txt");
renameFile(SD_MMC, "/hello.txt", "/foo.txt");
readFile(SD_MMC, "/foo.txt");
testFileIO(SD_MMC, "/test.txt");
Serial.printf("Total space: %lluMB\r\n", SD_MMC.totalBytes() / (1024 * 1024));
Serial.printf("Used space: %lluMB\r\n", SD_MMC.usedBytes() / (1024 * 1024));
}
void loop(){
delay(10000);
}

View File

@ -0,0 +1,154 @@
#include "sd_read_write.h"
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
Serial.printf("Listing directory: %s\n", dirname);
File root = fs.open(dirname);
if(!root){
Serial.println("Failed to open directory");
return;
}
if(!root.isDirectory()){
Serial.println("Not a directory");
return;
}
File file = root.openNextFile();
while(file){
if(file.isDirectory()){
Serial.print(" DIR : ");
Serial.println(file.name());
if(levels){
listDir(fs, file.path(), levels -1);
}
} else {
Serial.print(" FILE: ");
Serial.print(file.name());
Serial.print(" SIZE: ");
Serial.println(file.size());
}
file = root.openNextFile();
}
}
void createDir(fs::FS &fs, const char * path){
Serial.printf("Creating Dir: %s\n", path);
if(fs.mkdir(path)){
Serial.println("Dir created");
} else {
Serial.println("mkdir failed");
}
}
void removeDir(fs::FS &fs, const char * path){
Serial.printf("Removing Dir: %s\n", path);
if(fs.rmdir(path)){
Serial.println("Dir removed");
} else {
Serial.println("rmdir failed");
}
}
void readFile(fs::FS &fs, const char * path){
Serial.printf("Reading file: %s\n", path);
File file = fs.open(path);
if(!file){
Serial.println("Failed to open file for reading");
return;
}
Serial.print("Read from file: ");
while(file.available()){
Serial.write(file.read());
}
}
void writeFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Writing file: %s\n", path);
File file = fs.open(path, FILE_WRITE);
if(!file){
Serial.println("Failed to open file for writing");
return;
}
if(file.print(message)){
Serial.println("File written");
} else {
Serial.println("Write failed");
}
}
void appendFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Appending to file: %s\n", path);
File file = fs.open(path, FILE_APPEND);
if(!file){
Serial.println("Failed to open file for appending");
return;
}
if(file.print(message)){
Serial.println("Message appended");
} else {
Serial.println("Append failed");
}
}
void renameFile(fs::FS &fs, const char * path1, const char * path2){
Serial.printf("Renaming file %s to %s\n", path1, path2);
if (fs.rename(path1, path2)) {
Serial.println("File renamed");
} else {
Serial.println("Rename failed");
}
}
void deleteFile(fs::FS &fs, const char * path){
Serial.printf("Deleting file: %s\n", path);
if(fs.remove(path)){
Serial.println("File deleted");
} else {
Serial.println("Delete failed");
}
}
void testFileIO(fs::FS &fs, const char * path){
File file = fs.open(path);
static uint8_t buf[512];
size_t len = 0;
uint32_t start = millis();
uint32_t end = start;
if(file){
len = file.size();
size_t flen = len;
start = millis();
while(len){
size_t toRead = len;
if(toRead > 512){
toRead = 512;
}
file.read(buf, toRead);
len -= toRead;
}
end = millis() - start;
Serial.printf("%u bytes read for %u ms\r\n", flen, end);
file.close();
} else {
Serial.println("Failed to open file for reading");
}
file = fs.open(path, FILE_WRITE);
if(!file){
Serial.println("Failed to open file for writing");
return;
}
size_t i;
start = millis();
for(i=0; i<2048; i++){
file.write(buf, 512);
}
end = millis() - start;
Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
file.close();
}

View File

@ -0,0 +1,18 @@
#ifndef __SD_READ_WRITE_H
#define __SD_READ_WRITE_H
#include "Arduino.h"
#include "FS.h"
void listDir(fs::FS &fs, const char * dirname, uint8_t levels);
void createDir(fs::FS &fs, const char * path);
void removeDir(fs::FS &fs, const char * path);
void readFile(fs::FS &fs, const char * path);
void writeFile(fs::FS &fs, const char * path, const char * message);
void appendFile(fs::FS &fs, const char * path, const char * message);
void renameFile(fs::FS &fs, const char * path1, const char * path2);
void deleteFile(fs::FS &fs, const char * path);
void testFileIO(fs::FS &fs, const char * path);
#endif

View File

@ -0,0 +1,28 @@
/**********************************************************************
Filename : WiFi Station
Description : Connect to your router using ESP32
Auther : www.freenove.com
Modification: 2022/10/31
**********************************************************************/
#include <WiFi.h>
const char *ssid_Router = "********"; //Enter the router name
const char *password_Router = "********"; //Enter the router password
void setup(){
Serial.begin(115200);
delay(2000);
Serial.println("Setup start");
WiFi.begin(ssid_Router, password_Router);
Serial.println(String("Connecting to ")+ssid_Router);
while (WiFi.status() != WL_CONNECTED){
delay(500);
Serial.print(".");
}
Serial.println("\nConnected, IP address: ");
Serial.println(WiFi.localIP());
Serial.println("Setup End");
}
void loop() {
}

View File

@ -0,0 +1,36 @@
/**********************************************************************
Filename : WiFi AP
Description : Set ESP32 to open an access point
Auther : www.freenove.com
Modification: 2022/10/31
**********************************************************************/
#include <WiFi.h>
const char *ssid_AP = "WiFi_Name"; //Enter the router name
const char *password_AP = "12345678"; //Enter the router password
IPAddress local_IP(192,168,1,100);//Set the IP address of ESP32 itself
IPAddress gateway(192,168,1,10); //Set the gateway of ESP32 itself
IPAddress subnet(255,255,255,0); //Set the subnet mask for ESP32 itself
void setup(){
Serial.begin(115200);
delay(2000);
Serial.println("Setting soft-AP configuration ... ");
WiFi.disconnect();
WiFi.mode(WIFI_AP);
Serial.println(WiFi.softAPConfig(local_IP, gateway, subnet) ? "Ready" : "Failed!");
Serial.println("Setting soft-AP ... ");
boolean result = WiFi.softAP(ssid_AP, password_AP);
if(result){
Serial.println("Ready");
Serial.println(String("Soft-AP IP address = ") + WiFi.softAPIP().toString());
Serial.println(String("MAC address = ") + WiFi.softAPmacAddress().c_str());
}else{
Serial.println("Failed!");
}
Serial.println("Setup End");
}
void loop() {
}

View File

@ -0,0 +1,42 @@
/**********************************************************************
Filename : WiFi AP+Station
Description : ESP32 connects to the user's router, turning on an access point
Auther : www.freenove.com
Modification: 2022/10/31
**********************************************************************/
#include <WiFi.h>
const char *ssid_Router = "********"; //Enter the router name
const char *password_Router = "********"; //Enter the router password
const char *ssid_AP = "WiFi_Name"; //Enter the router name
const char *password_AP = "12345678"; //Enter the router password
void setup(){
Serial.begin(115200);
Serial.println("Setting soft-AP configuration ... ");
WiFi.disconnect();
WiFi.mode(WIFI_AP);
Serial.println("Setting soft-AP ... ");
boolean result = WiFi.softAP(ssid_AP, password_AP);
if(result){
Serial.println("Ready");
Serial.println(String("Soft-AP IP address = ") + WiFi.softAPIP().toString());
Serial.println(String("MAC address = ") + WiFi.softAPmacAddress().c_str());
}else{
Serial.println("Failed!");
}
Serial.println("\nSetting Station configuration ... ");
WiFi.begin(ssid_Router, password_Router);
Serial.println(String("Connecting to ")+ ssid_Router);
while (WiFi.status() != WL_CONNECTED){
delay(500);
Serial.print(".");
}
Serial.println("\nConnected, IP address: ");
Serial.println(WiFi.localIP());
Serial.println("Setup End");
}
void loop() {
}

View File

@ -0,0 +1,59 @@
/**********************************************************************
Filename : WiFi Client
Description : Use ESP32's WiFi client feature to connect and communicate with a remote IP.
Auther : www.freenove.com
Modification: 2022/10/31
**********************************************************************/
#include <WiFi.h>
const char *ssid_Router = "********"; //Enter the router name
const char *password_Router = "********"; //Enter the router password
#define REMOTE_IP "********" //input the remote server which is you want to connect
#define REMOTE_PORT 8888 //input the remote port which is the remote provide
WiFiClient client;
void setup() {
Serial.begin(115200);
delay(10);
WiFi.begin(ssid_Router, password_Router);
Serial.print("\nWaiting for WiFi... ");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
delay(500);
Serial.print("Connecting to ");
Serial.println(REMOTE_IP);
while (!client.connect(REMOTE_IP, REMOTE_PORT)) {
Serial.println("Connection failed.");
Serial.println("Waiting a moment before retrying...");
}
Serial.println("Connected");
client.print("Hello\n");
client.print("This is my IP.\n");
}
void loop() {
if (client.available() > 0) {
delay(20);
//read back one line from the server
String line = client.readString();
Serial.println(REMOTE_IP + String(":") + line);
}
if (Serial.available() > 0) {
delay(20);
String line = Serial.readString();
client.print(line);
}
if (client.connected () == 0) {
client.stop();
WiFi.disconnect();
}
}

View File

@ -0,0 +1,240 @@
/*
******************************************************************************
* Sketch WiFi Client and Server
* Author Zhentao Lin @ Freenove (http://www.freenove.com)
* Date 2020/7/11
******************************************************************************
* Brief
* This sketch is used to control a 2D ellipse through communicate to an
* ESP32 board or other micro controller.
* It will automatically detect and connect to a device (serial port) which
* use the same trans format.
******************************************************************************
* Copyright
* Copyright © Freenove (http://www.freenove.com)
* License
* Creative Commons Attribution ShareAlike 3.0
* (http://creativecommons.org/licenses/by-sa/3.0/legalcode)
******************************************************************************
*/
import controlP5.*;
import processing.net.*;
ControlP5 cp5;
//Println console;
Server myServer;
Client myClient;
int dataIn=0;
int radioFlag1=0;
int radioFlag2=0;
int send_flag=1;
void setup() {
size(600,400);
smooth();
noStroke();
cp5 = new ControlP5(this);
cp5.addTab("default")
.activateEvent(true)
.setHeight(30)
.setWidth(100)
.setLabel("TCP Server")
.setId(1)
;
cp5.getTab("TCP Client")
.activateEvent(true)
.setHeight(30)
.setWidth(100)
.setId(2)
;
cp5.addTextfield("Local IP")
.setPosition(20,40)
.setSize(160,40)
.setFont(createFont("微软雅黑 Light",20))
.setColor(color(255,255,0))
.setColorLabel(color(0))
.setColorBackground(color(100,255))
.moveTo("default")
;
cp5.addTextfield("Local PORT")
.setPosition(20,120)
.setSize(160,40)
.setFont(createFont("微软雅黑 Light",20))
.setColor(color(255,255,0))
.setColorLabel(color(0))
.setColorBackground(color(100,255))
.setText("8888")
.moveTo("default")
;
cp5.addRadioButton("connect1")
.setPosition(20,200)
.setSize(100,25)
.addItem("Listening", 1)
.setColorLabel(color(0))
.moveTo("default")
;
cp5.addTextfield("Remote IP")
.setPosition(20,40)
.setSize(160,40)
.setFont(createFont("微软雅黑 Light",20))
.setColor(color(255,255,0))
.setColorLabel(color(0))
.setColorBackground(color(100,255))
.setText("192.168.1.xxx")
.moveTo("TCP Client")
;
cp5.addTextfield("Remote PORT")
.setPosition(20,120)
.setSize(160,40)
.setFont(createFont("微软雅黑 Light",20))
.setColor(color(255,255,0))
.setColorLabel(color(0))
.setColorBackground(color(100,255))
.setText("80")
.moveTo("TCP Client")
;
cp5.addRadioButton("connect2")
.setPosition(20,200)
.setSize(100,25)
.addItem("connect Server",1)
.setColorLabel(color(0))
.moveTo("TCP Client")
;
cp5.addTextarea("recvData")
.setPosition(200,40)
.setSize(350,150)
.setFont(createFont("微软雅黑 Light",20))
.setColor(color(255,255,0))
.setColorBackground(color(100,255))
.scroll(15)
.setColorForeground(color(0,100))
.moveTo("global")
;
cp5.addTextfield("sendData")
.setPosition(200,230)
.setSize(350,80)
.setFont(createFont("微软雅黑 Light",20))
.setColor(color(255,255,0))
.setLabel("")
.setFocus(true)
.setColorBackground(color(100,255))
.setColorForeground(color(0,100))
.moveTo("global")
;
cp5.addButton("clearRecv")
.setValue(0)
.setPosition(200,200)
.setSize(100,20)
.setColorLabel(color(255,100))
.moveTo("global")
;
cp5.addButton("clearSend")
.setValue(0)
.setPosition(200,320)
.setSize(100,20)
.setColorLabel(color(255,100))
.moveTo("global")
;
cp5.addButton("Send")
.setValue(0)
.setPosition(450,320)
.setSize(100,20)
.plugTo(this,"send_Textfield_SendData")
.setColorLabel(color(255,100))
.moveTo("global")
;
cp5.get(Textfield.class,"Local IP").setText(Server.ip());
}
void draw(){
background(220);
if(radioFlag1==1){
Client thisClient = myServer.available();
if (thisClient !=null) {
String whatClientSaid = thisClient.readString();
if (whatClientSaid != null) {
cp5.get(Textarea.class,"recvData").append(thisClient.ip()+": ");
cp5.get(Textarea.class,"recvData").append(whatClientSaid+"\n");
}
}
}
// myServer.active()
if(radioFlag2==1){
if (myClient.available() > 0) {
String whatClientSaid = myClient.readString();
if (whatClientSaid != null) {
cp5.get(Textarea.class,"recvData").append(cp5.get(Textfield.class,"Remote IP").getText()+": ");
cp5.get(Textarea.class,"recvData").append(whatClientSaid+"\n");
}
}
}
}
void controlEvent(ControlEvent theControlEvent) {
if (theControlEvent.isTab()) {
if(theControlEvent.getTab().getId()==1){
cp5.get(Textarea.class,"recvData").clear();
cp5.get(Textfield.class,"sendData").clear();
send_flag=1;
}
else if(theControlEvent.getTab().getId()==2){
cp5.get(Textarea.class,"recvData").clear();
cp5.get(Textfield.class,"sendData").clear();
send_flag=2;
}
}
}
void connect1(int a) {
println("a radio Button event: "+a);
radioFlag1=a;
if(radioFlag1==1){
String port_buffer = cp5.get(Textfield.class,"Local PORT").getText();
int port = int(port_buffer);
myServer = new Server(this,port);
println(Server.ip());
cp5.get(Textfield.class,"Local IP").setText(Server.ip());
println(port);
}
else
myServer.stop();
}
void connect2(int a) {
println("a radio Button event: "+a);
radioFlag2=a;
if(radioFlag2==1){
String port_buffer = cp5.get(Textfield.class,"Remote PORT").getText();
String IP_buffer = cp5.get(Textfield.class,"Remote IP").getText();
int port = int(port_buffer);
if(IP_buffer.compareTo("192.168.1.xxx")==0){
println("connect error!");
}
else{
myClient = new Client(this,IP_buffer,port);
println("connect success!");
}
}
else
myClient.stop();
}
void clearRecv(){
cp5.get(Textarea.class,"recvData").clear();
}
void clearSend(){
cp5.get(Textfield.class,"sendData").clear();
}
void send_Textfield_SendData(){
if(send_flag==1){
myServer.write(cp5.get(Textfield.class,"sendData").getText());
cp5.get(Textfield.class,"sendData").clear();
}
else if(send_flag==2){
myClient.write(cp5.get(Textfield.class,"sendData").getText());
cp5.get(Textfield.class,"sendData").clear();
}
}

View File

@ -0,0 +1,53 @@
/**********************************************************************
Filename : WiFi Server
Description : Use ESP32's WiFi server feature to wait for other WiFi devices to connect.
And communicate with them once a connection has been established.
Auther : www.freenove.com
Modification: 2024/07/01
**********************************************************************/
#include <WiFi.h>
#define port 80
const char *ssid_Router = "********"; //input your wifi name
const char *password_Router = "********"; //input your wifi passwords
WiFiServer server(port);
void setup()
{
Serial.begin(115200);
Serial.printf("\nConnecting to ");
Serial.println(ssid_Router);
WiFi.disconnect();
WiFi.begin(ssid_Router, password_Router);
delay(1000);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected.");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
Serial.printf("IP port: %d\n",port);
server.begin(port);
WiFi.setAutoReconnect(true);
}
void loop(){
WiFiClient client = server.accept(); // listen for incoming clients
if (client) { // if you get a client,
Serial.println("Client connected.");
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
Serial.println(client.readStringUntil('\n')); // print it out the serial monitor
while(client.read()>0); // clear the wifi receive area cache
}
if(Serial.available()){ // if there's bytes to read from the serial monitor,
client.print(Serial.readStringUntil('\n')); // print it out the client.
while(Serial.read()>0); // clear the wifi receive area cache
}
}
client.stop(); // stop the client connecting.
Serial.println("Client Disconnected.");
}
}

View File

@ -0,0 +1,240 @@
/*
******************************************************************************
* Sketch WiFi Client and Server
* Author Zhentao Lin @ Freenove (http://www.freenove.com)
* Date 2020/7/11
******************************************************************************
* Brief
* This sketch is used to control a 2D ellipse through communicate to an
* ESP32 board or other micro controller.
* It will automatically detect and connect to a device (serial port) which
* use the same trans format.
******************************************************************************
* Copyright
* Copyright © Freenove (http://www.freenove.com)
* License
* Creative Commons Attribution ShareAlike 3.0
* (http://creativecommons.org/licenses/by-sa/3.0/legalcode)
******************************************************************************
*/
import controlP5.*;
import processing.net.*;
ControlP5 cp5;
//Println console;
Server myServer;
Client myClient;
int dataIn=0;
int radioFlag1=0;
int radioFlag2=0;
int send_flag=1;
void setup() {
size(600,400);
smooth();
noStroke();
cp5 = new ControlP5(this);
cp5.addTab("default")
.activateEvent(true)
.setHeight(30)
.setWidth(100)
.setLabel("TCP Server")
.setId(1)
;
cp5.getTab("TCP Client")
.activateEvent(true)
.setHeight(30)
.setWidth(100)
.setId(2)
;
cp5.addTextfield("Local IP")
.setPosition(20,40)
.setSize(160,40)
.setFont(createFont("微软雅黑 Light",20))
.setColor(color(255,255,0))
.setColorLabel(color(0))
.setColorBackground(color(100,255))
.moveTo("default")
;
cp5.addTextfield("Local PORT")
.setPosition(20,120)
.setSize(160,40)
.setFont(createFont("微软雅黑 Light",20))
.setColor(color(255,255,0))
.setColorLabel(color(0))
.setColorBackground(color(100,255))
.setText("8888")
.moveTo("default")
;
cp5.addRadioButton("connect1")
.setPosition(20,200)
.setSize(100,25)
.addItem("Listening", 1)
.setColorLabel(color(0))
.moveTo("default")
;
cp5.addTextfield("Remote IP")
.setPosition(20,40)
.setSize(160,40)
.setFont(createFont("微软雅黑 Light",20))
.setColor(color(255,255,0))
.setColorLabel(color(0))
.setColorBackground(color(100,255))
.setText("192.168.1.xxx")
.moveTo("TCP Client")
;
cp5.addTextfield("Remote PORT")
.setPosition(20,120)
.setSize(160,40)
.setFont(createFont("微软雅黑 Light",20))
.setColor(color(255,255,0))
.setColorLabel(color(0))
.setColorBackground(color(100,255))
.setText("80")
.moveTo("TCP Client")
;
cp5.addRadioButton("connect2")
.setPosition(20,200)
.setSize(100,25)
.addItem("connect Server",1)
.setColorLabel(color(0))
.moveTo("TCP Client")
;
cp5.addTextarea("recvData")
.setPosition(200,40)
.setSize(350,150)
.setFont(createFont("微软雅黑 Light",20))
.setColor(color(255,255,0))
.setColorBackground(color(100,255))
.scroll(15)
.setColorForeground(color(0,100))
.moveTo("global")
;
cp5.addTextfield("sendData")
.setPosition(200,230)
.setSize(350,80)
.setFont(createFont("微软雅黑 Light",20))
.setColor(color(255,255,0))
.setLabel("")
.setFocus(true)
.setColorBackground(color(100,255))
.setColorForeground(color(0,100))
.moveTo("global")
;
cp5.addButton("clearRecv")
.setValue(0)
.setPosition(200,200)
.setSize(100,20)
.setColorLabel(color(255,100))
.moveTo("global")
;
cp5.addButton("clearSend")
.setValue(0)
.setPosition(200,320)
.setSize(100,20)
.setColorLabel(color(255,100))
.moveTo("global")
;
cp5.addButton("Send")
.setValue(0)
.setPosition(450,320)
.setSize(100,20)
.plugTo(this,"send_Textfield_SendData")
.setColorLabel(color(255,100))
.moveTo("global")
;
cp5.get(Textfield.class,"Local IP").setText(Server.ip());
}
void draw(){
background(220);
if(radioFlag1==1){
Client thisClient = myServer.available();
if (thisClient !=null) {
String whatClientSaid = thisClient.readString();
if (whatClientSaid != null) {
cp5.get(Textarea.class,"recvData").append(thisClient.ip()+": ");
cp5.get(Textarea.class,"recvData").append(whatClientSaid+"\n");
}
}
}
// myServer.active()
if(radioFlag2==1){
if (myClient.available() > 0) {
String whatClientSaid = myClient.readString();
if (whatClientSaid != null) {
cp5.get(Textarea.class,"recvData").append(cp5.get(Textfield.class,"Remote IP").getText()+": ");
cp5.get(Textarea.class,"recvData").append(whatClientSaid+"\n");
}
}
}
}
void controlEvent(ControlEvent theControlEvent) {
if (theControlEvent.isTab()) {
if(theControlEvent.getTab().getId()==1){
cp5.get(Textarea.class,"recvData").clear();
cp5.get(Textfield.class,"sendData").clear();
send_flag=1;
}
else if(theControlEvent.getTab().getId()==2){
cp5.get(Textarea.class,"recvData").clear();
cp5.get(Textfield.class,"sendData").clear();
send_flag=2;
}
}
}
void connect1(int a) {
println("a radio Button event: "+a);
radioFlag1=a;
if(radioFlag1==1){
String port_buffer = cp5.get(Textfield.class,"Local PORT").getText();
int port = int(port_buffer);
myServer = new Server(this,port);
println(Server.ip());
cp5.get(Textfield.class,"Local IP").setText(Server.ip());
println(port);
}
else
myServer.stop();
}
void connect2(int a) {
println("a radio Button event: "+a);
radioFlag2=a;
if(radioFlag2==1){
String port_buffer = cp5.get(Textfield.class,"Remote PORT").getText();
String IP_buffer = cp5.get(Textfield.class,"Remote IP").getText();
int port = int(port_buffer);
if(IP_buffer.compareTo("192.168.1.xxx")==0){
println("connect error!");
}
else{
myClient = new Client(this,IP_buffer,port);
println("connect success!");
}
}
else
myClient.stop();
}
void clearRecv(){
cp5.get(Textarea.class,"recvData").clear();
}
void clearSend(){
cp5.get(Textfield.class,"sendData").clear();
}
void send_Textfield_SendData(){
if(send_flag==1){
myServer.write(cp5.get(Textfield.class,"sendData").getText());
cp5.get(Textfield.class,"sendData").clear();
}
else if(send_flag==2){
myClient.write(cp5.get(Textfield.class,"sendData").getText());
cp5.get(Textfield.class,"sendData").clear();
}
}

View File

@ -0,0 +1,119 @@
/**********************************************************************
Filename : Camera Web Server
Description : The camera images captured by the ESP32S3 are displayed on the web page.
Auther : www.freenove.com
Modification: 2024/07/01
**********************************************************************/
#include "esp_camera.h"
#include <WiFi.h>
// ===================
// Select camera model
// ===================
//#define CAMERA_MODEL_WROVER_KIT // Has PSRAM
//#define CAMERA_MODEL_ESP_EYE // Has PSRAM
#define CAMERA_MODEL_ESP32S3_EYE // Has PSRAM
//#define CAMERA_MODEL_M5STACK_PSRAM // Has PSRAM
//#define CAMERA_MODEL_M5STACK_V2_PSRAM // M5Camera version B Has PSRAM
//#define CAMERA_MODEL_M5STACK_WIDE // Has PSRAM
//#define CAMERA_MODEL_M5STACK_ESP32CAM // No PSRAM
//#define CAMERA_MODEL_M5STACK_UNITCAM // No PSRAM
//#define CAMERA_MODEL_AI_THINKER // Has PSRAM
//#define CAMERA_MODEL_TTGO_T_JOURNAL // No PSRAM
// ** Espressif Internal Boards **
//#define CAMERA_MODEL_ESP32_CAM_BOARD
//#define CAMERA_MODEL_ESP32S2_CAM_BOARD
//#define CAMERA_MODEL_ESP32S3_CAM_LCD
#include "camera_pins.h"
// ===========================
// Enter your WiFi credentials
// ===========================
const char* ssid = "********";
const char* password = "********";
void startCameraServer();
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
Serial.println();
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_sccb_sda = SIOD_GPIO_NUM;
config.pin_sccb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.frame_size = FRAMESIZE_UXGA;
config.pixel_format = PIXFORMAT_JPEG; // for streaming
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
config.fb_location = CAMERA_FB_IN_PSRAM;
config.jpeg_quality = 12;
config.fb_count = 1;
// if PSRAM IC present, init with UXGA resolution and higher JPEG quality
// for larger pre-allocated frame buffer.
if(psramFound()){
config.jpeg_quality = 10;
config.fb_count = 2;
config.grab_mode = CAMERA_GRAB_LATEST;
} else {
// Limit the frame size when PSRAM is not available
config.frame_size = FRAMESIZE_SVGA;
config.fb_location = CAMERA_FB_IN_DRAM;
}
// camera init
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
sensor_t * s = esp_camera_sensor_get();
// initial sensors are flipped vertically and colors are a bit saturated
s->set_vflip(s, 1); // flip it back
s->set_brightness(s, 1); // up the brightness just a bit
s->set_saturation(s, 0); // lower the saturation
WiFi.begin(ssid, password);
WiFi.setSleep(false);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
while (WiFi.STA.hasIP() != true) {
Serial.print(".");
delay(500);
}
Serial.println("");
Serial.println("WiFi connected");
startCameraServer();
Serial.print("Camera Ready! Use 'http://");
Serial.print(WiFi.localIP());
Serial.println("' to connect");
}
void loop() {
// Do nothing. Everything is done in another task by the web server
delay(10000);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,273 @@
#if defined(CAMERA_MODEL_WROVER_KIT)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 21
#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 19
#define Y4_GPIO_NUM 18
#define Y3_GPIO_NUM 5
#define Y2_GPIO_NUM 4
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
#elif defined(CAMERA_MODEL_ESP_EYE)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 4
#define SIOD_GPIO_NUM 18
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 36
#define Y8_GPIO_NUM 37
#define Y7_GPIO_NUM 38
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 35
#define Y4_GPIO_NUM 14
#define Y3_GPIO_NUM 13
#define Y2_GPIO_NUM 34
#define VSYNC_GPIO_NUM 5
#define HREF_GPIO_NUM 27
#define PCLK_GPIO_NUM 25
#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_M5STACK_V2_PSRAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 22
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_M5STACK_WIDE)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 22
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_M5STACK_ESP32CAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 17
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_M5STACK_UNITCAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_AI_THINKER)
#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
#elif defined(CAMERA_MODEL_TTGO_T_JOURNAL)
#define PWDN_GPIO_NUM 0
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 17
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_ESP32_CAM_BOARD)
// The 18 pin header on the board has Y5 and Y3 swapped
#define USE_BOARD_HEADER 0
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM 33
#define XCLK_GPIO_NUM 4
#define SIOD_GPIO_NUM 18
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 36
#define Y8_GPIO_NUM 19
#define Y7_GPIO_NUM 21
#define Y6_GPIO_NUM 39
#if USE_BOARD_HEADER
#define Y5_GPIO_NUM 13
#else
#define Y5_GPIO_NUM 35
#endif
#define Y4_GPIO_NUM 14
#if USE_BOARD_HEADER
#define Y3_GPIO_NUM 35
#else
#define Y3_GPIO_NUM 13
#endif
#define Y2_GPIO_NUM 34
#define VSYNC_GPIO_NUM 5
#define HREF_GPIO_NUM 27
#define PCLK_GPIO_NUM 25
#elif defined(CAMERA_MODEL_ESP32S3_CAM_LCD)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 40
#define SIOD_GPIO_NUM 17
#define SIOC_GPIO_NUM 18
#define Y9_GPIO_NUM 39
#define Y8_GPIO_NUM 41
#define Y7_GPIO_NUM 42
#define Y6_GPIO_NUM 12
#define Y5_GPIO_NUM 3
#define Y4_GPIO_NUM 14
#define Y3_GPIO_NUM 47
#define Y2_GPIO_NUM 13
#define VSYNC_GPIO_NUM 21
#define HREF_GPIO_NUM 38
#define PCLK_GPIO_NUM 11
#elif defined(CAMERA_MODEL_ESP32S2_CAM_BOARD)
// The 18 pin header on the board has Y5 and Y3 swapped
#define USE_BOARD_HEADER 0
#define PWDN_GPIO_NUM 1
#define RESET_GPIO_NUM 2
#define XCLK_GPIO_NUM 42
#define SIOD_GPIO_NUM 41
#define SIOC_GPIO_NUM 18
#define Y9_GPIO_NUM 16
#define Y8_GPIO_NUM 39
#define Y7_GPIO_NUM 40
#define Y6_GPIO_NUM 15
#if USE_BOARD_HEADER
#define Y5_GPIO_NUM 12
#else
#define Y5_GPIO_NUM 13
#endif
#define Y4_GPIO_NUM 5
#if USE_BOARD_HEADER
#define Y3_GPIO_NUM 13
#else
#define Y3_GPIO_NUM 12
#endif
#define Y2_GPIO_NUM 14
#define VSYNC_GPIO_NUM 38
#define HREF_GPIO_NUM 4
#define PCLK_GPIO_NUM 3
#elif defined(CAMERA_MODEL_ESP32S3_EYE)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 15
#define SIOD_GPIO_NUM 4
#define SIOC_GPIO_NUM 5
#define Y2_GPIO_NUM 11
#define Y3_GPIO_NUM 9
#define Y4_GPIO_NUM 8
#define Y5_GPIO_NUM 10
#define Y6_GPIO_NUM 12
#define Y7_GPIO_NUM 18
#define Y8_GPIO_NUM 17
#define Y9_GPIO_NUM 16
#define VSYNC_GPIO_NUM 6
#define HREF_GPIO_NUM 7
#define PCLK_GPIO_NUM 13
#else
#error "Camera model not selected"
#endif

View File

@ -0,0 +1,106 @@
/**********************************************************************
Filename : Video Web Server
Description : The camera images captured by the ESP32S3 are displayed on the web page.
Auther : www.freenove.com
Modification: 2022/11/01
**********************************************************************/
#include "esp_camera.h"
#include <WiFi.h>
#include "sd_read_write.h"
// Select camera model
#define CAMERA_MODEL_ESP32S3_EYE // Has PSRAM
#include "camera_pins.h"
const char* ssid = "********"; //input your wifi name
const char* password = "********"; //input your wifi passwords
void cameraInit(void);
void startCameraServer();
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
Serial.println();
cameraInit();
sdmmcInit();
removeDir(SD_MMC, "/video");
createDir(SD_MMC, "/video");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
startCameraServer();
Serial.print("Camera Ready! Use 'http://");
Serial.print(WiFi.localIP());
Serial.println("' to connect");
}
void loop() {
// put your main code here, to run repeatedly:
delay(10000);
}
void cameraInit(void){
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_sccb_sda = SIOD_GPIO_NUM;
config.pin_sccb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.frame_size = FRAMESIZE_UXGA;
config.pixel_format = PIXFORMAT_JPEG; // for streaming
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
config.fb_location = CAMERA_FB_IN_PSRAM;
config.jpeg_quality = 12;
config.fb_count = 1;
// if PSRAM IC present, init with UXGA resolution and higher JPEG quality
// for larger pre-allocated frame buffer.
if(psramFound()){
config.jpeg_quality = 10;
config.fb_count = 2;
config.grab_mode = CAMERA_GRAB_LATEST;
} else {
// Limit the frame size when PSRAM is not available
config.frame_size = FRAMESIZE_SVGA;
config.fb_location = CAMERA_FB_IN_DRAM;
}
// camera init
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
sensor_t * s = esp_camera_sensor_get();
// initial sensors are flipped vertically and colors are a bit saturated
s->set_vflip(s, 1); // flip it back
s->set_brightness(s, 1); // up the brightness just a bit
s->set_saturation(s, 0); // lower the saturation
}

View File

@ -0,0 +1,335 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "esp_http_server.h"
#include "esp_timer.h"
#include "esp_camera.h"
#include "img_converters.h"
#include "fb_gfx.h"
#include "driver/ledc.h"
#include "sdkconfig.h"
#include "Arduino.h"
#include "sd_read_write.h"
#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
#include "esp32-hal-log.h"
#define TAG ""
#else
#include "esp_log.h"
static const char *TAG = "camera_httpd";
#endif
typedef struct
{
httpd_req_t *req;
size_t len;
} jpg_chunking_t;
#define PART_BOUNDARY "123456789000000000000987654321"
static const char *_STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
static const char *_STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";
static const char *_STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\nX-Timestamp: %d.%06d\r\n\r\n";
httpd_handle_t stream_httpd = NULL;
httpd_handle_t camera_httpd = NULL;
static int button_state = 1;
typedef struct
{
size_t size; // number of values used for filtering
size_t index; // current value index
size_t count; // value count
int sum;
int *values; // array to be filled with values
} ra_filter_t;
static ra_filter_t ra_filter;
static ra_filter_t *ra_filter_init(ra_filter_t *filter, size_t sample_size)
{
memset(filter, 0, sizeof(ra_filter_t));
filter->values = (int *)malloc(sample_size * sizeof(int));
if (!filter->values)
{
return NULL;
}
memset(filter->values, 0, sample_size * sizeof(int));
filter->size = sample_size;
return filter;
}
static int ra_filter_run(ra_filter_t *filter, int value)
{
if (!filter->values)
{
return value;
}
filter->sum -= filter->values[filter->index];
filter->values[filter->index] = value;
filter->sum += filter->values[filter->index];
filter->index++;
filter->index = filter->index % filter->size;
if (filter->count < filter->size)
{
filter->count++;
}
return filter->sum / filter->count;
}
static esp_err_t stream_handler(httpd_req_t *req)
{
camera_fb_t *fb = NULL;
struct timeval _timestamp;
esp_err_t res = ESP_OK;
size_t _jpg_buf_len = 0;
uint8_t *_jpg_buf = NULL;
char *part_buf[128];
static int64_t last_frame = 0;
if (!last_frame)
{
last_frame = esp_timer_get_time();
}
res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE);
if (res != ESP_OK)
{
return res;
}
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
httpd_resp_set_hdr(req, "X-Framerate", "60");
while (true)
{
fb = esp_camera_fb_get();
if (!fb)
{
ESP_LOGE(TAG, "Camera capture failed");
res = ESP_FAIL;
}
else
{
_timestamp.tv_sec = fb->timestamp.tv_sec;
_timestamp.tv_usec = fb->timestamp.tv_usec;
if (fb->format != PIXFORMAT_JPEG)
{
bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len);
esp_camera_fb_return(fb);
fb = NULL;
if (!jpeg_converted)
{
ESP_LOGE(TAG, "JPEG compression failed");
res = ESP_FAIL;
}
}
else
{
_jpg_buf_len = fb->len;
_jpg_buf = fb->buf;
}
}
if (res == ESP_OK)
{
res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));
}
if (res == ESP_OK)
{
size_t hlen = snprintf((char *)part_buf, 128, _STREAM_PART, _jpg_buf_len, _timestamp.tv_sec, _timestamp.tv_usec);
res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen);
}
if (res == ESP_OK)
{
res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len);
}
if (fb)
{
esp_camera_fb_return(fb);
fb = NULL;
_jpg_buf = NULL;
}
else if (_jpg_buf)
{
free(_jpg_buf);
_jpg_buf = NULL;
}
if (res != ESP_OK)
{
ESP_LOGI(TAG, "res != ESP_OK : %d , break!", res);
break;
}
int64_t fr_end = esp_timer_get_time();
int64_t frame_time = fr_end - last_frame;
last_frame = fr_end;
frame_time /= 1000;
uint32_t avg_frame_time = ra_filter_run(&ra_filter, frame_time);
/*
ESP_LOGI(TAG, "MJPG: %uB %ums (%.1ffps), AVG: %ums (%.1ffps)",
(uint32_t)(_jpg_buf_len),
(uint32_t)frame_time, 1000.0 / (uint32_t)frame_time,
avg_frame_time, 1000.0 / avg_frame_time);
*/
}
ESP_LOGI(TAG, "Stream exit!");
last_frame = 0;
return res;
}
static esp_err_t parse_get(httpd_req_t *req, char **obuf)
{
char *buf = NULL;
size_t buf_len = 0;
buf_len = httpd_req_get_url_query_len(req) + 1;
if (buf_len > 1)
{
buf = (char *)malloc(buf_len);
if (!buf)
{
httpd_resp_send_500(req);
return ESP_FAIL;
}
if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK)
{
*obuf = buf;
return ESP_OK;
}
free(buf);
}
httpd_resp_send_404(req);
return ESP_FAIL;
}
const char index_web[]=R"rawliteral(
<html>
<head>
<title>Video Streaming Demonstration</title>
</head>
<body>
<p><h1>Video Streaming Demonstration</h1></p>
<p><img id="stream" src="" style="transform:rotate(180deg)"/></p>
<iframe width=0 height=0 frameborder=0 id="myiframe" name="myiframe"></iframe>
<p><form action="/button" method="POST" target="myiframe"><input type="submit" value="Save it to SDcard"></form></p>
</body>
<script>
document.addEventListener('DOMContentLoaded', function (event) {
var baseHost = document.location.origin
var streamUrl = baseHost + ':81'
const view = document.getElementById('stream')
view.src = `${streamUrl}/stream`
});
</script>
</html>)rawliteral";
static esp_err_t index_handler(httpd_req_t *req)
{
esp_err_t err;
err = httpd_resp_set_type(req, "text/html");
sensor_t *s = esp_camera_sensor_get();
if (s != NULL)
{
err = httpd_resp_send(req, (const char *)index_web, sizeof(index_web));
}
else
{
ESP_LOGE(TAG, "Camera sensor not found");
err = httpd_resp_send_500(req);
}
return err;
}
static esp_err_t button_handler(httpd_req_t *req)
{
esp_err_t err;
camera_fb_t * fb = NULL;
fb = esp_camera_fb_get();
if (!fb)
{
ESP_LOGE(TAG, "Camera capture failed");
err = ESP_FAIL;
}
else
{
String video = "/video";
int jpgCount=readFileNum(SD_MMC, video.c_str());
String path = video + "/" + String(jpgCount) +".jpg";
writejpg(SD_MMC, path.c_str(), fb->buf, fb->len);
esp_camera_fb_return(fb);
fb = NULL;
err=ESP_OK;
}
return err;
}
void startCameraServer()
{
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.max_uri_handlers = 16;
httpd_uri_t index_uri = {
.uri = "/",
.method = HTTP_GET,
.handler = index_handler,
.user_ctx = NULL};
httpd_uri_t stream_uri = {
.uri = "/stream",
.method = HTTP_GET,
.handler = stream_handler,
.user_ctx = NULL};
httpd_uri_t button_uri = {
.uri = "/button",
.method = HTTP_POST,
.handler = button_handler,
.user_ctx = NULL};
ra_filter_init(&ra_filter, 20);
ESP_LOGI(TAG, "Starting web server on port: '%d'", config.server_port);
if (httpd_start(&camera_httpd, &config) == ESP_OK)
{
httpd_register_uri_handler(camera_httpd, &index_uri);
httpd_register_uri_handler(camera_httpd, &button_uri);
// httpd_register_uri_handler(camera_httpd, &stream_uri);
}
config.server_port += 1;
config.ctrl_port += 1;
ESP_LOGI(TAG, "Starting stream server on port: '%d'", config.server_port);
if (httpd_start(&stream_httpd, &config) == ESP_OK)
{
httpd_register_uri_handler(stream_httpd, &stream_uri);
}
}

View File

@ -0,0 +1,273 @@
#if defined(CAMERA_MODEL_WROVER_KIT)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 21
#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 19
#define Y4_GPIO_NUM 18
#define Y3_GPIO_NUM 5
#define Y2_GPIO_NUM 4
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
#elif defined(CAMERA_MODEL_ESP_EYE)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 4
#define SIOD_GPIO_NUM 18
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 36
#define Y8_GPIO_NUM 37
#define Y7_GPIO_NUM 38
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 35
#define Y4_GPIO_NUM 14
#define Y3_GPIO_NUM 13
#define Y2_GPIO_NUM 34
#define VSYNC_GPIO_NUM 5
#define HREF_GPIO_NUM 27
#define PCLK_GPIO_NUM 25
#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_M5STACK_V2_PSRAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 22
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_M5STACK_WIDE)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 22
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_M5STACK_ESP32CAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 17
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_M5STACK_UNITCAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_AI_THINKER)
#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
#elif defined(CAMERA_MODEL_TTGO_T_JOURNAL)
#define PWDN_GPIO_NUM 0
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 17
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_ESP32_CAM_BOARD)
// The 18 pin header on the board has Y5 and Y3 swapped
#define USE_BOARD_HEADER 0
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM 33
#define XCLK_GPIO_NUM 4
#define SIOD_GPIO_NUM 18
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 36
#define Y8_GPIO_NUM 19
#define Y7_GPIO_NUM 21
#define Y6_GPIO_NUM 39
#if USE_BOARD_HEADER
#define Y5_GPIO_NUM 13
#else
#define Y5_GPIO_NUM 35
#endif
#define Y4_GPIO_NUM 14
#if USE_BOARD_HEADER
#define Y3_GPIO_NUM 35
#else
#define Y3_GPIO_NUM 13
#endif
#define Y2_GPIO_NUM 34
#define VSYNC_GPIO_NUM 5
#define HREF_GPIO_NUM 27
#define PCLK_GPIO_NUM 25
#elif defined(CAMERA_MODEL_ESP32S3_CAM_LCD)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 40
#define SIOD_GPIO_NUM 17
#define SIOC_GPIO_NUM 18
#define Y9_GPIO_NUM 39
#define Y8_GPIO_NUM 41
#define Y7_GPIO_NUM 42
#define Y6_GPIO_NUM 12
#define Y5_GPIO_NUM 3
#define Y4_GPIO_NUM 14
#define Y3_GPIO_NUM 47
#define Y2_GPIO_NUM 13
#define VSYNC_GPIO_NUM 21
#define HREF_GPIO_NUM 38
#define PCLK_GPIO_NUM 11
#elif defined(CAMERA_MODEL_ESP32S2_CAM_BOARD)
// The 18 pin header on the board has Y5 and Y3 swapped
#define USE_BOARD_HEADER 0
#define PWDN_GPIO_NUM 1
#define RESET_GPIO_NUM 2
#define XCLK_GPIO_NUM 42
#define SIOD_GPIO_NUM 41
#define SIOC_GPIO_NUM 18
#define Y9_GPIO_NUM 16
#define Y8_GPIO_NUM 39
#define Y7_GPIO_NUM 40
#define Y6_GPIO_NUM 15
#if USE_BOARD_HEADER
#define Y5_GPIO_NUM 12
#else
#define Y5_GPIO_NUM 13
#endif
#define Y4_GPIO_NUM 5
#if USE_BOARD_HEADER
#define Y3_GPIO_NUM 13
#else
#define Y3_GPIO_NUM 12
#endif
#define Y2_GPIO_NUM 14
#define VSYNC_GPIO_NUM 38
#define HREF_GPIO_NUM 4
#define PCLK_GPIO_NUM 3
#elif defined(CAMERA_MODEL_ESP32S3_EYE)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 15
#define SIOD_GPIO_NUM 4
#define SIOC_GPIO_NUM 5
#define Y2_GPIO_NUM 11
#define Y3_GPIO_NUM 9
#define Y4_GPIO_NUM 8
#define Y5_GPIO_NUM 10
#define Y6_GPIO_NUM 12
#define Y7_GPIO_NUM 18
#define Y8_GPIO_NUM 17
#define Y9_GPIO_NUM 16
#define VSYNC_GPIO_NUM 6
#define HREF_GPIO_NUM 7
#define PCLK_GPIO_NUM 13
#else
#error "Camera model not selected"
#endif

View File

@ -0,0 +1,211 @@
#include "sd_read_write.h"
void sdmmcInit(void){
SD_MMC.setPins(SD_MMC_CLK, SD_MMC_CMD, SD_MMC_D0);
if (!SD_MMC.begin("/sdcard", true, true, SDMMC_FREQ_DEFAULT, 5)) {
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD_MMC.cardType();
if(cardType == CARD_NONE){
Serial.println("No SD_MMC card attached");
return;
}
Serial.print("SD_MMC Card Type: ");
if(cardType == CARD_MMC){
Serial.println("MMC");
} else if(cardType == CARD_SD){
Serial.println("SDSC");
} else if(cardType == CARD_SDHC){
Serial.println("SDHC");
} else {
Serial.println("UNKNOWN");
}
uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);
Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize);
Serial.printf("Total space: %lluMB\r\n", SD_MMC.totalBytes() / (1024 * 1024));
Serial.printf("Used space: %lluMB\r\n", SD_MMC.usedBytes() / (1024 * 1024));
}
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
Serial.printf("Listing directory: %s\n", dirname);
File root = fs.open(dirname);
if(!root){
Serial.println("Failed to open directory");
return;
}
if(!root.isDirectory()){
Serial.println("Not a directory");
return;
}
File file = root.openNextFile();
while(file){
if(file.isDirectory()){
Serial.print(" DIR : ");
Serial.println(file.name());
if(levels){
listDir(fs, file.path(), levels -1);
}
} else {
Serial.print(" FILE: ");
Serial.print(file.name());
Serial.print(" SIZE: ");
Serial.println(file.size());
}
file = root.openNextFile();
}
}
void createDir(fs::FS &fs, const char * path){
Serial.printf("Creating Dir: %s\n", path);
if(fs.mkdir(path)){
Serial.println("Dir created");
} else {
Serial.println("mkdir failed");
}
}
void removeDir(fs::FS &fs, const char * path){
Serial.printf("Removing Dir: %s\n", path);
if(fs.rmdir(path)){
Serial.println("Dir removed");
} else {
Serial.println("rmdir failed");
}
}
void readFile(fs::FS &fs, const char * path){
Serial.printf("Reading file: %s\n", path);
File file = fs.open(path);
if(!file){
Serial.println("Failed to open file for reading");
return;
}
Serial.print("Read from file: ");
while(file.available()){
Serial.write(file.read());
}
}
void writeFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Writing file: %s\n", path);
File file = fs.open(path, FILE_WRITE);
if(!file){
Serial.println("Failed to open file for writing");
return;
}
if(file.print(message)){
Serial.println("File written");
} else {
Serial.println("Write failed");
}
}
void appendFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Appending to file: %s\n", path);
File file = fs.open(path, FILE_APPEND);
if(!file){
Serial.println("Failed to open file for appending");
return;
}
if(file.print(message)){
Serial.println("Message appended");
} else {
Serial.println("Append failed");
}
}
void renameFile(fs::FS &fs, const char * path1, const char * path2){
Serial.printf("Renaming file %s to %s\n", path1, path2);
if (fs.rename(path1, path2)) {
Serial.println("File renamed");
} else {
Serial.println("Rename failed");
}
}
void deleteFile(fs::FS &fs, const char * path){
Serial.printf("Deleting file: %s\n", path);
if(fs.remove(path)){
Serial.println("File deleted");
} else {
Serial.println("Delete failed");
}
}
void testFileIO(fs::FS &fs, const char * path){
File file = fs.open(path);
static uint8_t buf[512];
size_t len = 0;
uint32_t start = millis();
uint32_t end = start;
if(file){
len = file.size();
size_t flen = len;
start = millis();
while(len){
size_t toRead = len;
if(toRead > 512){
toRead = 512;
}
file.read(buf, toRead);
len -= toRead;
}
end = millis() - start;
Serial.printf("%u bytes read for %u ms\r\n", flen, end);
file.close();
} else {
Serial.println("Failed to open file for reading");
}
file = fs.open(path, FILE_WRITE);
if(!file){
Serial.println("Failed to open file for writing");
return;
}
size_t i;
start = millis();
for(i=0; i<2048; i++){
file.write(buf, 512);
}
end = millis() - start;
Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
file.close();
}
void writejpg(fs::FS &fs, const char * path, const uint8_t *buf, size_t size){
File file = fs.open(path, FILE_WRITE);
if(!file){
Serial.println("Failed to open file for writing");
return;
}
file.write(buf, size);
Serial.printf("Saved file to path: %s\r\n", path);
}
int readFileNum(fs::FS &fs, const char * dirname){
File root = fs.open(dirname);
if(!root){
Serial.println("Failed to open directory");
return -1;
}
if(!root.isDirectory()){
Serial.println("Not a directory");
return -1;
}
File file = root.openNextFile();
int num=0;
while(file){
file = root.openNextFile();
num++;
}
return num;
}

View File

@ -0,0 +1,27 @@
#ifndef __SD_READ_WRITE_H
#define __SD_READ_WRITE_H
#include "Arduino.h"
#include "FS.h"
#include "SD_MMC.h"
#define SD_MMC_CMD 38 //Please do not modify it.
#define SD_MMC_CLK 39 //Please do not modify it.
#define SD_MMC_D0 40 //Please do not modify it.
void sdmmcInit(void);
void listDir(fs::FS &fs, const char * dirname, uint8_t levels);
void createDir(fs::FS &fs, const char * path);
void removeDir(fs::FS &fs, const char * path);
void readFile(fs::FS &fs, const char * path);
void writeFile(fs::FS &fs, const char * path, const char * message);
void appendFile(fs::FS &fs, const char * path, const char * message);
void renameFile(fs::FS &fs, const char * path1, const char * path2);
void deleteFile(fs::FS &fs, const char * path);
void testFileIO(fs::FS &fs, const char * path);
void writejpg(fs::FS &fs, const char * path, const uint8_t *buf, size_t size);
int readFileNum(fs::FS &fs, const char * dirname);
#endif

View File

@ -0,0 +1,114 @@
/**********************************************************************
Filename : Camera and SDcard
Description : Use the onboard buttons to take photo and save them to an SD card.
Auther : www.freenove.com
Modification: 2022/11/02
**********************************************************************/
#include "esp_camera.h"
#define CAMERA_MODEL_ESP32S3_EYE
#include "camera_pins.h"
#include "ws2812.h"
#include "sd_read_write.h"
#define BUTTON_PIN 0
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(false);
Serial.println();
pinMode(BUTTON_PIN, INPUT_PULLUP);
ws2812Init();
sdmmcInit();
//removeDir(SD_MMC, "/camera");
createDir(SD_MMC, "/camera");
listDir(SD_MMC, "/camera", 0);
if(cameraSetup()==1){
ws2812SetColor(2);
}
else{
ws2812SetColor(1);
return;
}
}
void loop() {
if(digitalRead(BUTTON_PIN)==LOW){
delay(20);
if(digitalRead(BUTTON_PIN)==LOW){
ws2812SetColor(3);
while(digitalRead(BUTTON_PIN)==LOW);
camera_fb_t * fb = NULL;
fb = esp_camera_fb_get();
if (fb != NULL) {
int photo_index = readFileNum(SD_MMC, "/camera");
if(photo_index!=-1)
{
String path = "/camera/" + String(photo_index) +".jpg";
writejpg(SD_MMC, path.c_str(), fb->buf, fb->len);
}
esp_camera_fb_return(fb);
}
else {
Serial.println("Camera capture failed.");
}
ws2812SetColor(2);
}
}
}
int cameraSetup(void) {
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_sccb_sda = SIOD_GPIO_NUM;
config.pin_sccb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.frame_size = FRAMESIZE_UXGA;
config.pixel_format = PIXFORMAT_JPEG; // for streaming
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
config.fb_location = CAMERA_FB_IN_PSRAM;
config.jpeg_quality = 12;
config.fb_count = 1;
// if PSRAM IC present, init with UXGA resolution and higher JPEG quality
// for larger pre-allocated frame buffer.
if(psramFound()){
config.jpeg_quality = 10;
config.fb_count = 2;
config.grab_mode = CAMERA_GRAB_LATEST;
} else {
// Limit the frame size when PSRAM is not available
config.frame_size = FRAMESIZE_SVGA;
config.fb_location = CAMERA_FB_IN_DRAM;
}
// camera init
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return 0;
}
sensor_t * s = esp_camera_sensor_get();
// initial sensors are flipped vertically and colors are a bit saturated
s->set_vflip(s, 1); // flip it back
s->set_brightness(s, 1); // up the brightness just a bit
s->set_saturation(s, 0); // lower the saturation
Serial.println("Camera configuration complete!");
return 1;
}

View File

@ -0,0 +1,273 @@
#if defined(CAMERA_MODEL_WROVER_KIT)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 21
#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 19
#define Y4_GPIO_NUM 18
#define Y3_GPIO_NUM 5
#define Y2_GPIO_NUM 4
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
#elif defined(CAMERA_MODEL_ESP_EYE)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 4
#define SIOD_GPIO_NUM 18
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 36
#define Y8_GPIO_NUM 37
#define Y7_GPIO_NUM 38
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 35
#define Y4_GPIO_NUM 14
#define Y3_GPIO_NUM 13
#define Y2_GPIO_NUM 34
#define VSYNC_GPIO_NUM 5
#define HREF_GPIO_NUM 27
#define PCLK_GPIO_NUM 25
#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_M5STACK_V2_PSRAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 22
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_M5STACK_WIDE)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 22
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_M5STACK_ESP32CAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 17
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_M5STACK_UNITCAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_AI_THINKER)
#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
#elif defined(CAMERA_MODEL_TTGO_T_JOURNAL)
#define PWDN_GPIO_NUM 0
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 17
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_ESP32_CAM_BOARD)
// The 18 pin header on the board has Y5 and Y3 swapped
#define USE_BOARD_HEADER 0
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM 33
#define XCLK_GPIO_NUM 4
#define SIOD_GPIO_NUM 18
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 36
#define Y8_GPIO_NUM 19
#define Y7_GPIO_NUM 21
#define Y6_GPIO_NUM 39
#if USE_BOARD_HEADER
#define Y5_GPIO_NUM 13
#else
#define Y5_GPIO_NUM 35
#endif
#define Y4_GPIO_NUM 14
#if USE_BOARD_HEADER
#define Y3_GPIO_NUM 35
#else
#define Y3_GPIO_NUM 13
#endif
#define Y2_GPIO_NUM 34
#define VSYNC_GPIO_NUM 5
#define HREF_GPIO_NUM 27
#define PCLK_GPIO_NUM 25
#elif defined(CAMERA_MODEL_ESP32S3_CAM_LCD)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 40
#define SIOD_GPIO_NUM 17
#define SIOC_GPIO_NUM 18
#define Y9_GPIO_NUM 39
#define Y8_GPIO_NUM 41
#define Y7_GPIO_NUM 42
#define Y6_GPIO_NUM 12
#define Y5_GPIO_NUM 3
#define Y4_GPIO_NUM 14
#define Y3_GPIO_NUM 47
#define Y2_GPIO_NUM 13
#define VSYNC_GPIO_NUM 21
#define HREF_GPIO_NUM 38
#define PCLK_GPIO_NUM 11
#elif defined(CAMERA_MODEL_ESP32S2_CAM_BOARD)
// The 18 pin header on the board has Y5 and Y3 swapped
#define USE_BOARD_HEADER 0
#define PWDN_GPIO_NUM 1
#define RESET_GPIO_NUM 2
#define XCLK_GPIO_NUM 42
#define SIOD_GPIO_NUM 41
#define SIOC_GPIO_NUM 18
#define Y9_GPIO_NUM 16
#define Y8_GPIO_NUM 39
#define Y7_GPIO_NUM 40
#define Y6_GPIO_NUM 15
#if USE_BOARD_HEADER
#define Y5_GPIO_NUM 12
#else
#define Y5_GPIO_NUM 13
#endif
#define Y4_GPIO_NUM 5
#if USE_BOARD_HEADER
#define Y3_GPIO_NUM 13
#else
#define Y3_GPIO_NUM 12
#endif
#define Y2_GPIO_NUM 14
#define VSYNC_GPIO_NUM 38
#define HREF_GPIO_NUM 4
#define PCLK_GPIO_NUM 3
#elif defined(CAMERA_MODEL_ESP32S3_EYE)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 15
#define SIOD_GPIO_NUM 4
#define SIOC_GPIO_NUM 5
#define Y2_GPIO_NUM 11
#define Y3_GPIO_NUM 9
#define Y4_GPIO_NUM 8
#define Y5_GPIO_NUM 10
#define Y6_GPIO_NUM 12
#define Y7_GPIO_NUM 18
#define Y8_GPIO_NUM 17
#define Y9_GPIO_NUM 16
#define VSYNC_GPIO_NUM 6
#define HREF_GPIO_NUM 7
#define PCLK_GPIO_NUM 13
#else
#error "Camera model not selected"
#endif

View File

@ -0,0 +1,211 @@
#include "sd_read_write.h"
void sdmmcInit(void){
SD_MMC.setPins(SD_MMC_CLK, SD_MMC_CMD, SD_MMC_D0);
if (!SD_MMC.begin("/sdcard", true, true, SDMMC_FREQ_DEFAULT, 5)) {
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD_MMC.cardType();
if(cardType == CARD_NONE){
Serial.println("No SD_MMC card attached");
return;
}
Serial.print("SD_MMC Card Type: ");
if(cardType == CARD_MMC){
Serial.println("MMC");
} else if(cardType == CARD_SD){
Serial.println("SDSC");
} else if(cardType == CARD_SDHC){
Serial.println("SDHC");
} else {
Serial.println("UNKNOWN");
}
uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);
Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize);
Serial.printf("Total space: %lluMB\r\n", SD_MMC.totalBytes() / (1024 * 1024));
Serial.printf("Used space: %lluMB\r\n", SD_MMC.usedBytes() / (1024 * 1024));
}
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
Serial.printf("Listing directory: %s\n", dirname);
File root = fs.open(dirname);
if(!root){
Serial.println("Failed to open directory");
return;
}
if(!root.isDirectory()){
Serial.println("Not a directory");
return;
}
File file = root.openNextFile();
while(file){
if(file.isDirectory()){
Serial.print(" DIR : ");
Serial.println(file.name());
if(levels){
listDir(fs, file.path(), levels -1);
}
} else {
Serial.print(" FILE: ");
Serial.print(file.name());
Serial.print(" SIZE: ");
Serial.println(file.size());
}
file = root.openNextFile();
}
}
void createDir(fs::FS &fs, const char * path){
Serial.printf("Creating Dir: %s\n", path);
if(fs.mkdir(path)){
Serial.println("Dir created");
} else {
Serial.println("mkdir failed");
}
}
void removeDir(fs::FS &fs, const char * path){
Serial.printf("Removing Dir: %s\n", path);
if(fs.rmdir(path)){
Serial.println("Dir removed");
} else {
Serial.println("rmdir failed");
}
}
void readFile(fs::FS &fs, const char * path){
Serial.printf("Reading file: %s\n", path);
File file = fs.open(path);
if(!file){
Serial.println("Failed to open file for reading");
return;
}
Serial.print("Read from file: ");
while(file.available()){
Serial.write(file.read());
}
}
void writeFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Writing file: %s\n", path);
File file = fs.open(path, FILE_WRITE);
if(!file){
Serial.println("Failed to open file for writing");
return;
}
if(file.print(message)){
Serial.println("File written");
} else {
Serial.println("Write failed");
}
}
void appendFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Appending to file: %s\n", path);
File file = fs.open(path, FILE_APPEND);
if(!file){
Serial.println("Failed to open file for appending");
return;
}
if(file.print(message)){
Serial.println("Message appended");
} else {
Serial.println("Append failed");
}
}
void renameFile(fs::FS &fs, const char * path1, const char * path2){
Serial.printf("Renaming file %s to %s\n", path1, path2);
if (fs.rename(path1, path2)) {
Serial.println("File renamed");
} else {
Serial.println("Rename failed");
}
}
void deleteFile(fs::FS &fs, const char * path){
Serial.printf("Deleting file: %s\n", path);
if(fs.remove(path)){
Serial.println("File deleted");
} else {
Serial.println("Delete failed");
}
}
void testFileIO(fs::FS &fs, const char * path){
File file = fs.open(path);
static uint8_t buf[512];
size_t len = 0;
uint32_t start = millis();
uint32_t end = start;
if(file){
len = file.size();
size_t flen = len;
start = millis();
while(len){
size_t toRead = len;
if(toRead > 512){
toRead = 512;
}
file.read(buf, toRead);
len -= toRead;
}
end = millis() - start;
Serial.printf("%u bytes read for %u ms\r\n", flen, end);
file.close();
} else {
Serial.println("Failed to open file for reading");
}
file = fs.open(path, FILE_WRITE);
if(!file){
Serial.println("Failed to open file for writing");
return;
}
size_t i;
start = millis();
for(i=0; i<2048; i++){
file.write(buf, 512);
}
end = millis() - start;
Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
file.close();
}
void writejpg(fs::FS &fs, const char * path, const uint8_t *buf, size_t size){
File file = fs.open(path, FILE_WRITE);
if(!file){
Serial.println("Failed to open file for writing");
return;
}
file.write(buf, size);
Serial.printf("Saved file to path: %s\r\n", path);
}
int readFileNum(fs::FS &fs, const char * dirname){
File root = fs.open(dirname);
if(!root){
Serial.println("Failed to open directory");
return -1;
}
if(!root.isDirectory()){
Serial.println("Not a directory");
return -1;
}
File file = root.openNextFile();
int num=0;
while(file){
file = root.openNextFile();
num++;
}
return num;
}

View File

@ -0,0 +1,27 @@
#ifndef __SD_READ_WRITE_H
#define __SD_READ_WRITE_H
#include "Arduino.h"
#include "FS.h"
#include "SD_MMC.h"
#define SD_MMC_CMD 38 //Please do not modify it.
#define SD_MMC_CLK 39 //Please do not modify it.
#define SD_MMC_D0 40 //Please do not modify it.
void sdmmcInit(void);
void listDir(fs::FS &fs, const char * dirname, uint8_t levels);
void createDir(fs::FS &fs, const char * path);
void removeDir(fs::FS &fs, const char * path);
void readFile(fs::FS &fs, const char * path);
void writeFile(fs::FS &fs, const char * path, const char * message);
void appendFile(fs::FS &fs, const char * path, const char * message);
void renameFile(fs::FS &fs, const char * path1, const char * path2);
void deleteFile(fs::FS &fs, const char * path);
void testFileIO(fs::FS &fs, const char * path);
void writejpg(fs::FS &fs, const char * path, const uint8_t *buf, size_t size);
int readFileNum(fs::FS &fs, const char * dirname);
#endif

View File

@ -0,0 +1,35 @@
#include "ws2812.h"
Freenove_ESP32_WS2812 strip = Freenove_ESP32_WS2812(1, WS2812_PIN, 1, TYPE_GRB);
void ws2812Init(void)
{
strip.begin();
strip.setBrightness(10);
ws2812SetColor(0);
}
void ws2812SetColor(int color)
{
if(color==0)
{
strip.setLedColorData(0, 0, 0, 0);
}
else if(color==1)
{
strip.setLedColorData(0, 255, 0, 0);
}
else if(color==2)
{
strip.setLedColorData(0, 0, 255, 0);
}
else if(color==3)
{
strip.setLedColorData(0, 0, 0, 255);
}
strip.show();
}

View File

@ -0,0 +1,12 @@
#ifndef __WS2812_H
#define __WS2812_H
#include "Freenove_WS2812_Lib_for_ESP32.h"
#define WS2812_PIN 48
void ws2812Init(void);
void ws2812SetColor(int color);
#endif

View File

@ -0,0 +1,182 @@
/**********************************************************************
Filename : Camera Tcp Serrver
Description : Users use Freenove's APP to view images from ESP32S3's camera
Auther : www.freenove.com
Modification: 2024/07/01
**********************************************************************/
#include "esp_camera.h"
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiAP.h>
#define CAMERA_MODEL_ESP32S3_EYE
#include "camera_pins.h"
#define LED_BUILT_IN 2
const char* ssid_Router = "********";
const char* password_Router = "********";
const char *ssid_AP = "********";
const char *password_AP = "********";
WiFiServer server_Cmd(5000);
WiFiServer server_Camera(8000);
extern TaskHandle_t loopTaskHandle;
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(false);
Serial.println();
pinMode(LED_BUILT_IN, OUTPUT);
cameraSetup();
WiFi.softAP(ssid_AP, password_AP);
IPAddress myIP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(myIP);
server_Camera.begin(8000);
server_Cmd.begin(5000);
/////////////////////////////////////////////////////
WiFi.begin(ssid_Router, password_Router);
Serial.print("Connecting ");
Serial.print(ssid_Router);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
while (WiFi.STA.hasIP() != true) {
Serial.print(".");
delay(500);
}
Serial.println("");
Serial.println("WiFi connected");
/////////////////////////////////////////////////////
Serial.print("Camera Ready! Use '");
Serial.print(WiFi.softAPIP());
Serial.print(" or ");
Serial.print(WiFi.localIP());
Serial.println("' to connect in Freenove app.");
disableCore0WDT();
xTaskCreateUniversal(loopTask_Cmd, "loopTask_Cmd", 8192, NULL, 1, &loopTaskHandle, 0); //loopTask_Cmd uses core 0.
xTaskCreateUniversal(loopTask_Blink, "loopTask_Blink", 8192, NULL, 1, &loopTaskHandle, 0);//loopTask_Blink uses core 0.
}
//task loop uses core 1.
void loop() {
WiFiClient client = server_Camera.accept(); // listen for incoming clients
if (client) { // if you get a client,
Serial.println("Camera Server connected to a client.");// print a message out the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
camera_fb_t * fb = NULL;
while (client.connected()) {
fb = esp_camera_fb_get();
if (fb != NULL) {
uint8_t slen[4];
slen[0] = fb->len >> 0;
slen[1] = fb->len >> 8;
slen[2] = fb->len >> 16;
slen[3] = fb->len >> 24;
client.write(slen, 4);
client.write(fb->buf, fb->len);
esp_camera_fb_return(fb);
}
else {
Serial.println("Camera Error");
}
}
}
// close the connection:
client.stop();
Serial.println("Camera Client Disconnected.");
}
}
void loopTask_Cmd(void *pvParameters) {
Serial.println("Task Cmd_Server is starting ... ");
while (1) {
WiFiClient client = server_Cmd.accept(); // listen for incoming clients
if (client) { // if you get a client,
Serial.println("Command Server connected to a client.");// print a message out the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
client.write(c);
Serial.write(c); // print it out the serial monitor
if (c == '\n') { // if the byte is a newline character
currentLine = "";
}
else {
currentLine += c; // add it to the end of the currentLine
}
}
}
// close the connection:
client.stop();
Serial.println("Command Client Disconnected.");
}
}
}
void loopTask_Blink(void *pvParameters) {
Serial.println("Task Blink is starting ... ");
while (1) {
digitalWrite(LED_BUILT_IN, !digitalRead(LED_BUILT_IN));
delay(1000);
}
}
void cameraSetup() {
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_sccb_sda = SIOD_GPIO_NUM;
config.pin_sccb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.frame_size = FRAMESIZE_UXGA;
config.pixel_format = PIXFORMAT_JPEG; // for streaming
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
config.fb_location = CAMERA_FB_IN_PSRAM;
config.jpeg_quality = 12;
config.fb_count = 1;
// if PSRAM IC present, init with UXGA resolution and higher JPEG quality
// for larger pre-allocated frame buffer.
if(psramFound()){
config.jpeg_quality = 10;
config.fb_count = 2;
config.grab_mode = CAMERA_GRAB_LATEST;
} else {
// Limit the frame size when PSRAM is not available
config.frame_size = FRAMESIZE_SVGA;
config.fb_location = CAMERA_FB_IN_DRAM;
}
// camera init
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
sensor_t * s = esp_camera_sensor_get();
// initial sensors are flipped vertically and colors are a bit saturated
s->set_vflip(s, 1); // flip it back
s->set_brightness(s, 1); // up the brightness just a bit
s->set_saturation(s, 0); // lower the saturation
Serial.println("Camera configuration complete!");
}

View File

@ -0,0 +1,273 @@
#if defined(CAMERA_MODEL_WROVER_KIT)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 21
#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 19
#define Y4_GPIO_NUM 18
#define Y3_GPIO_NUM 5
#define Y2_GPIO_NUM 4
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
#elif defined(CAMERA_MODEL_ESP_EYE)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 4
#define SIOD_GPIO_NUM 18
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 36
#define Y8_GPIO_NUM 37
#define Y7_GPIO_NUM 38
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 35
#define Y4_GPIO_NUM 14
#define Y3_GPIO_NUM 13
#define Y2_GPIO_NUM 34
#define VSYNC_GPIO_NUM 5
#define HREF_GPIO_NUM 27
#define PCLK_GPIO_NUM 25
#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_M5STACK_V2_PSRAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 22
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_M5STACK_WIDE)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 22
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_M5STACK_ESP32CAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 17
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_M5STACK_UNITCAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_AI_THINKER)
#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
#elif defined(CAMERA_MODEL_TTGO_T_JOURNAL)
#define PWDN_GPIO_NUM 0
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 17
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_ESP32_CAM_BOARD)
// The 18 pin header on the board has Y5 and Y3 swapped
#define USE_BOARD_HEADER 0
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM 33
#define XCLK_GPIO_NUM 4
#define SIOD_GPIO_NUM 18
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 36
#define Y8_GPIO_NUM 19
#define Y7_GPIO_NUM 21
#define Y6_GPIO_NUM 39
#if USE_BOARD_HEADER
#define Y5_GPIO_NUM 13
#else
#define Y5_GPIO_NUM 35
#endif
#define Y4_GPIO_NUM 14
#if USE_BOARD_HEADER
#define Y3_GPIO_NUM 35
#else
#define Y3_GPIO_NUM 13
#endif
#define Y2_GPIO_NUM 34
#define VSYNC_GPIO_NUM 5
#define HREF_GPIO_NUM 27
#define PCLK_GPIO_NUM 25
#elif defined(CAMERA_MODEL_ESP32S3_CAM_LCD)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 40
#define SIOD_GPIO_NUM 17
#define SIOC_GPIO_NUM 18
#define Y9_GPIO_NUM 39
#define Y8_GPIO_NUM 41
#define Y7_GPIO_NUM 42
#define Y6_GPIO_NUM 12
#define Y5_GPIO_NUM 3
#define Y4_GPIO_NUM 14
#define Y3_GPIO_NUM 47
#define Y2_GPIO_NUM 13
#define VSYNC_GPIO_NUM 21
#define HREF_GPIO_NUM 38
#define PCLK_GPIO_NUM 11
#elif defined(CAMERA_MODEL_ESP32S2_CAM_BOARD)
// The 18 pin header on the board has Y5 and Y3 swapped
#define USE_BOARD_HEADER 0
#define PWDN_GPIO_NUM 1
#define RESET_GPIO_NUM 2
#define XCLK_GPIO_NUM 42
#define SIOD_GPIO_NUM 41
#define SIOC_GPIO_NUM 18
#define Y9_GPIO_NUM 16
#define Y8_GPIO_NUM 39
#define Y7_GPIO_NUM 40
#define Y6_GPIO_NUM 15
#if USE_BOARD_HEADER
#define Y5_GPIO_NUM 12
#else
#define Y5_GPIO_NUM 13
#endif
#define Y4_GPIO_NUM 5
#if USE_BOARD_HEADER
#define Y3_GPIO_NUM 13
#else
#define Y3_GPIO_NUM 12
#endif
#define Y2_GPIO_NUM 14
#define VSYNC_GPIO_NUM 38
#define HREF_GPIO_NUM 4
#define PCLK_GPIO_NUM 3
#elif defined(CAMERA_MODEL_ESP32S3_EYE)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 15
#define SIOD_GPIO_NUM 4
#define SIOC_GPIO_NUM 5
#define Y2_GPIO_NUM 11
#define Y3_GPIO_NUM 9
#define Y4_GPIO_NUM 8
#define Y5_GPIO_NUM 10
#define Y6_GPIO_NUM 12
#define Y7_GPIO_NUM 18
#define Y8_GPIO_NUM 17
#define Y9_GPIO_NUM 16
#define VSYNC_GPIO_NUM 6
#define HREF_GPIO_NUM 7
#define PCLK_GPIO_NUM 13
#else
#error "Camera model not selected"
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View File

@ -0,0 +1,29 @@
# ch343 linux serial driver
## Description
USB to UART(s) chip ch342/ch343/ch344/ch347/ch9101/ch9102/ch9103 are fully compliant to the Communications Device Class (CDC) standard, they will work with a standard CDC-ACM driver (CDC - Abstract Control Model). Linux operating systems supply a default CDC-ACM driver that can be used with these USB UART devices. In Linux, this driver file name is cdc-acm.
The CDC-ACM driver has limited capabilities to control specific devices. This generic driver does not have any knowledge about specific device protocols. Because of this, device manufacturers can create an alternate, or custom driver that is capable of accessing the device specific function sets, such as hardware flow control or GPIO functions.
If you use this VCP driver, please check that the CDC-ACM driver was not installed for the USB UART devices mentioned above. You can use command "ls /dev/ttyACM*" to confirm that, to remove the CDC-ACM driver, use command "rmmod cdc-acm".
This directory contains 2 parts, ch343 driver and gpio testing utility. This driver and application support USB to single serial port chip ch343/ch347/ch9101/ch9102, USB to dual serial ports chip ch342/ch347/ch9103, USB to quad serial ports chip ch344, etc.
1. Open "Terminal"
2. Switch to "driver" directory
3. Compile the driver using "make", you will see the module "ch343.ko" if successful
4. Type "sudo make load" or "sudo insmod ch343.ko" to load the driver dynamically
5. Type "sudo make unload" or "sudo rmmod ch343.ko" to unload the driver
6. Type "sudo make install" to make the driver work permanently
7. Type "sudo make uninstall" to remove the driver
8. You can refer to the link below to acquire uart application, you can use gcc or Cross-compile with cross-gcc
https://github.com/WCHSoftGroup/tty_uart
Before the driver works, you should make sure that the usb device has been plugged in and is working properly, you can use shell command "lsusb" or "dmesg" to confirm that, USB VID of these devices are [1A86], you can view all IDs from the id table which defined in "ch343.c".
If the device works well, the driver will created tty devices named "ttyCH343USBx" in /dev directory. Operating the device in the /dev directory under Linux requires root permission by default, if users want to access the device in a non root mode, they can create udev rule file related to the device.
## Note
Any question, you can send feedback to mail: tech@wch.cn

View File

@ -0,0 +1,22 @@
ifeq ($(KERNELRELEASE), )
KERNELDIR := /lib/modules/$(shell uname -r)/build
PWD :=$(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD)
clean:
rm -rf *.mk .tmp_versions Module.symvers *.mod.c *.o *.ko .*.cmd Module.markers modules.order *.a *.mod
load:
insmod ch343.ko
unload:
rmmod ch343
install: default
mkdir -p /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial
cp -f ./ch343.ko /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial
echo "ch343\n" >> /etc/modules
depmod -a
uninstall:
rm -rf /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial/ch343.ko
depmod -a
else
obj-m := ch343.o
endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,243 @@
#ifndef _CH343_H
#define _CH343_H
/*
* Baud rate and default timeout
*/
#define DEFAULT_BAUD_RATE 9600
#define DEFAULT_TIMEOUT 2000
/*
* CMSPAR, some architectures can't have space and mark parity.
*/
#ifndef CMSPAR
#define CMSPAR 0
#endif
/*
* Major and minor numbers.
*/
#define CH343_TTY_MAJOR 170
#define CH343_TTY_MINORS 256
#define USB_MINOR_BASE 70
/*
* Requests.
*/
#define USB_RT_CH343 (USB_TYPE_CLASS | USB_RECIP_INTERFACE)
#define CMD_R 0x95
#define CMD_W 0x9A
#define CMD_C1 0xA1
#define CMD_C2 0xA4
#define CMD_C3 0x05
#define CMD_C4 0xA8
#define CMD_C5 0x5E
#define CMD_C6 0x5F
#define CH343_CTO_O 0x10
#define CH343_CTO_D 0x20
#define CH343_CTO_R 0x40
#define CH343_CTO_A 0x80
#define CH343_CTI_C 0x01
#define CH343_CTI_DS 0x02
#define CH343_CTI_R 0x04
#define CH343_CTI_DC 0x08
#define CH343_CTI_ST 0x0f
#define CH343_CTT_M 0x08
#define CH343_CTT_F 0x44
#define CH343_CTT_P 0x04
#define CH343_CTT_O 0x02
#define CH343_LO 0x02
#define CH343_LE 0x04
#define CH343_LB
#define CH343_LP 0x00
#define CH343_LF 0x40
#define CH343_LM 0x08
#define CH343_L_R_CT 0x80
#define CH343_L_R_CL 0x04
#define CH343_L_R_T 0x08
#define CH343_L_E_R 0x80
#define CH343_L_E_T 0x40
#define CH343_L_P_S 0x38
#define CH343_L_P_M 0x28
#define CH343_L_P_E 0x18
#define CH343_L_P_O 0x08
#define CH343_L_SB 0x04
#define CH343_L_C8 0x03
#define CH343_L_C7 0x02
#define CH343_L_C6 0x01
#define CH343_L_C5 0x00
#define CH343_N_B 0x80
#define CH343_N_AB 0x10
/*
* Internal driver structures.
*/
/*
* The only reason to have several buffers is to accommodate assumptions
* in line disciplines. They ask for empty space amount, receive our URB size,
* and proceed to issue several 1-character writes, assuming they will fit.
* The very first write takes a complete URB. Fortunately, this only happens
* when processing onlcr, so we only need 2 buffers. These values must be
* powers of 2.
*/
#define CH343_NW 16
#define CH343_NR 16
struct ch343_wb {
unsigned char *buf;
dma_addr_t dmah;
int len;
int use;
struct urb *urb;
struct ch343 *instance;
};
struct ch343_rb {
int size;
unsigned char *base;
dma_addr_t dma;
int index;
struct ch343 *instance;
};
struct usb_ch343_line_coding {
__u32 dwDTERate;
__u8 bCharFormat;
#define USB_CH343_1_STOP_BITS 0
#define USB_CH343_1_5_STOP_BITS 1
#define USB_CH343_2_STOP_BITS 2
__u8 bParityType;
#define USB_CH343_NO_PARITY 0
#define USB_CH343_ODD_PARITY 1
#define USB_CH343_EVEN_PARITY 2
#define USB_CH343_MARK_PARITY 3
#define USB_CH343_SPACE_PARITY 4
__u8 bDataBits;
} __attribute__((packed));
typedef enum {
CHIP_CH342F = 0x00,
CHIP_CH342K,
CHIP_CH343GP,
CHIP_CH343G_AUTOBAUD,
CHIP_CH343K,
CHIP_CH343J,
CHIP_CH344L,
CHIP_CH344L_V2,
CHIP_CH344Q,
CHIP_CH347T,
CHIP_CH9101UH,
CHIP_CH9101RY,
CHIP_CH9102F,
CHIP_CH9102X,
CHIP_CH9103M,
CHIP_CH9104L,
} CHIPTYPE;
struct gpioinfo {
int group;
int pin;
};
struct ch343_gpio {
int gpiocount;
struct gpioinfo io[64];
};
struct ch343_gpio ch343_gpios[] = {
{ 0, {}},
{ 0, {}},
{ 0, {}},
{ 0, {}},
{ 0, {}},
{ 0, {}},
/* CH344L */
{ 8, {}},
/* CH344L-V2 */
{ 8, {}},
/* CH344Q */
{ 8, {}},
/* CH347T */
{ 4, {}},
/* CH9101UH */
{ 5, {{3, 2}, {3, 3}, {1, 3}, {1, 2}, {1, 5}, {2, 4}}},
/* CH9101RY */
{ 4, {{1, 3}, {3, 3}, {3, 2}, {2, 4}}},
/* CH9102F */
{ 5, {{2, 1}, {2, 7}, {2, 4}, {2, 6}, {2, 3}}},
/* CH9102X */
{ 6, {{2, 3}, {2, 5}, {2, 1}, {2, 7}, {3, 0}, {2, 2}}},
/* CH9103M */
{12, {{1, 3}, {1, 2}, {3, 2}, {2, 6}, {1, 0}, {1, 6}, {2, 3}, {2, 5}, {3, 0}, {2, 2}, {1, 5}, {2, 4}}},
/* CH9104L */
{24, {}},
};
struct ch343 {
struct usb_device *dev; /* the corresponding usb device */
struct usb_interface *control; /* control interface */
struct usb_interface *data; /* data interface */
struct tty_port port; /* our tty port data */
struct urb *ctrlurb; /* urbs */
u8 *ctrl_buffer; /* buffers of urbs */
dma_addr_t ctrl_dma; /* dma handles of buffers */
struct ch343_wb wb[CH343_NW];
unsigned long read_urbs_free;
struct urb *read_urbs[CH343_NR];
struct ch343_rb read_buffers[CH343_NR];
int rx_buflimit;
int rx_endpoint;
spinlock_t read_lock;
int write_used; /* number of non-empty write buffers */
int transmitting;
spinlock_t write_lock;
struct mutex mutex;
bool disconnected;
struct usb_ch343_line_coding line; /* bits, stop, parity */
struct work_struct work; /* work queue entry for line discipline waking up */
unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */
unsigned int ctrlout; /* output control lines (DTR, RTS) */
struct async_icount iocount; /* counters for control line changes */
struct async_icount oldcount; /* for comparison of counter */
wait_queue_head_t wioctl; /* for ioctl */
unsigned int writesize; /* max packet size for the output bulk endpoint */
unsigned int readsize, ctrlsize; /* buffer sizes for freeing */
unsigned int minor; /* ch343 minor number */
unsigned char clocal; /* termios CLOCAL */
unsigned int susp_count; /* number of suspended interfaces */
u8 bInterval;
struct usb_anchor delayed; /* writes queued for a device about to be woken */
unsigned long quirks;
u8 iface;
CHIPTYPE chiptype;
u16 idVendor;
u16 idProduct;
u8 gpio5dir;
};
#define CDC_DATA_INTERFACE_TYPE 0x0a
/* constants describing various quirks and errors */
#define NO_UNION_NORMAL BIT(0)
#define SINGLE_RX_URB BIT(1)
#define NO_CAP_LINE BIT(2)
#define NO_DATA_INTERFACE BIT(4)
#define IGNORE_DEVICE BIT(5)
#define QUIRK_CONTROL_LINE_STATE BIT(6)
#define CLEAR_HALT_CONDITIONS BIT(7)
#endif

Binary file not shown.

View File

@ -0,0 +1,5 @@
For MAC users, the CH343 driver will always need to go to the official website to download the latest version,
as older versions may not be suitable.
Below is the official download link:
http://www.wch-ic.com/search?t=all&q=ch343

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 KiB

View File

@ -0,0 +1,58 @@
Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License (CC BY-NC-SA 3.0)
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
1. Definitions
"Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License.
"Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(g) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined above) for the purposes of this License.
"Distribute" means to make available to the public the original and copies of the Work or Adaptation, as appropriate, through sale or other transfer of ownership.
"License Elements" means the following high-level license attributes as selected by Licensor and indicated in the title of this License: Attribution, Noncommercial, ShareAlike.
"Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License.
"Original Author" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast.
"Work" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work.
"You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation.
"Publicly Perform" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images.
"Reproduce" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium.
2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws.
3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below:
to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections;
to create and Reproduce Adaptations provided that any such Adaptation, including any translation in any medium, takes reasonable steps to clearly label, demarcate or otherwise identify that changes were made to the original Work. For example, a translation could be marked "The original work was translated from English to Spanish," or a modification could indicate "The original work has been modified.";
to Distribute and Publicly Perform the Work including as incorporated in Collections; and,
to Distribute and Publicly Perform Adaptations.
The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. Subject to Section 8(f), all rights not expressly granted by Licensor are hereby reserved, including but not limited to the rights described in Section 4(e).
4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:
You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(d), as requested. If You create an Adaptation, upon notice from any Licensor You must, to the extent practicable, remove from the Adaptation any credit as required by Section 4(d), as requested.
You may Distribute or Publicly Perform an Adaptation only under: (i) the terms of this License; (ii) a later version of this License with the same License Elements as this License; (iii) a Creative Commons jurisdiction license (either this or a later license version) that contains the same License Elements as this License (e.g., Attribution-NonCommercial-ShareAlike 3.0 US) ("Applicable License"). You must include a copy of, or the URI, for Applicable License with every copy of each Adaptation You Distribute or Publicly Perform. You may not offer or impose any terms on the Adaptation that restrict the terms of the Applicable License or the ability of the recipient of the Adaptation to exercise the rights granted to that recipient under the terms of the Applicable License. You must keep intact all notices that refer to the Applicable License and to the disclaimer of warranties with every copy of the Work as included in the Adaptation You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Adaptation, You may not impose any effective technological measures on the Adaptation that restrict the ability of a recipient of the Adaptation from You to exercise the rights granted to that recipient under the terms of the Applicable License. This Section 4(b) applies to the Adaptation as incorporated in a Collection, but this does not require the Collection apart from the Adaptation itself to be made subject to the terms of the Applicable License.
You may not exercise any of the rights granted to You in Section 3 above in any manner that is primarily intended for or directed toward commercial advantage or private monetary compensation. The exchange of the Work for other copyrighted works by means of digital file-sharing or otherwise shall not be considered to be intended for or directed toward commercial advantage or private monetary compensation, provided there is no payment of any monetary compensation in con-nection with the exchange of copyrighted works.
If You Distribute, or Publicly Perform the Work or any Adaptations or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and, (iv) consistent with Section 3(b), in the case of an Adaptation, a credit identifying the use of the Work in the Adaptation (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). The credit required by this Section 4(d) may be implemented in any reasonable manner; provided, however, that in the case of a Adaptation or Collection, at a minimum such credit will appear, if a credit for all contributing authors of the Adaptation or Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties.
For the avoidance of doubt:
Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License;
Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License if Your exercise of such rights is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(c) and otherwise waives the right to collect royalties through any statutory or compulsory licensing scheme; and,
Voluntary License Schemes. The Licensor reserves the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License that is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(c).
Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Adaptations or Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation. Licensor agrees that in those jurisdictions (e.g. Japan), in which any exercise of the right granted in Section 3(b) of this License (the right to make Adaptations) would be deemed to be a distortion, mutilation, modification or other derogatory action prejudicial to the Original Author's honor and reputation, the Licensor will waive or not assert, as appropriate, this Section, to the fullest extent permitted by the applicable national law, to enable You to reasonably exercise Your right under Section 3(b) of this License (right to make Adaptations) but not otherwise.
5. Representations, Warranties and Disclaimer
UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING AND TO THE FULLEST EXTENT PERMITTED BY APPLICABLE LAW, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO THIS EXCLUSION MAY NOT APPLY TO YOU.
6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
7. Termination
This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Adaptations or Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License.
Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above.
8. Miscellaneous
Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License.
Each time You Distribute or Publicly Perform an Adaptation, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License.
If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent.
This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You.
The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law.

View File

@ -0,0 +1,199 @@
# Freenove ESP32-S3 WROOM
What we need for functionality
- Freenove ESP32-S3 WROOM board with OV2640 camera module [ here ](#esp32)
- Supported camera modules [here](cam_modules)
- How to flash binary files to board from Linux/MAC/Windows [ here ](#flash_fw)
- How to compile software in the Arduino IDE [ here ](#arduino_cfg)
- How to reset the configuration to factory settings [here](#factory_cfg)
- Status LED [ here ](#status_led)
- Schematic main board is [here](#schematic)
- FLASH LED issue [here](#flash-led-issue)
- Power supply [here](#power_supply)
- External temperature sensor DHT22/DHT11 [here](#ext_sens)
- Potential issue [here](#issue)
<a name="esp32"></a>
## Freenove ESP32-S3 WROOM
Basic information:
- On the board is LED WS2812b for flash
- Option connecting external FLASH LED
- Micro SD card slot
- Internal WiFi antenna
- no additional HW is needed for programming
- 8MB FLASH and 8MB external PSRAM
- Excellent WiFi signal
This is a more expensive version with a more powerful ESP32-S3 processor. The board is sold with an OV2640 camera module. No additional hardware is required for programming. The ESP32-S3 processor is programmed via the processor's USB interface.
<img src="Board.jpg" width=30% height=30%>
<img src="board_des.jpg" width=30% height=30%>
<a name="cam_modules"></a>
## Supported camera modules
The board is officially sold with an OV2640 camera module with 66.5° field of view.
These are currently known or tested camera modules:
| Camera chip | FOV | Resolution | Tested | Works | Description |
|-------------|--------|------------|--------|-------|------------------------------------------|
| OV2640 | 66.5° | 2MP | Yes | Yes | Recommended. Standard camera module |
| OV2640 | 120° | 2MP | Yes | Yes | Recommended |
| OV2640 | 160° | 2MP | Yes | Yes | Recommended |
| OV2640IR | 160° | 2MP | Yes | Yes | |
<a name="flash_fw"></a>
## How to flash binary files to board from Linux/MAC/Windows
For programming we will use the right USB-C connector
<img src="prog.png" width=25% height=25%>
#### Partitions table for flashing FW
For uploading the firmware, it's important to use this configuration of addresses and files:
ZIP file with build binary files: **esp32-s3-wroom-freenove.zip**
- address **0x0** - **ESP32_PrusaConnectCam.ino.bootloader.bin**
- address **0x8000** - **ESP32_PrusaConnectCam.ino.partitions.bin**
- address **0x10000** - **ESP32_PrusaConnectCam.ino.bin**
**It is important to download the correct binary files! Each type of camera has its own ZIP archive with files for uploading the firmware.**
#### Linux/MAC
You must use the console to upload the firmware on the MAC or Linux platform. First, ensure you have installed esptool for Python. You can find it on the manufacturer's website, ESPRESSIF, [here](https://docs.espressif.com/projects/esp-at/en/latest/esp32/Get_Started/Downloading_guide.html#linux-or-macos).
And command for FLASH FW is here, where **/dev/ttya0** is your serial interface for communication with the ESP32-cam board. This is the command for the first flash FW to MCU.
```
./esptool --chip esp32s3 -p /dev/ttya0 -b 921600 --before default_reset --after hard_reset write_flash --erase-all --flash_mode qio --flash_size 8MB --flash_freq 80m 0x0 ESP32_PrusaConnectCam.ino.bootloader.bin 0x8000 ESP32_PrusaConnectCam.ino.partitions.bin 0x10000 ESP32_PrusaConnectCam.ino.bin
```
This command contains the parameter **--erase-all**, which erases the entire flash in the MCU. So, for just updating the firmware, it is necessary to remove the parameter **--erase-all**; otherwise, the MCU configuration will also be deleted. The basic command list can be found [here](https://docs.espressif.com/projects/esptool/en/latest/esp32s3/esptool/basic-commands.html)
Here is the command for updating the firmware in the MCU without erasing the MCU configuration
```
./esptool --chip esp32s3 -p /dev/ttya0 -b 921600 --before default_reset --after hard_reset write_flash --flash_mode qio --flash_size 8MB --flash_freq 80m 0x0 ESP32_PrusaConnectCam.ino.bootloader.bin 0x8000 ESP32_PrusaConnectCam.ino.partitions.bin 0x10000 ESP32_PrusaConnectCam.ino.bin
```
Launching the esptool application may be different in different operating systems
#### Windows
The driver should be installed automatically by Windows. SW for FW flash (Flash Download Tools) is [here](https://www.espressif.com/en/support/download/other-tools)
In the first step, you need to open the application **flash download tool**, and select MCU version
<img src="chip_select.jpg" width=25% height=25%>
Then, select the communication port. It's necessary to erase the FLASH using the **ERASE** button before the first firmware flash.
It's necessary to erase the FLASH using the **ERASE** button before the first firmware flash.
<img src="flash.jpg" width=30% height=30%>
<a name="arduino_cfg"></a>
## How to compile software in the Arduino IDE
Board configuration in the Arduino IDE 2.3.2
- Tools -> Board -> ESP32 Arduino -> ESP32S3 Dev Module
- Tools -> USB CDC on BOOT -> Disabled
- Tools -> CPU Frequency -> 240MHz (WiFi/BT)
- Tools -> Core debug level -> None
- Tools -> USB DFU on BOOT -> Disable
- Tools -> Erase all Flash Before Sketch Upload -> Disable (first flash, new board = enable. otherwise = disable)
- Tools -> Events Run On -> Core 0
- Tools -> Flash Mode -> QIO 80MHz
- Tools -> Flash Size -> 8MB
- Tools -> Jtag Adapter -> Disable
- Tools -> Arduino Runs On -> Core 0
- Tools -> USB Firmware MSC On Boot -> Disable
- Tools -> Partition scheme -> Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS)
- Tools -> PSRAM -> OPI PSRAM
- Tools -> Upload Mode -> UART0 / Hardware CDC
- Tools -> Upload Speed -> 921600
- Tools -> USB Mode -> Hardware CDC and JTAG
- Tools -> Zigbee mode -> Disable
When flashing the firmware to a new, empty Freenove ESP32-S3-Wroom device for the first time, it is necessary to use the 'Erase' function.
This can be found under **Tools** -> **Erase all Flash Before Sketch Upload** -> **Enable**.
After the initial firmware upload to the MCU, it's necessary to disable this option. If you do not disable this option, your camera configuration will continue to be erased from the flash memory after uploading new firmware from the Arduino IDE.
It is necessary to enable support for the correct board version in the file **mcu_cfg.h** after line 16.
<a name="factory_cfg"></a>
## How to reset configuration to factory settings
To reset the settings to factory defaults, follow these instructions:
<img src="factory_cfg.png" width=30% height=30%>
- Connect PIN **21** (red) to **ground** (blue).
- **Plug in** the power supply.
- Wait for **10 seconds**.
- After 10 seconds, the **STATUS LED will start flashing**.
- **Disconnect** PIN **21** from **ground** (but don't disconnect the power supply).
- After disconnecting **21** from **ground**, the **STATUS LED** will stop flashing, and the MCU will automatically reboot.
- Now the MCU is in the factory settings.
<a name="status_led"></a>
## Status LED
On the board, there is a status LED that provides a visual indicator of the module's current status
through blinking at defined intervals.
<img src="status_led.png" width=25% height=25%>
Upon module activation, the LED illuminates. After processor initialization, the LED exhibits different blinking intervals based on the current mode of the module
- **Service AP Mode only:** The LED blinks every **400 ms**, indicating the module's availability in service AP mode.
- **Connecting to WiFi AP:** While connecting to a WiFi Access Point, the LED blinks at intervals of **800 ms**.
- **Connected to WiFi Network:** Upon successful connection to a WiFi network, the LED blinks at intervals of **4000 ms**, signaling a stable connection.
- **Problematic State:** If an issue or error occurs, the LED accelerates its blinking to every **100 ms**.
The approximate boot time of the device is 15-20 seconds.
<a name="schematic"></a>
## Schematic for ESP32-cam board
For the board existing only pinout. I don't found schematic
<img src="ESP32S3_Pinout.png" width=25% height=25%>
<a name="led_issue"></a>
## FLASH LED issue
The board includes a single WS2812b FLASH LED. This FLASH LED emits light dimly. However, there is an option to use PIN 14, as a external flash light. The image shows 3 arrows:
- Green, PIN 14
- RED, VCC 3.3V
- BLUE, GND
<img src="ext_flash.png" width=25% height=25%>
<a name="power_supply"></a>
## Power Supply
The device requires a 5V power supply, with a maximum current consumption of 2A. Power is supplied via a micro USB connector when using the original programmer.
<a name="ext_sens"></a>
## External temperature sensor DHT22/DHT11
Below you will find the wiring diagram for the DHT22 or DHT11 sensor.
| Camera board | DHT22/DHT11 |
|--------------|-------------|
| 3.3V (red) | VCC |
| GND (blue) | GND |
| IO47 (green) | Data |
<img src="dht_22.png" width=30% height=30%>
<a name="issue"></a>
## Potential issue with this board

View File

@ -0,0 +1,86 @@
## Freenove_ESP32_S3_WROOM_Board
A kit with a Freenove® ESP32-S3 Board for learning programming and electronics.
<img src='Board.jpg' width='70%'/>
ESP32-S3 chip is manufactured by Espressif®.
>Espressif® is a trademark of Espressif Systems (Shanghai) Co.Ltd (https://www.espressif.com/).
Freenove ESP32-S3 Board can be uploaded code using Arduino® IDE.
> Arduino® is a trademark of Arduino LLC (https://www.arduino.cc/).
<img src='ESP32S3_Pinout.png' width='100%'/>
### Download
Click the green "Code" button, then click "Download ZIP" button in the pop-up window.
Do NOT click the "Open in Desktop" button, it will lead you to install Github software.
> If you meet any difficulties, please contact our technical team for help.
### Use
1. Download the ZIP file as above.
2. Unzip it and you will get a folder contains tutorials and related files.
3. Please start with "Start Here.pdf".
### Support
Freenove provides free and quick customer support. Including but not limited to:
* Quality problems of products
* Problems of products when used
* Questions of learning and creation
* Opinions and suggestions
* Ideas and thoughts
Please send an email to:
[support@freenove.com](mailto:support@freenove.com)
We will reply within one working day.
### Purchase
Please visit the following page to purchase our products:
http://freenove.com/store
Business customers please contact us through the following email address:
[sale@freenove.com](mailto:sale@freenove.com)
### About
Freenove provides open source electronic products and services.
Freenove is committed to helping customers learn programming and electronic knowledge, quickly implement product prototypes, realize their creativity and launch innovative products. Our services include:
* Kits for learning programming and electronics
* Kits compatible with Arduino®, Raspberry Pi®, micro:bit®, etc.
* Kits for robots, smart cars, drones, etc.
* Components, modules and tools
* Design and customization
To learn more about us or get our latest information, please visit our website:
http://www.freenove.com
### Copyright
All the files in this repository are released under [Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License](http://creativecommons.org/licenses/by-nc-sa/3.0/).
You can find a copy of the license in this repository.
![markdown](https://i.creativecommons.org/l/by-nc-sa/3.0/88x31.png)
> It means you can use these files on your own derived works, in part or completely. But not for commercial use.
Freenove® brand and logo are trademarks of Freenove Creative Technology Co., Ltd. Must not be used without permission.
Other registered trademarks and their owners appearing in this repository:
Arduino® is a trademark of Arduino LLC (https://www.arduino.cc/).
Raspberry Pi® is a trademark of Raspberry Pi Foundation (https://www.raspberrypi.org/).
micro:bit® is a trademark of Micro:bit Educational Foundation (https://www.microbit.org/).
Espressif® is a trademark of Espressif Systems (Shanghai) Co.Ltd (https://www.espressif.com/).

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Some files were not shown because too many files have changed in this diff Show More