Wasserzähler smart machen

Ich verwende als Impulsgeber einen Näherungssensor (M18 8mm DC 5V NPN LJ18A3-8-Z/BX-5V) in Kombination mit einem ESP32 Supermini. Da der Näherungssensor mit 5 Volt betrieben wird, habe ich eine Schutzschaltung mit einer Diode eingebaut. Zusätzlich habe ich den verwendeten GPIO5 des ESP32 mit einem 33-kOhm-Widerstand auf die 3,3-Volt-Spannung gezogen.

Den ESP32 habe ich in ESPHome als Wasserzähler konfiguriert, was bei mir einwandfrei funktioniert. Anfangs habe ich versucht, den Sensor mit der Konfiguration - platform: pulse_counter zu betreiben. Dies erwies sich jedoch als nicht zuverlässig, weshalb ich nun - platform: gpio verwende. Nach einer Laufzeit von etwa sechs Wochen konnte ich keine Abweichungen zwischen meiner Messung und dem Zählerstand


Anbei meine Konfiguration:
ohne Display


```substitutions:
  devicename: "smart-wasserzahler"
  long_devicename: "Smart Wasserzähler"
  pcb_version: "2024-12-19"

esphome:
  name: "${devicename}"
  name_add_mac_suffix: false
  comment: "${long_devicename} ${pcb_version}"
  platformio_options:
    board_build.flash_mode: dio

esp32:
  board: esp32-c3-devkitm-1
  variant: ESP32C3
  framework:
    type: esp-idf

# Aktiviert das Loggen
logger:

# Aktiviert die Home Assistant API
api:
  encryption:
    key: "="

  services:
    - service: set_total_pulses
      variables:
        new_value: int
      then:
        - lambda: |-
            id(total_pulses) = new_value;
            ESP_LOGD("Service", "Neuer Zählerstand: %d", id(total_pulses));


# Ermöglicht OTA-Updates
ota:
  - platform: esphome
    password: ""

# WLAN-Konfiguration
wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Optional manuelle IP
  manual_ip:
    static_ip: 
    gateway: 
    subnet: 255.255.255.0
  reboot_timeout: 0s # Neustart warten, wenn kein WLAN, 0s ist ausgeschaltet

  ap:
    ssid: "${long_devicename} hotspot"
    password: ""

# Webserver hinzufügen
web_server:
  port: 80    

# Fallback-Hotspot für Konfigurationsfehler
captive_portal:

globals:
  - id: total_pulses
    type: int
    restore_value: false  # Speichern im Flash deaktiviert, wenn nicht notwendig
    initial_value: '298'  # Startwert des Zählers (Ganzzahl)
  - id: imp_ratio
    type: float
    restore_value: false  # Keine Notwendigkeit, die Impulsrate zu speichern
    initial_value: '0.001'  # Impulsrate vom Wasserzähler (0.001 Liter pro Impuls)

binary_sensor:
  - platform: gpio
    id: internal_pulse_counter
    pin:
      number: GPIO5
      # mode: INPUT_PULLUP  # GPIO5 als Eingang mit Pullup-Widerstand, ohne mode-Attribut, wird standardmäßig der Pin als reiner Eingang ohne Pullup- oder Pulldown-Widerstand konfiguriert.
      inverted: true  # Signal invertieren test 21.12.2024
    name: "Impuls"
    # Diese Filter sorgen dafür, dass der Sensor zuverlässig arbeitet und nur gültige Impulse erkennt
    filters:     
      - delayed_on: 100ms  # Test mit 100ms  Debouncing, der Impuls muss mindestens 50ms dauern, um als gültig zu zählen
      - delayed_off: 400ms  # Test mit 500ms Nach dem Impuls muss eine Pause von mindestens 100ms folgen
    on_press:
      then:
        - lambda: 'id(total_pulses) += 1; ESP_LOGD("Wasserzähler", "Aktueller Zählerstand: %d", id(total_pulses));'
        - switch.turn_on: status_led  # Schaltet die LED ein, wenn ein Impuls empfangen wird
        - delay: 200ms  # LED bleibt 200ms an
        - switch.turn_off: status_led  # Schaltet die LED wieder aus

# Status-LED auf GPIO8
switch:
  - platform: gpio
    id: status_led
    name: "Status LED"
    pin: GPIO8
    inverted: true  # true Umgekehrte Logik: Ein (LOW) bedeutet "an", aus (HIGH) bedeutet "aus"

# Sensoren
sensor:
  # Uptime-Sensor (Betriebszeit)
  - platform: uptime
    name: "${long_devicename} Betriebszeit"
    id: uptime_seconds
    update_interval: 30s

  # WLAN-Signalstärke
  - platform: wifi_signal
    name: "${long_devicename} WLAN-Signal"
    update_interval: 60s

  # Sensor für Wasserverbrauch
  - platform: template
    name: "Wasserverbrauch"
    id: wasser_verbrauch_liter
    device_class: water
    unit_of_measurement: "Liter"
    state_class: "total_increasing"
    icon: "mdi:water"
    accuracy_decimals: 0
    lambda: |-
      return id(total_pulses);  
    # Berechnung in Litern (Anzahl der Impulse)

  - platform: template
    name: "Wasserverbrauch gesamt"
    id: wasser_verbrauch_total
    device_class: energy
    unit_of_measurement: "m³"
    state_class: "total_increasing"
    icon: "mdi:water"
    accuracy_decimals: 3
    lambda: |-
      return id(total_pulses) * id(imp_ratio);  
    # Umrechnung von Litern zu m³