Arduino – Zisternen-Überwachung mit HC-SR04

Um den Wasserstand einer Zisterne zu ermitteln, wird der Wasserpegel benötigt. Warum also nicht mit einem Arduino gestützten Ultraschall-Sensor realisieren?

Gesagt getan - Um das Vorhaben umzusetzen, habe ich erst einmal eine Simulation mit thinkercad vorgenommen.

Das 10kΩ Potentiometer ist dazu da, um den Kontrast zu regeln. Den 200Ω Wiederstand habe ich zum Schutz der LED-Hintergrundbeleuchtung eingesetzt. Das Display soll später den Inhalt der Zisterne in Liter sowie den Prozentualen Anteil anzeigen.

Der Code des Mikrocontrollers sieht in der Simulation wie folgt aus:

#include <LiquidCrystal.h>

// PINs
LiquidCrystal lcd(7,8,9,10,11,12);
const int signal = 6;

// VARs
const int durchgaenge = 3;
float cm, dauer, dauergesamt;

void setup() {
 // LCD
 lcd.begin(16, 2);
}

void loop() {
 // Reset Dauergesamt
 dauergesamt = 0;
 
 for (int i=0; i<durchgaenge; i++) {
  // Trigger für High Pulse
  pinMode(signal, OUTPUT);
  digitalWrite(signal, LOW);
  delayMicroseconds(2);
  digitalWrite(signal, HIGH);
  delayMicroseconds(10);
  digitalWrite(signal, LOW);

  // Erfassung - Dauer in Mikrosekunden
  pinMode(signal, INPUT);
  dauer = pulseIn(signal, HIGH);

  // Berechnung
  dauergesamt = dauergesamt + dauer;
 
  delay(500);
 }

 // Berechne Mikrosekunden in cm
 cm = ((dauergesamt/durchgaenge)/2)/29;
 
 // Ausgabe auf LCD
 lcd.clear();

 lcd.setCursor(0,0);
 lcd.print(" Testmode");
 
 lcd.setCursor(0,1);
 lcd.print("Abstand: ");
 lcd.print(round(cm), DEC);
 lcd.print(" cm");

 delay(100);
}

Ich habe in den Code mehrere Durchläufe eingebaut, um den cm-Durchschnitt zu ermitteln.

Die Berechnung stützt sich auf die physikalischen Eigenschaften von Ultraschall. Für einen cm benötigt der Ultraschall 29 Mikrosekunden. Da ich nur wissen möchte, wie lange der Schall für einen Weg benötigt, muss noch durch zwei geteilt werden.

Seit der Bestellung sind der Arduino sowie der Ultraschall-Sensor gekommen. Bisher sieht das Ganze noch so aus:

Der Unterscheid zur Simulation ist, dass der Ultraschallsensor 4-Pins, also einen mehr hat. Anstatt einen der beim Senden und Empfangen umgeschaltet werden muss, können diese fest definiert werden:

const int triggerPin = 5; //Trigger-Pin
const int echoPin = 6; // Echo-Pin
..
void setup() {
 // PIN-Modes
 pinMode(triggerPin, OUTPUT);
 pinMode(echoPin, INPUT);
}

void loop() {
 ...
 for (int i=1; i <=durchgaenge; i++) {
  // Trigger für High Pulse
  digitalWrite(triggerPin, LOW);
  delayMicroseconds(2);
  digitalWrite(triggerPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(triggerPin, LOW);

  // Erfassung - Dauer in Mikrosekunden
  dauer = pulseIn(echoPin, HIGH);
  ...
 }
}

Um den Sensor in der Zisterne geschützt anzubringen, hat sich ein Freund bereit erklärt, diesen Part umzusetzen. Mithilfe entsprechender CAD-Software und einem 3D-Drucker ist somit das Gehäuse für den Sensor entstanden. Einige Bilder dazu:

Mittlerweile ist auch das LCD-Display aus China angekommen. Zuerst habe ich die Steckleiste angelötet und wie geplant verkabelt. Funktionierte auf Anhieb!

Um den Füllstand über den cm-Wert zu ermitteln, haben wir mehrere Messungen durchgeführt. Der Ultraschall-Sensor soll später 20cm über dem Maximalstand angebracht werden:

Nach dem Übertrag in Excel und der Trendlinienfunktion, lies sich somit die Formel für den Füllstand ermitteln.
Dadurch konnte ich die Programmierung vorerst fertigstellen.

Um die Verkabelung im späteren Einbau einfach zu halten, habe ich mir ein I2C-Modul besorgt.
Dieses wird dann direkt an das Display gelötet und über (nur noch) zwei PINs angesprochen.
Die Verkabelung hat sich dann entsprechend entschlackt:

Mithilfe eines I2C-Scanners, entsprechender Bibliothek und Codeanpassung, ließ sich das Display dann auch problemlos ansprechen. Dadurch entfiel zusätzlich das Kontrast-Poti sowie der Hintergrund-Wiederstand.

Umsetzung/provisorischer Aufbau:

Der Mikrocontroller Code sieht jetzt nach der Anpassung wie folgt aus, die Ausgabe erfolgt in Zehnerschritten:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// PINs
LiquidCrystal_I2C lcd(0x3F, 16, 2);
const int triggerPin = 5;
const int echoPin = 6;

// VARs
const int cm_max = 20;
const int cm_min = 106;
const int liter_max = 1750;
const int durchgaenge = 3;
int liter, balken;
float cm, dauer, dauergesamt;

void setup() {
  // PIN-Modes
  pinMode(triggerPin, OUTPUT);
  pinMode(echoPin, INPUT);
  
  // LCD
  lcd.begin();
  lcd.setCursor(3,0);
  lcd.print("Willkommen");
}

void loop() {
  // Reset Dauergesamt
  dauergesamt = 0;
  
  for (int i=0; i<durchgaenge; i++) {
    // Trigger für High Pulse
    digitalWrite(triggerPin, LOW);
    delayMicroseconds(2);
    digitalWrite(triggerPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(triggerPin, LOW);

    // Erfassung - Dauer in Mikrosekunden
    dauer = pulseIn(echoPin, HIGH);

    // Berechnung
    dauergesamt = dauergesamt + dauer;
    
    delay(500);
  }

  // Berechne Mikrosekunden in cm
  cm = ((dauergesamt/durchgaenge)/2)/29;

  // Berechne Liter
  if (cm < cm_max) {
    liter = liter_max;
  } else if (cm >= cm_max && cm <= cm_min) {
    liter = CmZuLiter(cm);
  } else {
    liter = 0;
  }

  // Berechne Balken
  balken = LiterZuBalken(liter);

  // LCD-Ausgabe
  lcd.clear();
  
  // Zeile 1
  lcd.setCursor(4,0);
  lcd.print(liter);
  lcd.print(" Liter");

  // Zeile 2
  for (int i=0; i<balken; i++) {
    lcd.setCursor(i,1);
    lcd.write((unsigned char)1023);
  }
  
  delay(100);
}

int CmZuLiter(float x) {
  int result;
  result = round((-0.000006*pow(x,4)+0.0029*pow(x,3)-0.4321*pow(x,2)+2.8503*x+1850)/10)*10;
  return result;
}

int LiterZuBalken(int x) {
  int result;
  result = round((16.0*x)/liter_max);
  return result;
}

Der fast fertige Einbau in der Gartenhütte sieht jetzt wie folgt aus:

Damit ist das Projekt vorerst abgeschlossen.

Möchte man das ganze Platzsparend nachbauen, spricht nichts gegen einen Arduino Micro, Nano oder Mini.
Hier sind alle PINs gegeben und die Programmierung muss auch nicht angepasst werden.

Alternativ gibt es auch die Möglichkeit, statt einem Ultraschallsensor einen ToF-Sensor, der mit Lichtzeitmessung arbeitet, zu verwenden.

Über ein konstruktives Feedback würde ich mich freuen, auch unterstütze ich gerne bei ählichen Vorhaben 🙂 

Posted in Arduino and tagged , , , , , .