Wasserzähler Smart Home ESP8266 HMC5883L

Seit einiger Zeit beschäftigen mich die Fragen, wie ich meine Wasseruhr / Wasserzähler in meinem Haus ablesen kann. Ich habe eine Wasseruhr mit mechanischem Zählwerk, dessen Messdaten ich gerne in meinem Smart Home auswerten und anzeigen möchte.

Wie kann ich meinen analogen Wasserzähler ablesen?

  • Über den Hersteller, in meinem Fall ein Hauswasserzählwerk der Firma Zenner, lässt sich ein Magnetsensor und eine Datenschnittstelle mit LoRaWan oder M-Bus beziehen.
    zenner.de
  • Verschiedene Projekte im Internet beschäftigen sich damit, die Wasseruhr optisch mit einer ESP32 Cam auszulesen. Teilweise sogar AI gestützt, um die Zifferblätter abzulesen.
    haus-automatisierung.com
    smarthome.ms1.de
  • Ein weiterer Ansatz war eine eigene Messung mit Hilfe eines Durchflussmessers im Wasserkreislauf. Über ein kleines Flügelrad wird so ein elektrischer Impuls erzeugt, der dann Rückschluss auf die Durchflussmenge liefert.
    how2electronics.com
  • Der für mich kreativste und technisch einfachste Ansatz war, den Magnetsensor mit Hilfe eines Sensors zur Magnetfeldänderung zu erfassen.
    hackaday.io

Wie lese ich die magnetische Impulsgeberschnittstelle meiner Wasseruhr aus?

Auch hier gibt es wieder verschiedene Ansätze. Prinzipiell funktioniert es so, dass im Zählwerk schon vom Hersteller ein Magnet verbaut ist. Läuft Wasser durch die Wasseruhr, wird das Zählwerk angetrieben und auch der Magnet wird in Bewegung gesetzt. Mein Wasserzähler hat einen Magneten am Zählrad für 0,001 qm² Wasser, was 10 Litern Wasser je voller Umdrehung entspricht.

Reed Kontakt

Ein Reed-Kontakt, der wie ein Schalter arbeitet, kann so an der Wasseruhr positioniert werden, dass er bei einer vollen Umdrehung seinen Kontakt schließt und so den Wasserverbrauch von 10 Litern signalisiert. Oftmals gibt es hierfür auch vom Hersteller schon angebrachte Halterungen für die Hersteller eigenen Systeme zur digitalen Wasserverbrauchsanalyse.

Megnetsensor HMC5883L

Nun habe ich allerdings eine sehr interessante Methode bei meinen Recherchen entdeckt, die ich für mich nun getestet und auch eingesetzt habe. Ich suchte eine Messtechnik, bei der ich keinen direkten Kontakt zur Wasseruhr benötige. Ich wollte auch weiterhin in der Lage sein, die Wasseruhr manuell abzulesen, ohne mein DIY-Messsystem abzubauen. Im Internet fand ich einen Artikel, der einen Magnetfeldsensor HMC5883L verwendet. Damit kann ich die Änderungen des Magnetfelds, das bei Bewegung des Magnets im Messwerk entsteht, messen. Den Artikel habe ich hier verlinkt. hackaday.io

Technischer Aufbau

Die Bauteile

Aufbau auf dem Breadboard

Der Sensor HMC5883L wird mit 3V Spannung über den ESP8266 versorgt. Über zwei weitere Leitungen wird der ESP8266 für die I2C-Schnittstelle mit HMC5883L verbunden.

Wasserzähler magnetisch Smart Home ESP8266 HMC5883L
Breadboard ESP8266 HMC5883L
D1SCL, IOGPIO 5
D2SDA, IOGPIO 4

Der Sensor HMC5883L wird für die Messung direkt neben der Wasseruhr angebracht. Etwa auf Höhe des Messrads, das gemessen werden kann. Auf dem Bild ist auch die Kerbe erkennbar, die der Hersteller für den eigenen Reed-Kontakt vorbereitet hat.

Positionierung Wasserzähler magnetisch Smart Home ESP8266 HMC5883L
Positionierung Messgerät magnetisch ESP8266 HMC5883L

Schaltplan

Schaltplan Wasserzaehler magnetisch Smart-Home ESP8266 HMC5883L

Messung

Für die erste Messung habe ich mir ein Testprogramm erstellt. Der Sensor liefert für alle 3 Achsen jeweils ein Ergebnis. Ich möchte feststellen, welcher Sensorwert am geeignetsten ist, um mir den Wasserverbraucht anzuzeigen, der durch die Magnetfeldänderung ausgewertet wird. Am geeignetsten ist für das Auslesen der Wasseruhr die Achse, die eine schöne Sinuskurve ohne Unterbrechungen liefert, wenn im Haus Wasser verbracht wird.

#include <Wire.h> 

#define addr 0x0D 

int x, y, z;

void setup() {

  Serial.begin(115200);
  Wire.begin();

  Wire.beginTransmission(addr);
  Wire.write(0x09); // continuously Measurement
  Wire.write(0x1D);
  Wire.endTransmission();

}

void loop() {

  readSensor();

  Serial.print("X_Value:");
  Serial.print(x);
  Serial.print(",");
  Serial.print("Y_Value:");
  Serial.print(y);
  Serial.print(",");
  Serial.print("Z_Value:");
  Serial.println(z);

  delay(100);

}

void readSensor(){

  Wire.beginTransmission(addr);
  Wire.write(0x00);
  Wire.endTransmission();

  
  Wire.requestFrom(addr, 6);

  if (6 <= Wire.available()) {
    x = Wire.read();        //MSB x
    x |= Wire.read() << 8;  //LSB x
    z = Wire.read();        //MSB z
    z |= Wire.read() << 8;  //LSB z
    y = Wire.read();        //MSB y
    y |= Wire.read() << 8;  //LSB y
  }
}

Sensor Ausgabe mit dem Arduino Plotter

In der Arduino IDE können die Ausgaben im Serial Monitor auch auf einen Plotter als Diagramm dargestellt werden. Weitere Information zur Verwendung des Plotters findet man auch bei arduino.cc

Plotter Wasserzaehler magnetisch Smart Home ESP8266 HMC5883L
Plotter Programm ESP8266

Programm ESP8266 auswerten und per MQTT senden

In meinem Fall habe ich mich für die y-Achse entschieden, um in meinem Haus die Wasseruhr auszulesen. Das hing bei mir davon ab, wie der Sensor am Wasserzähler platziert ist. Ich übertrag meine Messungen direkt per MQTT an meinen Smart Home Server und werte die empfangenen Messdaten dort über die InfluxDB Datenbank aus. Ändert sich das Magnetfeld nicht, sende ich auch keine Daten an die Datenbank. Hier mein Programm für den ESP8266.

Weitere interessante ESP8266 Projekte gibt es hier.

#include <Wire.h> //I2C Arduino Library
#include "MqttSetup.h"

#define addr 0x0D //I2C Address for The HMC5883
#define MEASURMENTS 1

int x, y, z; //triple axis data

// buffer
#define bufferSize 5
#define bufferToll 50

int bufferLength = 0;
int readIndex = 0;
int writeIndex = 0;

float bufferB[bufferSize];

void setup() {

  Serial.begin(115200);

  setupWifiMqtt();

  Wire.begin();
  Wire.beginTransmission(addr); //start talking
  Wire.write(0x0B); // Tell the HMC5883 to Continuously Measure
  Wire.write(0x01); // Set the Register
  Wire.endTransmission();
}

void loop() {

  float avgY = avgMeasurement();

  // prüfen ob der neue Wert 
  // innerhalb der Tolleranz ist
  if(inTollBuffer(avgY) == false){

    String value = "";

    value.concat( avgY );

    buildMqttMessage("magnetFieldY",  String(value).c_str() );

    sendMqttMessage("mqtt/topic/you/wish/to/have");
  }

  Serial.print("Y_Value:");
  Serial.println(avgY);

  // Eintrag zum Ringbuffer hinzufügen
  writeBuffer(avgY);  

  delay(500);
}

float avgMeasurement(){

  float sumValues = 0;

  for (int i = 0; i < MEASURMENTS; i++) {

      readSensor();

      sumValues = sumValues + y;

      delay(250);
  }

  return sumValues / MEASURMENTS;
}

void readSensor(){

  x = 0;
  y = 0;
  z = 0;

  Wire.beginTransmission(addr);
  Wire.write(0x00); //start with register 3.
  Wire.endTransmission();

  //Read the data
  Wire.requestFrom(addr, 6);
  if (6 <= Wire.available()) {
    x = Wire.read();       //MSB  x
    x |= Wire.read() << 8; //LSB  x
    z = Wire.read();       //MSB  z
    z |= Wire.read() << 8; //LSB z
    y = Wire.read();       //MSB y
    y |= Wire.read() << 8; //LSB y
  }
}

void writeBuffer(float value){

  writeIndex++;

  if (writeIndex == bufferSize)
  {
      writeIndex = 0;
  }

  bufferB[ writeIndex ] = value;
}

boolean inTollBuffer(float value){

  for(int i = 0; i < bufferSize; i++ ){

    if(value < bufferB[i] - bufferToll){
      return false;       
    }

    if(value > bufferB[i] + bufferToll){
      return false;       
    }
  }
  return true;
}

Auszug aus der Datenbank

In meiner InfluxDB kann ich nun die Daten darstellen. Es ist die Sinuskurve zu sehen, wenn viel Wasser verbraucht wird und auch Abschnitte, bei denen kein oder nur wenig Wasser verbraucht wird. Jedes Maximum in der gezeigten Kurve beschreibt hier einen Verbrauch von 10 Litern.

InfluxDB Wasserzaehler magnetisch Smart Home ESP8266 HMC5883L
InfluxDB

Vorteil HMC5883L gegenüber Reed-Kontakt

Ein Reed-Kontakt kann nur einen Zustand 1 oder 0 erkennen. In diesem Anwendungsfall wäre eine 1 ein Verbrauch von 10 Litern.

Wie der Auszug aus der Datenbank im oberen Bild zeigt, misst der HMC5883L nicht nur 1 und 0, sondern hat eine detailliertere Skalierung mit vielen Teilwerten. Dadurch ist das Schaubild eine Kurve mit vielen Zuständen. Auch hier ist das Maximum ein Verbrauch von 10 Litern. Allerdings lässt sich auch ein kleinerer Verbrauch messen, so zum Beispiel eine halbe Umdrehung des Messrads aus der Wasseruhr erkennen. 5 Liter Verbrauch wären somit das Minimum im Diagramm. Mit etwas Mathematik ist es möglich, hier auch kleinere Verbrauchsmengen herauszulesen. So könnte zum Beispiel die Auflösung der Messung von 10 Liter auf 1 Liter herabgesetzt werden.