Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

Pool Fill Control

Een systeem om het waterpeil, de temperatuur, pH, ORP, filterdruk, elektrisch verbruik en pompwerking. Vult het zwembad indien nodig bij.

Verhaal

Het idee

In de zomer van 2015 hebben mijn zonen en ik ons ​​hele zwembadsysteem opnieuw opgebouwd. Het begon met een probleem met de waterleidingen en kleppen die we hebben geërfd toen we het huis kregen, filterproblemen en een in wezen onbeholpen zwembadbedrijf dat een overblijfsel was van toen we het huis kregen. Toen het er zo uit begon te zien, besloot ik dat het tijd was om iets te doen:

Onze eigen privélagune

Aan de slag

De eerste prioriteit was om het zwembad op te ruimen en vervolgens uit te zoeken hoe het zo te houden. Ik heb altijd van automatisering gehouden en ik dacht dat dit een perfecte plek was om het uit te proberen. Even later zag het zwembad er weer zo uit:

Terug naar normaal

Maar het probleem bleef dat het algehele systeem zowel capaciteit als intelligentie ontbeerde, iets dat ik wilde veranderen. Dus eerst moesten we het filter, de pomp en een aantal kleppen vervangen. Ik bracht veel tijd door op een website met de naam 'Trouble Free Pool' en het was een redding voor de doe-het-zelver.

Mijn beroepsbevolking

We kregen te maken met een paar tegenslagen, waaronder toen ze de omheining installeerden, ze beton goten rond de leidingen die van het filtersysteem naar het zwembad liepen.

Onnodig te zeggen dat al dat beton en die zwembadleidingen moesten worden vervangen om het project vooruit te helpen. Vrijwel alles moest weg.

Al vroeg had ik besloten om wat automatisering in het nieuwe poolsysteem op te nemen. Ik koos voor een beheersysteem genaamd de Autopilot. (Mijn familie zegt dat ik ervoor gekozen heb omdat ik piloot ben en de naam leuk vond! ) Met dit systeem zou ik het zwembad kunnen ombouwen tot een zoutwaterzwembad en een deel van het beheer kunnen uitvoeren, voornamelijk het laten draaien van de zoutwatergenerator wanneer nodig en het pompen van zuur om de pH te regelen. Er was geen andere automatisering dan die dingen.

Uiteindelijk kregen we alles door. We kregen ook onze keuken terug, die uiteindelijk mijn werkplaats voor het project werd.

Alles klaar:

Automatisering – het begin

Nu de fysieke installatie was geïnstalleerd en operationeel was, dacht ik dat het leuk zou zijn om het zwembad te kunnen vullen zonder de slang er steeds uit te hoeven halen. Ik dacht dat ik met een Raspberry Pi en een normale sprinklerklep in zaken zou zijn! Ik kocht een andere Pi (ik gebruik ze overal voor verschillende projecten) en legde uit wat ik wilde dat hij zou doen.

Raspberry Pi3

Aanvankelijk dacht ik dat ik twee dingen moest kunnen:

  • Een manier om het waterniveau te meten
  • Een manier om het zwembad te vullen zodra het water laag was

Ik begon onderzoek te doen en kwam langs een bedrijf dat een vloeibaar meetlint maakte dat van weerstand veranderde als het waterniveau (of een andere vloeistof) omhoog of omlaag ging. Milone zou ook graag een eenheid met een specifiek formaat voor mij maken, omdat geen van hun maten zou passen waar ik het wilde plaatsen.

eTape van Milone

UPDATE :Helaas had mijn Milone eTape om de een of andere reden last van water in de eigenlijke jas en faalde. Na het probleem met Milone te hebben besproken, besloot ik dat de kosten om het te vervangen en mogelijk hetzelfde probleem te hebben, de vervangingskosten niet waard waren. Om het nog erger te maken, heb ik een speciale maat nodig die ze speciaal voor mij moeten maken.

Water in de binnenhoes veroorzaakte de storing van de eTape...

Dus ik had een andere manier nodig om mijn zwembadniveau te meten en besloot een van deze te gebruiken:

Elecall roestvrijstalen tank waterniveausensor vlotterschakelaar

Aangezien het verschil tussen mijn lage waterpeil en mijn normale waterpeil ongeveer 15 cm is, werkte dit perfect voor mij. Ik moest alleen een manier vinden om het te monteren en het correct te laten werken.

Omdat ik verschillende andere mensen ken die de eTape met geweldige resultaten gebruiken, laat ik alles over de eTape in mijn project en voeg ik eraan toe zoals ik de dual float-opstelling heb gedaan. Op deze manier kunnen mensen verschillende opties zien.

Aangezien het aan de andere kant van het erf zou worden geplaatst van waar mijn Pi zou staan, zou het nodig zijn om het op zijn eigen apparaat aan te sluiten voor rapportage. Omdat ik hiervoor geen Pi nodig had, koos ik een batterijgevoede, energiezuinige Arduino draadloze kloon die de informatie terugstuurde naar een bestaand systeem dat ik al in huis had.

Deze apparaten heb ik gekocht bij Low Power Labs. Uiteindelijk heb ik er vier in mijn project gebruikt:één voor het waterniveau, één voor de temperatuur van het water en twee in het hoofdsysteem om een ​​combinatie van interne temperatuur van de behuizing, filterdruk en waterverbruik te bewaken.

Moteino R5-USB met Flash en RFM69HW 433Mhz transceiver

Deze Arduino-klonen gebruiken extreem weinig stroom - slechts ~7uA in diepe slaapmodus, wat betekent dat ze heel, heel lang meegaan op twee AA-batterijen. Mijn watertemperatuursensor zweeft rond mijn zwembad en mijn niveausensor is nergens in de buurt van een stroombron, dus ik moest draadloze apparatuur op batterijen gebruiken.

Aanvankelijk was ik niet van plan iets anders te doen dan automatisch water aan het zwembad toe te voegen, maar zoals zo vaak gaat, groeide het project met een eigen wil. Uiteindelijk zou ik het volgende kunnen doen:

  • Bewaak het waterpeil en voeg indien nodig water toe
  • Bewaak de zwembadtemperatuur
  • Bewaak de filterdruk
  • Houd de pH in de gaten
  • ORP controleren
  • Bewaak het stroomverbruik om te bepalen of de zwembadpomp draait
  • Bewaak mijn sprinklerinstallatie om te zien of de sprinklers werken
  • Laat me weten wanneer het systeem start of water toevoegt (via Pushbullet, e-mail of sms)
  • Laat me weten wanneer het systeem stopt met het toevoegen van water
  • Laat het me weten als het systeem een ​​foutconditie tegenkomt
  • Voeg handmatig water toe via CLI of door op een knop op de behuizing te drukken
  • Zorg voor een schone webinterface om de status van het systeem te zien en laat me starten en stoppen met het vullen van het zwembad via internet.
  • Interactie met mijn zwembadcontrolesysteem via Alexa (informatie krijgen en water starten/stoppen)

Het zwembad vullen

Ongeacht wat het vullen van het zwembad activeert (handmatig of automatisch), ik moest een manier hebben om het water in het zwembad te krijgen. Omdat we al een vacuümonderbreker tussen onze irrigatie en onze stadswatervoorziening moeten hebben, kies ik ervoor om deze in mijn bestaande sprinklersysteem te koppelen om water voor het zwembad te krijgen. Ik was eigenlijk een andere "zone" aan het maken voor mijn sprinklersysteem, compleet met klep.

Dit vormde een probleem in die zin dat als mijn sproeiers werken en ik besluit het zwembad te vullen, ik de graszone met stromend water zou beroven en het gazon niet goed zou besproeien. Dus moest ik een manier bedenken om te bepalen of de sprinklers werkten. Aanvankelijk gebruikte ik een "black-out" tijdzone - d.w.z. als ik wist dat mijn sprinklers van 3 uur 's ochtends tot 6 uur 's ochtends werkten, vul het zwembad dan niet gedurende die tijd. Maar dat leek een beetje niet-technisch. Bij het onderzoeken van mijn Rachio-sprinklersysteem kwam ik erachter dat ze een ingebouwde API hadden waarmee ik programmatisch de status van het sprinklersysteem kon opvragen. In mijn geval had ik een simpele vraag:Ben je aan het hardlopen?

In mijn geval gebruikte ik gewoon een eenvoudig curl-commando om te krijgen wat ik nodig had:

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

Dit wordt door mijn get_sprinkler_status functie als volgt aangeroepen:

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

Mijn hoofdtoepassing wordt elke 60 seconden uitgevoerd, dus als mijn sprinklers aan staan, doe ik gewoon 60 seconden niets en controleer ik het opnieuw. Uiteindelijk stoppen de sproeiers met draaien en begint het zwembad automatisch te vullen.

Om het zwembad daadwerkelijk te vullen, heb ik een normale 24V AC-sprinklerklep gebruikt die ik bij Home Depot heb gekocht. Ik heb dit met een eenrichtingsklep rechtstreeks in mijn zwembadleiding geïnstalleerd die naar mijn zwembad gaat. De eenrichtingsklep voorkomt dat de druk van de pomp water tegen de sprinklerklep duwt wanneer de pomp in bedrijf is.

Waterleiding met eenrichtingsklep

Aangezien het elektrische paneel van mijn zwembad 240 V is en ik geen nulleider in het paneel heb, moest ik een transformator van 240 VAC naar 24 VAC kopen. Simpel genoeg. Ik wilde de transformator echter niet zonder reden 24×7 laten draaien, dus gebruikte ik een relais om 1) de transformator aan te zetten en vervolgens 2) de 24VAC-uitgang van de transformator te nemen en deze aan te sluiten op de sprinklerklep.

Relaisconfiguratie

Ik gebruikte de Sainsmart solid-state relais (zeer goedkoop) in optisch geïsoleerde modus, waarbij ik een aparte voedingsingang heb die de relais van stroom voorziet in plaats van de 5v of 3,3v VCC van de Pi te gebruiken. Dit zou moeten helpen bij interferentie van de relais.

Sprinklerklep en slimme watermeter

Ik heb ook een slimme meter toegevoegd die ik in realtime kan uitlezen om me te laten zien dat er water stroomt en hoeveel water ik in de loop van de tijd heb gebruikt. Deze informatie wordt opgeslagen in een MySQL-database en historisch bewaard:

Scherm van mijn EmonCMS systeem voor mijn huiswatermeter

Kracht, kracht, kracht

Nu kwam het volgende dat ik moest bedenken. Terwijl mijn pomp liep, als ik probeerde het zwembad te vullen, zou ik tegen de druk van de pomp vechten. Ik stelde vast door de waterstroom te meten dat ik ongeveer 50% van mijn vulstroom verloor terwijl de pomp draaide, dus ik dacht dat het het beste zou zijn om niet te vullen terwijl de pomp helemaal in werking was. Dus ik had een manier nodig om het vermogen van mijn pomp te controleren en erachter te komen of deze liep of niet.

In dit geval had ik een heel gemakkelijke manier om dit te doen. Elk circuit in mijn huis wordt bewaakt door een elektrisch bewakingssysteem. Dit systeem wordt de GEM genoemd en wordt verkocht door Brultech.


Mijn zwembadpomp is de grootste stroomverbruiker in mijn huis

Met dit systeem kan ik al het elektrische verbruik in mijn huis bewaken en als onderdeel van de monitoring proces, sla ik deze gegevens op in een MySQL-database. Dus een keer per minuut doorzoek ik eenvoudig mijn MySQL-database en zoek uit hoeveel watt momenteel door mijn poolpaneel wordt gebruikt.

 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 moet AAN zijn. Dit is de GELE LED') indien DEBUG :print("PUMP_RUN_LED moet AAN zijn. Dit is de GELE LED") else:pool_fill_control.led_control(PUMP_RUN_LED, "OFF") pool_pump_running ="Nee" logger.debug('PUMP_RUN_LED moet UIT zijn. Dit is de GELE LED') if DEBUG:print ("PUMP_RUN_LED moet UIT zijn. Dit is de GELE LED")

Ik heb verschillende knoppen, schakelaars en LED's op de fysieke unit waarmee ik kan zien of de sprinklers werken, de pomp draait, het zwembad wordt gevuld of dat er een systeemfout is van een soort . Hierboven kun je zien waar ik de pomp draait-LED in- en uitschakel wanneer dat nodig is.

Naast de systeem-LED's heb ik een systeem AAN/UIT-knop (linksboven) waarmee ik het MightyHat-systeem kan gebruiken om mijn Pi intelligent opnieuw op te starten of af te sluiten zonder dat ik op de Pi hoef in te loggen om doe het vanuit de CLI. Ik heb ook een tijdelijke schakelaar (tweede van links) waarmee ik mijn zwembad handmatig kan vullen wanneer ik wil, en tot slot heb ik aan de linkerkant een DPDT-schakelaar die de stroom van mijn systeem naar de sprinklerklep fysiek onderbreekt en een GPIO activeert gebeurtenis om het systeem te laten weten dat we het vullen van de pool handmatig hebben uitgeschakeld. Niets werkt wanneer deze schakelaar is geactiveerd en als iets programmatisch zou falen, kan er hoe dan ook geen stroom van de transformator naar de sprinklerklep komen.

Zwembadcontroller – Extern

De pomp beheren

In de loop van de tijd heb ik een ander stuk toegevoegd aan mijn zwembadcontrolesysteem. De mogelijkheid om mijn Pentair-pomp met variabele snelheid te beheren. Voer Russell Goldin (tageyoureit) in en zijn softwareproject voor poolcontrollers. Dankzij de software van Russell kon ik rechtstreeks communiceren met mijn zwembadpomp via een RS485-interface. Eenmaal aangesloten, kan ik de pomp rechtstreeks opvragen voor systeeminformatie zoals RPM, GPM en watt in gebruik:

def get_pump_data(key):verbose_debug("get_pump_data() Started") verbose_debug("get_pump_data() aangeroepen met '{}' ".format(key)) log("INFO", " get_pump_data() aangeroepen met '{}' ".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() geretourneerd {}".format(pump_data)) log("INFO", "get_pump_data() geretourneerd { }".format(pump_data)) verbose_debug("get_pump_data() - Voltooid") log("INFO", "get_pump_data() - Voltooid") if key =="gpm":pump_gpm =pump_data update_database("pump_status", " pump_gpm", pump_gpm) log("INFO", "Huidige GPM:{}".format(pump_gpm)) log("DEBUG", "get_pump_gpm() Voltooid") debug("Huidige 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", "Huidige RPM:{}".format(pump_rpm)) log("DEBUG", "get_pump_rpm() Voltooid") debug("Huidige RPM:{}".format(pump_rpm)) verbose_debug("get_pump_rpm() Voltooid") else:pump_watts =pump_data update_database("pump_status", "pump_watts", pump_watts) log("INFO", "Current WATTS:{}".format(pump_watts)) log("DEBUG", "get_pump_watts() Completed") debug("Current WATTS :{}".format(pump_watts)) verbose_debug("get_pump_watts() Completed") retourneer pump_data uitzondering Uitzondering als fout:pump_data =0 debug("UITZONDERING:get_pump_data()") log("WARN", "UITZONDERING:get_pump_data( )") log("WARN", error) debug(type(error)) debug(error) verbose_debug("get_pump_data() - Voltooid met UITZONDERING") log("DEBUG", "get_pump_data() - Voltooid met UITZONDERING") retourpomp_data else:pump_data =0 retourpomp_data 

Nu kan ik de pomp opvragen en mijn pomp besturen door een andere mogelijkheid toe te voegen die ik voorheen niet had. Door mijn webinterface te wijzigen, heb ik de mogelijkheid toegevoegd om mijn pomp te starten of te stoppen en om een ​​van de vier verschillende pompprogramma's uit te voeren die ik op mijn pomp had geconfigureerd:

Pompbedieningspaneel

Natuurlijk kunnen we RPM, GPM en Watts in realtime bekijken:

Pompmeters op webinterface

Filterdruk bewaken

Eén ding dat ik ook wilde doen, was de filterdruk controleren, zodat ik wist wanneer ik ons ​​filter moest terugspoelen. Ik kocht een 100 PSI-druksensor van ebay en bond deze in mijn filter naast mijn analoge manometer die al op het filter zat.

Ik kocht een goedkope verzendeenheid van ebay (zie link hierboven) en bond deze als volgt in mijn filer:

100 PSI ZendeenheidDruk Verzendende eenheidVerzendeenheid Bedrading..

Ik heb dit vervolgens verbonden met een Moteino-R5 en ik lees de druk eenmaal per minuut en voer die informatie vervolgens uit naar mijn MySQL-database en gebruik die informatie vervolgens om stuur de meteroutput op mijn website.

// Haal onze filterdruk op void get_filter_pressure() { sensorVoltage =analogRead(PSI_SENSOR_PIN); // Laten we onze druksensorspanning PSI =((sensorVoltage-146)/204) * 25 lezen; // Enige kalibratie om de spanning om te zetten naar PSI en deze op nul te zetten pool_sensors.PSI =PSI; } 

PSI-meter voor zwembadfilter

Aanvullende hardware en software

Het hoofdsysteem is volledig in Python geschreven, maar ik heb andere software en hardware gebruikt om mijn systeem te laten werken.

Op mijn Raspberry Pi gebruik ik een Low Power Labs MightyHat die UPS-stroomback-up biedt voor de Pi, een LCD-statusscherm en intelligente stroomregeling voor de Pi. Ik kan de Pi ongeveer twee uur laten draaien op de kleine batterij die ik op het systeem heb aangesloten en als de stroom niet op tijd terugkomt, zal de MightyHat de Pi automatisch afsluiten om te voorkomen dat hij crasht als gevolg van een plotselinge stroomstoring.

Close-up van MightyHat op Pi3 met overvulwaarschuwing

De MightyHat is een Arduino-kloon, dus ik heb de Arduino IDE gebruikt om hem te programmeren om aan de behoeften van mijn project te voldoen.

Voor detectie gebruik ik verschillende sensoren en methoden om de informatie in een bruikbaar formaat te krijgen. Voor vrijwel alle sensorgegevens gebruik ik het gratis EmonCMS-platform van OpenEnergyMonitor.org. Met dit platform kan ik al mijn sensorgegevens overal in mijn huis verzamelen. Het slaat deze informatie op in een MySQL-database, waar ik het vervolgens kan gebruiken voor gebruik in mijn poolcontrolesysteem.

Een deel van de sensortracking voor mijn zwembadAanvullende trackinginformatie

Voor het werkelijke niveau van het zwembad gebruik ik eTape Resistive Liquid Measurement tape (http://www.milonetech.com):

eTape en Moteino Alles belachelijk maken

Een van mijn IO-controllerkaarten

IO-controllerkaart, LED-controller, voedingsinterfaceIO-controllerkaart – terug

USB pH- en ORP-sensorkaarten

Atlas Scientific pH- en ORP-sensorinterfacekaarten

Om nauwkeurige pH- en ORP-metingen te krijgen, gebruik ik Atlas Scientific pH- en ORP-sensoren en hun interfacekaarten. Ik heb ze in een stroomcel geïnstalleerd die ook controleert of de pomp draait. Ik bond de stroomcel in de leidingen met behulp van standaard John Guest 3/8″ snelkoppelingen, één aan de drukzijde van het filter en één aan de zuigzijde van de pomp om het water door de stroomcel te laten stromen.

Flow Cell (uiterst links) Flow Cell met sensoren John Guest 3/8 "schroefdraad Quick ConnectsReturn (zuig) LineOutput (druk) Line - geïnstalleerd VOORDAT zuurinjector

Onze pH lezen:

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 =="Ja":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_valueget_current_ph_ph.no ()) debug("Huidige pH is:{}".format(ph_value)) influx_data.write_data("pH", ph_value) influx_data.write_data("pool_temp", pool_temp) if pooldb.emoncms_server1 =="Ja":res =requests.get("http://" + pooldb.server1 + "/" + pooldb.emoncmspath1 + "/input/post?&node=" + str( pooldb.ph_node) + "&csv=" + ph_value + "&apikey =" + pooldb.apikey1) log("DEBUG", "Verstuur huidige pH-waarde van {} naar Emoncms Server 1".format(ph_value)) debug("Verstuur huidige pH-waarde van {} naar Emoncms Server 1".format( ph_value)) als pooldb.emoncms_server2 =="Ja":res =requests.get("https://" + pooldb.server2 + "/" + pooldb.emoncmspath2 + "/input/post?&node=" + str( pooldb.ph_node) + "&csv =" + ph_value + "&apikey=" + pooldb.apikey2) log("DEBUG", "Verzonden huidige pH-waarde van {} naar Emoncms Server 2".format( ph_value)) debug("Verzonden huidige pH-waarde van {} naar 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 NIET actief, kan geen nauwkeurige pH-waarde krijgen!") debug("Zwembadpomp werkt NIET, kan geen nauwkeurige pH-waarde krijgen!") log("DEBUG", "get_ph_reading() Voltooid")

Deze code roept de "get_ph.py"-module aan die er als volgt uitziet:

#!/usr/bin/python## Voor gebruik met pool_control_master.py__author__ ='Richard J. Sears'VERSION ="V3.4 (2018-03-16)"# [email protected ]# Dit is alleen voor gebruik met Atlas Scientific pH-board.import serialimport sysimport timefrom serial import SerialExceptionusbport ='/dev/PH'try:ser =serial.Serial(usbport, 38400, timeout=0)behalve serial.SerialException als e:print "Fout," 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 and line_buffer[-lsl:] ==list('\r')):break return ''.join(line_buffer)def read_lines():lines =[ ] try:while True:line =read_line() if not line:break ser.flush_input() lines.append(line) retourneer regels behalve SerialException als e:print "Error", e return Nonedef send_cmd(cmd):"" " Stuur opdracht naar de Atlas Sensor. Voeg voor het verzenden Carriage Return toe aan het einde van de opdracht. :param cmd::return:""" buf =cmd + "\r" # voeg regelretour toe try:ser.write(buf) return True behalve 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("Geen temperatuurkalibratie uitgevoerd:") for i in range(len(lines)):print lines[i]if __name__ =='__main__':main ()

De ORP wordt op dezelfde manier gedaan.

In deze stroomcel is ook een stroomindicator geïnstalleerd. Als er water door de cel stroomt, gaat de ring omhoog en sluit een magnetische schakelaar. De bedrading voor de schakelaar is verbonden met een GPIO-pin op de pi. Hier is mijn code om die schakelaar te lezen:

def pool_pump_running_chemical():pool_pump_running_chemical =GPIO.input(pool_pump_running_pin) if pool_pump_running_chemical ==False:debug("Zwembadpomp loopt via chemische sensorkamer:TRUE - PUMP IS RUNNING") else:debug( "Zwembadpomp loopt via chemische sensorkamer:FALSE - POMP IS UIT")

Waterniveausensor - Maakt het werk

Zoals ik hierboven heb laten zien, maakt de waterniveausensor gebruik van een MoteinoUBS op batterijen van LowPowerLab. Dit is een perfecte microcontroller voor deze toepassing. Kortom, ik maak de Moteino elke zestig seconden wakker, neem een ​​weerstandsmeting van de eTape, start mijn zender op en stuur deze informatie naar mijn EmonCMS-systeem voor gebruik door mijn poolscripts. Dan zet ik alles weer uit:

{ digitalWrite(ETAPE_POWER, HIGH); // Schakel de stroom in naar eTape pool.resistance =analogRead (ETAPE); // lees etape-weerstand digitalWrite (ETAPE_POWER, LOW); // Schakel de stroom naar eTape take_battery_reading(); // Take Battery Reading power_spi_enable(); rf12_sleep(RF12_WAKEUP); rf12_sendNow(0, &pool, grootte van pool); rf12_sendWacht(2); rf12_sleep(RF12_SLEEP); power_spi_disable(); if (debug){ flash_led(50); } // Dat is het - wacht tot de volgende keer :) sleep_until_next_reading(); } 

Ik houd ook mijn batterijspanningen bij, zodat ik weet wanneer het tijd is om mijn batterijen te vervangen. Het script heeft verschillende mechanismen om ervoor te zorgen dat de batterijen goed zijn. Ten eerste volg ik actief de batterijspanning zelf, en ten tweede houd ik bij hoe vaak de sensoren aan mij rapporteren en de tijddelta van die rapporten. Te veel gemiste metingen en ik weet dat er 'iets' mis is met die sensor en ik krijg een Pushbullet-melding om te gaan kijken wat er mis is. Bovendien, met het verlies van een sensor, gaat mijn zwembadvulsysteem in stand-by en weigert het het zwembad te vullen omdat het niet weet wanneer het moet stoppen.

Ik gebruik 2 x AA-lithiumbatterijen en tot nu toe gaan ze meer dan een jaar mee zonder te worden vervangen.

Om het zwembadniveau MoteinoUSB veilig te houden, had ik een of andere waterdichte behuizing nodig. Ik koos voor de weerbestendige doos van Adafruit met een doorzichtig deksel.

Weerbestendige behuizing van Adafruit

Vervolgens heb ik een Adafruit PG-9 kabelwartel gebruikt en heel voorzichtig door de zijkant van de doos geboord en de kabelwartel geïnstalleerd.

Adafruit PG-9 kabelwartel

Met behulp van de Adafruit waterdichte gelijkstroomkabel heb ik de eTape aangesloten op de MoteinoUSB en behuizing.

Adafruit waterdichte gelijkstroomkabel Complete behuizing van waterniveausensor

Voor een extra beetje droogheid kocht ik een droogmiddel om in de behuizing te plaatsen om te absorberen en vocht dat in de behuizing zou kunnen komen. Een ding om op te letten, dat heb ik op de harde manier geleerd (gelukkig zijn de sensoren niet duur) is om de bovenkant of de kabelwartels NIET te strak vast te draaien. Dit vergde een beetje vallen en opstaan. Uiteindelijk, nadat ik 'denk' dat ik het goed heb, vul ik mijn gootsteen en plaats ik de behuizing onder water en houd ik deze vast met een pan gevuld met water erop. Ik houd het een paar uur zo en controleer zo nu en dan of ik het juist heb.

Nu moest ik een manier en een plaats bedenken om mijn waterniveausensor te monteren. In mijn zwembad hebben we een kleine betonnen bak waarin vroeger de vlotter zat die handmatig water aan het zwembad toevoegde. Dit is lang geleden verroest en kon niet worden gerepareerd zonder de cementomhulling eruit te scheuren. Dit is waar mijn project in eerste instantie mee begon!

Cementbassin

Het cementbassin is verbonden met het zwembad met een kleine 3/4 "lijn waardoor ik het waterniveau kan zien, maar de kinderen die spetteren of rommelen in het zwembad hebben geen invloed op het niveau van het water in het bassin. Dit was de perfecte plek om de eTape-sensor te monteren. Om de eigenlijke montage te doen, nam ik een stuk PVC-buis, sneed het doormidden en schuurde het vervolgens zodat het dezelfde ronde vorm had als het cementbassin. Vervolgens heb ik dit stuk op zijn plaats rechtstreeks op de zijkant van het bassin geëpoxeerd. Toen dat eenmaal was gebeurd, gebruikte ik een paar gipsplaatschroeven en schroefde ik de eTape op de PVC-buis.

eTape-sensor gemonteerd op PVC-buis Voltooide eTape-sensorinstallatie

UPDATE:Nieuwe methode om waterpeil af te lezen!

Als je hierboven hebt gelezen, had ik wat problemen met mijn eTape-installatie waardoor mijn eTape niet meer werkte en foutieve metingen gaf waardoor het onbruikbaar werd. Ik sprak met Chris bij Mileone en we konden niet bedenken waarom de tape faalde. Uiteindelijk was het me niet nog eens $ 80 waard om nog een band te kopen en hetzelfde te laten gebeuren, dus veranderde ik van methode om mijn waterpeil af te lezen.

Omdat ik maar 3″ verschil heb tussen mijn lage en volledige niveaus, heb ik verschillende niveausensoren onderzocht en deze gekozen:

Elecall roestvrijstalen tank waterniveausensor vlotterschakelaar

Dus toen moest ik een manier bedenken om de nieuwe sensor te monteren. Ik besloot dat ik een 1/4 "plexiglas zou gebruiken om het te laten werken. Ik mat de breedte die ik nodig had en monteerde de vlotter met een extra stelschroef zodat ik fijne aanpassingen kon maken. Ik heb er ook een klein niveau op geplakt, dus als ik het zou monteren, zou het waterpas zijn:

Om het te monteren heb ik gewoon wat epoxy gebruikt en het waterpas gemaakt met behulp van mijn "ingebouwde niveau:

Om het niveau van de pool te kunnen lezen, moet ik de positie van beide drijvers weten. Dus programmeerde ik mijn code om de positie van beide drijvers te lezen en vervolgens een 0, 1 of 2 te sturen, afhankelijk van het waterniveau.

Als de bovenste vlotter open is en de onderste vlotter open (beide drijft naar beneden), dan zijn we laag en wordt een "0" verzonden. Als de onderste vlotter gesloten is (omhoog) en de bovenste vlotter open is (omlaag), dan zijn we halverwege en sturen we een “1”. Als beide drijvers dicht (omhoog) zijn, is het zwembad vol en hebben we geen water nodig. Zo ziet de code eruit:

UPPER_Float =digitalRead (17);LOWER_Float =digitalRead (3); if (UPPER_Float ==LAAG) { UPPER_Float_Position ="Gesloten"; } else { UPPER_Float_Position ="Open"; } if (LOWER_Float ==LAAG) { LOWER_Float_Position ="Gesloten"; } else { LOWER_Float_Position ="Open"; } if ((UPPER_Float ==LAAG) &&(LOWER_Float ==LAAG)) { 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:

  • Visually see all sensor data on nice gauges
  • See system status including overall status, pump status, filling status, sprinkler status (we cannot fill while the sprinklers are running) and our Acid level
  • Visually see battery status of pool level and temp sensors (including household temp sensors)
  • See temperature and humidity inside the actual sensor boxes so I can see if I have a potential water leak in my “water proof” boxes.
  • Have the ability to toggle various notifications such as debug, logging, email, pushbullet, and sms messages from the interface
  • Control Pentair Intelliflo pool pump

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


Productieproces

  1. Besturingscircuits
  2. Gazonsproeier
  3. Zwembad
  4. Vaatwasser
  5. Pooltafel
  6. Waterpistool
  7. Vuldam
  8. Toilet
  9. Birth Control Pil
  10. Brandkraan
  11. Water