ESP32 S3 Kamera - Intelligente Video-Türklingel mit einem Taster

Eine gekaufte Türklingel mit Kamera kostet viel Geld und benötigt ein kostenpflichtiges Konto. Diese hier kostet nur ein paar Euro und benötigt nichts außer Ihrem WLAN.

Ein Besucher drückt den Taster. Der ESP32 S3 macht ein Foto und sendet es mit Telegram an Ihr Handy, zusammen mit einem Link zum Live-Video. Sie sehen sich das Foto sofort an und tippen auf den Link, wenn Sie sehen möchten, was gerade passiert. Die kleine LED auf dem Board antwortet dem Besucher, sodass er weiß, dass die Klingel funktioniert hat.

ESP32 S3 Kamera - Intelligente Video-Türklingel mit einem Taster

Was Sie bauen werden:

  1. Einen Klingeltaster, der ein Foto des Besuchers macht
  2. Eine Telegram-Nachricht mit dem Foto und einem Link zum Live-Video
  3. Eine Live-Video-Seite, die jeder mit dem Link auf einem Handy oder Computer öffnen kann
  4. Eine LED, die dem Besucher antwortet, damit er weiß, dass die Klingel funktioniert hat
  5. Eine Ruhezeit, damit ein Kind, das den Taster zehnmal drückt, nicht zehn Fotos sendet

Erforderliche Hardware

1×ESP32 S3 N16R8 OV5640 Camera
1×(Alternativ) ESP32 S3 N16R8 OV2640 Camera
1×USB-Kabel Typ-A zu Typ-C (für USB-A PC)
1×USB-Kabel Typ-C zu Typ-C (für USB-C PC)
1×Breadboard-Taster mit Kappe
1×Breadboard-Taster-Kit
1×Panel-Drucktaster
1×Taster-Modul
1×Breadboard
1×Verbindungskabel
1×(Empfohlen) Screw Terminal Expansion Board for ESP32 S3
1×(Empfohlen) Breakout Expansion Board for ESP32 S3
1×(Empfohlen) Power Splitter for ESP32 S3

Oder Sie können die folgenden Kits kaufen:

1×DIYables Sensor-Kit (18 Sensoren/Displays)
Offenlegung: Einige der in diesem Abschnitt bereitgestellten Links sind Amazon-Affiliate-Links. Wir können eine Provision für Käufe erhalten, die über diese Links getätigt werden, ohne zusätzliche Kosten für Sie. Wir schätzen Ihre Unterstützung.

※ Notiz:

Das ESP32 S3 Kamera-Board hat 40 Pins, aber der Schraubklemmenblock und das Breakout-Board haben 44 Pins. Sie funktionieren trotzdem zusammen. Setzen Sie das Kamera-Board in die Mitte des 44-Pin-Boards, sodass links 2 Pins und rechts 2 Pins frei bleiben.

Mit dem Schraubklemmenblock können Sie Drähte mit einem Schraubendreher anschließen, ganz ohne Löten. Das Breakout-Board bietet Ihnen einfache Stiftleisten für ein Steckbrett.

Wie es funktioniert

Das ganze Projekt besteht aus sechs Schritten:

SchrittWas passiert
1Ein Besucher drückt den Taster
2Die LED geht an, sodass der Besucher sieht, dass die Klingel funktioniert
3Die Kamera macht ein Foto
4Der ESP32 S3 sendet das Foto UND den Live-Video-Link mit Telegram an Ihr Handy
5Die LED blinkt zweimal. Der Besucher weiß, dass die Nachricht unterwegs ist.
6Sie tippen auf den Link, wenn Sie die Tür live beobachten möchten

Die Nachricht auf Ihrem Handy sieht so aus:

Telegram
Telegram 12:45
Welcome to Telegram!
ArduinoBot 10:19
Chatting with Arduino...
telegram-botfather
BotFather Yesterday
Your bot has been created.

ArduinoBot

bot
Today
Somebody is at the door! Live video: http\://192.168.0.2/stream
10:15 AM

Warum ein Foto UND ein Link?

Ein Foto und ein Live-Video sind für unterschiedliche Dinge gut:

Foto in der NachrichtLive-Video-Link
Kommt von selbst anJaNein, Sie müssen darauf tippen
Funktioniert von überallJa, immerNur zu Hause, außer Sie richten eine Portweiterleitung ein
Zeigt einen MomentJaNein, es zeigt das Jetzt
Zeigt, was der Besucher als Nächstes tutNeinJa
Kostet Akku und WLANEin paar SekundenSolange Sie zuschauen

Das Foto sagt Ihnen also, dass jemand da ist, und der Link lässt Sie sehen, was er gerade tut. So funktioniert eine echte Video-Türklingel.

※ Notiz:

Das Live-Video stoppt nach 60 Sekunden von selbst. Das ist Absicht. Während jemand das Video ansieht, ist das Board beschäftigt und kann den Taster nicht erkennen. Das Zeitlimit stellt sicher, dass die Türklingel immer wieder zum Leben erwacht. Um es zu ändern, ändern Sie die Zeile #define STREAM_SECONDS 60.

Wie die ESP32 S3 Video-Türklingel funktioniert

Die LED spricht mit dem Besucher

Eine Türklingel ohne Antwort ist eine schlechte Türklingel. Niemand weiß, ob sie funktioniert hat, also drücken die Leute immer wieder. Die kleine Farb-LED, die bereits auf dem Board sitzt, gibt für jede Situation eine Antwort:

Was die LED tutWas es bedeutet
3-mal Blinken beim Einschalten des BoardsDie Türklingel ist bereit
Bleibt anDas Foto wird aufgenommen und gesendet. Bitte warten.
2 langsame BlinkerDas Foto wurde gesendet. Jemand wird kommen.
5 schnelle BlinkerEtwas ist schiefgelaufen. Kein WLAN, oder Telegram hat abgelehnt.
1 langer BlinkerSie haben zu früh nach dem letzten Klingeln gedrückt.

※ Notiz:

Dieser Teil lässt das Projekt fertig wirken. Der Code umfasst nur wenige Zeilen, aber ein Besucher, der eine Antwort erhält, drückt den Taster nicht zwanzigmal.

Warum ein Taster Hilfe braucht

Ein Drucktaster besteht aus zwei Metallstücken. Wenn sie sich berühren, prallen sie in den ersten Millisekunden viele Male gegeneinander. Ohne Schutz sieht ein Druck wie fünf Drücke aus, und Ihr Handy erhält fünf Fotos.

Sie könnten den Wartecode selbst schreiben, aber die Bibliothek ezButton erledigt das bereits. Drei Zeilen sind die ganze Arbeit:

ezButton button(BUTTON_PIN, EXTERNAL_PULLDOWN); // 1. make the button button.setDebounceTime(50); // 2. in setup() button.loop(); // 3. first line in loop()

Dann fragen Sie einfach, ob jemand ihn gedrückt hat:

if (button.isPressed()) { ringTheDoorbell(); }

※ Notiz:

isPressed() ist nur in dem Moment wahr, in dem der Taster heruntergedrückt wird, nicht solange er gehalten wird. Ein Druck erledigt die Arbeit also einmal, auch wenn ein Besucher den Taster drei Sekunden lang gedrückt hält.

※ Notiz:

button.loop() muss die erste Zeile in Ihrer eigenen loop() sein. Es ist die Zeile, die den Pin liest und das Warten übernimmt. Vergessen Sie sie, funktioniert der Taster nie.

Überblick über the Button Module

Wir verwenden ein Taster-Modul, keinen einzelnen Drucktaster. Ein Modul ist derselbe Taster, sitzt aber auf einer kleinen Platine, auf der der Widerstand bereits vorhanden ist, und hat drei saubere Pins. Sie stecken nur drei Drähte an, und nichts kann falsch herum sein.

Taster-Modul

Der Widerstand auf dem Modul ist ein Pull-down-Widerstand. Er hält den Pin auf GND, solange niemand den Taster berührt:

TasterPin liest
Niemand berührt ihnLOW, der Widerstand zieht ihn nach unten
Jemand drückt ihnHIGH, der Taster verbindet den Pin mit 3,3V

Wir teilen es der Bibliothek mit einem Wort mit:

ezButton button(BUTTON_PIN, EXTERNAL_PULLDOWN);

※ Notiz:

EXTERNAL_PULLDOWN bedeutet "der Widerstand befindet sich außerhalb des Chips, auf dem Modul, und zieht den Pin nach unten". Die Bibliothek weiß dann, dass HIGH gedrückt bedeutet.

Haben Sie statt eines Moduls einen einzelnen Drucktaster? Dann muss das Board den Widerstand selbst bereitstellen. Der Code enthält beide Zeilen. Tauschen Sie die //-Zeichen:

// A bare push button, with one leg on the pin and the other leg on GND. // The board uses its own resistor inside, and the pin reads LOW when pressed. ezButton button(BUTTON_PIN); // A button module, which carries its own resistor. // ezButton button(BUTTON_PIN, EXTERNAL_PULLDOWN);
Was Sie habenZu verwendende ZeileVerdrahtung
Taster-ModulezButton button(BUTTON_PIN, EXTERNAL_PULLDOWN);VCC, GND und OUT
Einzelner DrucktasterezButton button(BUTTON_PIN);Ein Bein an den Pin, ein Bein an GND

※ Notiz:

Verwenden Sie niemals beides. Bei einem einzelnen Taster benötigen Sie den Widerstand im Board, und bei einem Modul dürfen Sie ihn nicht verwenden, da das Modul bereits einen hat.

Erstellen Sie Ihren Telegram-Bot

Sie benötigen ein Bot-Token und eine Chat-ID. Das dauert drei Minuten.

Schritt 1: Erstellen Sie Ihren Bot

  1. Installieren Sie Telegram auf Ihrem Handy und erstellen Sie ein Konto.
  2. Suchen Sie in Telegram nach @BotFather. Er hat ein blaues Häkchen.
  3. Öffnen Sie den Chat mit BotFather und schreiben Sie ihm so:
Telegram
Telegram 12:45
Welcome to Telegram!
ArduinoBot 10:19
Chatting with Arduino...
telegram-botfather
BotFather Yesterday
Your bot has been created.
BotFather

BotFather

bot
Today
/newbot
10:15 AM ✓✓
Alright, a new bot. How are we going to call it? Please choose a name for your bot.
10:16 AM
My Doorbell
10:17 AM ✓✓
Good. Now let's choose a username for your bot. It must end in bot.
10:18 AM
my_esp32_doorbell_bot
10:19 AM ✓✓
Done! Congratulations on your new bot. Use this token to access the HTTP API: 8012345678:AAHxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
10:20 AM
  1. Kopieren Sie das Bot-Token aus der letzten Nachricht und bewahren Sie es sicher auf.

Schritt 2: Finden Sie Ihre Chat-ID

  1. Suchen Sie in Telegram nach dem Namen Ihres neuen Bots und öffnen Sie den Chat.
  2. Senden Sie eine beliebige Nachricht an Ihren Bot, zum Beispiel hello. Dieser Schritt ist notwendig. Telegram erlaubt einem Bot nicht, Ihnen zu schreiben, bevor Sie ihm geschrieben haben.
Telegram
Telegram 12:45
Welcome to Telegram!
ArduinoBot 10:19
Chatting with Arduino...
telegram-botfather
BotFather Yesterday
Your bot has been created.

ArduinoBot

bot
Today
hello
10:15 AM ✓✓
  1. Öffnen Sie diese Adresse in Ihrem Webbrowser. Setzen Sie Ihr eigenes Bot-Token anstelle von <YOUR_BOT_TOKEN> ein:
https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates
  1. Der Browser zeigt einen langen Text. Suchen Sie nach "chat":{"id":. Die Zahl dahinter ist Ihre Chat-ID.

※ Notiz:

Zeigt der Browser {"ok":true,"result":[]} ohne Inhalt an? Dann haben Sie Ihrem Bot noch keine Nachricht gesendet. Gehen Sie zurück zu Schritt 2, senden Sie hello an Ihren Bot und laden Sie die Adresse erneut.

※ Notiz:

Zeigen Sie Ihr Bot-Token niemals jemandem und stellen Sie es niemals auf eine Website oder auf GitHub. Wenn es bekannt wird, senden Sie /revoke an BotFather, und Sie erhalten ein neues.

Wiring Diagram between Button and ESP32 S3

ESP32 S3 Video-Türklingel Schaltplan

Dieses Bild wurde mit Fritzing erstellt. Klicken Sie, um das Bild zu vergrößern.

Taster-Modul PinESP32 S3 Pin
VCC (oder +)3.3V
GND (oder -)GND
OUT (oder S, oder SIG)GPIO47

Das ist die ganze Verdrahtung. Drei Drähte und kein Widerstand.

※ Notiz:

Sie benötigen keine LED. Das Board hat bereits eine kleine Farb-LED, und der Code verwendet diese:

#define LED_PIN LED_BUILTIN

※ Notiz:

Hat Ihr Board keine LED? Dann schließen Sie Ihre eigene LED mit einem 220-Ohm-Widerstand an einen freien Pin an, zum Beispiel GPIO21, und ändern Sie die Zeile in #define LED_PIN 21.

Sicherheitshinweise

Verwenden Sie 3,3V für das Taster-Modul, nicht 5V. Die Pins des ESP32 S3 sind für 3,3V ausgelegt, und 5V können sie beschädigen.

Das Taster-Modul benötigt keinen zusätzlichen Widerstand, da der Widerstand bereits auf dem Modul sitzt.

Die Kamera verwendet GPIO4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17 und 18. Verwenden Sie diese Pins nicht. GPIO47 ist frei, deshalb verwenden wir ihn für den Taster.

※ Notiz:

Ein echter Klingeltaster hat vier Beine, aber nur zwei davon werden benötigt. Wenn Ihr Taster nichts tut, drehen Sie ihn auf dem Steckbrett um eine Vierteldrehung und versuchen Sie es erneut. Zwei Beine, die intern bereits verbunden sind, funktionieren nie.

Die Bibliotheken installieren

Dieses Projekt benötigt zwei Bibliotheken.

DIYables ESP32 WebServer erstellt die Live-Video-Seite:

  1. Öffnen Sie die Arduino IDE.
  2. Klicken Sie auf das Symbol Libraries in der linken Leiste.
  3. Geben Sie DIYables ESP32 WebServer in das Suchfeld ein.
  4. Suchen Sie die Bibliothek von DIYables.io und klicken Sie auf INSTALL.
  • Search for DIYables ESP32 WebServer created by DIYables.io and click the Install button.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32S3 Dev Module
Library Manager
Type:
All
Topic:
All
DIYables ESP32 WebServer by DIYables.io
DIYables ESP32 WebServer library designed for ESP32 boards. It includes multi-page web server capabilities and WebSocket support for real-time communication, perfect for IoT projects and DIYables ESP32 boards. More info
1.0.1
INSTALL
Newbiely.ino
···
1 void setup() {
Output
Serial Monitor
Ln 1, Col 1
ESP32S3 Dev Module on COM15
1

ezButton liest den Taster und kümmert sich um das Prellen:

  1. Geben Sie ezButton in dasselbe Suchfeld ein.
  2. Suchen Sie die Bibliothek von ArduinoGetStarted.com und klicken Sie auf INSTALL.
  • Search for ezButton created by ArduinoGetStarted.com and click the Install button.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32S3 Dev Module
Library Manager
Type:
All
Topic:
All
ezButton by ArduinoGetStarted.com
Button library supports debounce, pressed/released events and the press counting. It is easy to use with multiple buttons. The library can be used for push-button, momentary switches, toggle switch, magnetic contact switch (door sensor)... It is designed for not only beginners but also experienced users. More info
1.0.6
INSTALL
Newbiely.ino
···
1 void setup() {
Output
Serial Monitor
Ln 1, Col 1
ESP32S3 Dev Module on COM15
1

Arduino IDE Einstellungen für die ESP32 S3 Kamera

Die Kamera funktioniert nicht mit den Standardeinstellungen der Arduino IDE. Sie müssen einige Punkte im Menü Tools ändern, bevor Sie den Code hochladen.

Menüpunkt in ToolsDiese Option wählen
BoardESP32S3 Dev Module
Flash Size16MB (128Mb)
PSRAMOPI PSRAM
Partition SchemeHuge APP (3MB No OTA/1MB SPIFFS)
CPU Frequency240MHz (WiFi)
USB ModeHardware CDC and JTAG
Upload ModeUART0 / Hardware CDC
Upload Speed921600
USB CDC On BootEnabled

ESP32 S3 Code

Ändern Sie Ihr WLAN, Ihr Bot-Token und Ihre Chat-ID am Anfang des Codes.

Die Einstellungen, die Sie ändern können:

NameStartwertWas es bewirkt
PUBLIC_ADDRESSleerDer Link in der Nachricht. Leer bedeutet die Adresse des Boards.
USE_PASSWORDfalseSetzen Sie es auf true, wenn Sie die Kamera für das Internet öffnen
QUIET_TIME10000Millisekunden Wartezeit bis zum nächsten Klingeln
STREAM_SECONDS60Das Live-Video stoppt nach so vielen Sekunden von selbst
DEBOUNCE_TIME50Millisekunden Wartezeit, weil der Taster prellt
/* * Dieser ESP32 S3 Code wurde von newbiely.de entwickelt * Dieser ESP32 S3 Code wird der Öffentlichkeit ohne jegliche Einschränkung zur Verfügung gestellt. * Für vollständige Anleitungen und Schaltpläne besuchen Sie bitte: * https://newbiely.de/tutorials/esp32-s3/esp32-s3-camera-smart-video-doorbell-with-a-button */ #include <WiFi.h> #include <WiFiClientSecure.h> #include <DIYables_ESP32_WebServer.h> // DIYables ESP32 WebServer library #include <ezButton.h> // ezButton library #include "esp_camera.h" const char *WIFI_SSID = "YOUR_WIFI_SSID"; // CHANGE IT const char *WIFI_PASSWORD = "YOUR_WIFI_PASSWORD"; // CHANGE IT const char *BOT_TOKEN = "1234567890:ABCDefGhIJKlmNoPQRsTUVwXYZ1234567890"; // CHANGE IT const char *CHAT_ID = "1234567890"; // CHANGE IT // The address of the live video that goes into the Telegram message. // // Leave it EMPTY to use the address of the board on your own WiFi. The link then // works only when your phone is at home, on the same WiFi. // // Did you make port forwarding on your router? Then write your own address here, // for example "http://my-house.duckdns.org:8080", and the link works from anywhere. const char *PUBLIC_ADDRESS = ""; // CHANGE IT, or leave it empty // A camera that anybody on the internet can watch is a bad idea. // Set this to true when you use PUBLIC_ADDRESS, and the page asks for a password. #define USE_PASSWORD false const char *WEB_USER = "admin"; // CHANGE IT const char *WEB_PASSWORD = "esp32s3"; // CHANGE IT #define BUTTON_PIN 47 // the OUT pin of the button module is connected to GPIO47 // The board already has a small colour LED on it, so you do not need // an extra LED and resistor. This LED answers the visitor. #define LED_PIN LED_BUILTIN // Has your board no LED on it? Then connect your own LED with a 220 ohm // resistor to a free pin, and use this line instead: // #define LED_PIN 21 #define DEBOUNCE_TIME 50 // wait 50 milliseconds, because the button bounces #define QUIET_TIME 10000 // wait 10 seconds before the next ring (10000 milliseconds) #define STREAM_SECONDS 60 // the live video stops by itself after 60 seconds // Camera pins of the ESP32-S3-N16R8 camera board. // The same pins work for the OV2640, OV3660 and OV5640 versions. #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 Y9_GPIO_NUM 16 #define Y8_GPIO_NUM 17 #define Y7_GPIO_NUM 18 #define Y6_GPIO_NUM 12 #define Y5_GPIO_NUM 10 #define Y4_GPIO_NUM 8 #define Y3_GPIO_NUM 9 #define Y2_GPIO_NUM 11 #define VSYNC_GPIO_NUM 6 #define HREF_GPIO_NUM 7 #define PCLK_GPIO_NUM 13 #define TELEGRAM_HOST "api.telegram.org" #define BOUNDARY "diyablesphoto" #define STREAM_MARK "diyablesframe" DIYables_ESP32_WebServer server(80); // The line below is for a BARE push button wired to GND. ezButton then // uses the internal pull-up resistor of the board, and the pin reads LOW // while the button is held down. // ezButton button(BUTTON_PIN); // If you use a BUTTON MODULE instead, the module carries its own resistor // on the board, so the internal one must not be used. Comment the line // above and use this line instead: ezButton button(BUTTON_PIN, EXTERNAL_PULLDOWN); unsigned long lastRingTime = 0; const char INDEX_HTML[] = R"rawliteral( <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>ESP32 S3 Doorbell</title> <style> body { background:#111; color:#eee; font-family:sans-serif; text-align:center; margin:0; padding:16px; } img { width:100%; max-width:800px; border-radius:8px; } p { color:#aaa; font-size:14px; } </style> </head> <body> <h2>Who is at the door?</h2> <img id="live" src="/stream"> <p>The live video stops by itself after a minute, so the doorbell button works again.</p> <script> // When the video stops, load the page again and start a new one document.getElementById("live").onerror = function () { setTimeout(function () { location.reload(); }, 1000); }; </script> </body> </html> )rawliteral"; // Returns the name of the camera sensor that is installed on the board const char *getSensorName(int pid) { switch (pid) { case OV2640_PID: return "OV2640 (2 MP, max UXGA 1600x1200)"; case OV3660_PID: return "OV3660 (3 MP, max QXGA 2048x1536)"; case OV5640_PID: return "OV5640 (5 MP, max QSXGA 2592x1944)"; default: return "Unknown sensor"; } } bool initCamera() { 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.pixel_format = PIXFORMAT_JPEG; config.frame_size = FRAMESIZE_SVGA; // 800x600 - small, so it is sent quickly config.jpeg_quality = 12; // 0 to 63, a lower number means a better image config.fb_count = 1; config.fb_location = CAMERA_FB_IN_DRAM; config.grab_mode = CAMERA_GRAB_WHEN_EMPTY; if (psramFound()) { config.fb_location = CAMERA_FB_IN_PSRAM; config.jpeg_quality = 10; config.fb_count = 2; config.grab_mode = CAMERA_GRAB_LATEST; } else { config.frame_size = FRAMESIZE_QVGA; Serial.println("WARNING: PSRAM not found. Please set PSRAM to OPI PSRAM in the Tools menu."); } esp_err_t err = esp_camera_init(&config); if (err != ESP_OK) { Serial.printf("Camera init failed with error 0x%x\n", err); return false; } sensor_t *s = esp_camera_sensor_get(); Serial.printf("Camera sensor: %s\n", getSensorName(s->id.PID)); // Each sensor needs slightly different settings switch (s->id.PID) { case OV2640_PID: s->set_vflip(s, 0); s->set_hmirror(s, 0); break; case OV3660_PID: s->set_vflip(s, 1); // the OV3660 image is upside down by default s->set_brightness(s, 1); // make the image a little brighter s->set_saturation(s, -2); // make the colors a little softer break; case OV5640_PID: s->set_vflip(s, 0); s->set_hmirror(s, 0); break; default: break; } return true; } // Builds the link to the live video that goes into the Telegram message String getLiveLink() { if (strlen(PUBLIC_ADDRESS) > 0) return String(PUBLIC_ADDRESS) + "/stream"; return "http://" + WiFi.localIP().toString() + "/stream"; } // Blinks the LED, so the visitor knows what is happening void blinkLed(int times, int speed) { for (int i = 0; i < times; i++) { digitalWrite(LED_PIN, HIGH); delay(speed); digitalWrite(LED_PIN, LOW); delay(speed); } } // Sends one photo and the live link to your Telegram chat bool sendPhotoToTelegram(camera_fb_t *fb) { WiFiClientSecure client; client.setInsecure(); // do not check the certificate of the Telegram server client.setTimeout(15); Serial.println("Connecting to Telegram..."); if (!client.connect(TELEGRAM_HOST, 443)) { Serial.println("Cannot connect to Telegram"); return false; } // The text under the photo, with the address of the live video String caption = "Somebody is at the door!\n"; caption += "Live video: " + getLiveLink(); // The first part of the message: who receives the photo, and the text String head = "--" BOUNDARY "\r\n"; head += "Content-Disposition: form-data; name=\"chat_id\"\r\n\r\n"; head += String(CHAT_ID) + "\r\n"; head += "--" BOUNDARY "\r\n"; head += "Content-Disposition: form-data; name=\"caption\"\r\n\r\n"; head += caption + "\r\n"; head += "--" BOUNDARY "\r\n"; head += "Content-Disposition: form-data; name=\"photo\"; filename=\"doorbell.jpg\"\r\n"; head += "Content-Type: image/jpeg\r\n\r\n"; // The last part of the message String tail = "\r\n--" BOUNDARY "--\r\n"; size_t totalLength = head.length() + fb->len + tail.length(); // Send the HTTP header client.print("POST /bot" + String(BOT_TOKEN) + "/sendPhoto HTTP/1.1\r\n"); client.print("Host: " TELEGRAM_HOST "\r\n"); client.print("Content-Type: multipart/form-data; boundary=" BOUNDARY "\r\n"); client.print("Content-Length: " + String(totalLength) + "\r\n"); client.print("Connection: close\r\n\r\n"); // Send the message client.print(head); // Send the photo in small pieces of 1024 bytes. // We check every piece. If one fails, Telegram would wait for ever. size_t sent = 0; for (size_t i = 0; i < fb->len; i += 1024) { size_t piece = fb->len - i; if (piece > 1024) piece = 1024; size_t written = client.write(fb->buf + i, piece); if (written != piece) { Serial.printf("Sending stopped after %u of %u bytes\n", (unsigned)(sent + written), (unsigned)fb->len); client.stop(); return false; } sent += written; } client.print(tail); // Read the answer of Telegram. // Do NOT stop when the connection closes. Telegram answers and closes at once, // and the answer is often still waiting in the buffer at that moment. String answer = ""; unsigned long startTime = millis(); while (millis() - startTime < 15000) { while (client.available()) { answer += (char)client.read(); startTime = millis(); } if (answer.length() > 0 && !client.connected()) break; // the whole answer arrived and the server hung up delay(10); } client.stop(); if (answer.length() == 0) { Serial.println("Telegram did not answer at all."); Serial.println("Check your internet, and check that your network does not block Telegram."); return false; } if (answer.indexOf("\"ok\":true") > 0) { Serial.println("The photo and the live link were sent to Telegram"); return true; } Serial.println("Telegram did not accept the photo. The answer was:"); Serial.println(answer); return false; } // The whole doorbell: light on, photo, send, answer with the LED void ringTheDoorbell() { Serial.println("The doorbell was pressed!"); digitalWrite(LED_PIN, HIGH); // the light stays on while we work camera_fb_t *fb = esp_camera_fb_get(); if (!fb) { Serial.println("Photo capture failed"); digitalWrite(LED_PIN, LOW); blinkLed(5, 100); // five fast blinks mean "something went wrong" return; } Serial.printf("Photo taken: %u bytes\n", fb->len); bool sent = sendPhotoToTelegram(fb); esp_camera_fb_return(fb); // give the memory back to the camera digitalWrite(LED_PIN, LOW); if (sent) blinkLed(2, 200); // two slow blinks mean "the message is on its way" else blinkLed(5, 100); // five fast blinks mean "something went wrong" } // Shows the web page with the live video void handleHome(WiFiClient &client, const String &method, const String &request, const QueryParams &params, const String &jsonData) { server.sendResponse(client, INDEX_HTML, "text/html"); } // Sends the live video to the phone or the computer that opened the link void handleStream(WiFiClient &client, const String &method, const String &request, const QueryParams &params, const String &jsonData) { Serial.println("Somebody is watching the live video"); client.print("HTTP/1.1 200 OK\r\n"); client.print("Content-Type: multipart/x-mixed-replace; boundary=" STREAM_MARK "\r\n"); client.print("Access-Control-Allow-Origin: *\r\n"); client.print("Connection: close\r\n\r\n"); unsigned long startTime = millis(); while (client.connected()) { // Stop by ourselves after a while, so the doorbell button works again if (millis() - startTime >= (unsigned long)STREAM_SECONDS * 1000) { Serial.println("The live video stopped after the time limit"); break; } camera_fb_t *fb = esp_camera_fb_get(); if (!fb) { Serial.println("Frame capture failed"); break; } size_t len = fb->len; client.print("--" STREAM_MARK "\r\n"); client.print("Content-Type: image/jpeg\r\n"); client.printf("Content-Length: %u\r\n\r\n", len); size_t sent = client.write(fb->buf, len); client.print("\r\n"); esp_camera_fb_return(fb); if (sent != len) // the phone closed the page break; } Serial.println("The live video was closed"); } void setup() { Serial.begin(115200); delay(1000); // The library watches the button and handles the bouncing for us button.setDebounceTime(DEBOUNCE_TIME); pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); if (!initCamera()) { Serial.println("Stopped"); blinkLed(10, 100); while (true) delay(1000); } WiFi.mode(WIFI_STA); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); Serial.print("Connecting to WiFi"); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(); WiFi.setSleep(false); // keep WiFi fast for the live video if (USE_PASSWORD) server.enableAuthentication(WEB_USER, WEB_PASSWORD); server.addRoute("/", handleHome); server.addRoute("/stream", handleStream); server.begin(); Serial.print("Live video on your own WiFi: http://"); Serial.print(WiFi.localIP()); Serial.println("/stream"); Serial.println("The link inside the Telegram message is: " + getLiveLink()); blinkLed(3, 150); // three blinks mean "the doorbell is ready" Serial.println("Ready. Waiting for somebody to press the button..."); } void loop() { server.handleClient(); // answers the phone that wants to watch the live video button.loop(); // the library must do its work first, in every loop // isPressed() is true only in the moment the button goes down if (button.isPressed()) { if (millis() - lastRingTime >= QUIET_TIME) { ringTheDoorbell(); lastRingTime = millis(); } else { Serial.println("Too soon after the last ring. Nothing is sent."); blinkLed(1, 400); } } }

Schnelle Schritte

  • Neu beim ESP32 S3? Absolvieren Sie zuerst unsere Anleitung Erste Schritte mit dem ESP32 S3.
  • Erstellen Sie Ihren Telegram-Bot und finden Sie Ihre Chat-ID. Siehe die Schritte oben.
  • Installieren Sie die Bibliotheken DIYables ESP32 WebServer und ezButton.
  • Ziehen Sie das USB-Kabel ab und verdrahten Sie dann das Taster-Modul wie in der Tabelle oben.
  • Kopieren Sie den obigen Code und fügen Sie ihn in die Arduino IDE ein.
  • Ändern Sie WIFI_SSID, WIFI_PASSWORD, BOT_TOKEN und CHAT_ID. Lassen Sie PUBLIC_ADDRESS vorerst leer.
  • Ändern Sie die Einstellungen im Menü Tools. Siehe die Tabelle oben.
  • Kompilieren Sie den Code und laden Sie ihn auf das ESP32 S3 Board hoch, indem Sie in der Arduino IDE auf die Schaltfläche Upload klicken.
Arduino IDE Code hochladen
  • Öffnen Sie den Seriellen Monitor in der Arduino IDE.
Wie man den Seriellen Monitor in der Arduino IDE öffnet
  • Drücken Sie einmal die Taste RESET. Die LED blinkt dreimal, sodass Sie wissen, dass die Türklingel bereit ist.
  • Richten Sie die Kamera auf Ihr Gesicht und drücken Sie den Klingeltaster.
  • Die LED bleibt einen Moment an und blinkt dann zweimal.
  • Schauen Sie auf Ihr Handy. Das Foto ist in Ihrem Telegram-Chat, mit dem Link darunter.
Telegram
Telegram 12:45
Welcome to Telegram!
ArduinoBot 10:19
Chatting with Arduino...
telegram-botfather
BotFather Yesterday
Your bot has been created.

ArduinoBot

bot
Today
Somebody is at the door! Live video: http\://192.168.0.2/stream
10:15 AM
  • Tippen Sie auf den Link. Ihr Handy öffnet das Live-Video Ihrer Tür.
  • Schauen Sie einen Moment zu und schließen Sie dann die Seite. Die Türklingel ist wieder bereit.
  • Profi-Tipp: Möchten Sie, dass der Link auch funktioniert, wenn Sie nicht zu Hause sind? Lesen Sie oben Der Live-Video-Link und richten Sie die Portweiterleitung ein.
ESP32 S3 Türklingel Foto in Telegram
ESP32 S3 Türklingel Live-Video

Serieller Monitor

Die folgenden Messwerte wurden im Jahr 2026 aufgezeichnet:

∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32S3 Dev Module
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32S3 Dev Module' on 'COM15')
New Line
9600 baud
[2026-09-28 17:00:01] Camera sensor: OV5640 (5 MP, max QSXGA 2592x1944) [2026-09-28 17:00:01] Connecting to WiFi... [2026-09-28 17:00:04] Live video on your own WiFi: http://192.168.0.2/stream [2026-09-28 17:00:04] The link inside the Telegram message is: http://192.168.0.2/stream [2026-09-28 17:00:05] Ready. Waiting for somebody to press the button... [2026-09-28 17:02:18] The doorbell was pressed! [2026-09-28 17:02:18] Photo taken: 51353 bytes [2026-09-28 17:02:18] Connecting to Telegram... [2026-09-28 17:02:21] The photo and the live link were sent to Telegram [2026-09-28 17:02:25] Too soon after the last ring. Nothing is sent. [2026-09-28 17:02:33] Somebody is watching the live video [2026-09-28 17:02:51] The live video was closed
Ln 11, Col 1
ESP32S3 Dev Module on COM15
2

※ Notiz:

Too soon after the last ring ist die Ruhezeit, die ihre Arbeit macht. Jemand hat den Taster nach 4 Sekunden erneut gedrückt, und der Code hat kein zweites Foto gesendet.

※ Notiz:

Somebody is watching the live video erscheint, wenn Sie auf den Link tippen. Wenn Sie diese Zeile nie sehen, hat der Link das Board nicht erreicht. Lesen Sie die Fehlerbehebung unten.

Die zwei Zeilen am Anfang zeigen Ihnen, was in die Nachricht eingefügt wurde. Wenn Sie PUBLIC_ADDRESS setzen, wird die zweite Zeile zu Ihrer eigenen Adresse:

∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32S3 Dev Module
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32S3 Dev Module' on 'COM15')
New Line
9600 baud
[2026-09-28 17:00:04] Live video on your own WiFi: http://192.168.0.2/stream [2026-09-28 17:00:04] The link inside the Telegram message is: http://my-house.duckdns.org:8080/stream
Ln 11, Col 1
ESP32S3 Dev Module on COM15
2

Fehlerbehebung

Nichts passiert, wenn ich den Taster drücke.

  • Prüfen Sie die drei Drähte. VCC an 3,3V, GND an GND, OUT an GPIO47.
  • Ist button.loop() die erste Zeile in loop()? Ohne sie liest die Bibliothek den Pin nie.
  • Hat Ihr Modul einen Pull-up-Widerstand statt eines Pull-down? Dann ändern Sie den Code in ezButton button(BUTTON_PIN, EXTERNAL_PULLUP);
  • Beobachten Sie den Seriellen Monitor, während Sie drücken. Keine Zeile dort bedeutet, dass es an der Verdrahtung liegt, nicht am Code.

Die Türklingel klingelt von selbst, obwohl niemand da ist.

Der OUT-Draht ist locker, sodass der Pin Störungen auffängt. Stecken Sie den Draht richtig ein. Ein Modul mit eigenem Widerstand sollte das bei korrekter Verdrahtung nie tun.

Ein Druck sendet zwei oder drei Fotos.

Erhöhen Sie DEBOUNCE_TIME von 50 auf 150.

Die LED blinkt nach jedem Druck fünfmal.

Fünf schnelle Blinker bedeuten, dass das Foto nicht gesendet werden konnte. Lesen Sie den Seriellen Monitor:

  • Telegram did not answer at all bedeutet, dass das Foto gesendet wurde, aber nichts zurückkam. Prüfen Sie Ihre Internetverbindung und versuchen Sie es mit einem Handy-Hotspot, da manche Netzwerke Telegram blockieren.
  • Sending stopped after ... bytes bedeutet, dass das WLAN mittendrin abgebrochen ist. Stellen Sie das Board näher an den Router.
  • Cannot connect to Telegram bedeutet, dass überhaupt kein Internet vorhanden ist.
  • Unauthorized bedeutet, dass Ihr Bot-Token falsch ist.
  • chat not found bedeutet, dass Ihre Chat-ID falsch ist.

Der Serielle Monitor zeigt Forbidden: bot can't initiate conversation with a user.

Sie haben Ihrem Bot nie geschrieben. Öffnen Sie Telegram, suchen Sie Ihren Bot und senden Sie ihm eine beliebige Nachricht. Drücken Sie dann RESET auf dem Board.

Die LED leuchtet nie auf.

Der Code verwendet die LED auf dem Board. Nicht jedes Board hat eine. Wenn Ihres keine hat, schließen Sie Ihre eigene LED mit einem 220-Ohm-Widerstand an GPIO21 an und ändern Sie die Zeile in #define LED_PIN 21.

Der Link in der Nachricht öffnet nichts.

  • Lassen Sie PUBLIC_ADDRESS leer und versuchen Sie es erneut zu Hause, im selben WLAN wie das Board. Das muss zuerst funktionieren.
  • Ihr Handy muss im WLAN sein, nicht in den mobilen Daten. Eine private Adresse wie 192.168.0.2 existiert außerhalb Ihres Hauses nicht.
  • Geben Sie http:// ein, nicht https://. Das Board verwendet kein https.

Der Link funktioniert zu Hause, aber nicht außerhalb.

Das ist bei leerem PUBLIC_ADDRESS normal. Damit er von überall funktioniert, benötigen Sie eine Portweiterleitung und einen DDNS-Namen. Lesen Sie oben Der Live-Video-Link.

Ich habe die Portweiterleitung eingerichtet, und es funktioniert immer noch nicht.

  • Geben Sie dem Board in Ihrem Router eine feste Adresse, sonst zeigt die Weiterleitung nach einem Stromausfall auf das falsche Gerät.
  • Manche Internetanbieter geben Ihnen eine Adresse, die mit anderen Häusern geteilt wird (CGNAT). Dann kann eine Portweiterleitung überhaupt nicht funktionieren. Fragen Sie Ihren Anbieter nach einer echten öffentlichen Adresse.
  • Testen Sie über mobile Daten, nicht über Ihr WLAN zu Hause. Viele Router können ihre eigene öffentliche Adresse nicht von innen öffnen.

Das Live-Video stoppt nach einer Minute.

Das ist Absicht. Während jemand zuschaut, kann das Board den Taster nicht erkennen. Laden Sie die Seite neu, um erneut zuzuschauen, oder ändern Sie #define STREAM_SECONDS 60.

Der Klingeltaster tut nichts, während jemand das Video ansieht.

Das Board kann nur eine Sache gleichzeitig tun. Schließen Sie die Video-Seite, und der Taster funktioniert wieder. Das ist auch der Grund, warum das Video nach einer Minute von selbst stoppt.

Das Foto zeigt den Besucher von unten, oder sein Kopf ist abgeschnitten.

Verschieben Sie die Kamera. Eine Türklingelkamera sollte etwa 150 cm über dem Boden sitzen, sodass sie auf ein Gesicht und nicht auf eine Brust schaut.

Das Foto ist am Abend dunkel.

Die Kamera kann im Dunkeln nicht sehen. Siehe das Tutorial ESP32 S3 Kamera - Blitz-LED für Nachtfotos hinzufügen. Ein Licht an der Tür ist auch freundlich für den Besucher.

Das Foto dauert lange.

Verwenden Sie eine kleinere Bildgröße. FRAMESIZE_VGA (640 × 480) ist etwa halb so groß wie SVGA.

Der Serielle Monitor zeigt nach den Boot-Meldungen nichts an.

Wenn Ihr USB-Kabel im Anschluss mit der Bezeichnung UART steckt, stellen Sie USB CDC On Boot auf Disabled. Wenn es im Anschluss mit der Bezeichnung USB steckt, stellen Sie es auf Enabled.

Anwendungen

Ein Taster, eine Kamera und eine Nachricht. Diese kleine Idee passt an viele Orte. Hier sind praktische Projekte, die Sie mit diesem Code bauen können:

  1. Video-Türklingel für Ihr Haus: Sehen Sie den Besucher auf Ihrem Handy, von überall.
  2. Türklingel für eine gehörlose Person: Das Foto und die Handy-Benachrichtigung ersetzen den Ton.
  3. Empfangsklingel im Büro: Ein Besucher klingelt, und die richtige Person sieht, wer es ist.
  4. Klingel für Werkstatt oder Garage: Erfahren Sie, dass jemand an der Hintertür ist, während eine Maschine laut ist.
  5. Hilfe-Taster für ältere Menschen: Ein Druck sendet ein Foto des Raumes an ein Familienmitglied.
  6. Klingel für Hotel oder Gästezimmer: Der Besitzer sieht den Gast, ohne zur Tür zu gehen.
  7. Lieferklingel im Lager: Der Fahrer klingelt, und das Büro sieht den Lkw.
  8. Service-Taster im Geschäft: Ein Kunde bittet um Hilfe, und ein Foto zeigt, wo er steht.
  9. Eingang von Schule oder Verein: Führen Sie eine Fotoaufzeichnung von jeder Person, die geklingelt hat.
  10. Fotobox-Taster: Drücken Sie, um Ihr eigenes Bild aufzunehmen und es auf Ihr Handy zu bekommen.

Video Tutorial

Wir erwägen die Erstellung von Video-Tutorials. Wenn Sie Video-Tutorials für wichtig halten, abonnieren Sie bitte unseren YouTube-Kanal , um uns zu motivieren, die Videos zu erstellen.

Sehen Sie sich unten die Schritt-für-Schritt-Videoanleitung für dieses ESP32 S3 Projekt an.

Herausforderungen

  1. Einsteiger: Ändern Sie den Text Somebody is at the door! in Ihre eigene Nachricht, zum Beispiel den Namen Ihres Hauses.
  2. Fortgeschritten: Fügen Sie einen Summer hinzu, der im Haus einen Ton erzeugt, wenn der Taster gedrückt wird, sodass Sie die Klingel sowohl hören als auch sehen.
  3. Profi: Speichern Sie zusätzlich jedes Foto auf der microSD-Karte, damit Sie eine Aufzeichnung aller Besucher behalten, auch wenn das Internet ausfällt. Siehe das Tutorial ESP32 S3 Kamera - Foto auf SD-Karte speichern, wenn die Tür geöffnet wird.

※ UNSERE NACHRICHTEN

  • Sie können gerne den Link zu diesem Tutorial teilen. Bitte verwenden Sie jedoch unsere Inhalte nicht auf anderen Websites. Wir haben viel Mühe und Zeit in die Erstellung der Inhalte investiert, bitte respektieren Sie unsere Arbeit!