Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Manufacturing Technology >> Processo de manufatura

Controle de enchimento da piscina

Um sistema para monitorar o nível de água, temperatura, pH, ORP, pressão do filtro, uso elétrico e operação da bomba. Reabastece a piscina quando necessário.

História

A ideia

No verão de 2015, meus filhos e eu reconstruímos todo o nosso sistema de piscina. Tudo começou com um problema com as linhas de água e válvulas que herdamos quando adquirimos a casa, problemas de filtro e uma empresa de piscinas basicamente inepta que era um remanescente de quando adquirimos a casa. Assim que começou a ficar assim, decidi que era hora de fazer algo:


Nossa própria lagoa particular

Primeiros passos

A primeira prioridade era limpar a piscina e, em seguida, descobrir como mantê-la assim. Sempre adorei automação e achei que este era o lugar perfeito para experimentá-la. Em breve, a piscina ficou assim novamente:


Voltar ao normal

Mas o problema ainda persistia:o sistema geral carecia de capacidade e inteligência, algo que eu queria mudar. Portanto, primeiro as coisas primeiro, precisamos substituir o filtro, a bomba e um monte de válvulas. Passei muito tempo em um site chamado Trouble Free Pool e foi um salva-vidas para o DIYer.


Minha força de trabalho

Fomos atingidos por alguns contratempos, um dos quais foi quando eles instalaram a cerca e colocaram concreto ao redor das linhas que iam do sistema de filtragem à piscina.

Desnecessário dizer que todo aquele concreto e as linhas de piscina tiveram que ser substituídos para que o projeto pudesse avançar. Quase tudo tinha que ir.

No início, decidi incorporar alguma automação ao novo sistema de piscina. Optei por um sistema de gestão chamado Autopilot. ( Minha família diz que escolhi porque sou piloto e gostei do nome! ) Este sistema me permitiria converter a piscina em uma piscina de água salgada e cuidar de parte do gerenciamento, principalmente executando o gerador de água salgada quando necessário e bombeando ácido para gerenciar o pH. Não havia nenhuma outra automação além dessas coisas.

Eventualmente, resolvemos tudo. Também recuperamos nossa cozinha que acabou sendo minha oficina para o projeto.

Tudo pronto:

Automação - o começo

Agora que a planta física estava instalada e operacional, achei que seria bom poder encher a piscina sem ter que tirar a mangueira o tempo todo. Achei que com um Raspberry Pi e uma válvula de sprinkler normal, eu estaria no negócio! Eu comprei outro Pi (eu os uso em todo lugar para vários projetos) e expus o que eu queria fazer.


Raspberry Pi3

Inicialmente, achei que precisava ser capaz de fazer duas coisas:

Comecei a fazer pesquisas e surgiu uma empresa que fabricava uma fita métrica para líquidos que mudava de resistência conforme o nível da água (ou outro líquido) subia ou descia. Milone ficaria feliz em criar uma unidade de tamanho específico para mim, já que nenhum de seus tamanhos caberia onde eu queria colocá-la.


eTape de Milone

ATUALIZAÇÃO :Infelizmente, por algum motivo, meu Milone eTape sofreu com a entrada de água na jaqueta real e falhou. Depois de discutir o problema com Milone, decidi que o custo para substituí-lo e, potencialmente, sofrer o mesmo problema, não compensava o custo da substituição. Para piorar as coisas, preciso de um tamanho especial que eles têm que fazer especificamente para mim.


Água na manga interna causou a falha do eTape ...

Então, eu precisava de outra maneira de medir o nível da minha piscina e decidi usar uma destas:


Interruptor flutuante do sensor de nível de água do tanque de aço inoxidável Elecall

Como a diferença entre meu nível de água baixo e meu nível de água normal é de cerca de sete centímetros, funcionou perfeitamente para mim. Eu só precisava descobrir uma maneira de montá-lo e fazê-lo funcionar corretamente.

Como conheço várias outras pessoas que usam o eTape com ótimos resultados, vou deixar tudo sobre o eTape em meu projeto e adicionar a ele a forma como fiz a configuração do dual float. Desta forma, as pessoas podem ver várias opções diferentes.

Como ele estaria localizado do outro lado do pátio de onde meu Pi residiria, seria necessário conectá-lo a seu próprio dispositivo para relatórios. Como eu não precisava de um Pi para isso, escolhi um clone sem fio do Arduino operado por bateria e de baixa potência que transmitiria as informações de volta para um sistema existente que eu já tinha instalado em casa.

Essas unidades eu comprei no Low Power Labs. Acabei usando quatro deles em meu projeto:um para o nível da água, um para a temperatura da água e dois no sistema principal para monitorar uma combinação de temperatura interna do invólucro, pressão do filtro e uso de água.


Moteino R5-USB com Flash e transceptor RFM69HW 433Mhz

Esses clones do Arduino usam energia extremamente baixa - apenas ~ 7uA em modo de hibernação profunda, o que significa que durariam muito, muito tempo com duas baterias AA. Meu sensor de temperatura da água flutua ao redor da piscina e meu sensor de nível não está nem perto de uma fonte de energia, então tive que usar um equipamento sem fio alimentado por bateria.

Inicialmente, eu não tinha intenção de fazer nada além de adicionar água à piscina automaticamente, mas como essas coisas geralmente acontecem, o projeto cresceu com vontade própria. Eventualmente, eu seria capaz de fazer o seguinte:

Encher a piscina

Independentemente do que aciona o roteamento de enchimento da piscina (manual ou automaticamente), eu precisava encontrar uma maneira de colocar a água na piscina. Como já precisamos ter um disjuntor a vácuo entre nossa irrigação e o abastecimento de água da cidade, opto por ligá-lo ao meu sistema de irrigação existente para obter água para a piscina. Eu estava basicamente criando outra “zona” para meu sistema de sprinklers, completa com válvula.

Isso apresentou um problema:se meus sprinklers estiverem funcionando e eu decidir encher a piscina, eu estaria roubando qualquer área do gramado que tivesse água corrente e ela não regaria o gramado corretamente. Então, tive que descobrir uma maneira de determinar se os sprinklers estavam funcionando. Inicialmente, usei um fuso horário de "blackout" - ou seja, se eu sabia que meus sprinklers estavam funcionando das 3h às 6h, não encha a piscina durante esse tempo. Mas isso parecia um pouco não técnico. Ao pesquisar meu sistema de sprinklers Rachio, descobri que eles tinham uma API integrada que me permitiria consultar programaticamente o status do sistema de sprinklers. No meu caso, eu só tinha uma pergunta simples:você está correndo?

No meu caso, usei apenas um comando curl simples para obter o que precisava:

 rachio_url ='curl -s -X GET -H "Tipo de conteúdo:aplicativo / json" -H "Autorização:Portador xxxx-xxxxx-xx-xxxx-xxxxx-xxx" https:/ /api.rach.io/1/public/device/00xx00x-00xxx000-xxx0x000-00x0x0x0/current_schedule '

Isso é chamado pela minha função get_sprinkler_status assim:

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

Meu aplicativo principal é executado a cada 60 segundos, então, se meus sprinklers estiverem funcionando, simplesmente não faço nada por mais 60 segundos e verifico novamente. Eventualmente, os aspersores irão parar de funcionar e a piscina começará a encher automaticamente.

Para realmente encher a piscina, usei uma válvula de sprinkler 24 V CA normal que comprei na Home Depot. Instalei isso com uma válvula unidirecional diretamente na tubulação da minha piscina. A válvula unidirecional evita que a pressão da bomba empurre a água contra a válvula do sprinkler quando a bomba estiver em operação.


Linha de água com válvula unidirecional

Como o painel elétrico da minha piscina é de 240 V e não tenho neutro no painel, tive que obter um transformador de 240 VCA a 24 VCA. Simples o suficiente. No entanto, eu não queria operar o transformador 24 × 7 sem motivo, então usei um relé para 1) ligar o transformador e, em seguida, 2) pegar a saída 24 VCA do transformador e conectá-la à válvula do sprinkler.


Configuração do relé

Usei os relés de estado sólido Sainsmart (muito baratos) no modo opticamente isolado, onde tenho uma entrada de alimentação separada alimentando os relés, em vez de usar 5v ou 3,3v VCC do Pi. Supõe-se que isso ajude com a interferência dos relés.


Válvula de aspersão e medidor inteligente de água

Também adicionei um medidor inteligente que posso ler em tempo real para me mostrar que a água está fluindo e quanta água estou usando ao longo do tempo. Essas informações são armazenadas em um banco de dados MySQL e armazenadas historicamente:
Tela do meu sistema EmonCMS para o medidor de água de minha casa

Potência, potência, potência

Agora veio a próxima coisa que eu precisava descobrir. Enquanto minha bomba estava funcionando, se eu estivesse tentando encher a piscina, estaria lutando contra a pressão da bomba. Determinei medindo o fluxo de água que perdi cerca de 50% do meu fluxo de enchimento enquanto a bomba estava funcionando, então achei que seria melhor não encher enquanto a bomba estava funcionando. Então, eu precisava de uma maneira de monitorar a energia da minha bomba e descobrir se ela estava funcionando ou não.

Nesse caso, eu tinha uma maneira muito fácil de fazer isso. Cada circuito da minha casa é monitorado por um sistema de monitoramento elétrico. Este sistema é denominado GEM e é comercializado pela Brultech.


Minha bomba de piscina é o maior consumidor de energia em minha casa

Com este sistema, posso monitorar todo o uso de eletricidade em minha casa e como parte do monitoramento processo, eu armazeno esses dados em um banco de dados MySQL. Então, uma vez por minuto, eu simplesmente consulto meu banco de dados MySQL e descubro quantos watts estão em uso no meu painel de pool.

 if pool_pump_running_watts> pooldb.max_wattage:pool_fill_control.led_control (PUMP_RUN_LED, "ON") pool_pump_running ="Yes" logger.debug ('PUMP_RUN_LED deve estar ON. Este é o LED DELED') se este é o LED DEUG. :print ("PUMP_RUN_LED deve estar LIGADO. Este é o LED AMARELO") else:pool_fill_control.led_control (PUMP_RUN_LED, "OFF") pool_pump_running ="Não" logger.debug ('PUMP_RUN_LED deve estar DESLIGADO. Este é o LED AMARELO') if DEBUG:print ("PUMP_RUN_LED deve estar OFF. Este é o LED AMARELO") 

Tenho vários botões, interruptores e LEDs na unidade física que me permitem ver se os sprinklers estão funcionando, a bomba está funcionando, a piscina está enchendo ou se há algum tipo de erro no sistema . Acima você pode ver onde eu ligo e desligo o LED da bomba funcionando quando necessário.

Além dos LEDs do sistema, tenho um botão ON / OFF do sistema (canto superior esquerdo) que me permite usar o sistema MightyHat para reiniciar ou desligar meu Pi de forma inteligente, sem ter que fazer login no Pi para faça-o a partir do CLI. Eu também tenho um interruptor momentâneo (o segundo à esquerda) que me permite encher manualmente minha piscina quando eu quiser e, finalmente, no lado esquerdo, tenho um interruptor DPDT que interrompe fisicamente a energia do meu sistema para a válvula de sprinkler e aciona um GPIO para informar ao sistema que desativamos manualmente o preenchimento da piscina. Nada funciona quando essa chave é acionada e se algo falha programaticamente, nenhuma energia pode passar do transformador para a válvula do sprinkler independentemente.


Controlador de piscina - externo

Gerenciando a bomba

Com o tempo, adicionei outra peça ao meu sistema de controle da piscina. A capacidade de gerenciar minha bomba de velocidade variável Pentair. Digite Russell Goldin (tageyoureit) e seu projeto de software de controlador de pool. O software de Russell permitiu que eu me comunicasse diretamente com minha bomba de piscina por meio de uma interface RS485. Uma vez conectado, posso consultar a bomba diretamente para obter informações do sistema, como RPM, GPM e Watts em uso:

 def get_pump_data (key):verbose_debug ("get_pump_data () Started") verbose_debug ("get_pump_data () chamado com '{}'" .format (key)) log ("INFO", " get_pump_data () chamado com '{}' ".format (chave)) 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"] [chave] verbose_debug ("get_pump_data () retornou {}". format (pump_data)) log ("INFO", "get_pump_data () retornou { } ". 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 "," GPM atual:{} ". format (pump_gpm)) log (" DEBUG "," get_pump_gpm () Completed ") debug (" GPM atual:{} ". format (pump_gpm )) verbose_debug ("get_pump_gpm () Completed") chave elif =="rpm":pump_rpm =pump_data update_database ("pump_status", "pump_rpm", pump_rpm) log ("INFO", "RPM atual:{} ". format (pump_rpm)) log (" DEBUG "," get_pump_rpm () Completed ") debug (" RPM atual:{} ". 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 :{} ". format (pump_watts)) verbose_debug (" get_pump_watts () Completed ") return pump_data exceto Exceção como erro:pump_data =0 debug (" EXCEÇÃO:get_pump_data () ") log (" WARN "," EXCEÇÃO:get_pump_data ( ) ") log (" WARN ", erro) debug (tipo (erro)) debug (erro) verbose_debug (" get_pump_data () - Concluído com EXCEÇÃO ") log (" DEBUG "," get_pump_data () - Concluído com EXCEÇÃO ") return pump_data else:pump_data =0 return pump_data 

Agora posso consultar a bomba e controlar minha bomba adicionando outro recurso que eu não tinha antes. Ao alterar minha interface da web, adicionei a capacidade de iniciar ou parar minha bomba, bem como executar um dos quatro programas de bomba diferentes que configurei em minha bomba:


Painel de controle da bomba

Claro, veremos RPM, GPM e Watts em tempo real:


Medidores de bomba na interface da web

Monitorando a pressão do filtro

Uma coisa que eu também queria fazer era monitorar a pressão do filtro para saber quando retroceder nosso filtro. Eu comprei um sensor de pressão de 100 PSI no ebay e o amarrei no meu filtro ao lado do meu medidor de pressão analógico já no filtro.

Eu comprei uma unidade remetente barata no ebay (veja o link acima) e amarrei em meu arquivador assim:


100 PSI Sender unitPressure Sending unitSending Unit Wiring ..

Em seguida, amarrei isso em um Moteino-R5 e li a pressão uma vez por minuto e, em seguida, enviar essa informação para meu banco de dados MySQL e usar essa informação para direcionar a saída do medidor em meu site.

 // Obtenha nossa pressão de filtro void get_filter_pressure () {sensorVoltage =analogRead (PSI_SENSOR_PIN); // Vamos ler a tensão do nosso sensor de pressão PSI =((sensorVoltage-146) / 204) * 25; // Alguma calibração para converter a tensão em PSI e zerá-la pool_sensors.PSI =PSI; } 

Medidor PSI de filtro de piscina

Hardware e software adicionais

O sistema principal foi escrito inteiramente em Python, mas usei outro software e hardware para fazer meu sistema funcionar.

No meu Raspberry Pi, utilizo um Low Power Labs MightyHat que fornece backup de energia do UPS para o Pi, uma tela de status LCD e controle inteligente de energia para o Pi. Posso executar o Pi por cerca de duas horas ou mais com a pequena bateria que coloquei no sistema e se a energia não voltar a tempo, o MightyHat desligará automaticamente o Pi para evitar que ele trave de repente falha de energia.


Close de MightyHat em Pi3 mostrando alerta de transbordamento

O MightyHat é um clone do Arduino, então usei o IDE do Arduino para programá-lo de acordo com as necessidades do meu projeto.

Para detecção, uso uma variedade de sensores e métodos para obter as informações em um formato utilizável. Para praticamente todos os dados do sensor, utilizo a plataforma EmonCMS gratuita OpenEnergyMonitor.org. Essa plataforma me permite coletar todos os dados do meu sensor de todos os lugares da minha casa. Ele armazena essas informações em um banco de dados MySQL, onde posso obtê-las para utilização em meu sistema de controle de pool.


Parte do rastreamento do sensor para minha piscinaInformações de rastreamento adicionais

Para o nível real da piscina, utilizo a fita de medição de líquidos resistiva eTape (http://www.milonetech.com):


eTape e MoteinoMocking Everything Up

Uma das minhas placas controladoras IO



Placa controladora IO, controlador LED, placa controladora Power InterfaceIO - Voltar

Placas de sensor de pH e ORP USB



Placas de interface de sensor de pH e ORP da Atlas Scientific

Para obter leituras precisas de pH e ORP, utilizo sensores de pH e ORP da Atlas Scientific, bem como suas placas de interface. Eu os instalei em uma célula de fluxo que também monitora se a bomba está funcionando. Amarrei a célula de fluxo nas linhas usando conexões rápidas John Guest 3/8 ″ padrão, uma no lado da pressão do filtro e outra no lado da sucção da bomba para manter a água fluindo através da célula de fluxo.


Célula de fluxo (extrema esquerda) Célula de fluxo com sensoresJohn Guest 3/8 ″ Rosca Quick ConnectsReturn (sucção) Linha de saída (pressão) - instalada ANTES do injetor de ácido

Lendo nosso 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 True_running") if pool_pump="pump_run_led") :if pooldb.temp_probe =="Sim":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_temphue else:float_temp) ()) debug ("pH atual é:{}". format (ph_value)) influx_data.write_data ("pH", ph_value) influx_data.write_data ("pool_temp", pool_temp) if pooldb.emoncms_server1 =="Sim":res =request.get ("http://" + pooldb.server1 + "/" + pooldb.emoncmspath1 + "/ input / post? &node =" + str (pooldb.ph_node) + "&csv =" + ph_value + "&apikey ="+ pooldb.apikey1) log (" DEBUG "," Enviado valor de pH atual de {} para Emoncms Server 1 ".format (ph_value)) debug (" Enviado valor de pH atual de {} para Emoncms Server 1 ".format ( ph_value)) if pooldb.emoncms_server2 =="Sim":res =requests.get ("https://" + pooldb.server2 + "/" + pooldb.emoncmspath2 + "/ input / post? &Node =" + str (pooldb.ph_node) + "&csv ="+ ph_value +" &apikey ="+ pooldb.apikey2) log (" DEBUG "," Enviado valor de pH atual de {} para Emoncms Server 2 ".format (ph_value)) debug (" Enviado valor de pH atual de {} para 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 () Concluído ") else:log (" INFO "," Pool NÃO está em execução, não é possível obter uma leitura precisa do pH! ") debug (" A bomba da piscina NÃO está funcionando, não é possível obter uma leitura precisa do pH! ") log (" DEBUG "," get_ph_reading () Completed ") 

Este código chama o módulo “get_ph.py”, que se parece com este:

 #! / usr / bin / python ## Para uso com pool_control_master.py__author__ ='Richard J. Sears'VERSION ="V3.4 (2016/03/2018)" # [email protected ] # Isso deve ser usado apenas com a placa de pH da Atlas Scientific.import serialimport sysimport timefrom serial import SerialExceptionusbport ='/ dev / PH'try:ser =serial.Serial (usbport, 38400, timeout =0) exceto serial.SerialException como e:imprimir "Erro,", e sys.exit (0) def read_line ():lsl =len ('\ r') line_buffer =[] enquanto Verdadeiro:next_char =ser.read (1) se next_char =='':quebrar line_buffer.append (next_char) if (len (line_buffer)> =lsl e line_buffer [-lsl:] ==list ('\ r')):break return '' .join (line_buffer) def read_lines ():lines =[ ] try:while True:line =read_line () se não line:break ser.flush_input () lines.append (line) retornar linhas exceto SerialException como e:print "Error,", e return Nonedef send_cmd (cmd):"" "Envie o comando para o Sensor Atlas. Antes de enviar, adicione Retorno de Carro no final do comando.:Param cmd::return:" "" buf =cmd + "\ r" # adicionar retorno de carro try:ser.write (buf) return True exceto 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 ("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 ("Nenhuma calibração de temperatura realizada:") para i no intervalo (len (linhas)):imprimir linhas [i] if __name__ =='__main__':principal () 

O ORP é feito da mesma maneira.

Esta célula de fluxo também possui um indicador de fluxo instalado. Se a água está fluindo pela célula, o anel sobe e fecha um interruptor magnético. A fiação para o switch é conectada a um pino GPIO no pi. Aqui está meu código para ler essa chave:

 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 ( "Bomba da piscina funcionando através da câmara do sensor químico:FALSE - PUMP IS OFF") 

Sensor de nível de água - Fazendo funcionar

Como mostrei acima, o sensor de nível de água utiliza um MoteinoUBS da LowPowerLab alimentado por bateria. Este é um microcontrolador perfeito para esta aplicação. Basicamente, eu acordo o Moteino a cada sessenta segundos, faço uma leitura de resistência do eTape, ligo meu transmissor e envio essas informações para meu sistema EmonCMS para uso por meus scripts de piscina. Então desligo tudo de novo:

 {digitalWrite (ETAPE_POWER, HIGH); // Ligue a energia para eTape pool.resistance =analogRead (ETAPE); // lê a resistência do etape digitalWrite (ETAPE_POWER, LOW); // Desligue a energia do eTape take_battery_reading (); // Faça a leitura da bateria power_spi_enable (); rf12_sleep (RF12_WAKEUP); rf12_sendNow (0, &pool, sizeof pool); rf12_sendWait (2); rf12_sleep (RF12_SLEEP); power_spi_disable (); if (debug) {flash_led (50); } // É isso - espere até a próxima vez :) sleep_until_next_reading (); } 

Também monito as tensões das baterias para saber quando é a hora de trocá-las. O script possui vários mecanismos para garantir que as baterias estejam boas. Em primeiro lugar, eu monitoro ativamente a própria tensão da bateria e, em segundo lugar, rastreio a frequência com que os sensores reportam de volta para mim e o delta de tempo desses relatórios. Para muitas leituras perdidas e eu sei que 'algo' está errado com esse sensor e vou receber uma notificação Pushbullet para ir ver o que está errado. Além disso, com a perda de um sensor, meu sistema de enchimento de piscina entra em espera e se recusa a encher a piscina, pois não saberá quando parar.

Eu uso 2 pilhas AA de lítio e até agora elas funcionam há mais de um ano sem serem substituídas.

Para manter o nível da piscina MoteinoUSB seguro, eu precisava de algum tipo de invólucro à prova d'água. Escolhi a caixa à prova d'água Adafruit com tampa transparente.


Caixa à prova de intempéries Adafruit

Em seguida, usei um prensa-cabo Adafruit PG-9 e perfurei com muito cuidado a lateral da caixa e instalei o prensa-cabo.


Prensa-cabo Adafruit PG-9

Usando o cabo de alimentação DC à prova d'água Adafruit, conectei o eTape ao MoteinoUSB e ao gabinete.


Cabo de alimentação CC à prova d'água Adafruit Caixa completa do sensor de nível de água

Para um pouco mais de secura, comprei um dessecante para colocar na caixa para absorver a umidade que pode entrar na caixa. Uma coisa a observar que aprendi da maneira mais difícil (felizmente os sensores são baratos) é NÃO apertar a parte superior ou os prensa-cabos com muita força. Isso exigiu um pouco de tentativa e erro. No final, depois de 'pensar' que acertei, eu realmente encho minha pia e coloco o invólucro debaixo d'água e seguro-o com uma panela cheia de água colocada em cima dele. Eu mantenho assim por algumas horas, verificando de vez em quando se está correto.

Agora eu precisava descobrir uma maneira e um lugar para montar meu sensor de nível de água. Na minha piscina, temos uma pequena bacia de cimento que albergava o flutuador que adicionava água manualmente à piscina. Isso há muito enferrujado e não podia ser consertado sem arrancar o invólucro de cimento. Foi isso que inicialmente deu início ao meu projeto!


Bacia de cimento

A bacia de cimento é conectada à piscina por uma pequena linha de 3/4 ″ que me permite ver o nível de água, mas as crianças espirrando ou brincando na piscina não afetarão o nível de a água na bacia. Este foi o lugar perfeito para montar o sensor eTape. Para fazer a montagem propriamente dita, peguei um pedaço de tubo de PVC, cortei ao meio e depois lixei para que ficasse do mesmo formato circular da bacia de cimento. Em seguida, coloquei este pedaço de epóxi diretamente na lateral da bacia. Feito isso, usei alguns parafusos de drywall e aparafusei a fita adesiva ao tubo de PVC.


Sensor eTape montado em tubo de PVC Instalação completa do sensor eTape

ATUALIZAÇÃO:Novo método para ler o nível de água!

Se você leu acima, tive alguns problemas com a instalação da minha eTape que fizeram com que ela parasse de funcionar e fornecesse leituras incorretas, tornando-a inutilizável. Falei com Chris em Mileone e não pudemos comparecer por um motivo pelo qual a fita falhou. No final, não valia a pena mais US $ 80 para eu conseguir outra fita e ter a mesma coisa acontecendo novamente, então mudei os métodos de leitura do meu nível de água.

Como eu realmente só tenho uma diferença de 3 ″ entre meus níveis baixo e total, pesquisei vários sensores de nível e escolhi este:


Interruptor flutuante do sensor de nível de água do tanque de aço inoxidável Elecall

Então, eu tive que descobrir uma maneira de montar o novo sensor. Decidi que usaria um plexiglas de 1/4 ″ para fazer funcionar. Medi a largura de que precisava e montei a bóia com um parafuso de fixação extra para poder fazer ajustes finos. Também colei um pequeno nível nele para que quando o montei ficasse nivelado:










Para montá-lo, usei apenas um pouco de epóxi e nivelei usando meu “nível integrado:

Para ler o nível da piscina, preciso saber a posição de ambos os flutuadores. Então programei meu código para ler a posição de ambos os flutuadores e enviar um 0, 1 ou 2 dependendo do nível da água.

Se o flutuador superior estiver aberto e o flutuador inferior estiver aberto (ambos flutuam para baixo), então estamos baixos e ele envia um “0”. Se o flutuador inferior estiver fechado (para cima) e o flutuador superior estiver aberto (para baixo), então estamos no meio do caminho e enviamos um “1”. Se os dois flutuadores estiverem fechados (para cima) a piscina está cheia e não precisamos de água. Esta é a aparência do código:

 UPPER_Float =digitalRead (17); LOWER_Float =digitalRead (3); if (UPPER_Float ==LOW) {UPPER_Float_Position ="Fechado"; } else {UPPER_Float_Position ="Abrir"; } if (LOWER_Float ==LOW) {LOWER_Float_Position ="Fechado"; } else {LOWER_Float_Position ="Abrir"; } if ((UPPER_Float ==LOW) &&(LOWER_Float ==LOW)) {pool_level.level =2; // Ambos fechados =Pool está FULL} else if ((UPPER_Float ==HIGH) &&(LOWER_Float ==LOW)) {pool_level.level =1; // Inferior fechado, Superior aberto =Pool MIDWAY} else {pool_level.level =0; // Ambos os flutuadores abertos =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

Processo de manufatura

  1. Circuitos de controle
  2. Aspersor de gramado
  3. Piscina
  4. Máquina de lavar louça
  5. Mesa de sinuca
  6. Pistola de água
  7. Preencher Barragem
  8. Vaso sanitário
  9. Pílula anticoncepcional
  10. Hidrante