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³