Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Manufacturing Technology >> Herstellungsprozess

Pool-Füllkontrolle

Ein System zur Überwachung von Wasserstand, Temperatur, pH, Redox, Filterdruck, Stromverbrauch und Pumpenbetrieb. Füllt den Pool bei Bedarf auf.

Geschichte

Die Idee

Im Sommer 2015 haben meine Söhne und ich unsere gesamte Poolanlage umgebaut. Es begann mit einem Problem mit den Wasserleitungen und Ventilen, die wir geerbt hatten, als wir das Haus bekamen, Filterproblemen und einer im Grunde unfähigen Poolfirma, die ein Überbleibsel aus der Zeit war, als wir das Haus bekamen. Als es anfing, so auszusehen, entschied ich, dass es an der Zeit war, etwas zu tun:

Unsere eigene private Lagune

Erste Schritte

Die erste Priorität bestand darin, den Pool sauber zu machen und dann herauszufinden, wie man das so hält. Ich habe Automatisierung schon immer geliebt und fand, dass dies der perfekte Ort ist, um sie auszuprobieren. In Kürze sah der Pool wieder so aus:

Zurück zur Normalität

Aber das Problem blieb, dass es dem Gesamtsystem sowohl an Fähigkeiten als auch an Intelligenz fehlte, was ich ändern wollte. Als erstes mussten wir den Filter, die Pumpe und ein paar Ventile ersetzen. Ich habe viel Zeit auf einer Website namens "Trouble Free Pool" verbracht und sie war ein Lebensretter für den Heimwerker.

Meine Arbeitskräfte

Wir wurden von einigen Rückschlägen getroffen. Einer davon war, als sie den Zaun installierten und Beton um die Leitungen vom Filtersystem zum Pool gegossen haben.

Unnötig zu erwähnen, dass all dieser Beton und diese Poolleitungen ersetzt werden mussten, damit das Projekt vorankommen konnte. So ziemlich alles musste raus.

Ich hatte schon früh beschlossen, etwas Automatisierung in das neue Poolsystem zu integrieren. Ich habe mich für ein Verwaltungssystem namens Autopilot entschieden. (Meine Familie sagt, ich hätte es gewählt, weil ich Pilot bin und der Name gefiel! ) Dieses System würde es mir ermöglichen, den Pool in einen Salzwasserpool umzuwandeln und einen Teil der Verwaltung zu übernehmen, hauptsächlich den Salzwassergenerator bei Bedarf zu betreiben und Säure zu pumpen, um den pH-Wert zu kontrollieren. Es gab keine andere Automatisierung als diese Dinge.

Irgendwann haben wir alles herausgefunden. Wir haben auch unsere Küche zurückbekommen, die letztendlich meine Werkstatt für das Projekt war.

Fertig:

Automatisierung – Der Anfang

Jetzt, da die physische Anlage installiert und in Betrieb war, dachte ich, es wäre schön, den Pool füllen zu können, ohne ständig den Schlauch herausziehen zu müssen. Ich dachte, mit einem Raspberry Pi und einem normalen Sprinklerventil wäre ich im Geschäft! Ich kaufte einen weiteren Pi (ich benutze ihn überall für verschiedene Projekte) und legte dar, was er tun sollte.

Raspberry Pi3

Anfangs dachte ich, ich muss zwei Dinge können:

Ich begann zu recherchieren und kam auf eine Firma, die ein flüssiges Maßband herstellte, das den Widerstand änderte, wenn der Wasserstand (oder eine andere Flüssigkeit) nach oben oder unten ging. Milone würde sich auch freuen, eine Einheit mit einer bestimmten Größe für mich zu erstellen, da keine ihrer Größen dorthin passt, wo ich sie platzieren wollte.

eTape von Milone

AKTUALISIERUNG :Leider hat mein Milone eTape aus irgendeinem Grund unter Wasser in die eigentliche Jacke gelitten und ist ausgefallen. Nachdem ich das Problem mit Milone besprochen hatte, entschied ich, dass die Kosten für den Ersatz und möglicherweise das gleiche Problem die Kosten für den Ersatz nicht wert waren. Zu allem Überfluss brauche ich eine Sondergröße, die sie speziell für mich anfertigen müssen.

Wasser in der Innenhülle verursachte das Versagen des eTape….

Also brauchte ich eine andere Methode, um meinen Poolpegel zu messen und entschied mich für eine dieser Methoden:

Elecall Edelstahl-Wasserstandssensor-Schwimmerschalter

Da der Unterschied zwischen meinem niedrigen Wasserstand und meinem normalen Wasserstand ungefähr drei Zoll beträgt, funktionierte dies perfekt für mich. Ich musste nur einen Weg finden, es zu montieren und richtig zu machen.

Da ich mehrere andere Leute kenne, die das eTape mit großartigen Ergebnissen verwenden, werde ich alles über das eTape in meinem Projekt belassen und es so ergänzen, wie ich das Dual-Float-Setup gemacht habe. Auf diese Weise können die Leute verschiedene Optionen sehen.

Da er sich auf der anderen Seite des Hofs von meinem Pi befinden sollte, musste er für die Berichterstellung an sein eigenes Gerät angeschlossen werden. Da ich dafür keinen Pi benötigte, wählte ich einen batteriebetriebenen, stromsparenden Arduino-Wireless-Klon, der die Informationen an ein vorhandenes System zurücksendet, das ich bereits im Haus hatte.

Diese Geräte habe ich bei Low Power Labs gekauft. Letztendlich habe ich vier davon in meinem Projekt verwendet:einen für den Wasserstand, einen für die Wassertemperatur und zwei im Hauptsystem, um eine Kombination aus Gehäuseinnentemperatur, Filterdruck und Wasserverbrauch zu überwachen.

Moteino R5-USB mit Flash und RFM69HW 433Mhz Transceiver

Diese Arduino-Klone verbrauchen extrem wenig Strom – nur ~7uA im Tiefschlafmodus, was bedeutet, dass sie mit zwei AA-Batterien sehr, sehr lange halten würden. Mein Wassertemperatursensor schwimmt um meinen Pool herum und mein Niveausensor befindet sich nicht in der Nähe einer Stromquelle, daher musste ich batteriebetriebene drahtlose Geräte verwenden.

Anfangs hatte ich nicht die Absicht, etwas anderes zu tun, als automatisch Wasser in den Pool zu geben, aber da diese Dinge so oft vorkommen, wuchs das Projekt mit einem eigenen Gedanken. Irgendwann könnte ich Folgendes tun:

Den Pool füllen

Egal was die Befüllungsroute des Pools auslöst (manuell oder automatisch), ich musste eine Möglichkeit haben, das Wasser in den Pool zu leiten. Da wir bereits einen Vakuumbrecher zwischen unserer Bewässerung und unserer städtischen Wasserversorgung haben müssen, beschließe ich, ihn in mein vorhandenes Sprinklersystem einzubinden, um Wasser für den Pool zu bekommen. Ich habe im Grunde eine weitere „Zone“ für meine Sprinkleranlage geschaffen, komplett mit Ventil.

Dies stellte insofern ein Problem dar, als dass, wenn meine Sprinkler laufen und ich beschließe, den Pool zu füllen, ich die Rasenzone mit fließendem Wasser berauben würde und der Rasen nicht richtig bewässert würde. Also musste ich einen Weg finden, um festzustellen, ob die Sprinkler liefen. Anfangs habe ich eine „Blackout“-Zeitzone verwendet – d.h. wenn ich wusste, dass meine Sprinkler von 3 Uhr morgens bis 6 Uhr morgens laufen, fülle den Pool in dieser Zeit nicht. Aber das schien ein wenig untechnisch. Bei der Recherche zu meinem Rachio-Sprinklersystem erfuhr ich, dass es eine integrierte API gab, die es mir ermöglichte, den Status des Sprinklersystems programmgesteuert abzufragen. In meinem Fall hatte ich nur eine einfache Frage:Läufst du?

In meinem Fall habe ich nur einen einfachen curl-Befehl verwendet, um das zu bekommen, was ich brauchte:

rachio_url ='curl -s -X GET -H "Content-Type:application/json" -H "Authorization:Bearer xxxx-xxxxx-xx-xxxx-xxxxx-xxx" https:/ /api.rach.io/1/public/device/00xx00x-00xxx000-xxx0x000-00x0x0x0/current_schedule' 

Dies wird von meiner get_sprinkler_status Funktion wie folgt aufgerufen:

output =subprocess.check_output(pooldb.rachio_url, shell=True)if output =="{}":Sprinklers_on ="Nein" 

Meine Hauptanwendung läuft alle 60 Sekunden. Wenn meine Sprinkler laufen, mache ich einfach 60 Sekunden lang nichts und überprüfe es erneut. Irgendwann hören die Sprinkler auf zu laufen und der Pool beginnt sich automatisch zu füllen.

Um den Pool tatsächlich zu füllen, habe ich ein normales 24-V-Wechselstrom-Sprinklerventil verwendet, das ich bei Home Depot gekauft habe. Ich habe dies mit einem Einwegventil direkt in meine Poolleitung installiert, die zu meinem Pool führt. Das Rückschlagventil verhindert, dass der Druck der Pumpe Wasser gegen das Sprinklerventil drückt, wenn die Pumpe in Betrieb ist.

Wasserleitung mit Einwegventil

Da mein Schaltschrank für den Pool 240 V hat und ich keinen Neutralleiter im Schaltschrank habe, musste ich einen Transformator von 240 VAC auf 24 VAC besorgen. Einfach genug. Ich wollte den Transformator jedoch nicht ohne Grund 24×7 betreiben, also habe ich ein Relais verwendet, um 1) den Transformator einzuschalten und dann 2) den 24VAC-Ausgang des Transformators zu nehmen und an das Sprinklerventil anzuschließen.

Relais-Setup

Ich habe die Halbleiterrelais von Sainsmart (sehr kostengünstig) im optisch isolierten Modus verwendet, wo ich einen separaten Stromeingang habe, der die Relais mit Strom versorgt, anstatt die 5 V oder 3,3 V VCC vom Pi zu verwenden. Dies soll bei Störungen durch die Relais helfen.

Sprinklerventil und intelligenter Wasserzähler

Ich habe auch einen intelligenten Zähler hinzugefügt, den ich in Echtzeit ablesen kann, um mir anzuzeigen, dass Wasser fließt und wie viel Wasser ich im Laufe der Zeit verbraucht habe. Diese Informationen werden in einer MySQL-Datenbank gespeichert und historisch gespeichert:

Bildschirm von meinem EmonCMS-System für meinen Hauswasserzähler

Macht, Macht, Macht

Jetzt kam das nächste, was ich herausfinden musste. Während meine Pumpe lief und ich versuchte, den Pool zu füllen, kämpfte ich gegen den Druck der Pumpe. Ich habe durch Messen des Wasserdurchflusses festgestellt, dass ich bei laufender Pumpe etwa 50% meines Füllflusses verloren habe, also dachte ich, dass es am besten wäre, überhaupt nicht zu füllen, während die Pumpe lief. Also brauchte ich eine Möglichkeit, die Leistung meiner Pumpe zu überwachen und herauszufinden, ob sie lief oder nicht.

In diesem Fall hatte ich eine sehr einfache Möglichkeit, dies zu tun. Jeder einzelne Stromkreis in meinem Haus wird von einem elektrischen Überwachungssystem überwacht. Dieses System heißt GEM und wird von Brultech verkauft.


Meine Poolpumpe ist der größte Stromverbraucher in meinem Haus

Mit diesem System kann ich den gesamten Stromverbrauch in meinem Haus und im Rahmen der Überwachung überwachen speichere ich diese Daten in einer MySQL-Datenbank. Also frage ich einmal pro Minute einfach meine MySQL-Datenbank ab und finde heraus, wie viel Watt derzeit von meinem Pool-Panel verwendet werden.

 if pool_pump_running_watts> pooldb.max_wattage:pool_fill_control.led_control(PUMP_RUN_LED, "ON") pool_pump_running ="Ja" logger.debug('PUMP_RUN_LED sollte EIN sein. Dies ist die GELBE LED') if DEBUG :print("PUMP_RUN_LED sollte AN sein. Dies ist die GELBE LED")else:pool_fill_control.led_control(PUMP_RUN_LED, "OFF") pool_pump_running ="Nein" logger.debug('PUMP_RUN_LED sollte AUS sein. Dies ist die GELBE LED') if DEBUG:print("PUMP_RUN_LED sollte AUS sein. Dies ist die GELBE LED")

Ich habe verschiedene Knöpfe, Schalter und LEDs an der physischen Einheit, mit denen ich sehen kann, ob die Sprinkler laufen, die Pumpe läuft, der Pool gefüllt wird oder ob ein Systemfehler vorliegt . Oben sehen Sie, wo ich die Pumpenbetriebs-LED bei Bedarf ein- und ausschalte.

Zusätzlich zu den System-LEDs habe ich eine System-EIN/AUS-Taste (oben links), mit der ich das MightyHat-System verwenden kann, um meinen Pi intelligent neu zu starten oder herunterzufahren, ohne mich am Pi anmelden zu müssen tun Sie es von der CLI aus. Ich habe auch einen Momentschalter (zweiter von links), der es mir ermöglicht, meinen Pool manuell zu füllen, wenn ich möchte, und schließlich habe ich auf der linken Seite einen DPDT-Schalter, der die Stromzufuhr von meinem System zum Sprinklerventil physisch unterbricht und einen GPIO auslöst -Ereignis, um dem System mitzuteilen, dass das Befüllen des Pools manuell deaktiviert wurde. Nichts funktioniert, wenn dieser Schalter ausgelöst wurde, und wenn etwas programmgesteuert ausfallen sollte, kann unabhängig davon kein Strom vom Transformator zum Sprinklerventil gelangen.

Pool-Controller – Extern

Verwaltung der Pumpe

Im Laufe der Zeit habe ich meinem Poolsteuerungssystem ein weiteres Stück hinzugefügt. Die Möglichkeit, meine Pentair-Pumpe mit variabler Drehzahl zu verwalten. Geben Sie Russell Goldin (tageyoureit) und sein Pool-Controller-Softwareprojekt ein. Mit der Software von Russell konnte ich über eine RS485-Schnittstelle direkt mit meiner Poolpumpe kommunizieren. Sobald die Verbindung hergestellt ist, kann ich die Pumpe direkt nach Systeminformationen wie RPM, GPM und verwendeter Watt abfragen:

def get_pump_data(key):verbose_debug("get_pump_data() Started") verbose_debug("get_pump_data() aufgerufen mit '{}' ".format(key)) log("INFO", " get_pump_data() aufgerufen mit '{}' ".format(key)) if pump_control_active:global json try:req =urllib2.Request(pooldb.PUMP_DATA_URL) opener =urllib2.build_opener() f =opener.open(req) data =json.load(f) pump_data =data["pump"]["1"][key] verbose_debug("get_pump_data() zurückgegeben {}".format(pump_data)) log("INFO", "get_pump_data() zurückgegeben { }".format(pump_data)) verbose_debug("get_pump_data() - Completed") log("INFO", "get_pump_data() - Completed") if key =="gpm":pump_gpm =pump_data update_database("pump_status", " pump_gpm", pump_gpm) log("INFO", "Aktuelles GPM:{}".format(pump_gpm)) log("DEBUG", "get_pump_gpm() Abgeschlossen") debug("Aktuelles GPM:{}".format(pump_gpm )) verbose_debug("get_pump_gpm() Completed") elif key =="rpm":pump_rpm =pump_data update_database("pump_status", "pump_rpm", pump_rpm) log("INFO", "Aktuelle Drehzahl:{}".format(pump_rpm)) log("DEBUG", "get_pump_rpm() Completed") debug("Aktuelle Drehzahl:{}".format(pump_rpm)) verbose_debug("get_pump_rpm() Completed") else:pump_watts =pump_data update_database("pump_status", "pump_watts", pump_watts) log("INFO", "Aktuelle WATTS:{}".format(pump_watts)) log("DEBUG", "get_pump_watts() Completed") debug("Aktuelle WATTS :{}".format(pump_watts)) verbose_debug("get_pump_watts() Completed") return pump_data außer Ausnahme als Fehler:pump_data =0 debug("EXCEPTION:get_pump_data()") log("WARN", "EXCEPTION:get_pump_data( )") log("WARN", error) debug(type(error)) debug(error) verbose_debug("get_pump_data() - Abgeschlossen mit AUSNAHME") log("DEBUG", "get_pump_data() - Abgeschlossen mit AUSNAHME") zurück pump_data sonst:pump_data =0 zurück pump_data 

Jetzt kann ich die Pumpe abfragen und meine Pumpe steuern, indem ich eine andere Funktion hinzufüge, die ich vorher nicht hatte. Durch die Änderung meiner Weboberfläche habe ich die Möglichkeit hinzugefügt, meine Pumpe zu starten oder zu stoppen sowie eines von vier verschiedenen Pumpenprogrammen auszuführen, die ich auf meiner Pumpe konfiguriert hatte:

Pumpenbedienfeld

Natürlich sehen wir uns RPM, GPM und Watt in Echtzeit an:

Pumpenanzeigen im Webinterface

Überwachung des Filterdrucks

Ich wollte auch den Filterdruck überwachen, damit ich weiß, wann wir unseren Filter rückspülen müssen. Ich habe einen 100-PSI-Drucksensor bei ebay gekauft und ihn neben meinem analogen Manometer, das sich bereits am Filter befindet, in meinen Filter eingebunden.

Ich habe eine preiswerte Sendereinheit von ebay gekauft (siehe Link oben) und sie wie folgt in meinen Filer eingebunden:

100 PSI Sender UnitPressure Sending UnitVerdrahtung der Sendeeinheit..

Ich habe dies dann in einen Moteino-R5 eingebunden und ich lese den Druck einmal pro Minute und gebe diese Informationen dann an meine MySQL-Datenbank aus und verwende diese Informationen dann für steuere die Messgerätausgabe auf meiner Website.

// Holen Sie sich unseren Filterdruck void get_filter_pressure() { sensorVoltage =analogRead(PSI_SENSOR_PIN); // Lesen wir unsere Drucksensorspannung PSI =((sensorVoltage-146)/204) * 25; // Etwas Kalibrierung, um die Spannung in PSI umzuwandeln und auf Null zu setzen pool_sensors.PSI =PSI; } 

PSI-Anzeige für Poolfilter

Zusätzliche Hardware und Software

Das Hauptsystem ist vollständig in Python geschrieben, aber ich habe andere Software und Hardware verwendet, damit mein System funktioniert.

Auf meinem Raspberry Pi verwende ich einen MightyHat von Low Power Labs, der eine USV-Stromversorgung des Pi, einen LCD-Statusbildschirm und eine intelligente Stromsteuerung für den Pi bietet. Ich kann den Pi ungefähr zwei Stunden lang oder so mit dem kleinen Akku betreiben, den ich an das System angeschlossen habe, und wenn der Strom nicht wiederkehrt, schaltet der MightyHat den Pi automatisch ab, um einen plötzlichen Absturz zu verhindern Stromausfall.

Nahaufnahme von MightyHat auf Pi3 mit Overfill Alert

Der MightyHat ist ein Arduino-Klon, daher habe ich die Arduino-IDE verwendet, um ihn so zu programmieren, dass er die Anforderungen meines Projekts erfüllt.

Für die Sensorik verwende ich verschiedene Sensoren und Methoden, um die Informationen in ein brauchbares Format zu bringen. Für so ziemlich alle Sensordaten verwende ich die kostenlose EmonCMS-Plattform von OpenEnergyMonitor.org. Diese Plattform ermöglicht es mir, alle meine Sensordaten von überall in meinem Haus zu sammeln. Es speichert diese Informationen in einer MySQL-Datenbank, wo ich sie dann zur Verwendung in meinem Pool-Steuerungssystem abrufen kann.

Einige der Sensor-Tracking für meinen PoolZusätzliche Tracking-Informationen

Für den tatsächlichen Füllstand des Pools verwende ich eTape Resistive Liquid Measurement Tape (http://www.milonetech.com):

eTape und Moteino, die alles verspotten

Eines meiner IO-Controller-Boards

IO Controller Board, LED Controller, Power InterfaceIO Controller Board – Zurück

USB-pH- und Redox-Sensorplatinen

Schnittstellenkarten für pH- und ORP-Sensoren von Atlas Scientific

Um genaue pH- und ORP-Messwerte zu erhalten, verwende ich pH- und ORP-Sensoren von Atlas Scientific sowie deren Schnittstellenkarten. Ich habe sie in eine Durchflusszelle eingebaut, die auch überwacht, ob die Pumpe läuft. Ich habe die Durchflusszelle mit standardmäßigen John Guest 3/8″-Schnellanschlüssen in die Leitungen eingebunden, einen auf der Druckseite des Filters und einen auf der Saugseite der Pumpe, damit das Wasser durch die Durchflusszelle fließt.

Fließzelle (ganz links)Fließzelle mit SensorenJohn Guest 3/8″-Schnellanschlüsse mit GewindeRücklaufleitung (Absaugleitung)Ausgangsleitung (Druck) – installiert VOR dem Säureinjektor

Ablesen unseres pH-Werts:

def get_ph_reading():log("DEBUG", "get_ph_reading() Started") pool_pump_running =read_pool_sensor_status_values("pool_sensor_status", "led_status", "pump_run_led" ) if pool_pump_running =="True" :if pooldb.temp_probe =="Yes":pool_temp =float(read_pool_sensor_status_values("pool_sensor_status", "system_status", "pool_current_temp" )) ph_value =float(get_ph.get_current_ph_with_temp(pool_temp)) else:ph_value =float(get_ph.get_tempcurrent ()) debug("Der aktuelle pH-Wert ist:{}".format(ph_value)) influx_data.write_data("pH", ph_value) influx_data.write_data("pool_temp", pool_temp) if pooldb.emoncms_server1 =="Ja":res =request.get("http://" + pooldb.server1 + "/" + pooldb.emoncmspath1 + "/input/post?&node=" + str( pooldb.ph_node) + "&csv=" + ph_value + "&apikey =" + pooldb.apikey1) log("DEBUG", "Aktuellen pH-Wert von {} an Emoncms Server 1 gesendet".format(ph_value)) debug("Aktuellen pH-Wert von {} an Emoncms Server 1 gesendet".format( ph_value)) wenn pooldb.emoncms_server2 =="Ja":res =request.get("https://" + pooldb.server2 + "/" + pooldb.emoncmspath2 + "/input/post?&node=" + str( pooldb.ph_node) + "&csv =" + ph_value + "&apikey=" + pooldb.apikey2) log("DEBUG", "Gesendet aktuellen pH-Wert von {} an Emoncms Server 2".format( ph_value)) debug("Gesendet aktuellen pH-Wert von {} an Emoncms Server 2".format( ph_value)) update_pool_sensor_status_values("pool_sensor_status", "pool_chemicals", "pool_current_ph", ph_value) log("DEBUG", "get_ph_reading() Completed") else:log("INFO", "Pool Pump läuft NICHT, kann keinen genauen pH-Wert erhalten!") debug("Poolpumpe läuft NICHT, kann keinen genauen pH-Wert erhalten!") log("DEBUG", "get_ph_reading() Completed")

Dieser Code ruft das Modul "get_ph.py" auf, das wie folgt aussieht:

#!/usr/bin/python## Zur Verwendung mit pool_control_master.py__author__ ='Richard J. Sears'VERSION ="V3.4 (2018-03-16)"# [email protected ]# Dies ist nur für die Verwendung mit dem pH-Board von Atlas Scientific vorgesehen.import serialimport sysimport timefrom serial import SerialExceptionusbport ='/dev/PH'try:ser =serial.Serial(usbport, 38400, timeout=0)außer serial.SerialException als e:print "Fehler, ", e sys.exit(0)def read_line():lsl =len('\r') line_buffer =[] while True:next_char =ser.read(1) if next_char =='':break line_buffer.append(next_char) if (len(line_buffer)>=lsl und line_buffer[-lsl:] ==list('\r')):break return ''.join(line_buffer)def read_lines():lines =[ ] try:while True:line =read_line() wenn nicht line:break ser.flush_input() lines.append(line) Zeilen außer SerialException zurückgeben als e:print "Error", e return Nonedef send_cmd(cmd):"" " Befehl an Atlas-Sensor senden. Vor dem Senden Carriage Return am Ende des Befehls hinzufügen. :param cmd::return:""" buf =cmd + "\r" # Wagenrücklauf hinzufügen try:ser.write(buf) true zurückgeben außer SerialException als e:print "Error, ", e return Nonedef get_current_ph_with_temp(current_temp):# send_cmd("RESPONSE,0") send_cmd ("C,0") send_cmd("T,%d" % current_temp) send_cmd("R") time.sleep(1.3) lines =read_line() return linesdef get_current_ph_no_temp():# send_cmd("RESPONSE,0") send_cmd("C,0") send_cmd("R") time.sleep(1.3) lines =read_line() return linesdef main():# send_cmd("RESPONSE,0") send_cmd("C,0") send_cmd( "R") time.sleep(1.3) lines =read_lines() print("Keine Temperaturkalibrierung durchgeführt:") for i in range(len(lines)):print lines[i]if __name__ =='__main__':main ()

Das ORP wird auf die gleiche Weise durchgeführt.

In dieser Durchflusszelle ist auch ein Durchflussanzeiger installiert. Fließt Wasser durch die Zelle, hebt sich der Ring und schließt einen Magnetschalter. Die Verkabelung für den Switch ist mit einem GPIO-Pin auf dem Pi verbunden. Hier ist mein Code, um diesen Schalter zu lesen:

def pool_pump_running_chemical():pool_pump_running_chemical =GPIO.input(pool_pump_running_pin) if pool_pump_running_chemical ==False:debug("Pool Pump Running via Chemical Sensor Chamber:TRUE - PUMP IS RUNNING") else:debug( "Poolpumpe läuft über Chemikaliensensorkammer:FALSCH - PUMPE IST AUS")

Wasserstandssensor – So funktioniert's

Wie ich oben gezeigt habe, verwendet der Wasserstandssensor ein batteriebetriebenes MoteinoUBS von LowPowerLab. Dies ist ein perfekter Mikrocontroller für diese Anwendung. Grundsätzlich wecke ich das Moteino alle sechzig Sekunden auf, nehme eine Widerstandsmessung vom eTape, starte meinen Sender und sende diese Informationen an mein EmonCMS-System zur Verwendung durch meine Pool-Skripte. Dann schalte ich alles wieder aus:

{ digitalWrite(ETAPE_POWER, HIGH); // Schalten Sie das eTape ein. pool.resistance =analogRead (ETAPE); // Etape-Widerstand lesen DigitalWrite (ETAPE_POWER, LOW); // Schalten Sie das eTape aus take_battery_reading(); // Batterie lesen power_spi_enable(); rf12_sleep(RF12_WAKEUP); rf12_sendNow(0, &pool, Größe des Pools); rf12_sendWait(2); rf12_sleep (RF12_SLEEP); power_spi_disable(); wenn (debuggen) { flash_led (50); } // Das war's - warte bis zum nächsten Mal :) sleep_until_next_reading(); } 

Ich verfolge auch meine Batteriespannungen, damit ich weiß, wann es Zeit ist, meine Batterien zu wechseln. Das Skript verfügt über mehrere Mechanismen, um sicherzustellen, dass die Batterien gut sind. Erstens verfolge ich aktiv die Batteriespannung selbst und zweitens verfolge ich, wie oft die Sensoren an mich zurückmelden und das Zeitdelta dieser Meldungen. Zu viele verpasste Messwerte und ich weiß, dass mit diesem Sensor etwas nicht stimmt, und ich erhalte eine Pushbullet-Benachrichtigung, um zu sehen, was nicht stimmt. Außerdem geht mein Pool-Füllsystem bei Verlust eines Sensors in den Standby-Modus und weigert sich, den Pool zu füllen, da es nicht weiß, wann es anhalten soll.

Ich verwende 2 x AA-Lithiumbatterien und bisher haben sie über ein Jahr ohne Austausch gelaufen.

Um die Poolebene MoteinoUSB sicher zu halten, brauchte ich eine Art wasserdichtes Gehäuse. Ich habe mich für die wetterfeste Box von Adafruit mit klarem Deckel entschieden.

Adafruit wetterfestes Gehäuse

Als nächstes habe ich eine Adafruit PG-9 Kabelverschraubung verwendet und sehr vorsichtig durch die Seite der Box gebohrt und die Kabelverschraubung installiert.

Adafruit PG-9 Kabelverschraubung

Mit dem wasserdichten Gleichstromkabel von Adafruit habe ich das eTape mit dem MoteinoUSB und dem Gehäuse verbunden.

Adafruit Waterproof DC Power CableCompleted Wasserstandssensorgehäuse

Für ein bisschen mehr Trockenheit habe ich ein Trockenmittel gekauft, das ich in das Gehäuse geben kann, um Feuchtigkeit aufzunehmen, die in das Gehäuse eindringen könnte. Eine Sache, die ich auf die harte Tour gelernt habe (zum Glück sind die Sensoren billig), ist, das Oberteil oder die Kabelverschraubungen NICHT zu fest anzuziehen. Dies erforderte ein wenig Versuch und Irrtum. Am Ende, nachdem ich "glaube", es richtig zu machen, fülle ich tatsächlich mein Waschbecken auf und stelle das Gehäuse unter Wasser und halte es mit einer darauf gestellten Pfanne mit Wasser fest. Ich halte es für ein paar Stunden so und überprüfe es von Zeit zu Zeit, ob ich es richtig habe.

Jetzt musste ich einen Weg und einen Ort finden, um meinen Wasserstandssensor zu montieren. In meinem Pool haben wir ein kleines Zementbecken, in dem früher der Schwimmer untergebracht war, der manuell Wasser in den Pool einfüllte. Dieser ist schon lange verrostet und konnte nicht repariert werden, ohne die Zementummantelung herauszureißen. Damit begann mein Projekt ursprünglich!

Zementbecken

Das Zementbecken ist mit einer kleinen 3/4-Zoll-Linie mit dem Pool verbunden, die es mir ermöglicht, den Wasserstand zu sehen, aber die Kinder, die im Pool planschen oder herumspielen, haben keinen Einfluss auf den Wasserstand das Wasser im Becken. Dies war der perfekte Ort, um den eTape-Sensor zu montieren. Für die eigentliche Montage nahm ich ein Stück PVC-Rohr, schnitt es in zwei Hälften und schleifte es dann so ab, dass es die gleiche Kreisform wie das Zementbecken hatte. Ich habe dann dieses Stück direkt an die Seite des Beckens geklebt. Als das erledigt war, benutzte ich ein paar Trockenbauschrauben und schraubte das eTape an das PVC-Rohr.

eTape-Sensor an PVC-Rohr montiertAbgeschlossene eTape-Sensorinstallation

UPDATE:Neue Methode zum Ablesen des Wasserstands!

Wenn Sie oben gelesen haben, hatte ich einige Probleme mit meiner eTape-Installation, die dazu führten, dass mein eTape nicht mehr funktionierte und fehlerhafte Messwerte anzeigte, wodurch es unbrauchbar wurde. Ich habe mit Chris bei Mileone gesprochen und wir konnten aus einem Grund nicht kommen, warum das Band fehlgeschlagen ist. Am Ende war es mir keine weiteren 80 Dollar wert, ein weiteres Band zu bekommen und das Gleiche noch einmal passieren zu lassen, also wechselte ich die Methoden zum Ablesen meines Wasserstands.

Da ich wirklich nur 3″ Unterschied zwischen meinem Low- und Full-Level habe, habe ich verschiedene Level-Sensoren recherchiert und mich für diesen entschieden:

Elecall Edelstahl-Wasserstandssensor-Schwimmerschalter

Also musste ich eine Möglichkeit finden, den neuen Sensor zu montieren. Ich beschloss, dass ich ein 1/4 "Plexiglas verwenden würde, damit es funktioniert. Ich habe die benötigte Breite gemessen und den Schwimmer mit einer zusätzlichen Stellschraube montiert, damit ich feine Einstellungen vornehmen konnte. Ich habe auch eine kleine Wasserwaage darauf geklebt, damit sie waagerecht ist, wenn ich sie montiert habe:

Um es zu montieren habe ich einfach etwas Epoxid verwendet und es mit meiner "eingebauten Wasserwaage" nivelliert:

Um den Füllstand des Beckens abzulesen, muss ich die Position der beiden Schwimmer kennen. Also habe ich meinen Code so programmiert, dass er die Position beider Schwimmer liest und dann je nach Wasserstand eine 0, 1 oder 2 sendet.

Wenn der obere Schwimmer offen und der untere Schwimmer offen ist (beide Schwimmer nach unten), dann sind wir niedrig und es wird eine „0“ gesendet. Wenn der untere Schwimmer geschlossen ist (oben) und der obere Schwimmer geöffnet ist (unten), sind wir mittendrin und senden eine „1“. Sind beide Schwimmer geschlossen (oben) ist der Pool voll und wir brauchen kein Wasser. So sieht der Code aus:

UPPER_Float =digitalRead(17);LOWER_Float =digitalRead(3); if (UPPER_Float ==LOW) { UPPER_Float_Position ="Geschlossen"; } else { UPPER_Float_Position ="Open"; } if (LOWER_Float ==LOW) { LOWER_Float_Position ="Closed"; } else { LOWER_Float_Position ="Open"; } if ((UPPER_Float ==LOW) &&(LOWER_Float ==LOW)) { pool_level.level =2; // Both closed =Pool is FULL } else if ((UPPER_Float ==HIGH) &&(LOWER_Float ==LOW)) { pool_level.level =1; // Lower closed, Upper open =Pool MIDWAY } else { pool_level.level =0; // Both floats open =Pool LOW add water }

So the value of 0, 1 or 2 is transmitted to EmonCMS and written to my database. Each minute we query that database to see if we need to add water:

get_pool_level_value =read_emoncms_database("data", pooldb.pool_level_table)

and if it is low, we add water:

if get_pool_level_value ==0:get_pool_level ="LOW" pool_fill_valve("OPEN")

And this is the new way we are reading our pool level and managing filling our pool.

Pool Temperature Sensor – Making it work

Following in the footsteps of my eTape sensor, I build the same configuration for my pool temperature sensor. This time however, I added a temp probe inside the enclosure so I could monitor the temperature in the enclosure. It would also let me know what the temperature was just above the surface of the water in the pool. The second temperature sensor was fed through the PG-9 cable gland and into the pool water. I then just tossed the enclosure into the pool and thought I was done. However, my kids had other ideas. They thought it was fun to grab the temperature sensor hanging down from the enclosure and spin it around like a top and throw it at each other. Needless to say the first one didn’t last long.

So I went down to my local pool store and purchased a chlorine floater and installed the enclosure and temp probe into it. We have not had a problem since doing so. Even if they throw it, it won’t bother it at all. Most people leave it alone since they think it is chlorine even though we have a saltwater pool.

Pool temp sensor floaterPool temp sensor floater

Keeping track of our Acid Level

Part of the pool automation system that is not handled by my project is the dispensing of muriatic acid to keep our pH under control. While the Pool Auto Pilot system handles that, we still need to be able to see if we need acid added to the tank. For this I used a $9.00 DFRobot Liquid Level Sensor:

XKC-Y25-T12V Liquid Level Sensor

This particular sensor is weatherproof and works by sensing when there is no longer liquid behind whatever you have it attached to and then sending a signal to the GPIO that you can read. Once you can read it, you can then do your alerting, etc.

I simply connected this to my Pi (it utilizes the 5v rail and one GPIO pin) and then added in a little bit of code to read the state of the sensor:

def acid_level():acid_level_ok =GPIO.input(acid_level_sensor_pin) if acid_level_ok ==True:

I then epoxied the sensor to our acid tank at the level where I wanted to be notified and hooked it all up:

This tank has a pretty thick wall and this sensor worked great. I tested it before affixing it just to make sure.

Web Interface

V3.5.0 Web Interface

Once I had all of this pretty much working like I wanted it, I decided that I needed to have a nice interface so we could track all of the data, manually add water to the pool without having to go to the pool room, stop an automatic fill that may be in progress and check the status of the batteries in our temperature sensor and our level sensor.

The main capabilities of the web interface as of right now are:

I am very thankful to Russell Goldin ([email protected]) for his amazing work on the Pentair RS-485 control software needed for my system to be able to talk to and control my pump. You can check out his github HERE.

With Russ’s software I am able to directly control my Pentair pump without having to spend several thousand dollars on their proprietary hardware!

I spent a lot of time programming everything in python but I did not have an experience building a web interface so I asked around and eventually decided on Flask as the web framework that I would use to build the web interface.

Learning Flask was not as hard as I had thought it was going to be and it integrates very well with the python code that I had already written to control the pool. Flask is a mix of python-like code and html like templates and did everything that I needed it to do:

Upper Control PanelSystem GaugesLower Panel

The control part of the interface is very easy. If I want to start a manual fill, I simply click on the “Manual Fill” button and as long as there is not a system problem, we are not running the sprinklers and we are not already “automatically” filling the pool, the system starts a manual fill of the pool. The “Pool Filling” led will turn blue, than “Manual Fill” button will toggle on and the “Fill Timer” will start a countup. Click the “Manual Fill” button again and the system stops filling and reverts back to normal.

If we are filling the pool automatically and I want to stop that process, I simply click the “Pool Filling” button (led reverts to button to show that you can push it to stop the automatic fill) and the system stops filling and sends me notifications based on the configuration of the system (debug, logging, email, pushbullet, sms).

Flask has the ability to process things prior to showing you the html output:

{% if system_error_led =="True" %}  {% elif system_run_led =="True" %}  {% else %}  {% endif %}

In this example, if there is a system error I show a red led, otherwise if the system is running I show a green led and if I am not running and there is no error, then I show a grey led. This statement is processed before the html is rendered and is a very powerful way to interact with a python driven system.

Historical Graphing

As I continue to extend the system and learn more about what I can do, I wanted to start to watch historical trends in my pool system along with a lot of other home automation stuff I have been playing around with lately. After looking around I choose Grafana and InfluxDB.

Basically I already had my data being recorded utilizing EmonCMS so I just needed to have a quick way to get it into InfluxDB so Grafana could do it’s magic. Basically within the mail pool program whenever I get a pH, ORP or temp reading, I write it to the influxdb:

def get_ph_reading():log("DEBUG", "get_ph_reading() Started") pool_pump_running =read_pool_sensor_status_values("pool_sensor_status", "led_status", "pump_run_led" ) if pool_pump_running =="True":if pooldb.temp_probe =="Yes":pool_temp =float(read_pool_sensor_status_values("pool_sensor_status", "system_status", "pool_current_temp" )) ph_value =float(get_ph.get_current_ph_with_temp(pool_temp)) else:ph_value =float(get_ph.get_current_ph_no_temp()) debug("Current pH is:{}".format(ph_value)) influx_data.write_data("pH", ph_value) influx_data.write_data("pool_temp", pool_temp) if pooldb.emoncms_server1 =="Yes":res =requests.get("http://" + pooldb.server1 + "/" + pooldb.emoncmspath1 + "/input/post?&node=" + str( pooldb.ph_node) + "&csv=" + ph_value + "&apikey=" + pooldb.apikey1) log("DEBUG", "Sent current pH Value of {} to Emoncms Server 1".format(ph_value)) debug("Sent current pH Value of {} to Emoncms Server 1".format(ph_value)) if pooldb.emoncms_server2 =="Yes":res =requests.get("https://" + pooldb.server2 + "/" + pooldb.emoncmspath2 + "/input/post?&node=" + str( pooldb.ph_node) + "&csv=" + ph_value + "&apikey=" + pooldb.apikey2) log("DEBUG", "Sent current pH Value of {} to Emoncms Server 2".format( ph_value)) debug("Sent current pH Value of {} to Emoncms Server 2".format( ph_value)) update_pool_sensor_status_values("pool_sensor_status", "pool_chemicals", "pool_current_ph", ph_value) log("DEBUG", "get_ph_reading() Completed") else:log("INFO", "Pool Pump is NOT running, cannot get accurate pH reading!") debug("Pool pump is NOT running, cannot get accurate pH reading!") log("DEBUG", "get_ph_reading() Completed") 

and from influx_data.py:

import syssys.path.append('../')from influxdb import InfluxDBClientimport pooldbdef write_data(measurement, value):client =InfluxDBClient(pooldb.influx_host, pooldb.influx_port, pooldb.influx_user, pooldb.influx_password, pooldb.influx_dbname) json_body =[ { "measurement":measurement, "fields":{ "value":value } } ] client.write_points(json_body)

From there it is a simple matter of setting up Grafana to look at the InfluxDB and make the graphs:

Notifications

My system relies heavily on notifications. Currently the system can provide notifications via logging to a log file, debug messages to stdout allowing for the running of the main program from the command line with valuable, immediate feedback, pushbullet, email and SMS via Twillio. Because of all they types of notifications as well as areas where there can be notifications, I created a system which allows me to fine tune my notifications very easily via my web interface.

By setting up the code in this manner, I can very easily and quickly adjust my notification settings as well as different categories that I want to have those notifications applied to at that time. In future versions of the code, I am going to create an entire “Notifications” panel that allows me the ability to set specific notification types by category. For example I might want an SMS message about filling events, but email notifications about system errors and pushbullet notifications about my pump. In this manner I am able to tweak all of my notification settings to be exactly how I want then to notify me…both the how and the when!

Current Notification Settings Panel
root scruffy:www # ./pool_control_master.pyStarted is_database_online()MightyHat Serial setup completedSystem Reset Status =No Reset RequestedStarted get_pool_temp()get_pool_temp returned 67.30Fpool_temp in C is 19.61Started is_pool_pump_running()pool_pump_running_watts returned 563 watts in use by pump.PUMP_RUN_LED should be ON. This is the YELLOW LEDCurrent unix datetime stamp is:1521835161Pool LEVEL sensor last updated at:1521835044Pool LEVEL sensor battery voltage is:3.2Pool LEVEL sensor battery percentage is 100Pool TEMP sensor last updated at:1521835131Pool TEMP sensor battery voltage is:3.2Pool TEMP sensor battery percentage is 100Pool FILTER PSI is:21Time dfference between last pool LEVEL sensor reading is:117 seconds.Time dfference between last pool TEMP sensor reading is:30 seconds.Everything appears to be OK with the pool sensors!pool_sensors:Pool Resistance is:724pool_sensors:Pool Level Percentage is:85pooldb:Static critical pool level resistance set at (740).pooldb:Static normal pool level resistance set at (710).Our Pool Level is MIDWAY.Total Gallons:22462Acid Level OKTotal Current Power Utilization:2039 wattsTotal Current Power Import:415 wattsTotal Current Solar Production:1624 wattsCurrent GPM:15Current RPM:2225Starting get_ph_reading().Current pH is:7.043Sent Emoncms Server 1 current PH Value:7.043Sent Emoncms Server 2 current PH Value:7.043Completed get_ph_reading()Starting get_orp_reading().Sent Emoncms Server 1 current ORP Value:669.8Sent Emoncms Server 2 current ORP Value:669.8Completed get_orp_reading()

Running from the cli

Alexa Skill and Interface

One of the last things I wanted to tackle was to integrate my pool control system with Alexa. We have Echo Dots and Echo Shows and I wanted to use the visual Echo Show when I could. So I spent a bunch of time learning how to do Alexa skills and then I used the Python microframework Flask-Ask to program the interconnection between my pool control system and the Alexa Skill.

It was a very interesting learning curve, but now I can query Alexa and get all of our pool stats and we can fill (or stop filling) our pool via voice commands:

Alexa Show Interface with pool, electrical and solar stats

Conclusion

I am running V3.5.0 of my code now which seriously changes the way I am checking sensors, and handling error checking. I have also started breaking out my code into separate python functions instead of a monolithic block of 4,000+ lines of code. I will put it up and include all of the Flask programming as well.

This project has taught me a lot about programming, the Pi and Arduinos.

Pool Control System – InternalPool Control System – External

To view all of the code, please visit my Github site HERE! Thank you for reading about my project.

Source: Pool Fill Control


Herstellungsprozess

  1. Steuerkreise
  2. Rasenregner
  3. Schwimmbad
  4. Geschirrspüler
  5. Billardtisch
  6. Wasserpistole
  7. Damm füllen
  8. Toilette
  9. Antibabypille
  10. Feuerhydrant