亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

漏水探测器和阀门控制

组件和用品

铝制外壳
× 1
Arduino UNO
× 1
Arduino Ethernet Shield 2
× 1
电源
× 1
空调外壳
× 1
带电阻的 LED 套件
× 1
继电器(1 个双 5v 和 1 个双 12v)
× 1
电动阀
× 1
JST 连接器
× 1
水传感器
× 1

关于这个项目

概览

在和朋友聊天时,我意识到漏水是一个大问题。我的朋友不得不更换他地下室的所有家具,因为他在工作时管子坏了。

该项目类似于我为 Microsoft IoT 竞赛发布的项目,但该项目基于 Arduino,而不是基于 Raspberry。我的观点如下:与其将许多职责集中在一个大平台(如 RasPi、DragonBoard 或 PC)上,我更喜欢委托 对简单设备(如 Arduino 等)的简单职责。他们将做他们应该做的事情,作为一种选择,他们将通过网络连接到其他(简单或复杂)设备以提供高级服务。万一网络出现故障,他们仍然继续做他们应该做的事情。

基本上,它会监控漏水情况,并根据检测到的故障触发诸如关闭主进水​​口之类的动作。

它还向 MQTT 代理发布消息。这个想法是该设备必须在本地管理水,但也与其他设备一起参与管理家庭自动化的更大系统。

这是它的样子:

主进水口位于底部。第一个装置由城市供水服务安装以控制水压。我将零件安装在图片的顶部。电动阀(蓝色)与手动阀并联安装。在此图中,手动阀打开,因此绕过电动阀。它在停电的情况下很有用。在正常模式下,手动阀必须关闭。

阀门内有一个直流电机 (12v),它根据极性顺时针或逆时针转动。有一个反馈回路指示阀门是有效打开还是关闭。要打开它,只需在左上角的连接上施加一个正电压。

这是控制器:

从左到右:AC 插头、一个复位按钮、一些显示状态的 LED、连接器(到传感器、到电机)、一个以太网和一个 USB 接口。

  • LED1 :红色常亮 =本地检测到水,红色闪烁 =远程检测到水,熄灭 =无漏水
  • LED 2 :稳定黄色 =无法控制电动阀,黄色闪烁 =无法连接到 MQTT 代理,关闭 =一切正常
  • LED3 :稳定的蓝色 =一切正常,闪烁的蓝色 =电动阀门关闭 关闭 =系统关闭或未通电

这是一个传感器,位于我认为可能会漏水的位置:

这是引擎盖下的内容:

警告!

我使用的 AC/DC 电源有两个输出:第一个是 12V DC,用于给电动阀供电(由控制电机旋转的两个继电器控制),第二个是精确的 5V DC,用于给电动阀供电阿杜诺。这就是为什么我直接在 5V 电路上供电,而不是需要至少 6V DC 的 Vin。连接 AC/DC 后,您永远不要(我说永远不要)插入 Arduino DC 插孔和 Arduino USB 电缆。如果您仍想通过 USB 进行调试,请设置一根自制电缆,无需电源线,仅保留数据线。顺便说一下,AC外壳和AC/DC电源之间的链接是110V。永远不要碰!

代码

  • 漏水检测和电动阀门控制
  • MQTT 库
漏水检测和电动阀门控制Arduino
#include #include #include #include #include #include #include /* 以下是硬件的工作原理有三个子系统:- 主盒:- 带有以太网屏蔽的 Arduino Uno - 红色 LED:在本地检测到水时稳定,远程检测到水时闪烁,否则关闭-黄色 LED:阀门出现故障时稳定,当 MQTT 代理无法访问(出于任何原因)时闪烁,否则关闭 - 蓝色 LED:阀门打开且系统正在监控泄漏时稳定,阀门关闭时闪烁系统停机 - 一个按钮:一旦按下,就会触发自检 - 一个双继电器控制远程电动阀 - 另一个双继电器检测安装在远程阀门上的开/关限位开关 - 一组水检测器(全部并联)(前面板上的所有 3 个连接器都并联连接)电动阀具有以下连接:- 黄色和 B lue:DC 为电机供电 - 黑色:限位开关输入(在我们的电路中将设置为 GND)-红色 =当阀门达到完全关闭位置时将变为 GND(注意:由于限位开关的内部设计, 无法保证阀门断电后仍会保持连续性)- 绿色 =当阀门到达全开位置时将变为 GND(注意:由于限位开关的内部设计,无法保证连续性如果关闭阀门,将保留一次)*/// Networkbyte mac[] ={ 0xDE, 0xAD, 0xBE, 0xCF, 0xFC, 0xEE }; // Arduino的MAC地址IPAddress ip(192, 168, 12, 215); // Arduino的IP地址IPAddress server(192, 168, 12, 130); // MQTT 代理地址EthernetClient ethClient;// MQTT PubSubClient client(ethClient); #define mqttClientPrefix "GLX" // 使用任何 MQTT 发布/订阅的前缀 #define mqttClientLocation "BASEMENT" // 客户端标识符的第二部分#define mqttClientUID "001" // 客户端标识符的最后一部分#define mqttClientStatusTopic "Status" // 用于发布设备状态的主题 #define mqttClientFaultTopic "Fault" // 用于发布/订阅 Faultsconst 的主题 int mqttInterval =20; // 确定系统向 MQTT 代理报告的频率(即每个 mqttInterval * mainLoopDelay ms )int mqttIntervalCnt =0; // 局部变量用于倒数int isConnectedToBroker =-1; // 1 连接时,-1 =未知,0 =无法连接// Pin-outconst int SystemLedPin =A0; // 蓝色 LED const int FaultLedPin =A1; // 黄色 LED const int AlarmLedPin =A2; // 红色 LED const int WaterDetectorPin =2; // 当检测到水时变为低电平,否则上拉到 VCCconst int ToggleButtonPin =3; // 当有人按下按钮时变为低电平,释放按钮时变为高电平,否则下拉至 GNDconst int SdCardPin =4; // 以太网屏蔽上的 SD 卡,未使用 const int ValveClosedPin =5; // 当电机达到闭合开关限制时变为低电平,否则上拉到 HIGHconst int ValveOpenedPin =6; // 当电机达到打开开关限制时变为低电平,否则上拉到 HIGHconst int ValveControl1 =8; // 控制第一个控制电动阀电源的继电器const int ValveControl2 =7; // 控制控制电动阀电源的第二个继电器 // 注意不要使用 D10、D11、D12 和 D13,因为这些引脚是为以太网屏蔽保留的 // WaterLeakage (local) int isWaterDetected =0; // 根据上次良好读数的状态// WaterLeakage (remote)int isWaterDetectedRemotely =0; // 根据从其他监控设备接收到的消息的状态// 电动阀int isValveClosed =-1; // 电动阀的状态(-1 =未知,0 =打开,1 =关闭))const int ValveTimeOut =15; // 以秒为单位,允许打开或关闭阀门的最长时间int isConnectedToValve =-1; // 当系统无法控制电动阀门时为 0,1 =已连接,-1 =未知// 手动复位按钮易失性布尔值 isResetRequested =0; // 当按钮触发中断时这个会改变// Logicconst int mainLoopDelay =500; // 主循环中的固定延迟,在 msvoid(* resetFunc) (void) =0;// 初始化 void setup(){ wdt_disable(); //总是很好禁用它,如果它被留在'on'或者你需要初始化时间Serial.begin(9600); Serial.println(F("开始设置")); // 硬件设置 pinMode (SystemLedPin, OUTPUT); pinMode (FaultLedPin, OUTPUT); pinMode (AlarmLedPin, OUTPUT); pinMode (WaterDetectorPin, INPUT); pinMode (ToggleButtonPin, INPUT); pinMode (ValveOpenedPin, INPUT); // 12V DC 继电器默认空闲。引脚连接到继电器 1 的 NO 侧,但有一个上拉。因此,引脚默认为高电平。 pinMode (ValveClosedPin, INPUT); // 12V DC 继电器默认空闲。引脚连接到继电器 2 的 NO 侧,但有一个上拉。因此,引脚默认为高电平。 pinMode (ValveControl1, OUTPUT);数字写入(阀门控制1,高); // 5V DC 继电器 1 默认空闲,即电机连接到 GND pinMode (ValveControl2, OUTPUT);数字写入(阀门控制2,高); // 5V DC 继电器 2 默认空闲,即电机连接到 GND pinMode(SdCardPin, OUTPUT);数字写入(SDCardPin,高); // 禁用 SD 卡,因为我们不使用它 // 自检 testLeds(); // 网络和 MQTT 设置 client.setServer(server, 1883); client.setCallback(MQTTBrokerCallback); Ethernet.begin(mac, ip); Serial.print(F("当前IP是:")); Serial.print(Ethernet.localIP()); Serial.print(F(" - MQTT 代理 IP 是:")); Serial.println(服务器); // 最初,我们不知道阀门的状态,限位开关不太可靠。 // 让我们打开电动阀并等待完成。最坏的情况,如果它已经打开,它只会短暂地点击限位开关 if (openValve() ==0) { Serial.println(F("Valve is open and system is now monitoring")); // 家里还有其他的监控设备,我们听听他们可以上报给MQTT代理的故障 subscribeToRemoteWaterSensors(); } else { Serial.println(F("无法打开阀门,系统故障。请使用管道旁路")); }; enableInterruptOnResetButton();延迟(1500); // 允许硬件自行排序 Serial.println(F("End of setup")); }// Main loopvoid loop(){ // LED configureLedsWithInitialStates(); // 响应重置请求 if (isResetRequested ==1) { Serial.println(F("有人按下按钮重置此设备"));发布状态(); wdt_enable(WDTO_1S); //启用看门狗,将在1秒延迟(5000)后触发; Serial.println(F("这条消息不应该出现")); } // 现在让我们检查是否检测到漏水 readLocalWaterSensor(); if (isWaterDetected ==1 || isWaterDetectedRemotely ==1) { if (isValveClosed ==0){ closeValve();}; } // 发布到 MQTT 代理 if (mqttIntervalCnt ==0) { if (isWaterDetected ==1){ publishFault();} publishStatus(); mqttIntervalCnt =mqttInterval; } else { if (isConnectedToValve ==0) { Serial.println(F(“系统故障 - 无法控制电动阀门。没有监控到位”)); } else { Serial.print(F(".")); } mqttIntervalCnt =mqttIntervalCnt - 1; } // 稍作休息延迟(mainLoopDelay / 2 );客户端循环(); // LED configureLedsWithFinalStates();延迟(mainLoopDelay / 2); }//// 本地水传感器管理//v​​oid readLocalWaterSensor(){ isWaterDetected =!getDebouncedValue(WaterDetectorPin, 100, 10); Serial.print(isWaterDetected); }//// 重置按钮管理//v​​oid enableInterruptOnResetButton(){ isResetRequested =0; attachInterrupt(1, onResetRequested, CHANGE);}void onResetRequested(){ detachInterrupt(1); isResetRequested =1; }// 管理阀门开启顺序int openValve(){ Serial.print(F("Opening Valve...")); // 首先,通过强制电机再次短暂击打“关闭”限位开关来确认阀门已关闭(因为这些限位开关不太可靠......) setupRelays(1); if (waitForEndOfCycle(ValveClosedPin) ==0) { // 现在,让我们尝试打开阀门 setupRelays(2); if (waitForEndOfCycle(ValveOpenedPin) ==0) { isConnectedToValve =1; isValveClosed =0;设置继电器(0); // 电源继电器关闭 Serial.println(F(""));返回0; } } setupRelays(0); // 电源继电器关闭 isConnectedToValve =0; return -1;}// 管理阀门关闭顺序int closeValve(){ Serial.print(F("Closing Valve...")); // 首先,通过强制电机再次短暂击打“打开”限位开关来确认阀门已打开(因为这些限位开关不太可靠......) setupRelays(2); if ( waitForEndOfCycle(ValveOpenedPin) ==0) { // 现在,让我们尝试关闭阀门 setupRelays(1); if (waitForEndOfCycle(ValveClosedPin) ==0) { isConnectedToValve =1; isValveClosed =1;设置继电器(0); // 电源继电器关闭 Serial.println(F("阀门已关闭。请仔细检查所有房间和清理探测器"));返回0; } } setupRelays(0); // 电源继电器关闭 isConnectedToValve =0; return -1;}// 设置继电器,以便以正确的极性为电机供电void setupRelays(int scene){ switch (scenario) { case 0:// 全部关闭,没有电源发送电动阀 digitalWrite(ValveControl1, HIGH );数字写入(阀门控制2,高);休息; case 1:// 关闭循环 digitalWrite(ValveControl1, HIGH);数字写入(阀门控制2,低);休息; case 2:// 开启循环 digitalWrite(ValveControl1, LOW);数字写入(阀门控制2,高);休息;默认值:Serial.print(F("意外的中继场景:")); Serial.println(场景);数字写入(阀门控制1,高);数字写入(阀门控制2,高);休息; }}// 等到限位开关被电动阀门的电机击中 int waitForEndOfCycle(int limitSwitchPin){ int cnt =ValveTimeOut; while (cnt> 0) { if (getDebouncedValue(limitSwitchPin, 10, 10) ==LOW) { return 0; } cnt =cnt - 1; Serial.print(F("."));延迟(1000); }; Serial.println(F(" - 关闭阀门时超时。检查阀门是否通电且电缆是否连接。")); return -1;}// 此例程有助于避免误报int getDebouncedValue(int inputPin, int intervalInMs, int requiredConfirmations){ int confirms =1; int currentValue =digitalRead(inputPin);而(确认<=requiredConfirmations){延迟(intervalInMs); if (currentValue ==digitalRead(inputPin)) { 确认 =确认 + 1; } else { 确认数 =1; currentValue =digitalRead(inputPin); } } return currentValue;}//// LED 管理//v​​oid configureLedsWithInitialStates(){ clearLeds(); // 重新评估 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);数字写入(FaultLedPin,低); digitalWrite(SystemLedPin, LOW);}void testLeds(){ clearLeds();数字写入(AlarmLedPin,高);延迟(500);数字写入(FaultLedPin,高);延迟(500);数字写入(SystemLedPin,高);延迟(500); clearLeds();}//// MQTT相关函数//// 处理传入的MQTT消息void MQTTBrokerCallback(char* subscribedTopic, byte* payload, unsigned int length){ Serial.print(F("New message received from MQTT broker. Topic =")); Serial.print(subscribedTopic); String payloadAsString =(char*)payload; String realPayload =payloadAsString.substring(0,length); // 否则我们会得到垃圾,因为缓冲区在 In 和 Out 之间共享 Serial.print(F(", content=")); Serial.print(realPayload); if (realPayload.indexOf("WaterDetected")> 0 &&realPayload.indexOf(mqttClientLocation) ==-1 ) // 测试的第二部分需要避免自触发故障 { isWaterDetectedRemotely =1; } // for (int i=0;i 

示意图


制造工艺

  1. 用于困难关闭和控制的阀门
  2. Raspberry Pi 传感器和执行器控制
  3. 水池填充控制
  4. Portenta H7 双核调试
  5. 使用 Arduino、1Sheeld 和 Android 的通用远程控制
  6. LCD 动画和游戏
  7. 使用 Arduino 控制硬币接收器
  8. Arduino 控制中心
  9. 音频检测器
  10. Arduino 带蓝牙控制 LED!
  11. 使用 Firmata 和 Xbox One 控制器控制 Arduino Rover
  12. Arduino 加湿器控制