Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

Détecteur de fuite d'eau et commande de vanne

Composants et fournitures

Boîtier en aluminium
× 1
Arduino UNO
× 1
Arduino Ethernet Shield 2
× 1
Alimentation
× 1
Boîtier AC
× 1
Kit de LED avec résistances
× 1
Relais (1 double 5v et 1 double 12v)
× 1
Vanne motorisée
× 1
Connecteurs JST
× 1
Capteur d'eau
× 1

À propos de ce projet

Présentation

Lors d'une conversation avec un ami, j'ai réalisé que les fuites d'eau étaient un gros problème. Mon ami a dû remplacer tous les meubles de son sous-sol, simplement parce qu'un tuyau s'était cassé pendant qu'il était au travail.

Ce projet est similaire à celui que j'ai publié pour le concours Microsoft IoT mais celui-ci est basé sur Arduino, pas sur Raspberry. Mon point de vue est le suivant :au lieu de centraliser de nombreuses responsabilités sur une grosse plateforme (comme RasPi, DragonBoard ou un PC), je préfère déléguer responsabilités simples à des appareils simples (comme Arduino et autres). Ils feront ce qu'ils sont censés faire et, en option, ils se connecteront via le réseau à d'autres appareils (simples ou complexes) pour offrir des services avancés. En cas de panne du réseau, ils continuent toujours à faire ce qu'ils sont censés faire.

Fondamentalement, il surveille les fuites d'eau et déclenche des actions comme la fermeture de l'entrée d'eau principale, en fonction du défaut détecté.

Il publie également des messages à un courtier MQTT. L'idée est que l'appareil doit gérer l'eau localement mais est également impliqué, avec d'autres appareils, dans un système plus important qui gère la domotique.

Voici à quoi cela ressemble :

L'entrée d'eau principale est située en bas. Le premier appareil est installé par les services d'approvisionnement en eau de la ville pour contrôler la pression de l'eau. J'ai installé la pièce en haut de la photo. La vanne motorisée (en bleu) est installée en parallèle avec une vanne manuelle. Sur ce dessin, la vanne manuelle est ouverte et la vanne motorisée est donc contournée. Il est utile en cas de panne de courant. En mode normal, la vanne manuelle doit être fermée.

Il y a un moteur à courant continu (12v) dans la vanne et il tourne dans le sens horaire ou antihoraire selon la polarité. Il existe une boucle de rétroaction qui indique si la vanne est effectivement activée ou désactivée. Pour l'allumer, appliquez simplement une tension positive à la connexion en haut à gauche.

Voici le contrôleur :

De gauche à droite :la prise AC, un bouton reset, des LED pour afficher les états, des connectiques (vers capteurs, vers moteur), une interface Ethernet et USB.

  • LED1 :Rouge fixe =eau détectée localement, Rouge clignotant =eau détectée à distance, Éteint =aucune fuite d'eau
  • LED 2 :Jaune fixe =impossible de contrôler la vanne motorisée, Jaune clignotant =impossible d'atteindre le courtier MQTT, Éteint =tout va bien
  • LED3 :Bleu fixe =tout va bien, Bleu clignotant =la vanne motorisée est fermée Éteint =le système est en panne ou n'est pas alimenté

Voici un capteur, situé là où je pense que de l'eau pourrait fuir :

Voici ce qu'il y a sous le capot :

AVERTISSEMENT!

L'alimentation AC/DC que j'utilise a deux sorties :la première est en 12V DC et sert à alimenter la vanne motorisée (contrôlée par deux relais qui contrôle la rotation du moteur) et la seconde est EXACTEMENT 5V DC, pour alimenter le Arduino. C'est pourquoi j'alimente directement sur le circuit 5V, pas le Vin qui nécessite au moins 6V DC. Une fois que l'AC/DC est connecté, vous ne devez JAMAIS (j'ai dit JAMAIS) brancher ni la prise Arduino DC ni le câble USB Arduino. Si vous souhaitez toujours déboguer via USB, configurez un câble fait maison SANS les lignes électriques, conservez uniquement les lignes de données. Soit dit en passant, le lien entre le boîtier AC et l'alimentation AC/DC est de 110V. Ne touchez jamais !

Code

  • Détection de fuite d'eau et commande de vanne motorisée
  • Bibliothèque MQTT
Détection de fuite d'eau et commande de vanne motoriséeArduino
#include #include #include #include #include #include #include /* Voici comment fonctionne le HW Il y a trois sous-systèmes :- le boitier principal :- un Arduino Uno avec et Ethernet shield - une LED rouge :fixe quand de l'eau est détectée localement clignotante quand de l'eau est détectée à distance, éteinte sinon - une LED jaune :fixe lorsque la vanne est en panne, clignotante lorsque le courtier MQTT est inaccessible (pour une raison quelconque), éteinte sinon - une LED bleue :fixe lorsque la vanne est ouverte et que le système surveille les fuites, clignote lorsque la vanne a été éteinte Ce système est en panne - un bouton poussoir :une fois appuyé, un autotest se déclenche - un double relais pour contrôler une vanne motorisée à distance - un autre double relais pour détecter les fins de course d'ouverture/fermeture installés sur la vanne à distance- un jeu d'eau détecteurs (tous en parallèle) (les 3 connecteurs sur le panneau avant sont connectés en parallèle) La vanne motorisée a les connexions suivantes :- Jaune et B lue :CC pour alimenter le moteur - Noir :entrée des interrupteurs de fin de course (sera réglé sur GND dans notre circuit) - Rouge =se tournera vers GND lorsque la vanne atteint sa position complètement fermée (remarque :en raison de la conception interne de l'interrupteur de fin de course , il n'y a aucune garantie que la continuité restera une fois la vanne éteinte) - Vert =se tournera vers GND lorsque la vanne atteint sa position complètement ouverte (remarque :en raison de la conception interne de l'interrupteur de fin de course, il n'y a aucune garantie que la continuité restera une fois la vanne si éteinte)*/// Networkbyte mac[] ={ 0xDE, 0xAD, 0xBE, 0xCF, 0xFC, 0xEE } ; // Adresse MAC d'ArduinoIPAddress ip (192, 168, 12, 215); // L'adresse IP d'ArduinoIPAddress server (192, 168, 12, 130); // Adresse du courtier MQTTEthernetClient ethClient ; // MQTT PubSubClient client(ethClient); #define mqttClientPrefix "GLX" // Préfixe pour utiliser n'importe quelle publication/abonnement MQTT #define mqttClientLocation "BASEMENT" // Deuxième partie de l'identifiant client#define mqttClientUID "001" // Dernière partie de l'identifiant client#define mqttClientStatusTopic "Status" // Sujet à utiliser pour publier l'état de l'appareil #define mqttClientFaultTopic "Fault" // Sujet à utiliser pour publier/s'abonner à Faultsconst int mqttInterval =20; // détermine la fréquence à laquelle le système fera rapport au courtier MQTT (c'est-à-dire chaque mqttInterval * mainLoopDelay ms )int mqttIntervalCnt =0; // variable locale utilisée pour compter downint isConnectedToBroker =-1; // 1 lorsqu'il est connecté, -1 =inconnu, 0 =impossible de se connecter // Pin-outconst int SystemLedPin =A0; // LED bleue const int FaultLedPin =A1; // Led jaune const int AlarmLedPin =A2; // LED rouge const int WaterDetectorPin =2; // passe à LOW lorsque de l'eau est détectée, sinon passe à VCCconst int ToggleButtonPin =3; // passe à BAS lorsque quelqu'un appuie sur le bouton, puis passe à HAUT lorsque le bouton est relâché, sinon déroulant à GNDconst int SdCardPin =4; // Carte SD sur Ethernet shield, non utiliséeconst int ValveClosedPin =5; // passe à LOW lorsque le moteur atteint la limite de l'interrupteur fermé, sinon pull-up à HIGHconst int ValveOpenedPin =6 ; // passe à LOW lorsque le moteur atteint la limite d'ouverture de l'interrupteur, sinon pull-up à HIGHconst int ValveControl1 =8 ; // pour contrôler le premier relais qui contrôle l'alimentation de la vanne motoriséeconst int ValveControl2 =7; // pour contrôler le deuxième relais qui contrôle l'alimentation de la vanne motorisée // Remarque ne pas utiliser D10, D11, D12 et D13 car ces broches sont réservées au blindage Ethernet // WaterLeakage (local) int isWaterDetected =0; // état selon la dernière bonne lecture// WaterLeakage (remote)int isWaterDetectedRemotely =0; // état selon les messages reçus d'autres dispositifs de surveillance// vanne motoriséeint isValveClosed =-1; // état de la vanne motorisée (-1 =inconnu, 0 =ouvert, 1 =fermé))const int valveTimeOut =15; // en secondes, temps maximum autorisé pour ouvrir ou fermer valveint isConnectedToValve =-1; // 0 lorsque le système ne peut pas contrôler la vanne motorisée, 1 =connecté, -1 =inconnu// Bouton RESET manuel volatile booléen isResetRequested =0 ; // celui-ci changera lorsque le bouton déclenchera une interruption // Logicconst int mainLoopDelay =500; // un délai fixe dans la boucle principale, dans msvoid(* resetFunc) (void) =0;// Initialisation void setup(){ wdt_disable(); // toujours bon de le désactiver, s'il est resté activé ou si vous avez besoin d'un temps d'initialisation Serial.begin(9600); Serial.println(F("Début de la configuration")); // Configuration matérielle pinMode (SystemLedPin, OUTPUT); pinMode (FaultLedPin, SORTIE); pinMode (AlarmLedPin, SORTIE); pinMode (WaterDetectorPin, INPUT); pinMode (ToggleButtonPin, INPUT); pinMode (ValveOpenedPin, INPUT); // Le relais 12V DC est inactif par défaut. La broche est connectée au côté NO du relais 1, mais il y a un pull-up. Pin est donc HAUT par défaut. pinMode (ValveClosedPin, INPUT); // Le relais 12V DC est inactif par défaut. La broche est connectée au côté NO du relais 2 mais il y a un pull-up. Pin est donc HAUT par défaut. pinMode (ValveControl1, SORTIE); digitalWrite(ValveControl1, HIGH); // Le relais 5 V CC 1 est inactif par défaut, c'est-à-dire que le moteur est connecté à GND pinMode (ValveControl2, OUTPUT); digitalWrite(ValveControl2, HIGH); // 5V DC relais 2 inactif par défaut, c'est-à-dire que le moteur est connecté à GND pinMode (SdCardPin, OUTPUT); digitalWrite (SdCardPin, HAUT); // pour désactiver la carte SD puisque nous ne l'utilisons pas // Self test testLeds(); // Configuration réseau et MQTT client.setServer(server, 1883); client.setCallback(MQTTBrokerCallback); Ethernet.begin(mac, ip); Serial.print(F("IP actuelle est :")); Serial.print(Ethernet.localIP()); Serial.print(F(" - L'IP du courtier MQTT est :")); Serial.println(serveur); // Initialement, nous ne connaissons pas l'état de la vanne et les interrupteurs de fin de course ne sont pas si fiables. // Ouvrons la vanne motorisée et attendons la fin. Dans le pire des cas, s'il est déjà ouvert, il frappera juste brièvement l'interrupteur de fin de course if (openValve() ==0) { Serial.println(F("La vanne est ouverte et le système surveille maintenant")); // Il y a d'autres appareils de surveillance dans la maison, écoutons les défauts qu'ils pourraient signaler au courtier MQTT subscriptionToRemoteWaterSensors(); } else { Serial.println(F("Impossible d'ouvrir la vanne, le système est en panne. Veuillez utiliser le bypass de plomberie")); } ; enableInterruptOnResetButton(); retard(1500); // autorise le matériel à se trier Serial.println(F("Fin de configuration")); }// Boucle principale loopvoid(){ // LED configureLedsWithInitialStates(); // Réagir à la demande de réinitialisation if (isResetRequested ==1) { Serial.println(F("Quelqu'un a appuyé sur le bouton pour réinitialiser ce périphérique")); publierÉtat(); wdt_enable(WDTO_1S); //activer le chien de garde, se déclenchera dans un délai de 1 seconde (5000); Serial.println(F("ce message ne doit jamais apparaître")); } // Vérifions maintenant si une fuite d'eau a été détectée readLocalWaterSensor(); if (isWaterDetected ==1 || isWaterDetectedRemotely ==1) { if (isValveClosed ==0){ closeValve();}; } // Publier sur le courtier MQTT if (mqttIntervalCnt ==0) { if (isWaterDetected ==1){ publishFault();} publishStatus(); mqttIntervalCnt =mqttInterval; } else { if (isConnectedToValve ==0) { Serial.println(F("Le système est en panne - impossible de contrôler la vanne motorisée. Aucune surveillance en place")); } else { Serial.print(F(".")); } mqttIntervalCnt =mqttIntervalCnt - 1; } // Prend un certain temps de repos (mainLoopDelay / 2 ); client.loop(); // LED configureLedsWithFinalStates(); retard(mainLoopDelay / 2); }//// Gestion du capteur d'eau local//void readLocalWaterSensor(){ isWaterDetected =!getDebouncedValue(WaterDetectorPin, 100, 10); Serial.print(isWaterDetected); }//// Gestion du bouton de réinitialisation//void enableInterruptOnResetButton(){ isResetRequested =0; attachInterrupt(1, onResetRequested, CHANGE);}void onResetRequested(){ detachInterrupt(1); isResetRequested =1 ; }// Gérer la séquence d'ouverture de vanneint openValve(){ Serial.print(F("Ouverture de vanne...")); // d'abord, confirmer que la vanne a été fermée en forçant le moteur à frapper à nouveau brièvement l'interrupteur de fin de course "fermé" (puisque ces interrupteurs de fin de course ne sont pas si fiables...) setupRelays(1); if (waitForEndOfCycle(ValveClosedPin) ==0) { // maintenant, essayons d'ouvrir la vanne setupRelays(2) ; if (waitForEndOfCycle(ValveOpenedPin) ==0) { isConnectedToValve =1; isValveClosed =0; configurationRelais(0) ; // relais d'alimentation OFF Serial.println(F("")); renvoie 0 ; } } setupRelays(0); // relais de puissance OFF isConnectedToValve =0; return -1;}// Gérer la séquence de fermeture de la vanneint closeValve(){ Serial.print(F("Closing valve...")); // d'abord, confirmez que la vanne était ouverte en forçant le moteur à frapper à nouveau brièvement l'interrupteur de fin de course "ouvert" (puisque ces interrupteurs de fin de course ne sont pas si fiables...) setupRelays(2); if ( waitForEndOfCycle(ValveOpenedPin) ==0) { // maintenant, essayons de fermer la vanne setupRelays(1); if (waitForEndOfCycle(ValveClosedPin) ==0) { isConnectedToValve =1; isValveClosed =1 ; configurationRelais(0) ; // relais d'alimentation OFF Serial.println(F("La vanne a été éteinte. Veuillez inspecter soigneusement toutes les pièces et les détecteurs de nettoyage")); renvoie 0 ; } } setupRelays(0); // relais de puissance OFF isConnectedToValve =0; return -1;}// Configurer les relais afin d'alimenter le moteur avec la bonne polaritévoid setupRelays(int scenario){ switch (scenario) { case 0 :// all OFF, aucune alimentation n'a envoyé la vanne motorisée digitalWrite(ValveControl1, HIGH ); digitalWrite(ValveControl2, HIGH); Pause; case 1 :// cycle de fermeture digitalWrite(ValveControl1, HIGH); digitalWrite(ValveControl2, LOW); Pause; case 2 :// cycle d'ouverture digitalWrite(ValveControl1, LOW); digitalWrite(ValveControl2, HIGH); Pause; par défaut :Serial.print(F("Scénario de relais inattendu :")); Serial.println(scénario); digitalWrite(ValveControl1, HIGH); digitalWrite(ValveControl2, HIGH); Pause; }}// Attendre que le fin de course soit touché par le moteur de la vanne motorisée int waitForEndOfCycle(int limitSwitchPin){ int cnt =valveTimeOut; while (cnt> 0) { if (getDebouncedValue(limitSwitchPin, 10, 10) ==LOW) { return 0; } cnt =cnt - 1; Serial.print(F(".")); retard(1000); } ; Serial.println(F(" - timeout atteint lors de la fermeture de la vanne. Vérifiez si la vanne est bien alimentée et si les câbles sont connectés.")); return -1;}// Cette routine permet d'éviter les fausses alarmesint getDebouncedValue(int inputPin, int intervalInMs, int requiredConfirmations){ int confirmations =1; int currentValue =digitalRead(inputPin); while (confirmations <=requiredConfirmations) { delay(intervalInMs); if (currentValue ==digitalRead(inputPin)) { confirmations =confirmations + 1; } else { confirmations =1; currentValue =digitalRead(inputPin); } } return currentValue;}//// Gestion des LEDs//void configureLedsWithInitialStates(){ clearLeds(); // Réévaluer 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, HAUT); retard (500); digitalWrite (FaultLedPin, HAUT); retard (500); digitalWrite (SystemLedPin, HAUT); retard (500); clearLeds();}//// Fonctions liées à MQTT//// Gérer les messages MQTT entrantsvoid MQTTBrokerCallback(char* SubscribedTopic, byte* payload, unsigned int length){ Serial.print(F("Nouveau message reçu du courtier MQTT. Sujet =")); Serial.print(subscribedTopic); Chaîne payloadAsString =(char*)payload ; String realPayload =payloadAsString.substring(0,length); // sinon nous obtenons des déchets puisque le tampon est partagé entre In et Out Serial.print(F(", content=")); Serial.print(realPayload); if (realPayload.indexOf("WaterDetected")> 0 &&realPayload.indexOf(mqttClientLocation) ==-1 ) // la deuxième partie du test est requise pour éviter les erreurs auto-déclenchées { isWaterDetectedRemotely =1; } // for (int i=0;i 

Schémas


Processus de fabrication

  1. Vannes pour fermeture et contrôle difficiles
  2. Contrôle du capteur et de l'actionneur Raspberry Pi
  3. Contrôle de remplissage de la piscine
  4. Débogage Portenta H7 Dual Core
  5. Télécommande universelle utilisant Arduino, 1Sheeld et Android
  6. Animation LCD et jeux
  7. Contrôler l'accepteur de pièces avec Arduino
  8. Centre de contrôle Arduino
  9. Détecteur de fréquence audio