Arduino Shield (Zusatzplatine) zur Wasserstandsanzeige. 17.1.2016 Nach langem Stillstand habe ich den Brunnen vor unserem Mehrfamilienhaus nach umfangreicher Reparatur wieder in Betrieb genommen. Gespeist wird der Brunnen über eine Pumpe aus einer Zisterne. Das Brunnenwasser läuft wieder zurück in die Zisterne, die wiederum von Dachregenwasser gespeist wird. Da in diesem Kreislauf ständig Wasser verloren geht, andererseits immer wieder Wasser vom Dach bei Regen nachgespeist wird, ist es von stetigem Interesse, wie ist der Wasserstand in der Zisterne. Auch darf die Pumpe bei Wassermangel nicht trocken laufen. Natürlich kann man alle erdenklichen Lösungen für solche Anzeigen kaufen, eine Finanzfrage. Die Idee für mein nächstes Bastelprojekt war geboren. Nach umfangreichen Recherchen im Internet und Diskussionen mit Bekannten habe ich mich entschlossen, den Füllstand in der Zisterne mittels der kapazitiven Messmethode zu ermitteln. Für die Auswertung und Verabeitung der Sensorsignale wollte ich den Arduino als Mikrocontroller verwenden. Also gings an die Arbeit. In der ersten Stufe möchte ich ein Shield (Zusatzplatine) für den Arduino bauen. 1
Das Mess- und Auswertungsprinzip sieht folgendermaßen aus: Die variable Sensorkapazität wird durch eine Sensorelektronik in eine variable Frequenz umgewandelt und in einen für den Arduino verständlichen 5V Pegel transformiert. Der Arduino Mikrocontroller erledigt die Signalverarbeitung. Er steuert, frequenzabhängig, eine LED-Kette als Anzeigemedium an. Die erste Aufgabe war der Sensor: Die physikalische Grundlage ist ein Plattenkondensator, der in eine Flüssigkeit getaucht wird. Ohne Flüssigkeit befindet sich zwischen den beiden Platten Luft als Dielektrikum. Mit steigendem Wasserstand wird diese Luft durch Wasser verdrängt. Da der Unterschied der Dielektrizitätskonstanten zwischen Wasser und Luft ca.75 beträgt, ist ein gut messbarer Kapazitätsunterschied zu erwarten. Die Kapazität einer solchen Anordnung bewegt sich im pf Bereich. Aus diesem Grund ist die "Signalplatte" des Kondensators mit der zugehörigen Leitung sehr empfindlich gegen Störungen oder Annäherung z.b. der Hand (Antenneneffekt). In einer praxisgerechten Lösung muß diese Platte incl. Leitung geschützt (abgeschirmt) werden. 2
Daraus entstand der "Rohrkondensator". Die eine Platte wird in Form eines Rohrs um die andere "gewickelt" (Rohr) und mit Massepotential belegt. Somit ist die innere Platte durch einen Schirm elektrisch geschützt, wie in einem Koaxialkabel. Beide "Platten" müssen gegen die Flüssigkeit elektrisch isoliert sein. Die nächste Aufgabe war geboren, einfache Zutaten sollten es sein. Installationsrohr, kupferkaschierte Epoxydharzplatte, Kupfer-Klebefolie und innen klebebeschichteter Schrumpfschlauch: Das ist der erste Prototyp, er ist ca. 25 cm lang: 3
An dem unten aufgeschnittenen Sensor sieht man deutlich das Rohr mit der außen aufgeklebten Kupferfolie, die äußere "Platte" des Kondensators. Das Ganze ist mit Schrumpfschlauch eingeschrumpft. In der inneren Rohr-Diagonalen sieht man die doppeltseitig beschichtete Epoxydharzplatte, die innere "Platte" des Kondensators. Man kann auch andere Kunststoffstreifen nehmen und einseitig Kupferfolie draufkleben. Das Ganze ist auch in Schrumpfschlauch eingeschrumpft. Bevorzugt ist Schrumpfschlauch mit einer innen aufgebrachten Klebeschicht. Das hat den Vorteil, daß kein Wasser eindringen kann. An der oberen Seite sind am Prototypen 2 Anschlußflächen frei gelassen. An sie ist direkt die Sensorelektronik angeschlossen. Die Leitung der inneren, "heißen" Platte ist somit extrem kurz. Die äußere Platte ist direkt mit der Masse der Sensorelektronik verbunden, die über eine abgeschirmte Leitung versorgt wird, somit ist der Schutz komplett. 4
Am fertigen Sensor ist der gesamte Kopf in Gießharz eingegossen, damit ist alles hermetisch gegen Wasser geschützt. Der freie Platz ist frei für die Elektronik. Man kann sich überlegen auch sie mit einzugießen. Das Gehäuse hat einen wasserdichten Deckel, immerhin wird die ganze Einheit in der Zisterne montiert. Den 25cm langen Prototypen habe ich in einer Wasserflasche getestet. Immerhin erhielt ich zwischen ausund eingetauchtem Sensor deutliche, erwartete Messwertunterschiede. Die ermittelten Daten (ca. Werte): Kapazität: 45pF frei, 200pF eingetaucht. Frequenz mit 100kOhm Widerstand in der Oszillatorelektronik: 115kHz frei, 36kHz eingetaucht. Der endgültige Sensor ist ca. 1,80m lang.. 5
Die fertige Schaltung sieht so aus: Die Sensorkapazität C50 bewegt sich zwischen ca. 40-800pF. Der Schaltkreis IC7 (NE555) wandelt den variablen Kondensator in eine variable Frequenz um. IC2, HEF4093 (Schmitt Trigger), ist der Treiber für Arduino Digitaleingang 5. Die Arduino Digitalausgänge 2-4 und 6-13 steuern direkt die LED Kette an. Das ist die zugehörige Shield Platine, passend für Arduino Duemillanove. 6
Das fertige Füllstands - Shield und die zugehörige Shield-Leiterbahnseite. Der Arduino Eigenbau: 7
Das sind die beiden zusammengesteckt: und eine Detaillansicht: 8
Nun ging es an die Programmierung des Arduino: // Shield Fuellstand Zisterne // Auswertung Wasserstand Zisterne // Arduino Uno Frequenzzaehler bis ca. 5 MHz // Eingangsspannung muss an Pin 5 mit 5V Pegel ankommen. // Beschreibung und Library unter: // http://interface.khm.de/index.php/lab/experiments/arduino-frequencycounter-library/ // Matthias Busse 11.04.2014 Version 1.0 // Frequenzzaehler, Unterprogramm einfuegen #include <FreqCounter.h> long int freq; // LED Kette, Variable festlegen int led010; //Deklarieren Variable, 10% Fuellstand int led020; // " 20% " int led030; // " 30% " int led040; // " 40% " int led050; // " 50% " int led060; // " 60% " int led070; // " 70% " int led080; // " 80% " int led090; // " 90% " int led100; // " 100% " // Pumpe, Variable festlegen int pumpefreig; //Deklarieren Variable, Pumpe Freigabe int pumpestop; // " Pumpe Stop int fuelmin; // " Fuellstand min int steuein; // " Steuerung ein int pumpemot; // " Pumpe Motor void setup() { // Frequenzzaehler, Serielle Ausgabe auf Monitor Serial.begin(38400); // Serielle Ausgabe Monitor Serial.println("Frequenz Zaehler V 1.0"); // LED Kette, Ausgangspins festlegen led010 = 12; //Initialisieren, LED10% an Pin12 led020 = 11; // " LED20% an Pin11 led030 = 10; // " LED30% an Pin10 led040 = 9; // " LED40% an Pin9 led050 = 8; // " LED50% an Pin8 led060 = 7; // " LED60% an Pin7 led070 = 6; // " LED70% an Pin6 led080 = 4; // " LED80% an Pin4 led090 = 3; // " LED90% an Pin3 led100 = 2; // " LED100%an Pin2 9
// Pumpe, Ausgangspins festlegen pumpemot = A0; //Initialisieren, Pumpe Motor an AnalogPinA0 pumpefreig = A3; // " Pumpe Freigabe an AnalogPinA3 pumpestop = A1; // " Pumpe Stop an AnalpgPinA1 fuelmin = A2; // " Fuellstand min. an AnalogPinA2 steuein = 13; // " Steuerung ein an Pin13 // Pins, Festlegung als Input oder Output pinmode(led010, OUTPUT); //LED 010%, Ausgang pinmode(led020, OUTPUT); //LED 020%, Ausgang pinmode(led030, OUTPUT); //LED 030%, Ausgang pinmode(led040, OUTPUT); //LED 040%, Ausgang pinmode(led050, OUTPUT); //LED 050%, Ausgang pinmode(led060, OUTPUT); //LED 060%, Ausgang pinmode(led070, OUTPUT); //LED 070%, Ausgang pinmode(led080, OUTPUT); //LED 080%, Ausgang pinmode(led090, OUTPUT); //LED 090%, Ausgang pinmode(led100, OUTPUT); //LED 100%, Ausgang pinmode(a0, OUTPUT); //A0, Steuerung ein, Ausgang pinmode(a1, OUTPUT); //A1, Pumpe Stop, Ausgang pinmode(a2, OUTPUT); //A2, Fuellstand min, Ausgang pinmode(a3, OUTPUT); //A3, Pumpe Freigabe, Ausgang pinmode(13, OUTPUT); //13, Pumpe Motor, ausgang } void loop() { // Funktion Frequenzzaehler FreqCounter::f_comp=8; FreqCounter::start(1); while (FreqCounter::f_ready == 0) freq=freqcounter::f_freq; Serial.println(freq); // Kompensation einstellen // Zaehler starten fuer 1ms // warten bis der Zaehler fertig ist // Ergebnis lesen // und ausgeben // Funktion Led Kette if(freq <= 332) //LED 10% digitalwrite(led010, HIGH); //ein digitalwrite(led010, LOW); //aus if(freq <= 304) //LED 20% digitalwrite(led020, HIGH); //ein digitalwrite(led020, LOW); //aus if(freq <= 280) //LED 30% digitalwrite(led030, HIGH); //ein digitalwrite(led030, LOW); //aus if(freq <= 264) //LED 40% digitalwrite(led040, HIGH); //ein digitalwrite(led040, LOW); //aus if(freq <= 248) //LED 50% digitalwrite(led050, HIGH); //ein digitalwrite(led050, LOW); //aus if(freq <= 234) //LED 60% digitalwrite(led060, HIGH); //ein digitalwrite(led060, LOW); //aus 10
if(freq <= 218) //LED 70% digitalwrite(led070, HIGH); //ein digitalwrite(led070, LOW); //aus if(freq <= 207) //LED 80% digitalwrite(led080, HIGH); //ein digitalwrite(led080, LOW); //aus if(freq <= 197) //LED 90% digitalwrite(led090, HIGH); //ein digitalwrite(led090, LOW); //aus if(freq <= 189) //LED 100% digitalwrite(led100, HIGH); //ein digitalwrite(led100, LOW); //aus // Funktion Steuerung ein if(freq >= 50) digitalwrite(steuein, HIGH); // Funktion Pumpe if(freq <= 355) digitalwrite(pumpestop, LOW); if(freq >= 360) digitalwrite(pumpestop, HIGH); if(freq <= 355) digitalwrite(pumpefreig, HIGH); if(freq >= 360) digitalwrite(pumpefreig, LOW); if(freq <= 355) digitalwrite(pumpemot, HIGH); if(freq >= 360) digitalwrite(pumpemot, LOW); // Funktion Fuellstand min. if(freq <= 320) digitalwrite(fuelmin, LOW); if(freq >= 325) digitalwrite(fuelmin, HIGH); //Steuerung ein //LED Pumpe stop //aus //ein //LED Pumpe Freigabe //ein //aus //Motor Pumpe //ein //aus //Fuellstand min. //aus //ein } 11
Der Sensor Prototyp funktioniert mit dem Arduino Shield in einer Wasserflasche ganz gut. Das endgültige Ziel war jedoch, eine komplette Steuerung mit folgenden Funktionen zu bauen: Anzeige des Wasserstands in der Zisterne (siehe Arduino Shield). Steuerung der Pumpe des Springbrunnens in Abhängikeit des Zisternen- Wasserstands (Trockenlaufschutz). Steuerung der Pumpe in Abhängigkeit von der Zeit (z.b. nachts abschalten). 12
Diese fertige Steuerung sieht so aus. Ich werde sie in einer separaten Doku näher vorstellen. Wie immer viel Spaß Gruß Günter 13