☰
Node-RED替代PLC:智能温室控制系统完整搭建指南
2026/10/22 7:51:56 网站建设 项目流程

去年帮朋友的农业园区做控制系统升级,园区里五个连栋温室,原来用的是传统继电器回路加手动控制,每天夜里都要有专人去棚里关风机、开侧窗,遇到天气突变更是手忙脚乱。我接手后没有继续走PLC那套路线,而是改用Node-RED做了一套智能温室控制系统,从传感器采集、自动控制到手机告警,整套系统跑下来不仅省掉了夜间巡查的人工,还把改造预算控制在传统方案的零头。这篇文章我想把完整的搭建思路、核心控制流程、多执行器联动策略和实际踩过的坑整理出来,给考虑用低代码思路做智慧农业的朋友一个参考。

这套系统能做什么?简单说,就是采集空气温湿度、土壤墒情、光照强度、二氧化碳浓度,自动联动风机、湿帘、侧窗、外遮阳网、补光灯、水肥电磁阀这些执行器,同时具备远程看板、异常告警、能耗统计和断网续传能力。如果你只是某个大棚的种植户,或者你是做农业物联网集成的工程师,又或者你想用低成本方式把家里或者园区里的老设备变成远程可控设备,这篇文章都值得往下看。

1. 为什么我弃用PLC和组态软件,改用Node-RED做温室控制

1.1 传统方案的隐性成本:改一处逻辑等于重来一遍

温室控制逻辑本身并不复杂,无非是温度高了开风机、湿帘,光照强了拉遮阳网,土壤干了启动灌溉。这些逻辑在PLC里写也就几十行梯形图,但真正让项目成本失控的,往往不是这些标准逻辑,而是后面没完没了的参数调整和策略变更。

我之前经手过一个用PLC加组态屏的项目,交付之后没两个月,甲方就提出要把白天和夜间的温度控制策略分开:白天26℃启动风机,夜间22℃启动热风机,还要根据不同季节切换目标。这在PLC里意味着要新增定时器、状态位、多个比较指令,然后修改梯形图、重新下载程序。每次改动都要联系工控工程师,现场调试一轮,少说半天,多则两三天。更头疼的是,程序注释写得很少,后面维护的人根本不敢动手。

这种隐性成本在农业场景里尤其突出。温室环境不像工厂车间那样稳定,作物对温湿度的耐受区间会随生长阶段变化,种植者的经验也在不断修正控制参数,整个控制策略长期处于“试错—优化—再试错”的状态。传统工控链路改一次成本太高,很多园区宁愿保留手动,也不愿意频繁改程序,于是所谓“自动化”很快变成了“摆设”。

1.2 Node-RED的价值不是“免费”,而是把改造成本压到可迭代的水平

后来我把重心转到Node-RED上,最直观的感受是控制策略变成了一张流程图。传感器是一根输入线,逻辑判断是一个功能节点,每次调整阈值、修改联动关系,只需要在画布上拖拽连线,点开节点改一下参数,然后重新部署,整个过程以分钟计算,不需要专门的编译下载工具。

不少人对Node-RED的印象是“低代码玩具”,但在温室控制这个场景里,它比传统方案更合适,原因有三点:一是事件驱动的消息模型天然匹配传感器上报模式;二是节点生态覆盖了Modbus、MQTT、HTTP、数据库、消息通知等常用协议;三是运行环境非常轻,一台价格不高的ARM板子就能跑起来。

我做过一个粗略的成本对比。同一个五连栋温室的自动化改造,传统PLC加组态方案,硬件和工程服务加起来大概要十几万;用Node-RED加工业网关和继电器模块的方案,硬件成本不到三分之一,而且后续策略调整完全自己完成,不需要每次请外部工程师。这笔账不是省在软件授权上,而是省在“改得起”这三个字上。

对比维度传统PLC+组态Node-RED低代码
控制逻辑修改需要工具、授权、专人,流程长画布拖拽改参数,分钟级
新人上手成本梯形图/ST语言,门槛高可视化流,初中级工程师可上手
协议接入能力依赖专用模块,扩展有限Modbus/MQTT/HTTP等生态丰富
硬件成本控制器+IO模块价格高低成本ARM板即可运行
大规模多点扩展强但联动繁琐需要合理架构,支持分布式

我并不是说PLC不好。大型产线、高实时性、高安全要求的设备,我依然会用PLC。只是温室控制这个场景,实时性要求不高、逻辑改动频繁、执行器大多数是开关量且安全等级有限,用Node-RED这种灵活的低代码平台,恰好能做到又便宜又跑得稳。

2. 温室控制系统的完整信息链路:从传感器到执行机构怎么串起来

2.1 一个闭环系统的四段构成:采集、决策、控制、反馈

智能温室控制系统要解决的基本问题,就是根据环境数据自动操作现场设备,给作物维持一套适宜的生长环境。整个闭环可以拆成四段:

  • 采集段:空气温湿度、土壤水分、光照强度、二氧化碳浓度、风向风速、雨量等传感器,通过RS485总线或无线方式把数据送到控制器。
  • 决策段:将采集数据与设定目标比较,得出“该不该动作”“该动哪个、动到什么程度”的结论。
  • 控制段:输出开关量或脉冲信号,驱动风机、湿帘、侧窗、遮阳网、补光灯、电磁阀、水泵等执行器。
  • 反馈段:执行器状态回传、传感器数据回流,形成闭环监测和异常报警。

在传统方案里,这四段割裂在不同设备里:传感器接在采集模块上,逻辑写在PLC程序中,继电器在配电柜里,人机交互在组态屏上。而在Node-RED里,四段可以统一在一张流程图上表达:数据从MQTT或串口进来,经过判断节点处理后发给执行器节点,再通过Dashboard可视化回显,整个信息链路一目了然。

2.2 Node-RED消息模型:理解msg.payload是读懂一切的钥匙

刚开始用Node-RED的人,容易被画布上密密麻麻的节点连线搞晕,其实核心只有一件事:消息对象。每个节点处理完数据后,会把结果放进msg.payload传给下一个节点。接串口时,串口节点输出的payload可能是Buffer或字符串;接MQTT时,mqtt节点收到的是从主题订阅到的字符串;处理后的payload可以是一个数字、一个JSON对象、一段指令字符串。

我在温室项目里会规定一套内部消息格式,让每一条设备数据都带设备编号、时间戳和数值,例如:

{ "device": "air_temp_house1", "value": 26.5, "unit": "celsius", "ts": 1735689600000 }

这样后面的判断节点、存储节点、告警节点都会很舒服,不用到处判断字段到底叫a还是叫temperature。统一消息格式是低代码项目最容易忽略的地方,但正是它决定了后面扩展的时候是省事还是返工。

2.3 设备接入的选型思路:串口、以太网和无线的取舍

温室现场最常见的设备接入方式是RS485总线加Modbus RTU协议,原因是布线简单、抗干扰强、传感器成本低。Node-RED侧可以接一块USB转RS485模块,挂到一台ARM工控板上;也可以用支持Modbus TCP的工业网关,把RS485数据转成以太网口,Node-RED通过modbus节点直接读写。

如果温室距离机房远,或者传感器节点分散,我会优先考虑带4G/DTU功能的无线传感器。这类传感器通常直接上报到MQTT服务器,Node-RED订阅对应主题即可,省掉现场布线。需要注意的是,无线传感器走运营商网络会产生流量费用,断网时会丢数据,所以关键决策点还是要有本地有线采集兜底。

执行器侧,我用的是带Modbus地址的继电器模块,例如8路或16路输出,通过Modbus寄存器写单个线圈。这样Node-RED只需调用modbus写节点,就能控制任意一路继电器通断,进而驱动交流接触器控制风机、水泵等大功率设备。这比用一个一个单独射频开关可靠得多,因为Modbus有响应帧,能确认指令是否执行成功。

3. 核心控制流程搭建:从设备接入到自动决策的完整示例

3.1 先定好全局配置,不要在节点里到处写死参数

在搭建流程时我踩过一个坑:一开始图省事,把温度阈值26℃直接写在判断节点里。结果过了一周要改成25.5℃,相当于要找出所有写死温度的地方逐个改。后来我把所有可调参数全部抽到Node-RED的global上下文或一个配置文件节点里。

具体做法是:用一个inject节点,在流程启动时触发一个function节点,把整套默认参数塞进global上下文:

const cfg = { tempHigh: 26, tempLow: 20, humHigh: 85, co2High: 1000, fanDelay: 5, wetCurtainThreshold: 30 }; global.set("cfg", cfg);

在业务逻辑节点中,需要阈值时统一用global.get("cfg").tempHigh。这样以后要调参数,或者不同温室要配不同参数,只需要改这一个节点,甚至可以把参数来源改成HTTP接口,让管理后台远程下发。流可以画得复杂,但参数如果不统一管理,流越长越难维护。

3.2 核心温控逻辑:用function节点代替一堆判断节点

很多Node-RED新手喜欢用switch节点串联嵌套做条件判断,画布上很快变成一团乱麻。比如“温度高且湿度低于80时启动风机”,你需要两个switch再加一个join,如果还有夜间模式、应急模式,基本不可维护。

我的做法是:把组合判断收进一个function节点,用JavaScript写简单的决策函数,画布上只留一条主线。下面是我项目中处理空气温湿度控制的一段简化代码:

const cfg = global.get("cfg"); const temp = msg.payload.value; const rh = msg.payload.rh; let actions = []; if (temp > cfg.tempHigh) { // 高温优先启动风机,持续高温再开湿帘 actions.push("fan_on"); if (temp > cfg.tempHigh + cfg.wetCurtainThreshold) { actions.push("wet_curtain_on"); } } if (rh > cfg.humHigh && temp < cfg.tempHigh) { // 高湿但不高温时,只通风,不降温 actions.push("fan_on"); } msg.actions = actions; return msg;

输出到下一个节点后,再根据actions数组写执行器,例如通过Modbus写线圈。这样做的好处是规则都集中在代码里,可注释、可复用、可测试。对于不太熟悉JavaScript的人,function节点只需要学会if/else和数组操作,难度比想象中低很多。

3.3 告警链路:把异常变成可处理的事件而不是事后发现

智能温室控制除了自动控制,最重要的就是异常告警。我通常在主流程末尾加一个“告警判断”function节点,专门检查当前状态是否触发告警条件:

  • 温度低于冻害阈值或高于热害阈值
  • 停电和恢复供电
  • 设备长时间运行但环境数据无变化,判断执行器是否故障
  • 通信超时:某个传感器超过设定时长不上报

满足条件时,用Node-RED的消息通知节点推送到手机。实践中最简单稳定的方式是接IM群机器人的Webhook:构造一个JSON,POST到机器人地址,手机立刻能收到告警。这套方式不需要写小程序、不用做App,十分钟就能跑通。

需要注意告警必须防抖和升级。我遇到过一晚上收到几百条告警的情况,原因是温度恰好卡在阈值边缘不断抖动,每次上报都触发推送。后来我在function节点里加了一个状态锁:同一个告警,如果已经推送过,必须间隔30分钟才能再次推送,或者等恢复消息消除后才能再次触发,告警疲劳的问题很快就解决了。

4. 多执行器协同策略:水肥一体化、风机湿帘与遮阳的联动决策

4.1 水肥灌溉不是简单的“土壤干了就浇水”

水肥一体化是智能温室里比较容易出问题的环节。如果用土壤湿度传感器触发水泵开关,很容易造成根部长时间积水,影响根系呼吸。我在项目里把灌溉逻辑分成了三层:

  • 第一层,判断是否处于适合作物生长的时间段,例如夜间低温时段不启动灌溉;
  • 第二层,读取土壤湿度、EC、pH数据,根据目标区间综合判断是否缺水和缺养分;
  • 第三层,启动灌溉后设置持续灌水时间,达到设定灌水量后自动停止,同时错开风机湿帘等大功率设备,避免电网冲击。

Node-RED里可以用delay节点设定电磁阀动作持续时间,也可以用function节点写一个简单的定时器状态机。我选了后者,因为需要记录每个灌区的最后灌溉时间、累计流量,并防止多个灌区同时启动。

const lastTime = global.get("lastIrrigationTime") || 0; if (soilMoisture < cfg.soilDryThreshold && Date.now() - lastTime > cfg.irrigationInterval) { msg.command = "valve_on"; msg.duration = cfg.irrigationDuration; global.set("lastIrrigationTime", Date.now()); }

这样即使传感器数据出现短暂波动,也不会触发连续灌水,能有效保护幼苗根系。

4.2 风机、湿帘、侧窗、遮阳网的联动优先顺序

温室的高温控制有多种手段:开侧窗自然通风、开风机强制通风、开湿帘风机水冷降温、拉外遮阳网减少太阳辐射。如果每种设备只按各自阈值独立动作,很容易出现频繁启停,甚至相互打架。我通常用一套“阶梯式升温控制”策略。

温度区间动作策略
< 25℃关闭降温设备,侧窗微开换气
25~28℃开启侧窗,必要时启动一台风机
28~32℃启动全部风机,关闭侧窗让气流穿堂
32~35℃启动湿帘泵,风机+湿帘水冷降温
> 35℃拉外遮阳网,全面降温并触发高温告警

这样每个执行器只在对应温度区间动作,避免随机启停。同时要注意设备之间的物理约束:湿帘启动前必须确保风机已在运行,否则湿气排不出去;冬季夜间要保温,侧窗和风机必须关闭,但长期不通风又会造成棚内湿度过高,这个矛盾要靠“短时通风窗间歇开启”解决。

在Node-RED里实现这种阶梯联动,最简单的方式是把所有判断都写进一个function节点,逐个温度段返回一组设备状态。执行器状态用“设备+优先级”的方式管理,例如风机、湿帘、侧窗各自注册一个状态对象,每次决策后统一计算再下发,而不是让每个温度节点单独控制一条线。这样逻辑清晰,也方便后面加“手动优先”“远程锁定”等模式。

5. 降本增效落地细节:老设备改造、边缘部署与远程运维

5.1 用Modbus把存量手动设备变成可远程控制的设备

项目里最省钱的一环是改造存量设备。很多旧温室已经有手动按钮、接触器和水泵,只缺远程控制能力。我没有把配电柜整体换掉,而是采购了带Modbus RTU的继电器输出模块,将其接入原控制回路,保留手动旁路开关作为应急。Node-RED通过Modbus写线圈,就能远程控制接触器。

具体实施步骤如下:

  1. 确认原控制柜内接触器线圈电压,选配合适的中间继电器或固态继电器;
  2. 在控制柜中新增一个Modbus RTU继电器模块,供电用12V或24V直流;
  3. 用屏蔽双绞线把模块的RS485 A/B接到网关或USB转RS485;
  4. 在Node-RED中配置modbus节点,填写从站地址、功能码和寄存器地址;
  5. 先用串口调试工具验证寄存器地址正确,再接入Node-RED流程。

这样改造一台旧温室的硬件成本可以控制在很低的水平,现场工人仍然能手动操作,主控远程也能操作,解决了“改造后手动失效”的顾虑。

5.2 边缘部署选型与断网续传:不能把鸡蛋全放在云上

温室现场环境比较恶劣,高温、高湿、灰尘大,我不会把Node-RED部署在普通服务器机房,而是放在现场控制箱里的ARM工控机上。选型核心标准是:低功耗、被动散热、带双网口或4G模块、可插内存卡。这类设备的价格不高,足够跑Node-RED、MQTT broker和本地数据库。

联网设计上,控制流程所有传感器采集和执行器控制都在本机完成,云端只做远程看板和历史存储。一旦断网,本地自动控制照常运行,数据先写入本地数据库或文件,网络恢复后再通过缓存节点补传。这样即使运营商网络抖动,也不会影响温室安全。

我在实际项目里还加了看门狗机制:Node-RED以系统服务方式运行,配置了自动重启;另有一个健康检查节点,定期检查主进程是否正常,发现异常就执行重启,同时推送告警。这套机制保证系统可以长期无人值守运行。

5.3 轻量可视化与能耗分析:给管理者一个看板而不是一堆日志

降本增效的另一层含义,是让管理者和工人能快速掌握温室状态,而不是去翻一堆日志。我用Node-RED Dashboard搭了一个监控看板,核心页面包括:

  • 总览页:各温室实时温湿度、光照强度、CO2浓度,用仪表盘和曲线展示;
  • 设备页:各执行器当前开关状态和累计运行时长;
  • 能耗页:电表数据、风机和水泵的运行时长,辅助发现浪费;
  • 告警页:最近24小时告警事件,支持按设备筛选。

这些页面用Dashboard节点自动生成,无需写前端代码。数据存储方面,我用轻量级时序数据库保存温湿度历史,再按天聚合成均值和极值,看板每几秒刷新一次,对现场监控完全够用。

能耗分析值得多说一点。我在风机电路里加了电能表,通过Modbus读取实时功率和累计电量。Node-RED每5分钟记录一次功率数据,按天汇总。后来发现某个温室的风机每天多运行了两个多小时,对照看板才发现是温控阈值设置得太低、执行器频繁启动。调整策略之后,每月电费明显下降。这就是降本增效真正落到纸面上的体现。

6. 实际部署后踩过的坑:排查链路与修复方法

6.1 共享MQTT主题导致跨棚设备误动作

项目上线第一个月,出现过一次奇怪故障:1号温室的高温风机启动后,2号温室的湿帘也跟着启动。一开始怀疑是继电器模块串线,用万用表测了一遍没发现问题,后来打开Node-RED的调试窗口,才发现两套温室订阅了同一个MQTT主题前缀。

原因是MQTT broker上使用了设备类型作为主题,比如greenhouse/temp,两个温室的数据都会发布到这一个主题。Node-RED一旦订阅它,自然会把两个温室的数据混在一起处理,条件判断就乱了。修复方式是把主题改成按场地、温室、设备类型和编号隔离,例如siteA/house1/air_temp、siteA/house2/air_temp,并在流程入口加过滤节点,只处理与当前温室ID一致的消息。

这个坑提醒我:主题命名就是系统架构的一部分,设计阶段必须先规划好“场地/温室/设备类型/设备编号”的层级,而不是先跑通再改名。改主题意味着所有下游节点、存储逻辑都要一起改,代价比想象中大得多。

6.2 传感器数据抖动导致设备频繁启停

另一个常见坑是温湿度传感器上报的数据抖动。比如实际温度稳定在25℃,传感器偶尔跳变到26.3℃,刚好超过阈值,设备就会反复启停,既磨损接触器,又浪费电。

我在数据处理链路上加了一个防抖节点:用滑动窗口保存最近5次采样,只有当连续3次超过阈值才下发动作;同时设定设备动作保持时间,比如风机启动后至少运行10分钟,即使温度短暂回落也不立刻停止。这样设备启停频率大幅降低。

代码思路大致如下:

const last = global.get("fanWindow") || []; last.push(temp); if (last.length > 5) last.shift(); global.set("fanWindow", last); const overCount = last.filter(v => v > cfg.tempHigh).length; if (overCount >= 3) { msg.action = "fan_on"; }

另外还要处理乱序上报的问题。某些无线传感器延迟不稳定,先发的数据反而后到,如果拿旧数据做决策,会造成错误动作。我的做法是在每个采集分支给数据打上节点接入时间戳,在决策节点里检查当前数据时间是否比上一次处理的数据旧,旧数据一律丢弃。时间戳校验虽然多写几行,但能避免很多莫名其妙的联动。

6.3 Node-RED服务挂掉的兜底与恢复

最后说说服务稳定性。Node-RED毕竟是软件,会遇到内存占用增长、流配置加载失败等情况。最开始我只用普通脚本方式启动,运行两个月后遇到一次进程退出,现场设备全部失去控制,幸好当时环境变化不大,才没有造成损失。

之后我做了两件事。第一,把Node-RED注册为系统服务,配置自动重启,让它在异常退出后自动拉起。第二,写一个健康检查节点,定时向本地固定端口发送请求,如果不通就重启服务并推送告警。另外,每次修改流版本之前先导出备份到另一台设备,出问题可以马上回滚到上一个可用版本。

这些措施看似简单,但直接决定这套系统能不能做到“无人值守”。我见过很多Demo项目只验证了流程能跑通,却没有考虑服务挂了怎么办。真到生产环境,一次宕机造成的损失,足够让整个项目被否定。

最后分享一点个人体会。做这套系统最大的收获,不是学会了Node-RED这个工具,而是意识到降本增效的关键不在于用多便宜的硬件,而在于让修改变得便宜。Node-RED这种低代码方式,恰好把策略迭代的边际成本压得很低,特别适合像温室控制这样需求长期演进的场景。如果你想自己尝试,我建议不要追求一次性做完整个大棚的自动化,而是先从“一个温室的温度控制”这个小闭环跑起来,把参数管理、告警防抖、服务守护这些基本功做扎实,再逐步扩展到水肥、遮阳、多温室联动。每一步都能验证,出问题也容易定位,希望这些经验能帮你少走一些弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询