Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Manufacturing Technology >> Proceso de manufactura

Control de llenado de piscinas

Un sistema para monitorear el nivel del agua, temperatura, pH, ORP, presión del filtro, uso eléctrico y funcionamiento de la bomba. Rellena la piscina cuando sea necesario.

Historia

La idea

Durante el verano de 2015, mis hijos y yo reconstruimos todo nuestro sistema de piscinas. Comenzó con un problema con las líneas de agua y las válvulas que heredamos cuando obtuvimos la casa, problemas con los filtros y una empresa de piscinas básicamente inepta que era un vestigio de cuando obtuvimos la casa. Una vez que comenzó a verse así, decidí que era hora de hacer algo:

Nuestra propia laguna privada

Comenzando

La primera prioridad era limpiar la piscina y luego averiguar cómo mantenerla así. Siempre amé la automatización y pensé que este era un lugar perfecto para probarla. En breve, la piscina se veía así de nuevo:

De vuelta a la normalidad

Pero el problema seguía siendo que el sistema en general carecía de capacidad e inteligencia, algo que quería cambiar. Así que lo primero es lo primero, necesitábamos reemplazar el filtro, la bomba y un montón de válvulas. Pasé mucho tiempo en un sitio web llamado Trouble Free Pool y fue un salvavidas para el aficionado al bricolaje.

Mi fuerza laboral

Tuvimos algunos contratiempos, uno de los cuales fue cuando instalaron la cerca y vertieron concreto alrededor de las líneas que iban desde el sistema de filtrado hasta la piscina.

No hace falta decir que todo ese concreto y esas líneas de la piscina tuvieron que ser reemplazados para que el proyecto avanzara. Casi todo tenía que desaparecer.

Al principio, había decidido incorporar algo de automatización en el nuevo sistema de piscinas. Opté por un sistema de gestión llamado Autopilot. ( ¡Mi familia dice que lo elegí porque soy piloto y me gustó el nombre! ) Este sistema me permitiría convertir la piscina en una piscina de agua salada y manejar parte del manejo, principalmente haciendo funcionar el generador de agua salada cuando fuera necesario y bombeando ácido para controlar el pH. No había otra automatización más allá de esas cosas.

Al final, logramos todo resuelto. También recuperamos nuestra cocina, que terminó siendo mi taller para el proyecto.

Todo listo:

Automatización:el comienzo

Ahora que la planta física estaba instalada y operativa, pensé que sería bueno poder llenar la piscina sin tener que sacar la manguera todo el tiempo. Pensé que con una Raspberry Pi y una válvula de riego normal, ¡estaría en el negocio! Compré otra Pi (las uso por todas partes para varios proyectos) y expuse lo que quería que hiciera.

Raspberry Pi3

Inicialmente pensé que necesitaba poder hacer dos cosas:

Comencé a investigar y encontré una empresa que fabricaba una cinta métrica líquida que cambiaba la resistencia a medida que el nivel del agua (u otro líquido) subía o bajaba. Milone también estaría feliz de crear una unidad de tamaño específico para mí, ya que ninguno de sus tamaños encajaría donde quería colocarlo.

eTape de Milone

ACTUALIZACIÓN :Desafortunadamente, por alguna razón, mi Milone eTape sufrió de agua dentro de la chaqueta real y falló. Después de discutir el problema con Milone, decidí que el costo de reemplazarlo y potencialmente sufrir el mismo problema, no valía la pena el costo de reemplazo. Para empeorar las cosas, necesito un tamaño especial que tienen que hacer específicamente para mí.

El agua en la funda interior causó la falla del eTape….

Entonces necesitaba otra forma de medir el nivel de mi piscina y decidí usar una de estas:

Interruptor de flotador con sensor de nivel de agua de tanque de acero inoxidable Elecall

Dado que la diferencia entre mi nivel de agua bajo y mi nivel de agua normal es de aproximadamente tres pulgadas, esto funcionó perfectamente para mí. Solo necesitaba encontrar una manera de montarlo y hacer que funcione correctamente.

Como conozco a otras personas que utilizan eTape con excelentes resultados, voy a dejar todo sobre eTape en mi proyecto y agregarlo de la misma manera que hice la configuración de flotador dual. De esta forma, las personas pueden ver varias opciones diferentes.

Dado que iba a estar ubicado al otro lado del patio desde donde residiría mi Pi, sería necesario conectarlo a su propio dispositivo para informar. Como no necesitaba un Pi para esto, elijo un clon inalámbrico Arduino de bajo consumo que funciona con baterías y que transmitiría la información a un sistema existente que ya tenía en casa.

Estas unidades las compré en Low Power Labs. Terminé usando cuatro de ellos en mi proyecto:uno para el nivel del agua, uno para la temperatura del agua y dos en el sistema principal para monitorear una combinación de temperatura interna del gabinete, presión del filtro y uso de agua.

Moteino R5-USB con Flash y transceptor RFM69HW 433Mhz

Estos clones de Arduino usan una energía extremadamente baja, solo ~ 7uA en modo de suspensión profunda, lo que significa que durarían mucho, mucho tiempo con dos baterías AA. Mi sensor de temperatura del agua flota alrededor de mi piscina y mi sensor de nivel no está cerca de una fuente de energía, así que tuve que usar un equipo inalámbrico que funciona con baterías.

Inicialmente, no tenía ninguna intención de hacer nada más que agregar agua a la piscina automáticamente, pero como suelen suceder estas cosas, el proyecto creció con una mente propia. Eventualmente podré hacer lo siguiente:

Llenando la piscina

Independientemente de lo que desencadena la ruta de llenado de la piscina (manual o automáticamente), tenía que encontrar una forma de hacer que el agua entrara en la piscina. Dado que ya se nos exige que tengamos un interruptor de vacío entre nuestro sistema de riego y el suministro de agua de la ciudad, elijo conectarlo a mi sistema de rociadores existente para obtener agua para la piscina. Básicamente estaba creando otra "zona" para mi sistema de rociadores, con válvula.

Esto presentaba un problema, ya que si mis aspersores estaban funcionando y decido llenar la piscina, estaría robando cualquier zona del césped que tuviera agua corriente y no regaría el césped correctamente. Así que tuve que idear una forma de determinar si los aspersores estaban funcionando. Inicialmente usé una zona horaria de "apagón", es decir, si sabía que mis rociadores estaban funcionando desde las 3 a. M. Hasta las 6 a. M., No llene la piscina durante ese tiempo. Pero eso parecía un poco poco técnico. Al investigar mi sistema de rociadores Rachio, descubrí que tenían una API incorporada que me permitía consultar programáticamente el estado del sistema de rociadores. En mi caso, solo tenía una pregunta simple:¿estás corriendo?

En mi caso, solo usé un comando curl simple para obtener lo que necesitaba:

 rachio_url ='curl -s -X GET -H "Tipo de contenido:aplicación / json" -H "Autorización:Portador xxxx-xxxxx-xx-xxxx-xxxxx-xxx" https:/ /api.rach.io/1/public/device/00xx00x-00xxx000-xxx0x000-00x0x0x0/current_schedule '

Esto es llamado por mi función get_sprinkler_status como tal:

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

Mi aplicación principal se ejecuta cada 60 segundos, así que si mis aspersores están funcionando, simplemente no hago nada durante otros 60 segundos y vuelvo a verificar. Finalmente, los aspersores dejarán de funcionar y la piscina comenzará a llenarse automáticamente.

Para llenar realmente la piscina, utilicé una válvula de riego normal de 24 V CA que compré en Home Depot. Instalé esto con una válvula unidireccional directamente en la tubería de mi piscina que va a mi piscina. La válvula unidireccional evita que la presión de la bomba empuje el agua contra la válvula del rociador cuando la bomba está en funcionamiento.

Línea de agua con válvula unidireccional

Como el panel eléctrico de mi piscina es de 240V y no tengo neutro en el panel, tuve que conseguir un transformador de 240VAC a 24VAC. Suficientemente simple. Sin embargo, no quería hacer funcionar el transformador 24 × 7 sin ninguna razón, así que usé un relé para 1) encender el transformador y luego 2) tomar la salida de 24 VCA del transformador y conectarla a la válvula del rociador.

Configuración de relés

Usé los relés de estado sólido Sainsmart (muy económicos) en modo ópticamente aislado donde tengo una entrada de energía separada que alimenta los relés en lugar de usar el VCC de 5v o 3.3v del Pi. Se supone que esto ayudará con la interferencia de los relés.

Válvula de rociador y medidor de agua inteligente

También agregué un medidor inteligente que puedo leer en tiempo real para mostrarme que el agua está fluyendo y cuánta agua he estado usando a lo largo del tiempo. Esta información se almacena en una base de datos MySQL y se almacena históricamente:

Pantalla de mi sistema EmonCMS para el medidor de agua de mi casa

Poder, poder, poder

Ahora vino lo siguiente que necesitaba averiguar. Mientras mi bomba estaba funcionando, si intentaba llenar la piscina, estaría luchando contra la presión de la bomba. Al medir el flujo de agua, determiné que perdí aproximadamente el 50% de mi flujo de llenado mientras la bomba estaba funcionando, por lo que pensé que sería mejor no llenar mientras la bomba estaba funcionando. Entonces necesitaba una forma de monitorear la energía de mi bomba y averiguar si estaba funcionando o no.

En este caso, tenía una manera muy fácil de hacer esto. Cada circuito de mi casa es monitoreado por un sistema de monitoreo eléctrico. Este sistema se llama GEM y lo vende Brultech.


La bomba de mi piscina es el principal consumidor de energía en mi casa

Con este sistema puedo monitorear todo el uso eléctrico en mi casa y como parte del monitoreo proceso, guardo estos datos en una base de datos MySQL. Entonces, una vez por minuto, simplemente consulto mi base de datos MySQL y averiguo cuántos vatios está usando actualmente mi panel de piscina.

 if pool_pump_running_watts> pooldb.max_wattage:pool_fill_control.led_control (PUMP_RUN_LED, "ON") pool_pump_running ="Sí" logger.debug ('PUMP_RUN_LED' debe estar ENCENDIDO). :print ("PUMP_RUN_LED debe estar ENCENDIDO. Este es el LED AMARILLO") else:pool_fill_control.led_control (PUMP_RUN_LED, "OFF") pool_pump_running ="No" logger.debug ('PUMP_RUN_LED debe estar APAGADO. Este es el LED AMARILLO') if DEBUG:print ("PUMP_RUN_LED debe estar APAGADO. Este es el LED AMARILLO") 

Tengo varios botones, interruptores y LED en la unidad física que me permiten ver si los aspersores están funcionando, la bomba está funcionando, la piscina se está llenando o si hay algún tipo de error en el sistema. . Arriba puede ver dónde enciendo y apago el LED de funcionamiento de la bomba cuando es necesario.

Además de los LED del sistema, tengo un botón de ENCENDIDO / APAGADO del sistema (arriba a la izquierda) que me permite usar el sistema MightyHat para reiniciar o apagar mi Pi de forma inteligente sin tener que iniciar sesión en el Pi para hágalo desde la CLI. También tengo un interruptor momentáneo (segundo a la izquierda) que me permite llenar manualmente mi piscina cuando quiero, y finalmente en el lado izquierdo tengo un interruptor DPDT que interrumpe físicamente la energía de mi sistema a la válvula del rociador y activa un GPIO evento para decirle al sistema que hemos desactivado manualmente el llenado de la piscina. Nada funciona cuando se ha activado este interruptor y si algo fallara programáticamente, no hay energía que pueda pasar del transformador a la válvula del rociador independientemente.

Controlador de piscina:externo

Manejo de la bomba

Con el tiempo, agregué otra pieza a mi sistema de control de piscina. La capacidad de administrar mi bomba de velocidad variable Pentair. Introduzca Russell Goldin (tageyoureit) y su proyecto de software de controlador de piscina. El software de Russell me permitió comunicarme directamente con la bomba de mi piscina a través de una interfaz RS485. Una vez conectado, puedo consultar la bomba directamente para obtener información del sistema como RPM, GPM y Watts en uso:

 def get_pump_data (key):verbose_debug ("get_pump_data () Started") verbose_debug ("get_pump_data () llamado con '{}'" .format (key)) log ("INFO", " get_pump_data () llamado con '{}' ".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 ["bomba"] ["1"] [clave] verbose_debug ("get_pump_data () devuelto {}". format (pump_data)) log ("INFO", "get_pump_data () devuelto { } ". 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 "," Current GPM:{} ". format (pump_gpm)) log (" DEBUG "," get_pump_gpm () Completed ") debug (" Current 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", "RPM actuales:{} ". format (pump_rpm)) log (" DEBUG "," get_pump_rpm () Completed ") debug (" Current RPM:{} ". format (pump_rpm)) verbose_debug (" get_pump_rpm () Completed ") 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 ( ) ") log (" WARN ", error) debug (type (error)) debug (error) verbose_debug (" get_pump_data () - Completado con EXCEPCIÓN ") log (" DEBUG "," get_pump_data () - Completado con EXCEPTION ") return pump_data else:pump_data =0 return pump_data 

Ahora puedo consultar la bomba y controlarla agregando otra capacidad que no tenía antes. Al modificar mi interfaz web, agregué la capacidad de iniciar o detener mi bomba, así como ejecutar uno de los cuatro programas de bomba diferentes que había configurado en mi bomba:

Panel de control de la bomba

Por supuesto, podemos ver las RPM, GPM y Watts en tiempo real:

Medidores de bombas en la interfaz web

Supervisión de la presión del filtro

Una cosa que también quería hacer era controlar la presión del filtro para saber cuándo hacer retrolavado de nuestro filtro. Compré un sensor de presión de 100 PSI en eBay y lo até a mi filtro junto a mi manómetro analógico que ya estaba en el filtro.

Compré una unidad remitente económica en eBay (ver enlace arriba) y la até a mi archivador de esta manera:

Unidad emisora ​​de 100 PSI Unidad de envío de presión Cableado de la unidad de envío ...

Luego até esto a un Moteino-R5 y leo la presión una vez por minuto y luego envío esa información a mi base de datos MySQL y luego uso esa información para impulsar la salida del medidor en mi sitio web.

 // Obtenga nuestra presión de filtro void get_filter_pressure () {sensorVoltage =analogRead (PSI_SENSOR_PIN); // Leamos el voltaje de nuestro sensor de presión PSI =((sensorVoltage-146) / 204) * 25; // Alguna calibración para convertir el voltaje a PSI y ponerlo a cero pool_sensors.PSI =PSI; } 

Medidor de PSI del filtro de piscina

Hardware y software adicionales

El sistema principal está escrito completamente en Python, pero utilicé otro software y hardware para que mi sistema funcione.

En mi Raspberry Pi, utilizo un MightyHat de Low Power Labs que proporciona respaldo de energía UPS al Pi, una pantalla de estado LCD y control inteligente de energía para el Pi. Puedo hacer funcionar el Pi durante aproximadamente dos horas con la pequeña batería que he conectado al sistema y si la energía no regresa a tiempo, entonces el MightyHat apagará automáticamente el Pi para evitar que se bloquee debido a un repentino corte de energía.

Primer plano de MightyHat en Pi3 mostrando Overfill Alert

El MightyHat es un clon de Arduino, así que utilicé el IDE de Arduino para programarlo para que se ajustara a las necesidades de mi proyecto.

Para la detección, utilizo una variedad de sensores y métodos para obtener la información en un formato utilizable. Para casi todos los datos de los sensores, utilizo la plataforma gratuita EmonCMS de OpenEnergyMonitor.org. Esta plataforma me permite recopilar todos los datos de mis sensores de cualquier lugar de mi casa. Almacena esta información en una base de datos MySQL donde luego puedo obtenerla para utilizarla en mi sistema de control de piscinas.

Parte del seguimiento del sensor para mi piscina Información de seguimiento adicional

Para el nivel real de la piscina, utilizo la cinta métrica de líquidos resistivos eTape (http://www.milonetech.com):

eTape y Moteino Burlándose de todo

Una de mis placas de controlador IO

Tarjeta controladora IO, controlador LED, interfaz de alimentación Tarjeta controladora IO - Parte posterior

Placas de sensores USB de pH y ORP

Placas de interfaz de sensor de pH y ORP de Atlas Scientific

Para obtener lecturas precisas de pH y ORP, utilizo los sensores de pH y ORP de Atlas Scientific, así como sus placas de interfaz. Los instalé en una celda de flujo que también monitorea si la bomba está funcionando. Até la celda de flujo a las líneas usando conexiones rápidas estándar John Guest de 3/8 ″, una en el lado de presión del filtro y otra en el lado de succión de la bomba para mantener el agua fluyendo a través de la celda de flujo.

Celda de flujo (extremo izquierdo) Celda de flujo con sensores John Guest Conexiones rápidas roscadas de 3/8 ″ Línea de retorno (succión) Línea de salida (presión) - instalada ANTES del inyector de ácido

Leyendo nuestro pH:

 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_led ") :if pooldb.temp_probe =="Sí":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_temp) =más ()) debug ("El pH actual es:{}". format (ph_value)) influx_data.write_data ("pH", ph_value) influx_data.write_data ("pool_temp", pool_temp) if pooldb.emoncms_server1 =="Sí":res =request.get ("http://" + pooldb.server1 + "/" + pooldb.emoncmspath1 + "/ input / post? &node =" + str (pooldb.ph_node) + "&csv =" + ph_value + "&apikey ="+ pooldb.apikey1) log (" DEBUG "," Valor de pH actual enviado de {} a Emoncms Server 1 ".format (ph_value)) debug (" Valor de pH actual enviado de {} a Emoncms Server 1 ".format ( ph_value)) si pooldb.emoncms_server2 =="Sí":res =request.get ("https://" + pooldb.server2 + "/" + pooldb.emoncmspath2 + "/ input / post? &Node =" + str (pooldb.ph_node) + "&csv ="+ ph_value +" &apikey ="+ pooldb.apikey2) log (" DEBUG "," Enviado el valor de pH actual de {} a Emoncms Server 2 ".format (ph_value)) debug (" Enviado el valor de pH actual de {} a 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 NO se está ejecutando, no se puede obtener una lectura precisa del pH ") debug (" La bomba de la piscina NO está funcionando, no se puede obtener una lectura precisa del pH ") log (" DEBUG "," get_ph_reading () Completed ") 

Este código llama al módulo "get_ph.py" que se ve así:

 #! / usr / bin / python ## Para usar con pool_control_master.py__author__ ='Richard J. Sears'VERSION ="V3.4 (2018-03-16)" # [email protected ] # Esto es para usar con la placa Atlas Scientific pH solamente. print "Error", 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 y line_buffer [-lsl:] ==list ('\ r')):break return '' .join (line_buffer) def read_lines ():lines =[ ] try:while True:line =read_line () si no es line:break ser.flush_input () lines.append (line) return lines excepto SerialException como e:print "Error,", e return Nonedef send_cmd (cmd):"" "Enviar comando al sensor Atlas. Antes de enviarlo, agregue retorno de carro al final del comando.:Param cmd::return:" "" buf =cmd + "\ r" # agregar retorno de carro intente:ser.write (buf) return True excepto SerialException como 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 ("RESPUESTA, 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 ("Sin calibración de temperatura realizada:") para i en el rango (len (líneas)):imprime líneas [i] si __name__ =='__main__':main () 

El ORP se realiza de la misma manera.

Esta celda de flujo también tiene un indicador de flujo instalado. Si el agua fluye a través de la celda, el anillo se eleva y cierra un interruptor magnético. El cableado para el interruptor está conectado a un pin GPIO en el pi. Aquí está mi código para leer ese interruptor:

 def pool_pump_running_chemical ():pool_pump_running_chemical =GPIO.input (pool_pump_running_pin) if pool_pump_running_chemical ==False:debug ("Bomba de la piscina funcionando a través de la cámara del sensor químico:VERDADERO - LA BOMBA ESTÁ FUNCIONANDO") else:debug ( "Bomba de la piscina funcionando a través de la cámara del sensor de productos químicos:FALSO - LA BOMBA ESTÁ APAGADA") 

Sensor de nivel de agua:cómo funciona

Como mostré arriba, el sensor de nivel de agua utiliza un MoteinoUBS de LowPowerLab que funciona con batería. Este es un microcontrolador perfecto para esta aplicación. Básicamente, despierto el Moteino cada sesenta segundos, tomo una lectura de resistencia del eTape, enciendo mi transmisor y envío esta información a mi sistema EmonCMS para que la utilicen mis scripts de piscina. Luego apago todo de nuevo:

 {digitalWrite (ETAPE_POWER, HIGH); // Encienda el eTape pool.resistance =analogRead (ETAPE); // leer resistencia etape digitalWrite (ETAPE_POWER, LOW); // Apague eTape take_battery_reading (); // Toma la lectura de la batería power_spi_enable (); rf12_sleep (RF12_WAKEUP); rf12_sendNow (0, &grupo, tamaño del grupo); rf12_sendWait (2); rf12_sleep (RF12_SLEEP); power_spi_disable (); if (depurar) {flash_led (50); } // Eso es todo - espere hasta la próxima :) sleep_until_next_reading (); } 

También hago un seguimiento de los voltajes de mis baterías para saber cuándo es el momento de cambiar mis baterías. El guión tiene varios mecanismos para asegurarse de que las baterías estén en buen estado. Primero, realizo un seguimiento activo del voltaje de la batería y, en segundo lugar, hago un seguimiento de la frecuencia con la que los sensores me informan y el tiempo delta de esos informes. A muchas lecturas perdidas y sé que "algo" está mal con ese sensor y recibiré una notificación Pushbullet para ver qué está mal. Además, con la pérdida de un sensor, mi sistema de llenado de piscina entra en modo de espera y se negará a llenar la piscina porque no sabrá cuándo detenerse.

Utilizo 2 pilas de litio AA y hasta ahora han estado funcionando durante más de un año sin ser reemplazadas.

Para mantener seguro el MoteinoUSB a nivel de la piscina, necesitaba un recinto hermético de algún tipo. Elegí la caja resistente a la intemperie Adafruit con tapa transparente.

Estuche resistente a la intemperie de Adafruit

Luego, utilicé un prensaestopas Adafruit PG-9 y con mucho cuidado taladré el costado de la caja e instalé el prensaestopas.

Prensaestopas Adafruit PG-9

Con el cable de alimentación de CC impermeable Adafruit, conecté el eTape al MoteinoUSB y al gabinete.

Cable de alimentación de CC resistente al agua Adafruit Carcasa del sensor de nivel de agua completo

Para un poco más de sequedad, compré desecante para colocar en la carcasa para absorber la humedad que podría entrar en la carcasa. Una cosa a tener en cuenta que aprendí de la manera difícil (afortunadamente, los sensores son económicos) es NO apretar la parte superior o los prensaestopas con demasiada fuerza. Esto requirió un poco de prueba y error. Al final, después de "pensar" que lo he hecho bien, lleno mi fregadero y pongo el recinto bajo el agua y lo sostengo con una cacerola llena de agua colocada encima. Lo mantengo así durante unas horas comprobando de vez en cuando que sea correcto.

Ahora necesitaba encontrar una forma y un lugar para montar mi sensor de nivel de agua. En mi piscina, tenemos una pequeña palangana de cemento que solía albergar el flotador que agregaba agua manualmente a la piscina. Esto hace mucho tiempo que se oxidó y no se pudo reparar sin romper el cerramiento de cemento. ¡Esto es lo que inició inicialmente mi proyecto!

Cuenca de cemento

La cuenca de cemento está conectada a la piscina con una pequeña línea de 3/4 ″ que me permite ver el nivel del agua, pero los niños que chapotean o juegan en la piscina no afectarán el nivel de el agua en la palangana. Este era el lugar perfecto para montar el sensor eTape. Para hacer el montaje real, tomé un trozo de tubería de PVC, lo corté por la mitad y luego lo lijé para que tuviera la misma forma circular que la cubeta de cemento. Luego apliqué esta pieza con epoxi en su lugar directamente al costado del lavabo. Una vez hecho esto, utilicé un par de tornillos para paneles de yeso y atornillé el eTape a la tubería de PVC.

Sensor eTape montado en tubería de PVC Instalación completa del sensor eTape

ACTUALIZACIÓN:¡Nuevo método para leer el nivel del agua!

Si leíste arriba, tuve algunos problemas con la instalación de mi eTape que hicieron que mi eTape dejara de funcionar y arrojara lecturas erróneas que lo inutilizaban. Hablé con Chris en Mileone y no pudimos encontrar una razón por la que la cinta falló. Al final, no valió la pena otros $ 80 para que comprara otra cinta y volviera a suceder lo mismo, así que cambié los métodos de lectura de mi nivel de agua.

Como en realidad solo tengo una diferencia de 3 ″ entre mis niveles bajo y completo, investigué varios sensores de nivel y elegí este:

Interruptor de flotador del sensor de nivel de agua del tanque de acero inoxidable Elecall

Entonces tuve que encontrar una manera de montar el nuevo sensor. Decidí que usaría plexiglás de 1/4 ″ para que funcionara. Medí el ancho que necesitaba y monté el flotador con un tornillo de fijación adicional para poder hacer ajustes finos. También le pegué un nivel pequeño para que cuando lo montara estuviera nivelado:

Para montarlo, solo usé un poco de epoxi y lo nivelé usando mi "nivel incorporado:

Para leer el nivel de la piscina, necesito conocer la posición de ambos flotadores. Así que programé mi código para leer la posición de ambos flotadores y luego enviar un 0, 1 o 2 dependiendo del nivel del agua.

Si el flotador superior está abierto y el flotador inferior está abierto (ambos flotan hacia abajo) entonces estamos bajos y envía un “0”. Si el flotador inferior está cerrado (hacia arriba) y el flotador superior está abierto (hacia abajo) entonces estamos a mitad de camino y enviamos un “1”. Si ambos flotadores están cerrados (arriba) la piscina está llena y no necesitamos agua. Así es como se ve el código:

UPPER_Float =digitalRead(17);LOWER_Float =digitalRead(3); if (UPPER_Float ==LOW) { UPPER_Float_Position ="Closed"; } 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


Proceso de manufactura

  1. Circuitos de control
  2. Aspersor para césped
  3. Piscina
  4. Lavavajillas
  5. Mesa de billar
  6. Pistola de agua
  7. Rellenar la presa
  8. Inodoro
  9. Píldora anticonceptiva
  10. Boca de incendios
  11. Agua