Wasserstand in Zisterne messen

Ja. Bei mir ist es aufgebaut wie Wasserstand in Zisterne messen - #9 von noschvie hier

Welche Spannungsversorgung hast du im Einsatz?

Das ganze wird bei mir über den Micro USB Port vom NodeMCU Board versorgt. Das müsste ein altes Netzteil vom Handy sein wenn ich es richtig in Erinnerung habe mit 5V / 1A

Würde mal ein anderes Netzteil probieren.
Oder ein 24V Netzteil und ein Step-Down Modul für die 5V.

Ich habe das Netzteil mal getauscht aber leider hat sich am Ergebnis nichts geändert.

Ich würde abwarten bis du den 3m sensor hast.
Dann besorge dir an ein Kunstoff Rohr 3 m mit verschluss.
Mit wasser füllen und referenz Messungen z. B ALLE 10 Zentimeter.
Kannst du natürlich auch an der Zisterne machen falls genügent Wasser vorhanden.

@simon42

wie dir schon geschrieben wollte ich dir und auch alle anderen meinen Zisternen Wasserstandsensor zur Verfügung stellen. Dieser hängt bei mir seit ungefähr Januar 2023 in der Zisterne ohne Störung und Probleme, seit dem heute zum erstmal wieder geöffnet.

Bauteile

  • 1x Shelly Uni (kann analoge Signale einlesen, WLAN-fähig)

  • 1x Widerstand 470 Ω (zur Umwandlung des 4–20 mA Signals in eine Spannung)

  • 1x Füllstandssensor 4–20 mA, DC-24V (druckbasiert, misst den Wasserstand in der Zisterne)

  • 1x 24V Netzteil (Versorgung für den Sensor und Shelly Uni)

Verdrahtung

  1. Netzteil (24 V DC)

    • + an Sensor + (rot) und an den Shelly Uni

    • an Sensor – (schwarz) und GND des Shelly Uni

  2. Signalanschluss

    • Der Füllstandssensor gibt ein 4–20 mA Stromsignal aus.

    • Dieses wird über den 470-Ω-Widerstand in eine Spannung (ca. 1,88 V bei 4 mA bis 9,4 V bei 20 mA) umgewandelt.

    • Widerstand liegt zwischen Shelly Uni Analog In und GND.

  3. Mechanik

    • Sensor in der Zisterne befestigt (z. B. an einem Stein, damit er nicht aufschwimmt).

Kalibrierung des Wasserstandssensors

Nachdem der Sensor eingebaut ist, braucht ihr drei Referenzwerte:

  1. Spannung im leeren Zustand (Sensor komplett trocken bzw. Zisterne leer)

  2. Spannung im vollen Zustand (Zisterne randvoll)

  3. Gesamtvolumen der Zisterne in Litern

Beispielwerte aus meiner Installation

  • Leer: 1,96 V

  • Voll: 2,65 V

  • Zisternenvolumen: 8.500 Liter

unter template:

sensor:
  - name: "Zisterne geglättet"
    unit_of_measurement: "L"
    state: >
      {% set voltage = states('sensor.zisterne_gefiltert') | float(0) %}
      {{ (((voltage - 1.96) / 2.65) * 8500) | round(0) }}

unter sensors:

platform: filter
name: "zisterne gefiltert"
entity_id: sensor.shelly_uni_adc
filters:
- filter: lowpass
  time_constant: 20
  precision: 2

Dashboad Beispiel:

type: picture-elements
elements:
  - type: custom:fluid-level-background-card
    entity: sensor.zisterne_geglattet
    style:
      z-index: 1
      top: 47%
      left: 51.5%
      transform: translate(-50%, -50%)
      width: 270%
      height: 80%
    card_mod:
      style: |
        ha-card {
          text-align: center;
          --ha-card-border-color: transparent !important;
          box-shadow: none !important;
          background: none !important;
          border-radius: 50px;
          overflow: hidden;
        }  
        #container, .container {
          width: 23.3% !important;
          height: 70% !important;
          position: relative !important;
          border-radius: 40px !important;
          margin-left: 38.2%;
          margin-top: 8%;
          # transform: translate(150%, -50%);
          opacity: 0.9;
          overflow: hidden;
        }
    level_color:
      - 82
      - 171
      - 255
    severity:
      - color:
          - 255
          - 71
          - 71
        value: 8500
      - color:
          - 112
          - 200
          - 255
        value: 5000
      - color:
          - 56
          - 179
          - 255
        value: 2000
      - color:
          - 0
          - 145
          - 255
        value: 0
    fill_entity: null
    full_value: "8500"
    card:
      type: custom:card-templater
      card:
        type: entity
        entity: sensor.zisterne_geglattet
        title_template: "{{states('sensor.zisterne_geglattet')|round(0)}}L "
        show_header_toggle: false
        show_name: false
        name: " "
        show_icon: false
        icon: mdi.water
        position:
          value: "off"
        card_mod:
          style: |
            ha-card {
             --ha-card-header-font-size: 14px;
               height: 225px !important;
               
            }
            .card-header {
             justify-content: center !important;
            }
            .name {
             overflow: unset !important;
            }
image: /image/512x512
card_mod:
  style:
    hui-image $: |
      img {
        z-index: 1 !important;
        position: relative !important;
        right: 0px;
        top: 0px;
        width: 100% !important;
        opacity: 1
      }

entities:
  - entity: sensor.zisterne_geglattet
    name: Zisterne
    animation:
      state: "on"
      speed: "2"
decimal: 0
unit_of_measurement: L
max: 8500
min: 0
severity:
  - color: "#eb4034"
    from: "0"
    to: "2000"
  - color: orange
    from: "2000"
    to: "4000"
  - color: "#3deb34"
    from: "4000"
    to: "6000"
  - color: "#0320fc"
    from: "6000"
    to: "8500"
direction: up
height: 150px
width: 150px
animation:
  state: "on"
speed: "2"
positions:
  indicator: outside
  icon: "off"
style: |-
  .card-header {
    font-size: 18px;
  }
  bar-card-value, bar-card-name {
    font-size: 12px;
    transform-origin: 0 0;
    transform: rotate(270deg);
    text-shadow: 1px 1px #0008;
    white-space: nowrap;
  }
  bar-card-value {
    margin-right: auto;
    margin-left: 6px;
    margin-bottom: auto;
    margin-top: auto;
  }
  bar-card-name {
    margin-right: auto;
    margin-left: 0px;
    margin-bottom: -130px;
    margin-top: 130px;
    right: 20px;
  }
  bar-card-currentbar, bar-card-backgroundbar {
    border-radius: 12px;
    border: 1px solid #DDD9;
  }
card_mod:
  style: |
    bar-card-backgroundbar {
      border-radius: 8px;
     }
     bar-card-currentbar {
     border-radius: 8px;
     }
stack: horizontal
title: Zisterne 8500 L geglättet
type: custom:bar-card

Automatisierung :

alias: Benachrichtigung bei Regen Zisterne Füllstand stündlich
description: ""
triggers:
  - minutes: "0"
    trigger: time_pattern
    hours: "1"
conditions:
  - condition: time
    after: "07:00:00"
    before: "22:00:00"
    weekday:
      - mon
      - tue
      - wed
      - thu
      - fri
  - condition: state
    entity_id: weather.ort
    state: rainy
actions:
  - data:
      message: >
        Es regnet! Der aktuelle Füllstand deiner Zisterne ist: {{
        states('sensor.zisterne_geglattet') }} Liter.
      title: Regen und Zisternenstatus
    action: notify.mobile_app

1 „Gefällt mir“

Den TL-136 habe ich auch schon lange im Einsatz.

Funktioniert super, besser als jede optische oder Ultraschall Variante und dazu noch kosten günstig.

Danke an nachbelichtet für die Inspiration und tolle Vorarbeit. Aufbauend auf dieses Projekt stand ich vor dem Problem, dass ich an der Stelle meines Wassertanks keine Stromversorgung zu liegen habe und dort für einen Bewegungsmelder mit LED-Leuchte nur ein Solar-Panel mit Akkus und einem Waveshare Solar Power Manger mit 5V USB vorhanden ist.

Die Schaltung von nachbelichtet hat jedoch in dieser Variante eine Stromaufnahme von ca. 200mA und würde die über den Tag aufgeladenen Akkus vorzeitig leer saugen.

Deshalb habe ich die Schaltung von nachbelichtet.com um die Deep-Sleep Funktion des Wemos D1 Mini erweitert und musste zur Abschaltung der Komponenten und Sensoren noch einen Mosfet-Switch Io15A01/MEM2313 und einen Step-Down Wandler AMS1117 5V auf 3,3V in die 5V zwischenschalten.

Bevor der Wemos D1 Mini in den Deep-Sleep geht, trennt der Mosfet-Switch Io15A01/MEM2313 die +5V und zusätzlich über den nachgeschalteten ADS1117 auch die 3,3V für die Komponenten und Sensoren. Dadurch reduziert sich die Stromaufnahme im Deep-Sleep auf ca. 3mA. Im Wachzustand, also während der Messung liegt die Stromaufnahme bei ca. 200mA mit Display ohne Hintergrundbeleuchtung. Aktuell ist im Arduino-Sketch eine Deep-Sleep-Zeit von 5 Minuten eingestellt. Bedeutet, für ca. 10 Sekunden ist der Wemos D1 Mini im Wachzustand mit Messung der Volt des TL-136 und der Temperatur des DS18B20 und der Übertragung der Werte per MQTT beschäftigt und danach geht der Wemos D1 Mini für 5 Minuten in den Deep-Sleep und schaltet wieder alle Komponenten vor dem Schlafen per Mosfet-Switch ab.

Der bistabile Mosfet-Switch wird über D7 vom Wemos D1 Mini mit einem Low-Impuls getriggert. 1x kurz Low und Mosfet-Switch schaltet die 5V durch und wieder kurz Low und Mosfet-Switch schaltet die 5V wieder ab. Da ich nicht zwei bistabile Mosfet-Switches einsetzen wollte, erzeuge ich die 3,3V mit einem nach dem Mosfet-Switch angeschlossenen AMS1117 Step-Down-Wandler. Damit sichergestellt ist, dass nach dem Aufwachen und zuschalten der 5V durch den bistabilen Mosfet-Switch alle Spannungen 5V + 3,3V anliegen, gibt es eine Rückleitung von 3,3V Vout des AMS1117 Step-Down-Wandler an den A0 des Wemos D1 Mini. Erst wenn diese Messung bzw. Überwachung okay ist, also eine Art einschwingen, erst dann erfolgt im Code die Messung über die Sensoren. Mein Wemos D1 Mini ist mit einer internen Widerstandsbrücke 220Kohm/100Kohm ausgestattet, sodass ich hier die 3,3V direkt anlegen und messen kann. Es soll aber auch ESP8266-Varianten geben, welche nur 1,0V an A0 vertragen. Dann muss die Widerstandsbrücke mit zwei Widerständen selbst davorgeschaltet werden.

Die Skizze der Schaltung bitte nicht überbewerten. Besser ging es leider nicht. :wink:

Den Arduino-Sketch habe ich mir mit Hilfe der KI erstellen müssen, da ich bis dato keine Programmierkenntnisse in dieser Richtung hatte. Der Code dient also nur als Demo oder Inspiration, ist aber für meine Bedürfnisse voll lauffähig. Für den Upload des Codes mit der Arduino IDE muss der Taster zwischen D0 und RST geöffnet werden, ansonsten wird der Upload blockiert. Und für den normalen Betrieb des Sensors muss dieser Taster geschlossen sein, damit der Wemos D1 Mini aus dem Deep-Sleep wieder aufwacht. Statt Taster als Öffner kann man natürlich auch einen Jumper dafür verwenden. Über die zugewiesene IP-Adresse ist auch ein OTA-Upload der Firmware möglich. Es kann also auch per Export in der Arduino IDE die BIN-Datei per OTA hochgeladen werden und der Sensor muss bei einer Code-Anpassung nicht immer kompliziert abgebaut werden.

Die Wifi- und MQTT-Verbindungsdaten sind im Code fest vorgegeben. Wem das nicht reicht, kann sich das entsprechend im Sketch auf WifiScan oder ähnliches umschreiben. Eine kleine WEB-Oberfläche ist im Wachzustand unter der IP des Sensors auch erreichbar und hierüber erfolgt auch der OTA-Upload.

Der Sensor überträgt per MQTT aktuell nur drei Werte: Wasserlevel in Volt, Wasser-Temperatur und Status des Sensors. Die Umrechnung der Volt-werte erfolgt dann nachgelagert im HA. Dafür müssen drei MQTT-Sensoren für den Empfang der MQTT-Werte angelegt werden und zusätzlich Template-Sensoren für die Umrechnung der Volt des Wasser-Levels in Liter und Wasserstand in cm und ähnliches.Auch hier, wem das nicht reicht, kann sich auch noch die MQTT-Topics für eine Auto-Discovery einbauen. Mir war das zu viel Aufwand für nur drei MQTT-Werte.

Der Sketch ist aktuell an einen TL-136 mit 0-1m Messgenauigkeit angepasst. Da ich nur einen 100l-Wassertank 780 * 780mm * Wasserhöhe nutzbar 150mm einer Außendusch messe, liegt meine maximal Wasserstandshöhe bei 15cm, sodass ich für den ADS1115 mit einem Gain-Wert 1024 (ads.setGain(GAIN_FOUR); // ±1.024V Messbereich) arbeite. Ich messe praktisch Volt-Werte mit nur einer Spannungsdifferenz von Min. 0V bis Max. 0,495V. Bedeutet, dass 0,032V vom TL-136 = 1cm Wasserstand in meinem 100l-Wassertank entsprechen. Deshalb im Template Sensor die Zeile {{ (v / 0.032) | round(1) }}. 1 Volt wären in meinem Behälter dann ca. 190 Liter und die maximalen 0,495V ca. 91 Liter. Bei sowas ist die KI auch mal hilfreich und treffsicher. :wink:

Ich kann leider keine Fragen zu evtl. Portierung des Codes zu ESPHome oder den Eigenheiten der Arduino IDE und deren Librarys oder Justierung des AMS1115 / 4-20mA Wandlers bzgl. Gain-Wert beantworten, da davon keine bzw nicht viel Ahnung.

#include <ESP8266WiFi.h>
#include <AsyncMqttClient.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Adafruit_ADS1X15.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPUpdateServer.h>

AsyncMqttClient mqttClient;
ESP8266WebServer server(80);
ESP8266HTTPUpdateServer httpUpdater;

// -------- WLAN --------
const char* ssid = "deine WLAN-ssid";
const char* password = "dein WLAN-Passort";
IPAddress local_IP(192,168,1,125);  // Die IP des Sensors in deinem Netzwerk
IPAddress gateway(192,168,1,1);     // Die IP des Routers in deinem Netzwerk
IPAddress subnet(255,255,255,0);
IPAddress dns(192,168,1,1);         // Vermutlich die IP des Routers in deinem Netzwerk

const char* topic_temp   = "wassertank/temperature";
const char* topic_volt   = "wassertank/waterlevel_voltage";
const char* topic_status = "wassertank/status";

// -------- MQTT --------
const char* mqtt_server = "192.168.1.127";  // Die IP deines MQTT-Brokers deines Home Assistant in deinem Netzwerk
const char* mqtt_user   = "mqtt-user";      // Dein MQTT-User-Name 
const char* mqtt_pass   = "mqtt-pass";      // Dein MQTT-User-Passowrt
bool mqttConnected = false;
bool mqttDataSent = false;

// -------- Hardware --------
#define PIN_ONEWIRE D6
#define PIN_WAKE    D0   // per Taster mit RST verbunden - Standart geschlossen für Deep-Sleep - gedrückt=offen für Sketch-Upload
#define PIN_PWR_TOGGLE D7   // IO15A01 Toggle-Trigger - Low-Impuls für Ein oder Aus
#define PIN_A0_READY   A0   // 3.3V Überwachung ob Power-On
#define READY_THRESHOLD 0.70   // bei A0=max.1V ~0.28V erwartet - bei A0=max.3,3V ~0.78V erwartet - Wemos D1 Mini = A0=max.3,3V
#define DISPLAY_ADDR 0x27   // Adresse des Displays

LiquidCrystal_I2C lcd(DISPLAY_ADDR,16,2);
OneWire oneWire(PIN_ONEWIRE);
DallasTemperature ds18b20(&oneWire);
Adafruit_ADS1115 ads;

float temperature = NAN;
float waterVolt   = NAN;

#define SLEEP_TIME_US 300e6  // 10e6 = 10 Sekunden / 300e6 = 5 Minuten Deep-Sleep-Zeit
unsigned long bootTime;

void onMqttConnect(bool sessionPresent) {
  Serial.println("MQTT connected");
  mqttConnected = true;

  // ---- Online Status ----
  mqttClient.publish(topic_status, 1, true, "online");

  // ---- Sensorwerte senden ----
  mqttClient.publish(topic_temp, 1, true, String(temperature,1).c_str());
  mqttClient.publish(topic_volt, 1, true, String(waterVolt,3).c_str());

  mqttDataSent = true;   // jetzt darf später geschlafen werden
}

void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
  Serial.println("MQTT disconnected");
  mqttConnected = false;
}

// ------ IO15A01 ------
void togglePowerIO15A01() {
  pinMode(PIN_PWR_TOGGLE, OUTPUT);
  digitalWrite(PIN_PWR_TOGGLE, HIGH);
  delay(50);
  digitalWrite(PIN_PWR_TOGGLE, LOW);   // Falling edge trigger
  delay(200);
  digitalWrite(PIN_PWR_TOGGLE, HIGH);
}

void  waitFor3V3fromStepDown() {
  Serial.println("Warte auf 3.3V Rail...");
  unsigned long start = millis();

  while (true) {
    float v = analogRead(A0) * (1.0 / 1023.0); // 0..1V Bereich
    Serial.println("IO15A01 Power-On...");
    Serial.printf("A0 ready check: %.3f V\n", v);
    if (v > READY_THRESHOLD) {
      Serial.println("3.3V ready!");
      break;
    }
    if (millis() - start > 5000) {
      Serial.println("Timeout 3.3V!");
      break;
    }
    delay(100);
  }
}

// -------- Sensoren lesen --------
void readSensors() {
  Serial.println("readSensors...");
  ds18b20.requestTemperatures();
  temperature = ds18b20.getTempCByIndex(0);

  ads.setGain(GAIN_FOUR);   // ±1.024V Messbereich
  int16_t raw = ads.readADC_SingleEnded(0);
  waterVolt = raw * 1.024 / 32768.0;

  Serial.printf("Temp: %.2f C\n", temperature);
  Serial.printf("Volt: %.3f V\n", waterVolt);
}

// -------- Display --------
bool lcdPresent = false;

bool i2cDeviceExists(byte addr) {
  Wire.beginTransmission(addr);
  return (Wire.endTransmission() == 0);
}

void updateDisplay() {
  if (!lcdPresent) return;
  Serial.println("updateDisplay...");
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Temp:");
  lcd.print(temperature,2);
  lcd.print("C");
  lcd.setCursor(0,1);
  lcd.print("Volt:");
  lcd.print(waterVolt,3);
  lcd.print("V");
}

// -------- OTA Webserver --------
void startWebserver() {
  Serial.println("startWebserver...");
  
  // Minimalistische Web-Seite
  server.on("/", HTTP_GET, [](){
    String page =
      "<h2>Wassertank Sensor</h2>"
      " <br>"
      "Temp: " + String(temperature,1) + " C<br>"
      "Volt: " + String(waterVolt,3) + " V<br>"
      " <br>"
      "<a href='/update'>OTA Update</a>";
    server.send(200,"text/html",page);
  });

  // HTTP Update Server (OTA)
  httpUpdater.setup(&server, "/update"); // nur Firmware, kein FileSystem
  server.begin();
  Serial.println("HTTPUpdateServer bereit");
}

// -------- SETUP --------
void setup() {
  Serial.begin(74880);
  delay(2000);

  // IO15A01 einschalten
  togglePowerIO15A01();
  waitFor3V3fromStepDown();

  // Begin I2C
  Wire.begin();
  lcdPresent = i2cDeviceExists(0x27);

  if (lcdPresent) {
    lcd.begin();
    lcd.backlight();
    Serial.println("LCD gefunden");
  } else {
    Serial.println("LCD NICHT vorhanden");
  }

  // Begin ADS1115
  ads.begin(0x49);

  // Begin DS18B20
  ds18b20.begin();
  delay(50);              // 30–100ms warten, bis Sensor stabil
  ds18b20.requestTemperatures();
  temperature = ds18b20.getTempCByIndex(0);
  if (temperature == 85.0) {   // falls noch nicht bereit = 85C nochmals warten, bis Sensor stabil
    delay(100);
    ds18b20.requestTemperatures();
    temperature = ds18b20.getTempCByIndex(0);
  }

  readSensors();
  updateDisplay();

  // -------- WIFI FAST CONNECT --------
  WiFi.persistent(false);     // nichts ins Flash schreiben
  WiFi.mode(WIFI_STA);
  WiFi.setAutoReconnect(true);
  WiFi.hostname("Wassertank-Sensor");

  // feste IP -> kein DHCP warten
  WiFi.config(local_IP, gateway, subnet, dns);
  WiFi.begin(ssid, password);
  Serial.println("WiFi connecting fast...");

  unsigned long start = millis();
  while (WiFi.status() != WL_CONNECTED && millis() - start < 10000) {
    delay(100);
    Serial.print(".");
  }
  Serial.println();

  // MQTT vorbereiten
  mqttClient.onConnect(onMqttConnect);
  mqttClient.onDisconnect(onMqttDisconnect);
  mqttClient.setServer(mqtt_server, 1883);
  mqttClient.setCredentials(mqtt_user, mqtt_pass);

  // LAST WILL (OFFLINE wenn ESP stirbt)
  mqttClient.setWill(topic_status, 1, true, "offline");
  mqttClient.setKeepAlive(10);
  
  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("WiFi connected FAST");
    Serial.println(WiFi.localIP());
    mqttClient.connect();
  } else {
    Serial.println("WiFi FAILED");
  }
  startWebserver();
  bootTime = millis();
}

// -------- LOOP --------
void loop() {

  server.handleClient();   // wichtig für HTTPUpdateServer / Web-Seite
  
  // warten bis MQTT Daten gesendet wurden und 10 Sekunden OTA Fenster
  if (mqttDataSent && millis() - bootTime > 10000) {
    Serial.println("sendMQTT-Status sleep...");
    mqttClient.publish(topic_status, 1, true, "sleep");
    delay(300);   // QoS1 ACK abwarten (wichtig!)
    Serial.println("IO15A01 Power-Off...");
    togglePowerIO15A01();
    delay(300);
    mqttClient.disconnect();
    delay(100);
    Serial.println("WiFi.disconnect...");
    WiFi.disconnect(true);
    WiFi.mode(WIFI_OFF);
    Serial.println("going to ESP.deepSleep...");
    ESP.deepSleep(SLEEP_TIME_US);
  }
}

MQTT.yaml
sensor:
  - name: "Wassertank_Temperature" 
    state_topic: "wassertank/temperature" 
    unit_of_measurement: "°C" 
    device_class: temperature

  - name: "Wassertank_Volt" 
    state_topic: "wassertank/waterlevel_voltage" 
    unit_of_measurement: "V" 
    device_class: voltage
    
  - name: "Wassertank_Status" 
    state_topic: "wassertank/status"

templates/Wassertank.yaml
sensor:
  - name: "Wassertank Wasserstand"
    unique_id: wassertank_level_cm
    unit_of_measurement: "cm"
    state_class: measurement
    state: >
      {% set v = states('sensor.wassertank_volt') | float(0) %}
      {{ (v / 0.032) | round(1) }}

  - name: "Wassertank Inhalt"
    unique_id: wassertank_liter
    unit_of_measurement: "L"
    device_class: water
    state_class: measurement
    state: >
      {% set v = states('sensor.wassertank_volt') | float(0) %}
      {{ (v * 190) | round(1) }}

  - name: "Wassertank Füllstand"
    unique_id: wassertank_percent
    unit_of_measurement: "%"
    device_class: battery
    state_class: measurement
    state: >
      {% set v = states('sensor.wassertank_volt') | float(0) %}
      {% set percent = (v / 0.48 * 100) %}
      {{ [percent, 100] | min | round(1) }}
      
  - name: "Wassertank Resttage"
    unique_id: wassertank_days_left
    unit_of_measurement: "Tage"
    icon: mdi:calendar-clock
    state: >
      {% set liter = states('sensor.wassertank_inhalt') | float(0) %}
      {% set daily = states('sensor.wassertank_daily_usage') | float(0) %}
      {% if daily > 0 %}
        {{ (liter / daily) | round(1) }}
      {% else %}
        unknown
      {% endif %}

binary_sensor:
  - name: "Wassertank Low Water"
    unique_id: wassertank_low_water
    device_class: problem
    state: >
      {{ states('sensor.wassertank_inhalt') | float(0) < 20 }}

configuration.yaml
utility_meter:
  wassertank_daily_usage:
    source: sensor.wassertank_inhalt
    cycle: daily
1 „Gefällt mir“

Warum hast du das Display nicht weggelassen?

War für mich mein erstes Projekt mit der Arduino IDE und wollte mich auch bzgl I2C und Displays dazulernen.

Mit Display kann ich so auch ohne Handy vor Ort am Sensor mal schnell die Wassertemperatur prüfen. Kurz die Reset Taste drücken und der ESP wacht kurz auf und zeigt die Temperatur. Ja die Volt in der Anzeige ist in diesem Fall nicht besonders aussagekräftig. Theoretisch könnte ich jedoch auch noch die Umrechnung von Volt in Liter oder von Volt in cm in den Code statt nur in den Template Sensor einbauen und dies dann zusätzlich zur Temperatur mit anzeigen.

Display ist Spielerei, aber da meine solare Stromversorgung für diesen deep sleep sensor mehr als ausreichend ist, sind die 7mA zusätzliche Stromaufnahme ohne Hintergrundbeleuchtung für die 10 Sekunden Wachzustand vertretbar. Aber wie im Schaltplan ersichtlich ist das Display kein muss und kann im Code bei Bedarf auskommentiert werden.