Hausgemachter mmWave-Präsenzmelder HLK-LD2410

Erfahre, wie du ein mmWave Präsenzmelder Selbstbauen kannst!

Ein Smarthome braucht so viele Daten wie möglich. Nachdem mein Smarthome mit Bewegungsmeldern in jedem Raum ausgestattet war, konnte ich das Licht beim Betreten des Raumes automatisieren.

Allerdings stand ich schnell vor einem Problem bzw. im Dunkeln. Der Bewegungsmelder erkennt nicht, wenn sich eine Person im Raum befindet, aber z.B. still auf dem Sofa sitzt. Das Licht ging aus – ich saß im dunklen. Hier hilft ein LD2410 mmWave Präsenzmelder!

Wie das Wort schon sagt, reagiert dieser nicht auf Bewegungen, sondern meldet die Anwesenheit im Raum. Dies erschreckend genau. Auf mehrere Meter entfernen wird sogar ein Atmen erkannt.

Diese Aufgabe lösen wir mit einem mmWave-Radarsensor.

mmWave Präsenzmelder

Was ist ein mmWave Präsenzmelder

Ein mmWave-Sensor sendet elektromagnetische Wellen im Millimeterwellenbereich aus, die von Objekten in der Umgebung reflektiert oder gestreut werden. Der Sensor empfängt die reflektierten oder gestreuten Wellen und analysiert ihre Eigenschaften wie Laufzeit, Phasenverschiebung und Intensität.

Basierend auf diesen Eigenschaften werden Informationen über die Umgebung, wie Entfernung, Geschwindigkeit, Richtung und Größe von Objekten, gewonnen. Die Laufzeit der Wellen ermöglicht die Messung der Entfernung von Objekten, während die Phasenverschiebung die Messung der Geschwindigkeit ermöglicht.

Die Intensität der reflektierten oder gestreuten Wellen gibt Aufschluss über die Größe oder Beschaffenheit von Objekten. Zusammen ermöglicht die Analyse dieser Welleneigenschaften dem mmWave-Sensor präzise Erfassung und Detektion von Objekten und Informationen über die Umgebung.

Neben der vorgestellten Selbstbaulösung gibt es z.B. das Fertigprodukt Aqara FP1. Eine selbstgebaute Variante hat zum einen den Preisvorteil (ca. 10€). Zum anderen kann diese einfach per MQTT in das Smathome System eingebunden werden.

Was wird benötigt für einen mmWave Präsenzmelder

  • Wemos D1 Mini: Ein günstiger, aber leistungsstarker ESP8266-basierter Mikrocontroller
  • HLK-LD2410-Modul: ein mmWave Sensor der besonders günstig ist
  • Kabel: Zum Verbinden der Komponenten.
  • USB-Kabel: Zum Flashen der Firmware auf den Wemos D1 Mini.
  • Lötkolben / Lötzinn / Seitenschneider
  • Optional: Jumper-Kabel
  • Optional: Ein 3D gedrucktes Gehäuse

Schritt 1 – Hardware

Als erstes wird die Platine HLK-LD2410 mit dem Wemos D1 Mini verbunden. Das Herzstück des mmWave Präsenzmelder. Beim Kauf des Moduls empfiehlt es sich, die Platine mit angelöteten Pins zu bestellen.

Der Sensor ist erstaunlich klein. Mit einem Lochabstand von nur 1,27 mm wird es eine knifflige Angelegenheit, die Kabel anzulöten.

  1. Verbinde den VCC-Pin des HLK-LD2410-Moduls mit dem 5V-Pin des Wemos D1 Mini.
  2. Verbinde den GND-Pin des HLK-LD2410-Moduls mit dem GND-Pin des Wemos D1 Mini.
  3. Verbinde den RX-Pin des HLK-LD2410-Moduls mit dem TX-Pin des Wemos D1 Mini.
  4. Verbinde den TX-Pin des HLK-LD2410-Moduls mit dem RX-Pin des Wemos D1 Mini.
  5. Verbinde den OUT-Pin des HLK-LD2410-Moduls mit dem D1-Pin des Wemos D1 Mini.

Stelle sicher, dass du die Verbindungen fest und korrekt machst, um eine zuverlässige Kommunikation zwischen den Komponenten sicherzustellen.

mmWave Präsenzmelder HLK-LD2410 Schaltplan

Schritt 2 – yaml erstellen

Als nächstes erstellen wir die Firmware für den Wemos. Hier wecken wir den mmWave Präsenzmelder zum leben. Da wir ESPHome verwenden, müssen wir eine yaml-Datei erstellen. Hier kürzen wir ab. Denn im ioBroker Forum bin ich auf einen Beitrag gestoßen, wo ein User das Script bereits erstellt hat.

Neben dem Script wird noch die uart_read_line_sensor_ld2410v3.h benötigt. Diese muss im ioBroker in den Pfad /opt/iobroker/iobroker-data/esphome.0 kopiert werden.

Nachdem dies geschehen ist, öffnen wir ESPHome. Danach erstellen wir eine Standard ESP-Home yaml, welcher nachher auf den mmWave Präsenzmelder gespielt wird.

ESPHome New Device

Anschließend wird dem Sensor ein Name gegeben.

EspHome vorbereiten

Hier wählen wir ESP8266 für einen Wemos d1 mini.

ESPHome Edit

Bearbeiten und Ersetzen des Codes

Nun editieren wir diese und ersetzen den Code mit dem aus dem ioBroker Beitrag:

esphome:
 name: ld2410m3d1
 includes:
   - uart_read_line_sensor_ld2410v3.h
 on_boot:
    priority: -100
    then:
     - script.execute: get_config


esp8266:
     board: esp01_1m


# Enable logging
logger:
 baud_rate: 0
 logs:
   sensor: INFO # DEBUG level with uart_target_output = overload!
   binary_sensor: INFO
   text_sensor: INFO

# Enable Home Assistant API
api:

ota:
 

wifi:
 ssid: "yyyyyyyyy1"
 password: "xxxxxxxxxxxxxx2"
 use_address: 192.168.178.67



substitutions:
 device_name: dev-sensor

mqtt:
 broker: 192.168.178.59
 port: 1506
 topic_prefix: ld2410motion/motion3
 
 
web_server:
 port: 80
 version: 2
 include_internal: true
 ota: false

captive_portal:

uart:
 id: uart_bus
 tx_pin:
   number: GPIO1
 rx_pin: 
   number: GPIO3
 baud_rate: 256000
 parity: NONE
 stop_bits: 1

switch:
 - platform: safe_mode
   name: use_safe_mode
   
 - platform: template
   name: configmode
   id: configmode
   optimistic: true
   # assumed_state: false
   turn_on_action:
     # - switch.turn_off: engineering_mode
     - lambda: 'static_cast<LD2410 *>(ld2410)->setConfigMode(true);'
     - delay: 100ms
     - script.execute: clear_targets
   turn_off_action:
     - lambda: 'static_cast<LD2410 *>(ld2410)->setConfigMode(false);'

 - platform: template
   name: show_target_stats
   id: show_stats
   optimistic: true
   internal: true
   turn_off_action:
     - script.execute: clear_targets

text_sensor:
 - platform: template
   name: uptime_human_readable
   id: uptime_human_readable
   icon: mdi:clock-start
   update_interval: 60s

sensor:
 - platform: uptime
   name: uptime_sensor
   id: uptime_sensor
   update_interval: 60s
   internal: true
   on_raw_value:
     then:
       - text_sensor.template.publish:
           id: uptime_human_readable
           state: !lambda |-
                     int seconds = round(id(uptime_sensor).raw_state);
                     int days = seconds / (24 * 3600);
                     seconds = seconds % (24 * 3600);
                     int hours = seconds / 3600;
                     seconds = seconds % 3600;
                     int minutes = seconds /  60;
                     seconds = seconds % 60;
                     return (
                       (days ? to_string(days)+":" : "00:") +
                       (hours ? to_string(hours)+":" : "00:") +
                       (minutes ? to_string(minutes)+":" : "00:") +
                       (to_string(seconds))
                     ).c_str();

 - platform: custom # currently crashes ESP32
   lambda: |-
     auto uart_component = static_cast<LD2410 *>(ld2410);
     //return {uart_component->movingTargetDistance,uart_component->movingTargetEnergy,uart_component->stillTargetDistance,uart_component->stillTargetEnergy,uart_component->detectDistance};
     return {};
   sensors:
   
 - platform: template
   name: movingTargetDistance
   id: movingTargetDistance
   unit_of_measurement: "cm"
   accuracy_decimals: 0
   internal: true
   
 - platform: template
   name: movingTargetEnergy
   id: movingTargetEnergy
   unit_of_measurement: "%"
   accuracy_decimals: 0
   internal: true
   
 - platform: template
   name: stillTargetDistance
   id: stillTargetDistance
   unit_of_measurement: "cm"
   accuracy_decimals: 0
   internal: true
   
 - platform: template
   name: stillTargetEnergy
   id: stillTargetEnergy
   unit_of_measurement: "%"
   accuracy_decimals: 0
   internal: true
   
 - platform: template
   name: detectDistance
   id: detectDistance
   unit_of_measurement: "cm"
   accuracy_decimals: 0
   internal: true
   
custom_component:
 - lambda: |-
     return {new LD2410(id(uart_bus))};
   components:
     - id: ld2410
     
binary_sensor:
 - platform: gpio
   name: mmwave_presence_ld2410
   id: mmwave_presence_ld2410
   pin: GPIO5
   device_class: motion
   on_state:
     then:
       - if: 
           condition: 
             - binary_sensor.is_off: mmwave_presence_ld2410
           then: 
             - delay: 150ms
             - script.execute: clear_targets

number:  
 - platform: template
   name: configMaxDistance
   id: maxconfigDistance
   unit_of_measurement: "M"
   min_value: 0.75
   max_value: 6
   step: 0.75
   update_interval: never
   optimistic: true
   set_action:
     - switch.turn_on: configmode
     - delay: 50ms
     - lambda: |-
         auto uart_component = static_cast<LD2410 *>(ld2410);
         uart_component->setMaxDistancesAndNoneDuration(x/0.75,x/0.75,id(noneDuration).state);
     - delay: 50ms
     - lambda: 'static_cast<LD2410 *>(ld2410)->queryParameters();'
     - delay: 50ms
     - switch.turn_off: configmode

 - platform: template
   name: "sensitivity_threshold_(%)"
   id: allSensitivity
   min_value: 10
   max_value: 100
   step: 5
   mode: box
   update_interval: never
   optimistic: true
   set_action:
     - switch.turn_on: configmode
     - delay: 50ms
     - lambda: |-
         auto uart_component = static_cast<LD2410 *>(ld2410);
         uart_component->setAllSensitivity(x);
     - delay: 50ms
     - lambda: 'static_cast<LD2410 *>(ld2410)->queryParameters();'
     - delay: 50ms
     - switch.turn_off: configmode
     
 - platform: template
   name: "motion_hold_(sec)"
   id: noneDuration
   min_value: 0
   # max_value: 32767
   max_value: 900
   step: 1
   mode: box
   update_interval: never
   optimistic: true
   set_action:
     - switch.turn_on: configmode
     - delay: 50ms
     - lambda: |-
         auto uart_component = static_cast<LD2410 *>(ld2410);
         uart_component->setMaxDistancesAndNoneDuration(id(maxconfigDistance).state, id(maxconfigDistance).state, x);
     - delay: 50ms
     - lambda: 'static_cast<LD2410 *>(ld2410)->queryParameters();'
     - delay: 50ms
     - switch.turn_off: configmode
button:
 - platform: restart
   name: "reset/restart_ESP/MCU"
   entity_category: diagnostic
   on_press:
     - switch.turn_on: configmode
     - delay: 50ms
     - lambda: 'static_cast<LD2410 *>(ld2410)->factoryReset();'
     - delay: 150ms
     - lambda: 'static_cast<LD2410 *>(ld2410)->reboot();'
     - delay: 150ms

script:
 - id: get_config
   then:
     - switch.turn_on: configmode
     - delay: 500ms
     - lambda: 'static_cast<LD2410 *>(ld2410)->queryParameters();'
     - delay: 500ms
     - switch.turn_off: configmode
     
 - id: clear_targets
   then:
     - lambda: |-
         //id(hasTarget).publish_state(0);
         //id(hasMovingTarget).publish_state(0);
         //id(hasStillTarget).publish_state(0);
         id(movingTargetDistance).publish_state(0);
         id(movingTargetEnergy).publish_state(0);
         id(stillTargetDistance).publish_state(0);
         id(stillTargetEnergy).publish_state(0);
         id(detectDistance).publish_state(0);
Erweitern

Hier müssen wir noch folgende Änderungen vornehmen:

wifi:
 ssid: "yyyyyyyyy1"
 password: "xxxxxxxxxxxxxx2"
 use_address: 192.168.178.67

Hier müssen die WLAN-Zugangsdaten eingegeben werden. Soll der Sensor eine feste IP erhalten, so kann diese hier eingetragen werden. Falls keine vergeben werden soll, muss die Zeile gelöscht werden.

mqtt:
 broker: 192.168.178.59
 port: 1506
 topic_prefix: ld2410motion/motion3

Hier werden die Zugangsdaten für die MQTT-Verbindung festgelegt. Die IP des MQTT Brokers und der Port müssen angegeben werden. Im Topic geben wir an, in welchem Kanal der Sensor seine Werte ablegen soll.

Der mmWave Präsenzmelder zusammengebaut

Schritt 3 – Konfigurieren des mmWave Präsenzmelder

Jetzt können wir den Wemos flashen. Wir speichern die Datei und gehen auf „Install“ jetzt wählen wir mit welcher Methode wir flashen wollen. Ich bevorzuge es die Datei herunterzuladen und mit dem ESPHome-Flasher zu flashen.

ESPHome flashvorgang

Sobald der Flashvorgang abgeschlossen ist, sollte der Sensor mit dem WLAN und dem MQTT Broker kommunizieren.

Über die <<ip-adresse:80>> kann die Webkonfiguration geöffnet werden.

mmWave Präsenzmelder - ESPHome Übersicht

Hier können wir die Empfindlichkeit, die Entfernung und die Zeit einstellen, nach der der mmWave Präsenzmelder wieder den Wert „off“ ausgibt.

Hier hilft nur ausprobieren. Platziere den Sensor an der Stelle, an der er später sein soll. Dann stelle die Werte so ein, dass der Sensor die Anwesenheit erkennt.

Nun kontrollieren wir noch, ob die Werte über MQTT ankommen. Dazu gehen wir im ioBroker in die Objekte und öffnen den MQTT Adapter.

Optional kann der mmWave Präsenzmelder auch in einem 3D gedruckten Gehäuse untergebracht werden. Mir hat dieses Gehäuse sehr gut gefallen, da der Sensor so noch leicht in seiner Position verstellt werden kann.

mmWave Präsenzmelder - 3D Druck Gehäuse

Beispiele für Automationen

  • Beim Verlassen des Raumes wird das Licht ausgeschaltet.
  • Beim Betreten des Arbeitszimmers an Werktagen morgens werden Monitore, Drucker und der Heimarbeitsplatz-Computer eingeschaltet. Beim Verlassen des Raumes werden die Minitore ausgeschaltet, um Energie zu sparen.

Hat dir der Beitrag gefallen?

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert