From 652d9a82aa9b33afc0da66d0c720f0630912b77e Mon Sep 17 00:00:00 2001 From: princerodrick59 Date: Mon, 20 Jul 2026 16:02:42 -0500 Subject: [PATCH] added code --- ESP32_S3_ETH_RTSP/ESP32_S3_ETH_RTSP.ino | 178 ++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 ESP32_S3_ETH_RTSP/ESP32_S3_ETH_RTSP.ino diff --git a/ESP32_S3_ETH_RTSP/ESP32_S3_ETH_RTSP.ino b/ESP32_S3_ETH_RTSP/ESP32_S3_ETH_RTSP.ino new file mode 100644 index 0000000..5e72d97 --- /dev/null +++ b/ESP32_S3_ETH_RTSP/ESP32_S3_ETH_RTSP.ino @@ -0,0 +1,178 @@ +/* + Waveshare ESP32-S3-ETH + OV5640 RTSP/MJPEG camera + + Install first in Arduino IDE Library Manager: + ESP32-RTSPServer by Richard Sachse (version 1.3.5 or newer) + + Open in VLC: rtsp://:8554/ + + This is MJPEG carried over RTSP, not H.264. The stream is 720p (1280x720). +*/ + +#include +#include +#include +#include +#include +#include +#include "esp_camera.h" +#include + +constexpr int ETH_MOSI = 11, ETH_MISO = 12, ETH_SCK = 13; +constexpr int ETH_CS = 14, ETH_RST = 9, ETH_INT = 10, ETH_ADDR = 1; +constexpr int CAMERA_POWER = 8; // Active-low power enable on ESP32-S3-ETH. +const char *otaHostname = "esp32s3-camera-node"; +const char *otaPassword = "1gYh0Y"; +uint32_t last_ota_time = 0; + +SPIClass ethSpi(FSPI); +static bool ethConnected = false; + +RTSPServer rtspServer; +TaskHandle_t videoTaskHandle = nullptr; +int cameraQuality = 20; + +static bool startCamera() { + camera_config_t config = {}; + config.ledc_channel = LEDC_CHANNEL_0; + config.ledc_timer = LEDC_TIMER_0; + config.pin_d0 = 41; config.pin_d1 = 45; config.pin_d2 = 46; config.pin_d3 = 42; + config.pin_d4 = 40; config.pin_d5 = 38; config.pin_d6 = 15; config.pin_d7 = 18; + config.pin_xclk = 3; config.pin_pclk = 39; config.pin_vsync = 1; config.pin_href = 2; + config.pin_sccb_sda = 48; config.pin_sccb_scl = 47; + config.pin_pwdn = -1; config.pin_reset = -1; + config.xclk_freq_hz = 10000000; + config.pixel_format = PIXFORMAT_JPEG; + config.frame_size = FRAMESIZE_HD; // 1280x720 (720p). Requires PSRAM. + config.jpeg_quality = cameraQuality; // Higher number = smaller/lower-quality JPEG. + config.fb_count = 1; + config.fb_location = psramFound() ? CAMERA_FB_IN_PSRAM : CAMERA_FB_IN_DRAM; + config.grab_mode = CAMERA_GRAB_WHEN_EMPTY; + + esp_err_t error = esp_camera_init(&config); + if (error != ESP_OK) { + Serial.printf("Camera init failed: 0x%x\n", error); + return false; + } + return true; +} + +static void sendVideo(void *) { + while (true) { + if (rtspServer.readyToSendFrame()) { + camera_fb_t *frame = esp_camera_fb_get(); + if (frame) { + rtspServer.sendRTSPFrame(frame->buf, frame->len, cameraQuality, frame->width, frame->height); + esp_camera_fb_return(frame); + } + } + vTaskDelay(pdMS_TO_TICKS(1)); + } +} + +static void startOTA() { + // Explicit mDNS binding before ArduinoOTA prevents unreliable Ethernet OTA discovery. + if (!MDNS.begin(otaHostname)) { + Serial.println("mDNS responder setup failed!"); + } + ArduinoOTA.setHostname(otaHostname); + ArduinoOTA.setPassword(otaPassword); + ArduinoOTA + .onStart([]() { + String type = ArduinoOTA.getCommand() == U_FLASH ? "sketch" : "filesystem"; + Serial.println("Start updating " + type); + }) + .onEnd([]() { + Serial.println("\nEnd"); + }) + .onProgress([](unsigned int progress, unsigned int total) { + if (millis() - last_ota_time > 500) { + Serial.printf("Progress: %u%%\n", progress / (total / 100)); + last_ota_time = millis(); + } + }) + .onError([](ota_error_t error) { + Serial.printf("Error[%u]: ", error); + if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); + else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); + else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); + else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); + else if (error == OTA_END_ERROR) Serial.println("End Failed"); + }); + ArduinoOTA.begin(); + Serial.println("Ready"); + Serial.print("IP address: "); + Serial.println(ETH.localIP()); +} + +static void onEthEvent(arduino_event_id_t event, arduino_event_info_t info) { + switch (event) { + case ARDUINO_EVENT_ETH_START: + Serial.println("ETH: Started, setting hostname."); + ETH.setHostname(otaHostname); + break; + case ARDUINO_EVENT_ETH_CONNECTED: + Serial.println("ETH: Link up."); + break; + case ARDUINO_EVENT_ETH_GOT_IP: + Serial.print("ETH: Got IP: "); + Serial.println(ETH.localIP()); + ethConnected = true; + break; + case ARDUINO_EVENT_ETH_DISCONNECTED: + Serial.println("ETH: Link down."); + ethConnected = false; + break; + case ARDUINO_EVENT_ETH_STOP: + Serial.println("ETH: Stopped."); + ethConnected = false; + break; + default: + break; + } +} + +void setup() { + Serial.begin(115200); + delay(1000); + Serial.println("\nESP32-S3 Ethernet RTSP camera starting"); + + // Required for camera power on this Waveshare board. + pinMode(CAMERA_POWER, OUTPUT); + digitalWrite(CAMERA_POWER, LOW); + delay(200); + + Network.onEvent(onEthEvent); + ethSpi.begin(ETH_SCK, ETH_MISO, ETH_MOSI); + Serial.println("Network: Initializing W5500 over SPI..."); + if (!ETH.begin(ETH_PHY_W5500, ETH_ADDR, ETH_CS, ETH_INT, ETH_RST, ethSpi)) { + Serial.println("Network: Fatal error - W5500 initialization failed."); + while (true) delay(1000); + } + Serial.println("Network: Waiting for DHCP lease..."); + unsigned long dhcpWaitStart = millis(); + while (!ethConnected && millis() - dhcpWaitStart < 15000) { + delay(100); + } + if (!ethConnected) { + Serial.println("Connection Failed! Rebooting..."); + delay(5000); + ESP.restart(); + } + startOTA(); + if (!startCamera()) return; + + rtspServer.transport = RTSPServer::VIDEO_ONLY; + rtspServer.rtspPort = 8554; + if (!rtspServer.init(RTSPServer::VIDEO_ONLY, 8554)) { + Serial.println("RTSP server failed to start"); + return; + } + xTaskCreate(sendVideo, "RTSP video", 5 * 1024, nullptr, 5, &videoTaskHandle); + Serial.printf("RTSP ready: rtsp://%s:8554/\n", ETH.localIP().toString().c_str()); +} + +void loop() { + ArduinoOTA.handle(); + delay(2); +}