- Deutsch (de)
- English (en)
Unsere Haustür ist in der Aussenmauer unseres Grundstücks und daher mehrere Meter vom eigentlichen Haus entfernt. Als Klingel nutzen wir bisher eine proprietäre Lösung über Funk aber mit nur einem Endgerät (Klingel). Bei einem L-Bungalow gibt aber keine geeignete Stelle für das Endgerät von der aus wir die Klingel von überall wahrnehmen können.
Zum anderen kommen die thailändischen Paketdienste zeitlich sehr flexible, da kann man nicht immer vor Ort sein. Daher wäre eine smarte Funkklingel der starke Wunsch. Die Anforderungen kann man wie folgt zusammenfassen:
Bei diesem Projekt habe ich mit der Planung bei der Mechanik angefangen. Da ich an der neuen Klingel täglich vorbeigehen werde, muss das Ganze modern und nahezu perfekt aussehen, damit ich mich nicht jedesmal darüber ärgere. Beim Stöbern im Internet konnte ich ein Menge DIY Varianten entdecken (hier ein Auszug):
Am besten hat mir aber vom mechanischen Design die Variante von EI23 gefallen (neben dem witzigen Video ).
Da wie schon erwähnt die Optik bei diesem Projekt eine wichtige Rolle spielt fange ich bei der Planung mit der Mechanik an.
Basis für einen sicheren Einbau ist eine passende Unterputzdose. Fündig geworden bin ich bei GIRA. Die Variante E2 ist von den Maßen bestens geeignet, ermöglicht Verschraubungen der Abdeckeinheit und ist mit ca. 3.50€ auch noch erschwinglich.
Der Bedien- und Sichtbereich wird aus Glas sein, was wir beim örtlichen oder Onlinehändler passend schneiden lassen:
Der Coverframe ist aus zwei Lagen 2mm gefrästen Aluminium oder kommt aus dem 3D-Drucker/Laser Cutter. Da ich die Schrauben gerne verdeckt haben möchte, gibt es die zwei Teile. Unten ist der große Frame mit den Befestigungslöchern zu sehen und oben dann mit der Abdeckung, die übrigens magnetisch gehalten wird. Dazu kleben wir ein dünnes Metallband (z.B. von einem Heftstreifen) auf die Rückseite. Die Magnete befinden sich auf der inneren Halterung (siehe unten).
Um die Befestigungslöcher nutzen zu können, modifizieren wir die Leerdose etwas indem die 4 Eckbefestigungsschrauben gegen 12mm lange M3 Sechskant-Abstandhalter ausgetauscht werden. Diese werden von unter mit M3 Schrauben fixiert, so stehen dann die M3 Gewinde für das Coverframe zur Verfügung.
Die Glasscheibe wird von hinten mit einer bedruckten Folie beklebt die man frei designen kann. Dabei handelt es sich um:
Die Designvorlage kann man in einem Vektor-Designtool seiner Wahl maßstabsgerecht erstellen (ich benutze auf OSX BoxySVG):
Die Folie muss im vollständigen Weissdruck beauftragt werden damit sie auch Blickdicht ist, sonst sieht man das Framegerippe später.
Hinter dem roten Button verbirgt sich später der Berührungssensor, der mittige, rechteckige Ausschnitt ist für die Anzeige und die Löcher oben für die Kamera und das Flashlight. Vor der Verklebung müssen die weissen Flächen noch mit einem Cutter ausgeschnitten werden.
Ist die Folie vom Dienstleister angekommen wird sie mit einem Rakel auf das Glas geklebt. Anschließend kann das Glas dann mit einem Spezialkleber für Glas oder einem entsprechenden Klebeband auf dem Frame fixiert werden. Den Spalt zwischen Glas und Frame habe ich zusätzlich noch mit schwarzen Acryl abgedichtet/geklebt.
Der fertige Aufbau hat meine Zustimmung und motiviert mich weiterzumachen…
Ein Blick auf die Anforderungsliste zeigt vier Funktionseinheiten, die es gilt zu implementieren:
Es gibt fertige Lösungen die in unserem Fall völlig ausreichen. Sie haben meist einen TTP223 Baustein an Board der einen kapazitiven Sensor zur Verfügung stellt. Die Sensorfläche ist schon auf dem PCB. Die Empfindlichkeit ist hoch genug um durch unsere Glasscheibe hindurch zu reagieren. Am Ausgang wird ein digitales Signal für die Auswertung zur Verfügung gestellt.
Wegen der hohen Helligkeit hier in Thailand vermeide ich selbstleuchtende Anzeigen im Aussenbereich auch wenn er beschattet ist. Daher kam die Idee auf doch ein e-paper Display zu verwenden. Schnelle Inhaltswechsel sind nicht zu erwarten und die Lesbarkeit (es ist ja auch das Klingelschild) ist selbst bei Stromausfall gegeben. Auch hier gib es wieder fertige Lösungen mit Controller. Die größt mögliche Anzeige die ins Gehäuse passt, ist ein 2.13 inch Display von Waveshare.
Dabei habe ich die Variante HAT für Raspberry Pi genommen, da der Controller dann auch einen Kabelanschluss hat und die Verdrahtung vereinfacht.
Auch hier werden wir wieder mit einer Fertiglösung zufriedengestellt. Das ESP32 CAM Modul bietet eine kompakte Kamera. Das Objektiv tauschen wir gegen ein Weitwinkel (160°) mit längerem Verbindungskabel aus. So verringert sich der tote Winkel und wir haben mechanisch mehr Spielraum das Objektiv weiter weg von Modul zu platzieren.
Mit dem Modul sind wir auch gleich im heimischen WiFi-Netz und können es zusätzlich als Steuerung der anderen Komponenten wie Tour Button und Sound verwenden.
Eine Möglichkeit der Sprachausgabe ist eine synthetische Lösung. Damit wären beliebige Texte on-the-fly möglich. Da aber die Vielfalt der Textbausteine überschaubar ist, gehe ich eher den Weg über einen MP3 Player. Das folgende kompakte Modul DFPlplayer Mini hat alles was wir brauchen:
Es ist auch über eine serielle Schnittstelle ansprechbar, hat einen SD Card Slot für gespeicherte Soundfiles und kann direkt einen 3W Lautsprecher treiben. Da fängt man nicht an etwas eigenes zu designen. Um später die abgesicherten MP3 Dateien auch einfach aufrufen zu können habe ich folgende Struktur auf der SD-Karte aufgesetzt:
/DoorBell.mp3 Ding-Dong /01/ (English) 001.mp3 Please wait. We will open the door. 002.mp3 Please leave the parcel in front of the door. 003.mp3 Please call the number shown on display. Thanks. 004.mp3 Please wait a moment. /02/ (Thai) 001.mp3 Please wait. We will open the door. 002.mp3 Please leave the parcel in front of the door. 003.mp3 Please call the number shown on display. Thanks. 004.mp3 Please wait a moment.
Will man nicht seine eigene Stimme dort verewigen, so gibt es auch Sprachausgaben von professionellen Sprechern in unterschiedlichen Sprachen. Ein Blick hierher nach text-to-speech lohnt sich da.
Als Lautsprecher hatte ich in anderen Projekten schonmal den kompakten Kleinlautsprecher LSM-S30K verwendet. Hier passt er auch perfekt. Durch den Resonanzraum des Leergehäuses ist der Sound voluminös und laut genug selbst durch die Glasscheibe. Ich habe dabei die Lautstärke nicht auf Vollauschlag.
Bevor wir alle Module verbinden zuerst ein Blick auf die innere Mechanik. Das Leergehäuse hat eine untere Ebene 12mm tiefer, die wir als Fixierung für die Frontseite wie aber auch die Steuermodule verwenden können. Einige Experimente haben dann zu der folgenden Halterung geführt:
Die 4 Blöcke beherbergen die Neodym Magnete (∅ 6 mm) zur Befestigung der Schraubencover. Der untere Frame ist für den Touch Sensor, der mittlere für das Display und der obere für das Weitwinkelobjektiv. Links neben dem Einschub für den Touch Button befindet sich noch eine Klebefläche für eine 5dB Antenne, da die eingebauten meist in der Reichweite versargen, Für die Unterseite brauchen wir einen Frame für den DFPlayer sowie das ESP32 CAM Module. Nach erfolgten 3D Druck werden diese beiden auf der Rückseite mit dem großen Frame verklebt, das Loch für die FLASH Led ist gut zu sehen..
Jetzt fehlt nur noch die Halterung für den Lautsprecher (dafür ist es zu eng auf der Oberseite) und dem Netzteil. Das Leergehäuse hat dafür in der Mitte schon einen Einschub vorgesehen, so dass wir einfach die Maße vom Original übernehmen und ein neues 3D Objekt kreieren.
Auf dem Mittelframe kann der Lautsprecher direkt aufgesteckt werden. Auch das Netzteil findet dort Platz. Wie schon beim Wasserstandsmesser verwende ich umgebaute USB Netzteile. Dieses kann mit dem mittleren Frame fest verschraubt werden.
Nun haben wir ein kompaktes Module was nur an 230V angeschlossen und mit 4x M3 Senkkopfschrauben mit dem Leergehäuse verschraubt wird.
Das muss dafür alles aus dem 3D Drucker kommen::
Die Anzahl der freien Pins am ESP32 CAM Modul reicht gerade so eben aus um alles anzuschliessen. Allerdings müssen wir den SD-Slot dafür aufgeben und das FLASH light mit dem CS Signal des Displays teilen. Wir können die Bilder aber übertragen und auf Home Assistant speichern (siehe Softwareteil) und das FLASH light ist träge genug, die kurzen CS Pulse nicht zu bemerken. An das Display gehen sechs Signalleitungen und an den DFPlayer zwei.
DoorBell Function | PIN @ESP32 CAM | PIN @ESP32 CAM | DoorBell Function | |
---|---|---|---|---|
FLASH light / CS - Display | GPIO4 | GND | GND | |
RESET - Display | GPIO2 | GPIO1 | RxD - DFPlayer | |
SPI CLK - Display | GPIO14 | GPIO3 | TxD - DFPlayer | |
DC - Display | GPIO15 | 3.3V/5V | n/c | |
SPI MOSI - Display | GPIO13 | GND | GND | |
BUSY - Display | GPIO12 | GPIO0 | n/n (External Clock) | |
GND | GND | GPIO16 | Touch Sensor | |
5V | 5V | 3.3V | 3.3V |
Nachdem alles gesteckt bzw. verlötet ist, geht es an die Programmierung…
Es ist nichts Neues das wieder ESPHome für die Software herhalten muss. Diesmal geht es aber sogar ohne jegliche custom components
, da alle benötigten Funktionen schon in ESPHome implementiert sind. Dazu legen wir wieder ein neues Device an und ergänzen die Funktionsblöcke:
Der Touch Button wird ein einfacher Binary Sensor:
binary_sensor: - platform: gpio pin: GPIO16 name: "Ring Door" id: ring_door_sensor
Für das Display brauchen wir erstmal Fonts und Sonderzeichen, die wir verwenden wollen. Es können alle TTF Fonts verwendet werden. Die TTF files müssen dafür nach /config/esphome/fonts/
kopiert werden.
# e-paper display 250x122 (128) font: - file: 'fonts/ComicSansMS3.ttf' id: font_comic24 size: 24 ...
Dann muss die SPI Schnittstelle und die restlichen Pins zugeordnet werden. Die lambda Funktion and Ende erlaubt einem jetzt die freie Programmierung des Display Inhalts. Die verfügbaren Rendering Funktionen sind in der Home Assistant Dokumentation unter Display Component zu finden.
spi: clk_pin: GPIO14 mosi_pin: GPIO13 display: - platform: waveshare_epaper id: doorbell_display cs_pin: GPIO33 dc_pin: GPIO15 busy_pin: GPIO12 reset_pin: GPIO2 model: 2.13in-ttgo-dke full_update_every: 60 update_interval: never reset_duration: 2ms rotation: 90 auto_clear_enabled: true lambda: |- ...
Weiter oben definiert man noch einen Service für das Display update, so kann man auch ausserplanmäßig den Inhalt neu schreiben lassen:
services: - service: update_display then: - component.update: doorbell_display
Bei der Kamera hat sich die maximale Auflösung 800×600 als tauglich herausgestellt, höhere Auflösungen haben bei mir nicht geklappt. Die fest verdrahteten Pins des CAM Moduls müssen hier angegeben:
# doorbell camera esp32_camera: name: Doorbell_Cam vertical_flip: false horizontal_mirror: false external_clock: pin: GPIO0 frequency: 20MHz i2c_pins: sda: GPIO26 scl: GPIO27 data_pins: [GPIO5, GPIO18, GPIO19, GPIO21, GPIO36, GPIO39, GPIO34, GPIO35] vsync_pin: GPIO25 href_pin: GPIO23 pixel_clock_pin: GPIO22 power_down_pin: GPIO32 #resolution: 640x480 resolution: 800x600 #resolution: 1024x768 #resolution: 1280x1024 #resolution: 1600x1200 #jpeg_quality: 10
Damit wir auch die Kontrolle über das FLASH light bekommen, müssen wir es wie folgt einbinden:
output: #flashlight - platform: gpio pin: GPIO4 id: gpio_4 light: #flashlight - platform: binary output: gpio_4 id: cam_flash name: Doorbell Cam flash
Der DFPLayer braucht eine serielle Schnittstelle für die Kommunikation:
# DF MP3 Player uart: tx_pin: GPIO1 rx_pin: GPIO3 baud_rate: 9600 dfplayer: on_finished_playback: then: logger.log: 'Playback finished event'
und eine Reihe von Services:
- service: dfplayer_play_folder variables: folder: int file: int then: - dfplayer.play_folder: folder: !lambda 'return folder;' file: !lambda 'return file;' ...
Darüber hinaus sind noch einige weitere Sensoren eingebaut um die Wifi-Signalstärke, die Aussentemperatur sowie Feuchtigkeit, die Uhrzeit und vorselektierte Texte auf dem Display anzuzeigen. Einfach ein Gimmick weil es geht…
Das vollständige File ist hier nochmal gelistet:
substitutions: device_name: "doorbell" esphome: name: "${device_name}" esp32: board: esp-wrover-kit framework: type: arduino # Enable logging logger: baud_rate: 0 # Enable Home Assistant API api: encryption: key: "MHhpWqaQqGakECxCuyzUl28EHQ0p9UmCPsC1gCR5kVY=" services: - service: update_display then: - component.update: doorbell_display - service: dfplayer_next then: - dfplayer.play_next: - service: dfplayer_previous then: - dfplayer.play_previous: - service: dfplayer_play variables: file: int then: - dfplayer.play: !lambda 'return file;' - service: dfplayer_play_folder variables: folder: int file: int then: - dfplayer.play_folder: folder: !lambda 'return folder;' file: !lambda 'return file;' - service: dfplayer_set_device_tf then: - dfplayer.set_device: TF_CARD - service: dfplayer_set_volume variables: volume: int then: - dfplayer.set_volume: !lambda 'return volume;' - service: dfplayer_set_eq variables: preset: int then: - dfplayer.set_eq: !lambda 'return static_cast<dfplayer::EqPreset>(preset);' - service: dfplayer_sleep then: - dfplayer.sleep - service: dfplayer_reset then: - dfplayer.reset - service: dfplayer_start then: - dfplayer.start - service: dfplayer_pause then: - dfplayer.pause - service: dfplayer_stop then: - dfplayer.stop - service: dfplayer_volume_up then: - dfplayer.volume_up - service: dfplayer_volume_down then: - dfplayer.volume_down ota: password: "----password----" time: - platform: homeassistant id: esptime timezone: Europe/Berlin - platform: sntp on_time: # Every minute - seconds: 0 minutes: '*' then: - component.update: doorbell_display wifi: ssid: !secret wifi_ssid password: !secret wifi_password # Enable fallback hotspot (captive portal) in case wifi connection fails ap: ssid: "Doorbell Fallback Hotspot" password: "----password----" captive_portal: # doorbell camera esp32_camera: name: Doorbell_Cam vertical_flip: false horizontal_mirror: false external_clock: pin: GPIO0 frequency: 20MHz i2c_pins: sda: GPIO26 scl: GPIO27 data_pins: [GPIO5, GPIO18, GPIO19, GPIO21, GPIO36, GPIO39, GPIO34, GPIO35] vsync_pin: GPIO25 href_pin: GPIO23 pixel_clock_pin: GPIO22 power_down_pin: GPIO32 #resolution: 640x480 resolution: 800x600 #resolution: 1024x768 #resolution: 1280x1024 #resolution: 1600x1200 #jpeg_quality: 10 output: #flashlight - platform: gpio pin: GPIO4 id: gpio_4 light: #flashlight - platform: binary output: gpio_4 id: cam_flash name: Doorbell Cam flash binary_sensor: - platform: gpio pin: GPIO16 name: "Ring Door" id: ring_door_sensor #on_press: # then: # - component.update: doorbell_display #on_release: # then: # - component.update: doorbell_display - platform: homeassistant id: phone_message entity_id: input_boolean.phone_message internal: true sensor: - platform: wifi_signal id: wifi_strength name: "${device_name} WiFi Signal" update_interval: 5s - platform: homeassistant id: outdoor_temperature entity_id: sensor.aussensensor_temperature internal: true - platform: homeassistant id: outdoor_humidity entity_id: sensor.aussensensor_humidity internal: true text_sensor: - platform: homeassistant id: phone_number entity_id: input_select.door_phone_number internal: true # e-paper display 250x122 (128) font: - file: 'fonts/ComicSansMS3.ttf' id: font_comic24 size: 24 - file: 'fonts/ComicSansMS3_bold.ttf' id: font_comic_bold24 size: 24 - file: "fonts/Roboto-Regular.ttf" id: font_roboto20 size: 20 - file: "fonts/Roboto-Bold.ttf" id: font_roboto_bold24 size: 24 - file: 'fonts/materialdesignicons-webfont.ttf' id: font_icon20 size: 20 glyphs: [ "\U000F092E", # wifi-off "\U000F092F", # wifi-strength-0 "\U000F091F", # wifi-strength-1 "\U000F0922", # wifi-strength-2 "\U000F0925", # wifi-strength-3 "\U000F0928", # wifi-strength-4 "\U000F050F", # temp "\U000F058E", # humidity % "\U000F0150", # clock ] - file: 'fonts/materialdesignicons-webfont.ttf' id: font_icon24 size: 24 glyphs: [ "\U000F009A", # mdi-bell "\U000F009E", # mdi-bell-ring "\U000F1191", # phone ] spi: clk_pin: GPIO14 mosi_pin: GPIO13 display: - platform: waveshare_epaper id: doorbell_display cs_pin: GPIO33 dc_pin: GPIO15 busy_pin: GPIO12 reset_pin: GPIO2 model: 2.13in-ttgo-dke full_update_every: 60 update_interval: never reset_duration: 2ms rotation: 90 auto_clear_enabled: true lambda: |- #define H_WIFI 1 #define V_WIFI 4 #define H_TEMP 30 #define V_TEMP 2 #define H_HUM 115 #define V_HUM 2 #define H_CLOCK 180 #define V_CLOCK 2 // Wifi float wifi_rssi = id(wifi_strength).state; if (wifi_rssi > -50) { it.printf( H_WIFI, V_WIFI, id(font_icon20), "\U000F0928"); } else if (wifi_rssi > -60) { it.printf( H_WIFI, V_WIFI, id(font_icon20), "\U000F0925"); } else if (wifi_rssi > -70) { it.printf( H_WIFI, V_WIFI, id(font_icon20), "\U000F0922"); } else if (wifi_rssi > -80) { it.printf( H_WIFI, V_WIFI, id(font_icon20), "\U000F091F"); } else if (wifi_rssi > -90) { it.printf( H_WIFI, V_WIFI, id(font_icon20), "\U000F092F"); } else { it.printf( H_WIFI, V_WIFI, id(font_icon20), "\U000F092E"); } // Temp it.printf( H_TEMP, V_TEMP+2, id(font_icon20), "\U000F050F"); it.printf(H_TEMP+20, V_TEMP, id(font_roboto20), "%.1f°C", id(outdoor_temperature).state); // Humidity it.printf( H_HUM, V_HUM+2, id(font_icon20), "\U000F058E"); it.printf(H_HUM+20, V_HUM, id(font_roboto20), "%.0f%%", id(outdoor_humidity).state); // Clock it.printf( H_CLOCK, V_CLOCK+2, id(font_icon20), "\U000F0150"); it.strftime(H_CLOCK+20, V_CLOCK, id(font_roboto20), "%H:%M", id(esptime).now()); // ------------------------- it.line(0, 25, 250, 25); // Name plate it.print(70, 30, id(font_comic_bold24), "It's line 1"); it.print(7, 60, id(font_comic_bold24), "It's line 2"); if(id(phone_message).state) { it.printf(05, 100, id(font_icon24), "\U000F1191"); it.printf(35, 97, id(font_roboto_bold24), "%s", id(phone_number).state.c_str()); } else { it.print(53, 97, id(font_roboto_bold24), "It's line 3"); } # DF MP3 Player uart: tx_pin: GPIO1 rx_pin: GPIO3 baud_rate: 9600 dfplayer: on_finished_playback: then: logger.log: 'Playback finished event'
Nach der Kompilierung und Programmierung integrieren wir das Modul doorbell.yaml
und schon stehen alle wichtigen Funktionen in Home Assistant zur Verfügung. Wir können mit der Automatisierung beginnen. So sieht unsere persönliche Node-Red Umsetzung aus:
Wenn der Button am Klingelbrett berührt wird passieren jetzt folgende Dinge:
Man kann sich natürlich auch Emails mit dem aufgenommen Bild schicken lassen, weitere Beleuchtung einschalten oder die Katze füttern lassen …
Das fertige Modul sieht dann Innen und Außen so aus (Display verpixelt):
Im Trockentest in Deutschland hat alles perfekt funktioniert. In 2023 erfolgt der Einbau vor Ort in Thailand. Ich werde weiter berichten…
Wenn ihr meine Arbeit unterstützen wollt, so könnt ihr mir gerne einen Cappuccino oder so spenden: .