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

Detector de vazamento de água e controle da válvula

Componentes e suprimentos

Gabinete de alumínio
× 1
Arduino UNO
× 1
Arduino Ethernet Shield 2
× 1
Fonte de alimentação
× 1
Alojamento AC
× 1
Kit de LEDs com resistores
× 1
Relés (1 dual 5v e 1 dual 12v)
× 1
Válvula motorizada
× 1
conectores JST
× 1
Sensor de água
× 1

Sobre este projeto





Visão geral


Durante uma conversa com um amigo, percebi que vazamentos de água são um grande problema. Meu amigo teve que substituir todos os móveis de seu porão, só porque um cano quebrou enquanto ele estava no trabalho.

Este projeto é semelhante ao que publiquei para o concurso Microsoft IoT, mas este é baseado no Arduino, não no Raspberry. Meu ponto de vista é o seguinte:em vez de centralizar muitas responsabilidades em uma grande plataforma (como RasPi, DragonBoard ou um PC), prefiro delegar responsabilidades simples para dispositivos simples (como Arduino e outros). Eles farão o que devem fazer e, como opção, se conectarão pela rede a outros dispositivos (simples ou complexos) para oferecer serviços avançados. Em caso de falha de rede, eles ainda continuam a fazer o que deveriam fazer.

Basicamente, ele monitora vazamentos de água e aciona ações como o fechamento da entrada principal de água, dependendo da falha detectada.

Ele também publica mensagens para um MQTT Broker. A ideia é que o dispositivo tenha que gerenciar a água localmente, mas também esteja envolvido, junto com outros dispositivos, em um sistema maior que gerencia a automação residencial.





Aqui está o que parece:


A entrada principal de água está localizada na parte inferior. O primeiro dispositivo é instalado pelos serviços de abastecimento de água da cidade para controlar a pressão da água. Instalei a peça no topo da imagem. A válvula motorizada (em azul) é instalada em paralelo com uma válvula manual. Neste desenho, a válvula manual é aberta e a válvula motorizada é, portanto, desviada. É útil em caso de queda de energia. No modo normal, a válvula manual deve ser desligada.

Há um motor DC (12v) dentro da válvula e ele gira no sentido horário ou anti-horário dependendo da polaridade. Há um loop de feedback que indica se a válvula está efetivamente ligada ou desligada. Para ligá-lo, basta aplicar uma tensão positiva na conexão superior esquerda.





Aqui está o controlador:


Da esquerda para a direita:o plugue AC, um botão de reset, alguns LEDs para exibir status, conectores (para sensores, para motor), uma interface Ethernet e uma interface USB.
  • LED1 :Vermelho constante =água detectada localmente, Vermelho piscando =água detectada remotamente, Desligado =sem vazamento de água
  • LED 2 :Amarelo constante =incapaz de controlar a válvula motorizada, Amarelo piscando =incapaz de alcançar o corretor MQTT, Desligado =tudo bom
  • LED3 :Azul constante =tudo bem, azul piscando =válvula motorizada fechada Desligado =sistema desligado ou desligado

Aqui está um sensor, localizado onde acho que pode haver vazamento de água:

Aqui está o que está por baixo do capô:





AVISO!


A fonte de alimentação AC / DC que estou usando tem duas saídas:a primeira é 12V DC e é usada para alimentar a válvula motorizada (controlada por dois relés que controlam a rotação do motor) e a segunda é EXATAMENTE 5V DC, para alimentar o Arduino. É por isso que estou alimentando diretamente no circuito de 5 V, não no Vin que requer pelo menos 6 V CC. Assim que o AC / DC estiver conectado, você NUNCA (eu disse NUNCA) conecte nem o conector DC do Arduino nem o cabo USB do Arduino. Se você ainda deseja depurar por USB, configure um cabo caseiro SEM as linhas de força, mantenha apenas as linhas de dados. A propósito, o link entre o invólucro CA e a fonte de alimentação CA / CC é de 110V. Não toque, nunca!

Código

  • Detecção de vazamento de água e controle de válvula motorizada
  • biblioteca MQTT
Detecção de vazamento de água e controle de válvula motorizada Arduino
 #include  #include  #include  #include  #include  #include  #include  / * Aqui está como o HW funcionaTherea são três subsistemas:- a caixa principal:- um Arduino Uno com e escudo Ethernet - um LED vermelho:constante quando a água é detectada localmente piscando quando a água é detectada remotamente, desligado caso contrário - um LED amarelo:estável quando a válvula está fora de serviço, piscando quando o corretor MQTT está inacessível (por qualquer motivo), desligado caso contrário - um LED azul:estável quando a válvula está aberta e o sistema está monitorando vazamentos, piscando quando a válvula foi desligada Este sistema está inativo - um botão de pressão:uma vez pressionado, um autoteste é acionado - um relé duplo para controlar uma válvula motorizada remota - outro relé duplo para detectar os interruptores de limite de abertura / fechamento instalados na válvula remota - um conjunto de água detectores (todos em paralelo) (todos os 3 conectores no painel frontal são conectados em paralelo) A válvula motorizada tem as seguintes conexões:- Amarelo e B lue:DC para alimentar o motor - Preto:entrada dos interruptores de limite (será definido como GND em nosso circuito) - Vermelho =mudará para GND quando a válvula atingir sua posição totalmente fechada (nota:devido ao design interno do interruptor de limite , não há garantia de que a continuidade permanecerá quando a válvula for desligada) - Verde =mudará para GND quando a válvula atingir sua posição totalmente aberta (nota:devido ao design interno da chave fim de curso, não há garantia de continuidade permanecerá uma vez a válvula se desligar) * /// Networkbyte mac [] ={0xDE, 0xAD, 0xBE, 0xCF, 0xFC, 0xEE}; // Endereço MAC do ArduinoIPAddress ip (192, 168, 12, 215); // servidor IPAddress do endereço IP do Arduino (192, 168, 12, 130); // endereço do corretor MQTTEthernetClient ethClient; // Cliente MQTT PubSubClient (ethClient); #define mqttClientPrefix "GLX" // Prefixo para usar qualquer publicação / assinatura MQTT #define mqttClientLocation "BASEMENT" // Segunda parte do identificador de cliente # define mqttClientUID "001" // Última parte do identificador de cliente # define mqttClientStatusTopic "Status" // Tópico a ser usado para publicar o status do dispositivo #define mqttClientFaultTopic "Fault" // Tópico a ser usado para publicar / assinar Faultsconst int mqttInterval =20; // determina com que frequência o sistema reportará ao broker MQTT (ou seja, a cada ms mqttInterval * mainLoopDelay) int mqttIntervalCnt =0; // variável local usada para contagem regressivaint isConnectedToBroker =-1; // 1 quando conectado, -1 =desconhecido, 0 =incapaz de conectar // Pin-outconst int SystemLedPin =A0; // Led azul const int FaultLedPin =A1; // Led amarelo const int AlarmLedPin =A2; // Led vermelho const int WaterDetectorPin =2; // vai para BAIXO quando a água é detectada, caso contrário, puxado para VCCconst int ToggleButtonPin =3; // vai para BAIXO quando alguém pressiona o botão e depois vai para ALTO quando o botão é liberado, caso contrário, puxe para baixo até GNDconst int SdCardPin =4; // Cartão SD na blindagem Ethernet, não usadoconst int ValveClosedPin =5; // vai para BAIXO quando o motor atinge o limite da chave fechada, caso contrário, aumenta para HIGHconst int ValveOpenedPin =6; // vai para BAIXO quando o motor atinge o limite da chave aberta, caso contrário, aumenta para HIGHconst int ValveControl1 =8; // para controlar o primeiro relé que controla o fornecimento de energia da válvula motorizadaconst int ValveControl2 =7; // para controlar o segundo relé que controla a fonte de alimentação da válvula motorizada // Observação, não use D10, D11, D12 e D13, pois esses pinos são reservados para blindagem Ethernet // WaterLeakage (local) int isWaterDetected =0; // status de acordo com a última boa leitura // WaterLeakage (remote) int isWaterDetectedRemotely =0; // status de acordo com as mensagens recebidas de outros dispositivos de monitoramento // Valvula motorizada isValveClosed =-1; // status da válvula motorizada (-1 =desconhecido, 0 =aberto, 1 =fechado)) const int valveTimeOut =15; // em segundos, tempo máximo permitido para abrir ou fechar valveint isConnectedToValve =-1; // 0 quando o sistema não pode controlar a válvula motorizada, 1 =conectado, -1 =desconhecido // RESET manual buttonvolatile boolean isResetRequested =0; // este mudará quando o botão disparar uma interrupção // Logicconst int mainLoopDelay =500; // um atraso fixo dentro do loop principal, em msvoid (* resetFunc) (void) =0; // Inicialização void setup () {wdt_disable (); // sempre bom desabilitá-lo, se ele foi deixado 'ligado' ou você precisa do init time Serial.begin (9600); Serial.println (F ("Início da configuração")); // Configuração de HW pinMode (SystemLedPin, OUTPUT); pinMode (FaultLedPin, OUTPUT); pinMode (AlarmLedPin, OUTPUT); pinMode (WaterDetectorPin, INPUT); pinMode (ToggleButtonPin, INPUT); pinMode (ValveOpenedPin, INPUT); // O relé de 12 Vcc está ocioso por padrão. O pino está conectado ao lado NÃO do relé 1, mas há um pull-up. O pino é portanto ALTO por padrão. pinMode (ValveClosedPin, INPUT); // O relé de 12 Vcc está ocioso por padrão. O pino está conectado ao lado NÃO do relé 2, mas há um pull-up. O pino é portanto ALTO por padrão. pinMode (ValveControl1, OUTPUT); digitalWrite (ValveControl1, HIGH); // O relé 1 de 5 Vcc está ocioso por padrão, ou seja, o motor está conectado ao GND pinMode (ValveControl2, OUTPUT); digitalWrite (ValveControl2, HIGH); // Relé 5 V CC 2 ocioso por padrão, ou seja, o motor está conectado ao GND pinMode (SdCardPin, OUTPUT); digitalWrite (SdCardPin, HIGH); // para desabilitar o cartão SD já que não o usamos // Autoteste testLeds (); // Configuração de rede e MQTT client.setServer (servidor, 1883); client.setCallback (MQTTBrokerCallback); Ethernet.begin (mac, ip); Serial.print (F ("IP atual é:")); Serial.print (Ethernet.localIP ()); Serial.print (F ("- IP do broker MQTT é:")); Serial.println (servidor); // Inicialmente, não sabemos o status da válvula e os interruptores de limite não são tão confiáveis. // Vamos abrir a válvula motorizada e aguardar a conclusão. Na pior das hipóteses, se já estiver aberto, ele apenas atingirá o interruptor de limite brevemente se (openValve () ==0) {Serial.println (F ("A válvula está aberta e o sistema agora está monitorando")); // Existem outros dispositivos de monitoramento na casa, vamos ouvir as falhas que eles podem relatar ao corretor MQTT subscribeToRemoteWaterSensors (); } else {Serial.println (F ("Não foi possível abrir a válvula, o sistema está fora de serviço. Use o bypass do encanamento")); }; enableInterruptOnResetButton (); atraso (1500); // permite que o hardware se auto-classifique Serial.println (F ("Fim da configuração")); } // Main loopvoid loop () {// LEDs configureLedsWithInitialStates (); // Reage à solicitação de reinicialização if (isResetRequested ==1) {Serial.println (F ("Alguém pressionou o botão para reinicializar este dispositivo")); publicarStatus (); wdt_enable (WDTO_1S); // habilita o watchdog, irá disparar em 1 segundo de atraso (5000); Serial.println (F ("esta mensagem nunca deve aparecer")); } // Vamos verificar agora se algum vazamento de água foi detectado readLocalWaterSensor (); if (isWaterDetected ==1 || isWaterDetectedRemotely ==1) {if (isValveClosed ==0) {closeValve ();}; } // Publicar no broker MQTT if (mqttIntervalCnt ==0) {if (isWaterDetected ==1) {publishFault ();} publishStatus (); mqttIntervalCnt =mqttInterval; } else {if (isConnectedToValve ==0) {Serial.println (F ("O sistema está fora de serviço - não é possível controlar a válvula motorizada. Sem monitoramento no local")); } else {Serial.print (F (".")); } mqttIntervalCnt =mqttIntervalCnt - 1; } // Demore um pouco para descansar (mainLoopDelay / 2); client.loop (); // LEDs configureLedsWithFinalStates (); atraso (mainLoopDelay / 2); } //// Gerenciamento do sensor de água local // void readLocalWaterSensor () {isWaterDetected =! GetDebounceValue (WaterDetectorPin, 100, 10); Serial.print (isWaterDetected); } //// Redefinir gerenciamento do botão // void enableInterruptOnResetButton () {isResetRequested =0; attachInterrupt (1, onResetRequested, CHANGE);} void onResetRequested () {detachInterrupt (1); isResetRequested =1; } // Gerenciar a sequência de abertura da válvula openValve () {Serial.print (F ("válvula de abertura ...")); // primeiro, confirme se a válvula foi fechada forçando o motor a bater brevemente no interruptor de limite "fechado" novamente (uma vez que esses interruptores de limite não são tão confiáveis ​​...) setupRelays (1); if (waitForEndOfCycle (ValveClosedPin) ==0) {// agora, vamos tentar abrir a válvula setupRelays (2); if (waitForEndOfCycle (ValveOpenedPin) ==0) {isConnectedToValve =1; isValveClosed =0; setupRelays (0); // relés de energia desligados Serial.println (F ("")); return 0; }} setupRelays (0); // relés de energia desligados isConnectedToValve =0; return -1;} // Gerencia a sequência de fechamento da válvulaint closeValve () {Serial.print (F ("Closing valve ...")); // primeiro, confirme se a válvula foi aberta forçando o motor a bater brevemente no interruptor de limite "aberto" novamente (uma vez que esses interruptores de limite não são tão confiáveis ​​...) setupRelays (2); if (waitForEndOfCycle (ValveOpenedPin) ==0) {// agora, vamos tentar fechar a válvula setupRelays (1); if (waitForEndOfCycle (ValveClosedPin) ==0) {isConnectedToValve =1; isValveClosed =1; setupRelays (0); // relés de energia DESLIGADOS Serial.println (F ("A válvula foi desligada. Por favor, inspecione cuidadosamente todos os quartos e detectores de limpeza")); return 0; }} setupRelays (0); // relés de energia desligados isConnectedToValve =0; return -1;} // Configure os relés a fim de alimentar o motor com a polaridade correta para evitar setupRelays (cenário interno) {switch (cenário) {case 0:// todos OFF, sem energia enviada para a válvula motorizada digitalWrite (ValveControl1, HIGH ); digitalWrite (ValveControl2, HIGH); pausa; caso 1:// ciclo de fechamento digitalWrite (ValveControl1, HIGH); digitalWrite (ValveControl2, LOW); pausa; caso 2:// ciclo de abertura digitalWrite (ValveControl1, LOW); digitalWrite (ValveControl2, HIGH); pausa; padrão:Serial.print (F ("Cenário de retransmissão inesperado:")); Serial.println (cenário); digitalWrite (ValveControl1, HIGH); digitalWrite (ValveControl2, HIGH); pausa; }} // Espere até que a chave fim de curso seja atingida pelo motor da válvula motorizada int waitForEndOfCycle (int limitSwitchPin) {int cnt =valveTimeOut; while (cnt> 0) {if (getDebounceValue (limitSwitchPin, 10, 10) ==LOW) {return 0; } cnt =cnt - 1; Serial.print (F (".")); atraso (1000); }; Serial.println (F ("- tempo limite atingido ao fechar a válvula. Verifique se a válvula está bem alimentada e se os cabos estão conectados.")); return -1;} // Esta rotina ajuda a evitar falsos alarmesint getDebounceValue (int inputPin, int intervalInMs, int requiredConfirmations) {int confirmations =1; int currentValue =digitalRead (inputPin); enquanto (confirmações <=necessáriasConfirmações) {atraso (intervaloInMs); if (currentValue ==digitalRead (inputPin)) {confirmações =confirmações + 1; } mais {confirmações =1; currentValue =digitalRead (inputPin); }} return currentValue;} //// Gerenciamento de LEDs // void configureLedsWithInitialStates () {clearLeds (); // Reavaliar if (isWaterDetectedRemotely ==1 || isWaterDetected ==1) {digitalWrite (AlarmLedPin, HIGH);}; if (isConnectedToValve ==0 || isConnectedToBroker ==0) {digitalWrite (FaultLedPin, HIGH);}; digitalWrite (SystemLedPin, HIGH);} void configureLedsWithFinalStates () {if (isWaterDetectedRemotely ==1) {digitalWrite (AlarmLedPin, LOW);}; if (isConnectedToBroker ==0) {digitalWrite (FaultLedPin, LOW);}; if (isValveClosed ==1) {digitalWrite (SystemLedPin, LOW);}; } void clearLeds () {digitalWrite (AlarmLedPin, LOW); digitalWrite (FaultLedPin, LOW); digitalWrite (SystemLedPin, LOW);} void testLeds () {clearLeds (); digitalWrite (AlarmLedPin, HIGH); atraso (500); digitalWrite (FaultLedPin, HIGH); atraso (500); digitalWrite (SystemLedPin, HIGH); atraso (500); clearLeds ();} //// MQTT related functions //// Manipular mensagens MQTT de entrada evite MQTTBrokerCallback (char * subscribedTopic, byte * payload, comprimento interno não assinado) {Serial.print (F ("Nova mensagem recebida do broker MQTT. Tópico =")); Serial.print (subscribedTopic); String payloadAsString =(char *) payload; String realPayload =payloadAsString.substring (0, comprimento); // caso contrário, obteremos lixo, pois o buffer é compartilhado entre In e Out Serial.print (F (", content =")); Serial.print (realPayload); if (realPayload.indexOf ("WaterDetected")> 0 &&realPayload.indexOf (mqttClientLocation) ==-1) // a segunda parte do teste é necessária para evitar falhas auto-acionadas {isWaterDetectedRemotely =1; } // for (int i =0; i  

Esquemas


Processo de manufatura

  1. Válvulas para difícil desligamento e controle
  2. Sensor Raspberry Pi e controle do atuador
  3. Controle de enchimento da piscina
  4. Portenta H7 Dual Core Debugging
  5. Controle remoto universal usando Arduino, 1Sheeld e Android
  6. Animação de LCD e jogos
  7. Aceitar moeda de controle com Arduino
  8. Arduino Control Center
  9. Detector de frequência de áudio
  10. Arduino com Bluetooth para controlar um LED!