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

Waterlekkagedetector en klepregeling

Componenten en benodigdheden

Aluminium behuizing
× 1
Arduino UNO
× 1
Arduino Ethernet Shield 2
× 1
Voeding
× 1
AC-behuizing
× 1
Kit van LED's met weerstanden
× 1
Relais (1 dubbele 5v en 1 dubbele 12v)
× 1
Gemotoriseerde klep
× 1
JST-connectoren
× 1
Watersensor
× 1

Over dit project

Overzicht

Tijdens een gesprek met een vriend realiseerde ik me dat waterlekkage een groot probleem is. Mijn vriend moest al het meubilair in zijn kelder vervangen, alleen omdat er een pijp was gebroken terwijl hij aan het werk was.

Dit project is vergelijkbaar met het project dat ik heb gepubliceerd voor de Microsoft IoT-wedstrijd, maar dit is gebaseerd op Arduino, niet op Raspberry. Mijn standpunt is het volgende:in plaats van veel verantwoordelijkheden te centraliseren op een groot platform (zoals RasPi, DragonBoard of een pc), geef ik er de voorkeur aan om delegeren eenvoudige verantwoordelijkheden voor eenvoudige apparaten (zoals Arduino en anderen). Ze zullen doen wat ze moeten doen en als optie zullen ze via het netwerk verbinding maken met andere (eenvoudige of complexe) apparaten om geavanceerde diensten aan te bieden. In geval van een netwerkstoring blijven ze doen wat ze moeten doen.

Kortom, het bewaakt waterlekkage en activeert acties zoals het sluiten van de hoofdwatertoevoer, afhankelijk van de gedetecteerde fout.

Het publiceert ook berichten naar een MQTT-makelaar. Het idee is dat het apparaat het water lokaal moet beheren, maar ook betrokken is, samen met andere apparaten, in een groter systeem dat Home Automation beheert.

Zo ziet het eruit:

De hoofdwatertoevoer bevindt zich aan de onderkant. Het eerste apparaat wordt geïnstalleerd door stadswatervoorzieningsdiensten om de waterdruk te regelen. Ik heb het onderdeel bovenaan de foto gemonteerd. De gemotoriseerde klep (in blauw) wordt parallel met een handmatige klep geïnstalleerd. In deze tekening is de handmatige klep geopend en wordt de gemotoriseerde klep dus overbrugd. Het is handig bij stroomuitval. In de normale modus moet de handmatige klep worden uitgeschakeld.

Er zit een gelijkstroommotor (12v) in de klep en deze draait met de klok mee of tegen de klok in, afhankelijk van de polariteit. Er is een feedbacklus die aangeeft of de klep effectief aan of uit staat. Om het in te schakelen, past u gewoon een positieve spanning toe op de verbinding linksboven.

Hier is de controller:

Van links naar rechts:de AC-stekker, een resetknop, enkele LED's om statussen weer te geven, connectoren (naar sensoren, naar motor), een Ethernet en een USB-interface.

  • LED1 :Continu rood =water lokaal gedetecteerd, Rood knipperend =water op afstand gedetecteerd, Uit =geen waterlekkage
  • LED 2 :Constant geel =kan de gemotoriseerde klep niet bedienen, Geel knipperend =kan de MQTT-makelaar niet bereiken, Uit =alles goed
  • LED3 :Constant blauw =alles goed, blauw knipperend =gemotoriseerde klep is gesloten Uit =systeem is uitgeschakeld of niet gevoed

Hier is een sensor op de plek waar ik denk dat er water zou kunnen lekken:

Dit is wat er onder de motorkap zit:

WAARSCHUWING!

De AC/DC-voeding die ik gebruik heeft twee uitgangen:de eerste is 12V DC en wordt gebruikt om de gemotoriseerde klep te voeden (aangestuurd door twee relais die de motorrotatie regelen) en de tweede is PRECIES 5V DC, om de Arduino. Daarom voed ik rechtstreeks op het 5V-circuit, niet op de Vin die minimaal 6V DC nodig heeft. Zodra de AC/DC is aangesloten, mag u NOOIT (ik zei NOOIT) de Arduino DC-aansluiting of Arduino USB-kabel aansluiten. Als je nog steeds via USB wilt debuggen, installeer dan een zelfgemaakte kabel ZONDER de stroomkabels, bewaar alleen de datalijnen. De link tussen AC-behuizing en AC/DC-voeding is trouwens 110V. Niet aanraken, nooit!

Code

  • Waterlekkagedetectie en gemotoriseerde klepbediening
  • MQTT-bibliotheek
Waterlekkagedetectie en gemotoriseerde klepbedieningArduino
#include #include #include #include #include #include #include /* Hier is hoe de HW werkt Er zijn drie subsystemen:- de hoofdbox:- een Arduino Uno met en Ethernet-schild - een rode LED:constant wanneer water wordt gedetecteerd lokaal knipperend wanneer water op afstand wordt gedetecteerd, anders uit - een gele LED:continu wanneer de klep defect is, knipperend wanneer de MQTT-broker onbereikbaar is (om welke reden dan ook), anders uit - een blauwe LED:continu wanneer de klep open is en het systeem lekkages controleert, knipperend wanneer de klep is uitgeschakeld is het systeem niet beschikbaar - een drukknop:eenmaal ingedrukt, wordt een zelftest geactiveerd - een dubbel relais om een ​​gemotoriseerde klep op afstand te bedienen - nog een dubbel relais om de open/dicht-eindschakelaars te detecteren die op de externe klep zijn geïnstalleerd - een set water detectoren (allemaal in parallel) (alle 3 connectoren op het frontpaneel zijn parallel aangesloten) De gemotoriseerde klep heeft de volgende aansluitingen:- Geel en B lue:DC om de motor aan te drijven- Zwart:ingang van eindschakelaars (wordt ingesteld op GND in ons circuit)- Rood =zal naar GND draaien wanneer de klep zijn volledig gesloten positie bereikt (let op:vanwege het interne ontwerp van de eindschakelaar , er is geen garantie dat continuïteit zal blijven zodra de klep is uitgeschakeld) - Groen =zal naar GND draaien wanneer de klep de volledig open positie bereikt (opmerking:vanwege het interne ontwerp van de eindschakelaar is er geen garantie dat continuïteit blijft zodra de klep is uitgeschakeld)*/// Networkbyte mac[] ={ 0xDE, 0xAD, 0xBE, 0xCF, 0xFC, 0xEE }; // Arduino's MAC-adresIPAdres ip(192, 168, 12, 215); // Arduino's IP-adresIPAddress-server (192, 168, 12, 130); // MQTT-makelaarsadresEthernetClient ethClient;// MQTT PubSubClient-client (ethClient); #define mqttClientPrefix "GLX" // Prefix om elke MQTT-publicatie/-abonnement te gebruiken #define mqttClientLocation "BASEMENT" // Tweede deel van de client-ID#define mqttClientUID "001" // Laatste deel van de client-ID#define mqttClientStatusTopic "Status" // Onderwerp dat moet worden gebruikt om de apparaatstatus te publiceren #define mqttClientFaultTopic "Fault" // Onderwerp dat moet worden gebruikt om te publiceren/abonneren op Faultsconst int mqttInterval =20; // bepaalt hoe vaak het systeem rapporteert aan MQTT-broker (dwz elke mqttInterval * mainLoopDelay ms )int mqttIntervalCnt =0; // lokale variabele die wordt gebruikt om af te tellen isConnectedToBroker =-1; // 1 indien verbonden, -1 =onbekend, 0 =kan niet worden verbonden// Pin-outconst int SystemLedPin =A0; // Blauwe led const int FaultLedPin =A1; // Gele led const int AlarmLedPin =A2; // Rode led const int WaterDetectorPin =2; // gaat naar LAAG wanneer water wordt gedetecteerd, anders omhoog getrokken naar VCCconst int ToggleButtonPin =3; // gaat naar LAAG wanneer iemand op de knop drukt en gaat vervolgens naar HOOG wanneer de knop wordt losgelaten, anders naar GNDconst int SdCardPin =4; // SD-kaart op ethernet-schild, niet gebruiktconst int ValveClosedPin =5; // gaat naar LAAG wanneer de motor de limiet van de gesloten schakelaar bereikt, anders omhoog trekken naar HIGHconst int ValveOpenedPin =6; // gaat naar LAAG wanneer de motor de open schakelaarlimiet bereikt, anders omhoog trekken naar HIGHconst int ValveControl1 =8; // om het eerste relais te besturen dat de voeding van de gemotoriseerde klep regelt int ValveControl2 =7; // om het tweede relais te besturen dat de voeding van de gemotoriseerde klep regelt // Let op:gebruik geen D10, D11, D12 en D13 aangezien die pinnen zijn gereserveerd voor Ethernet-schild// WaterLeakage (local) int isWaterDetected =0; // status volgens de laatste goede lezing// WaterLeakage (remote)int isWaterDetectedRemotely =0; // status volgens berichten ontvangen van andere bewakingsapparatuur// Gemotoriseerde valveint isValveClosed =-1; // status van gemotoriseerde klep (-1 =onbekend, 0 =geopend, 1 =gesloten))const int valveTimeOut =15; // in sec, max. toegestane tijd om valveint te openen of te sluiten isConnectedToValve =-1; // 0 wanneer het systeem de gemotoriseerde klep niet kan bedienen, 1 =aangesloten, -1 =onbekend// Handmatige RESET-knop vluchtige boolean isResetRequested =0; // deze verandert wanneer de knop een interrupt activeert// Logicconst int mainLoopDelay =500; // een vaste vertraging binnen de hoofdlus, in msvoid(* resetFunc) (void) =0;// Initialization void setup(){ wdt_disable(); //altijd goed om het uit te schakelen, als het 'aan' was gelaten of als je init time Serial.begin (9600) nodig hebt; Serial.println(F("Begin van setup")); // HW setup pinMode (SystemLedPin, OUTPUT); pinMode (FaultLedPin, UITGANG); pinMode (AlarmLedPin, UITGANG); pinMode (WaterDetectorPin, INPUT); pinMode (ToggleButtonPin, INPUT); pinMode (ValveOpenedPin, INPUT); // 12V DC-relais is standaard inactief. Pin is verbonden met GEEN kant van relais 1, maar er is een pull-up. Pin is daarom standaard HOOG. pinMode (ValveClosedPin, INPUT); // 12V DC-relais is standaard inactief. Pin is verbonden met GEEN kant van relais 2 maar er is een pull-up. Pin is daarom standaard HOOG. pinMode (ValveControl1, UITGANG); digitalWrite (ValveControl1, HOOG); // 5V DC-relais 1 is standaard inactief, d.w.z. de motor is aangesloten op GND pinMode (ValveControl2, OUTPUT); digitalWrite (ValveControl2, HOOG); // 5V DC relais 2 standaard inactief, d.w.z. de motor is aangesloten op GND pinMode (SdCardPin, OUTPUT); digitalWrite (SdCardPin, HOOG); // om de SD-kaart uit te schakelen omdat we deze niet gebruiken // Zelftest testLeds(); // Netwerk en MQTT setup client.setServer (server, 1883); client.setCallback(MQTTBrokerCallback); Ethernet.begin(mac, ip); Serial.print(F("Huidige IP is:")); Serial.print(Ethernet.localIP()); Serial.print(F(" - MQTT broker IP is:")); Seriële.println(server); // Aanvankelijk kennen we de status van de klep niet en de eindschakelaars zijn niet zo betrouwbaar. // Laten we de gemotoriseerde klep openen en wachten op voltooiing. In het ergste geval, als het al geopend is, zal het de limietschakelaar kort indrukken als (openValve() ==0) { Serial.println(F("Klep is open en het systeem controleert nu")); // Er zijn andere bewakingsapparatuur in huis, laten we eens luisteren naar de fouten die ze kunnen melden aan de MQTT-makelaar subscribeToRemoteWaterSensors(); } else { Serial.println(F("Kan klep niet openen, systeem werkt niet. Gebruik a.u.b. sanitair bypass")); }; enableInterruptOnResetButton(); vertraging (1500); // laat hardware zichzelf uitzoeken Serial.println(F("Einde setup")); }// Main loopvoid loop(){ // LED's configureLedsWithInitialStates(); // Reageer op resetverzoek if (isResetRequested ==1) { Serial.println (F ("Iemand heeft op de knop gedrukt om dit apparaat te resetten")); publishStatus(); wdt_enable(WDTO_1S); // schakel waakhond in, zal in 1 seconde vertraging (5000) vuren; Serial.println(F("dit bericht mag nooit verschijnen")); } // Laten we nu controleren of er een waterlekkage is gedetecteerd readLocalWaterSensor(); if (isWaterDetected ==1 || isWaterDetectedRemotely ==1) { if (isValveClosed ==0){ closeValve();}; } // Publiceer naar MQTT broker if (mqttIntervalCnt ==0) { if (isWaterDetected ==1){ publishFault();} publishStatus(); mqttIntervalCnt =mqttInterval; } else { if (isConnectedToValve ==0) { Serial.println(F("Systeem is defect - kan gemotoriseerde klep niet regelen. Geen bewaking aanwezig")); } else { Serial.print(F(".")); } mqttIntervalCnt =mqttIntervalCnt - 1; } // Neem wat rustvertraging (mainLoopDelay / 2 ); cliënt.loop(); // LED's configureLedsWithFinalStates(); vertraging (mainLoopDelay / 2); }//// Lokaal watersensorbeheer//void readLocalWaterSensor(){ isWaterDetected =!getDebouncedValue(WaterDetectorPin, 100, 10); Serial.print (isWaterDetected); }//// Resetknopbeheer//void enableInterruptOnResetButton(){ isResetRequested =0; attachInterrupt(1, onResetRequested, CHANGE);}void onResetRequested(){ detachInterrupt(1); isResetRequested =1; }// Beheer de openingsvolgorde van de klep in openValve(){ Serial.print(F("Opening klep...")); // controleer eerst of de klep gesloten was door de motor te dwingen de "gesloten" eindschakelaar opnieuw kort in te drukken (aangezien die eindschakelaars niet zo betrouwbaar zijn...) setupRelays(1); if (waitForEndOfCycle(ValveClosedPin) ==0) { // laten we nu proberen de klep setupRelays(2) te openen; if (waitForEndOfCycle (ValveOpenedPin) ==0) { isConnectedToValve =1; isValveClosed =0; setupRelais(0); // stroomrelais UIT Serial.println (F ("")); retourneer 0; } } setupRelais(0); // vermogensrelais UIT isConnectedToValve =0; return -1;}// Beheer de sluitvolgorde van de klepint closeValve(){ Serial.print(F("Sluitklep...")); // controleer eerst of de klep open was door de motor te dwingen de "open" eindschakelaar opnieuw kort in te drukken (aangezien die eindschakelaars niet zo betrouwbaar zijn...) setupRelays(2); if ( waitForEndOfCycle (ValveOpenedPin) ==0) { // laten we nu proberen de klep setupRelays(1) te sluiten; if (waitForEndOfCycle (ValveClosedPin) ==0) { isConnectedToValve =1; isValveClosed =1; setupRelais(0); // voedingsrelais UIT Serial.println(F ("Klep is uitgeschakeld. Inspecteer zorgvuldig alle kamers en opruimdetectoren")); retourneer 0; } } setupRelais(0); // vermogensrelais UIT isConnectedToValve =0; return -1;}// Stel de relais in om de motor met de juiste polariteit te voeden leeg setupRelais(int scenario){ schakelaar (scenario) { geval 0:// alles UIT, geen stroom gestuurd naar de gemotoriseerde klep digitalWrite(ValveControl1, HIGH ); digitalWrite (ValveControl2, HOOG); pauze; geval 1:// sluitcyclus digitalWrite(ValveControl1, HIGH); digitalWrite (ValveControl2, LAAG); pauze; geval 2:// openingscyclus digitalWrite(ValveControl1, LOW); digitalWrite (ValveControl2, HOOG); pauze; standaard:Serial.print(F("Onverwacht relaisscenario:")); Serial.println(scenario); digitalWrite (ValveControl1, HOOG); digitalWrite (ValveControl2, HOOG); pauze; }}// Wacht tot de eindschakelaar wordt geraakt door de motor van de gemotoriseerde klep int waitForEndOfCycle (int limitSwitchPin) {int cnt =valveTimeOut; while (cnt> 0) {if (getDebouncedValue(limitSwitchPin, 10, 10) ==LAAG) {return 0; } cnt =cnt - 1; Serial.print(F(".")); vertraging (1000); }; Serial.println(F(" - time-out bereikt tijdens het sluiten van de klep. Controleer of de klep goed is ingeschakeld en de kabels zijn aangesloten.")); return -1;}// Deze routine helpt valse alarmen te vermijdensint getDebouncedValue(int inputPin, int intervalInMs, int requiredConfirmations){int confirms =1; int currentValue =digitalRead (inputPin); while (bevestigingen <=requiredConfirmations) {delay (intervalInMs); if (currentValue ==digitalRead (inputPin)) {bevestigingen =bevestigingen + 1; } else { bevestigingen =1; currentValue =digitalRead (inputPin); } } return currentValue;}//// LED's management//void configureLedsWithInitialStates(){ clearLeds(); // Evalueer opnieuw of (isWaterDetectedRemotely ==1 || isWaterDetected ==1) {digitalWrite (AlarmLedPin, HIGH);}; if (isConnectedToValve ==0 || isConnectedToBroker ==0) {digitalWrite(FaultLedPin, HIGH);}; digitalWrite(SystemLedPin, HIGH);}ongeldig 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, LAAG); digitalWrite(SystemLedPin, LOW);}void testLeds(){ clearLeds(); digitalWrite (AlarmLedPin, HOOG); vertraging (500); digitalWrite (FaultLedPin, HOOG); vertraging (500); digitalWrite (SystemLedPin, HOOG); vertraging (500); duidelijk =")); Serial.print (subscribeTopic); String payloadAsString =(char*)payload; String realPayload =payloadAsString.substring(0,lengte); // anders krijgen we rommel omdat de buffer wordt gedeeld tussen In en Out Serial.print(F(", content=")); Serial.print (realPayload); if (realPayload.indexOf("WaterDetected")> 0 &&realPayload.indexOf(mqttClientLocation) ==-1 ) // het tweede deel van de test is vereist om door zichzelf veroorzaakte fouten te voorkomen { isWaterDetectedRemotely =1; } // for (int i=0;i 

Schema's


Productieproces

  1. Kleppen voor moeilijk afsluiten en regelen
  2. Raspberry Pi-sensor en actuatorbediening
  3. Pool Fill Control
  4. Portenta H7 Dual Core-foutopsporing
  5. Universele afstandsbediening met Arduino, 1Sheeld en Android
  6. LCD-animatie en gaming
  7. Bedien muntvangers met Arduino
  8. Arduino-controlecentrum
  9. Audiofrequentiedetector
  10. Arduino met Bluetooth om een ​​LED te bedienen!
  11. Bedien Arduino Rover met Firmata en Xbox One Controller