Beim letzten Starkregen (welcher in Deutschland ja verheerende Schäden angerichtet hat) kam auch bei uns die Kanalisation nicht mehr mit. Gott sei Dank gab es nicht so große Probleme wie anderswo, aber unsere Zisterne ist übergelaufen und dadurch ist mein Sensor in der Zisterne abgesoffen.

Durch Wasser zerstörter Zisternensensor
Durch Wasser zerstörter Zisternen-Sensor

Interessanterweise läuft der ESP8266 noch problemlos, aber die Messung liefert Mondwerte.

Mein Plan ist Elektronik und Sensor wieder zu trennen. Der Sensor wird in der Zisterne versenkt, die Elektronik kommt ins Pumpenhaus.

Wasserstandssensor auf Druckbasis mit Stromschleife
Wasserstandssensor auf Druckbasis mit Stromschleife

Doch wie bringt man einem ESP8266 bei Strom zu messen? Sicher gibt es viele Möglichkeiten, doch ich entscheide mich ganz simpel für einen (passenden) Widerstand, an dem die gewünschte Spannung abfällt.

Wir erinnern uns kurz zurück an die Schule: Da war mal was das hieß “U = I * R”
Und ich möchte das an meinem ADC, wenn der Sensor 20mA liefert eine Spannung von 3.3V anliegt. Das ist die Betriebsspannung meines ESP8266.
Das heißt: R = 3,3V / 0,020A = 165 Ohm -> Ich nehme also einen 150 Ohm Widerstand.
Bei minimaler und maximaler Wassertiefe (= Stromfluss) ergeben sich dann folgende Spannungen.
V = 0,004A * 150 Ohm = 0,6V (minimal)
V = 0,020A * 150 Ohm = 3,0V (maximal)
Das passt also, auch wenn ich nicht den ganzen Messbereich des ADC ausschöpfe!

Jetzt möchte ich den µC noch gegen Spannungen die größer als VCC (=3,3V) + 0.6V sind schützen und den Strom auf unter 0,1mA bringen. Kann ja immer mal passieren das irgendwo ein Kurzschluss entsteht oder beim Aufbau Kabel vertauscht werden.
R= (24V-(3,3V+0,6V)) / 0,0009A = 22333 Ohm -> Ich nehme also einen 27k Widerstand.

So sieht die modifizierte Schaltung nun aus:

Schaltplan des neuen Zisternen-Sensors mit Wasserdrucksensor
Schaltplan des neuen Zisternen-Elektronik mit Wasserdrucksensor.
Wichtig: Die GNDs der beiden Spannungsquellen sind verbunden! (auf dem Schaltplan nicht zu sehen)

Jetzt schaut man sich den Schaltplan an und denkt: Ok, R2 = 27kOhm, das ist also der Schutzwiderstand.
Aber sollte R3 lt. Berechnung nicht 150 Ohm sein? Warum steht im Schaltplan 50 Ohm?
Das liegt daran, das ich in die Falle meines ESP-Moduls getappt bin. Nachdem ich das so gebaut hatte und der ADC irgendwie nichts sinnvolles gemessen hat, habe ich etwas Datenblätter gewälzt und festgestellt, das die “rohen” ESP-Module – wie ich sie verwende – einen Spannungsbereich am ADC von 0-1V erwarten (trotz 3,3V Betriebsspannung). Es gibt Module da ist direkt ein Spannungsteiler eingebaut, bei meinem nackten Modul aber nicht.

Also nochmal neu gerechnet:
R = 1.0V / 0,020A = 50 Ohm -> Ich nehme also einen 51 Ohm Widerstand.
Der Schutzwiderstand bleibt gleich.
Proberechnung:
V = 0,004A * 50 Ohm = 0,2V (minimal)
V = 0,020A * 50 Ohm = 1,0V (maximal) (hier liefert der ADC dann den Wert 1023)

Neue Schaltung auf Lochrasterplatine
Neue Schaltung auf Lochrasterplatine

Man sieht meine geliebte (aber sehr labile) Wurfverkabelung, mit der ich quasi immer arbeite. 😉
Im Hintergrund ist der USB->Seriell Konverter zu sehen (zum Programmieren) und vorne links, unter der Platine ist der Step-Up-Wandler. Die Platine ist jetzt durch das aus- und einlöten diverser Bauteile ganz schön verbraten, aber muss ja auch keinen Schönheitspreis gewinnen.

Ordentlich verpackt in eine Abzweigdose die rumlag sieht es dann so aus.

Schaltung in Abzweigdose
Schaltung in Abzweigdose

Wie man sieht habe ich das Kabel vom Sensor mit einem Hohlstecker versehen, damit ich die Elektronik für Wartungszwecke leicht vom Sensor trennen kann.

Jetzt fehlt noch der angepasste Arduino Sketch:

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

const int sensorEnable = 15; // PIN für den Transistor zum aktivieren des Step-Up-Wandlers
const byte sensorPin = A0; // ADC für den sensor
const uint16_t resistor = 51; // Eingesetzter Pull-Down Widerstand
const int maxAdcWennVoll = 472; // Prozentuale Umrechnung

ESP8266WebServer server(80); // Webserver
WiFiClient client;

              
void setup() {
  Serial.begin(115200);

  IPAddress ip(192, 168, X, Y);
  IPAddress gateway(192, 168, X, Z); 
  IPAddress subnet(255, 255, 255, 0); 
  WiFi.config(ip, gateway, subnet);
  WiFi.begin("**netzwerk**", "**geheim**");

  Serial.print("Connecting");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();

  Serial.print("Connected, IP address: ");
  Serial.println(WiFi.localIP());  

  server.on("/", handle_normal);
  server.on("/hs", handle_hs);
  server.on("/hs/1", handle_hs);
  server.onNotFound(handle_NotFound);  
  server.begin();
  Serial.println("http server startet");

  pinMode(sensorEnable, OUTPUT);
  digitalWrite(sensorEnable, LOW);
  
  pinMode(sensorPin, INPUT); 
}

void loop() {
  server.handleClient();
}

void handle_NotFound(){
  server.send(404, "text/plain", "Not found");
}

void handle_normal() {
  Serial.println("handle /");
  long pressure = measurePressure();  
  long percent = pressure * 100 / maxAdcWennVoll; //umrechnen auf prozent
  
  String msg = String("<!DOCTYPE html><html>") + 
    "<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">" + 
    "<link rel=\"icon\" href=\"data:,\">" + 
    "<body><h1>Zisterne Measusement Server</h1>" + 
    "<p>Use get parameter hs for homeserver</p>" + 
    "<p>Exampe: /hs/1</p>" + 
    "<br><br><p>Current pressure: " + String(pressure) + "</p>" + 
    "<br><br><p>Current percent: " + String(percent) + "</p>" + 
    "</body></html>\r\n" ;
  server.send(200, "text/html", msg); 
}

void handle_hs() {
  Serial.println("handle /hs");
  long pressure = measurePressure();
  long percent = pressure * 100 / maxAdcWennVoll; //umrechnen auf prozent
  String msg = String("D=" + String(percent) + "\r\n");
  server.send(200, "text/html", msg); 
} 

int measurePressure() {
  Serial.println("setting 24v on");
  digitalWrite(sensorEnable, HIGH);
  delay(5*1000); //auf sensor warten
  
  Serial.println("start measuring");
  int myValue = doMeasure(); 
  Serial.println("done measuring");
  
  Serial.println("setting 24v off");
  digitalWrite(sensorEnable, LOW);
  return myValue;
}

int32_t doMeasure() {
  float minAdc = 0.004 * resistor * 1024;
  float maxAdc = 0.020 * resistor * 1024;
  
  int adc = 0;
  for (byte i = 0; i < 3; i++)
  {
    int m = analogRead(sensorPin);
    Serial.println("adc" + String(m));
    adc += m;    
    delay(10);
  }
  adc = adc / 3;
  int32_t value = (adc - minAdc) * int32_t(1023) / (maxAdc - minAdc);
  if (value > 1023) value = 1023;
  else if (value < 0) value = 0;
  return  value;
}

Ich hoffe das diese Version jetzt rebust genug ist und der China-Sensor auch ein paar Jahre durchhält.

2 Gedanken zu „Regenwasser Zisterne 4.0

  1. Hallo,

    Bin ganz per Zufall auf das Projekt gestossen mit der Zisterne 4.0. Ich habe fast genau das selbe diesen Sommer gebaut, den Transistor für den StepUp habe ich nicht, dafür einen besseren ADC, als die ESP32 integrierten. Dennoch habe ich ein recht grosses driften der Werte. Wollte fragen ob das bei Ihrer Lösung auch der Fall ist?

    mit freundlichen Grüssen aus der Schweiz
    Fabio

    Kommentiere
    • Hi. Wie beschrieben runde ich das ja auf einen Prozentwert. Der ist aber +-1% konstant.
      Aktuell habe ich das Problem das mein Stecker Netzteil bei den Temperaturen manchmal nicht will und sich der Prozessor einfach resettet. So 1-2 mal pro Tag und dann wieder Tage gar nicht.

      Kommentiere

Schreibe eine Antwort

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> 

Erforderlich