智慧农业-自动控制逻辑开发:阈值触发自动浇水、自动通风、温控联动
2026/8/31 23:26:32 网站建设 项目流程

自动控制逻辑开发:阈值触发自动浇水、自动通风、温控联动

作者:黒漂技术佬

前面四篇文章都在讲数据怎么采集、怎么传输、怎么存储。这当然重要——但说实话,纯「数据大屏」的项目,农户看了只会说一句「好是好,但能不能帮我干点活?」

本文就来回答这个问题:怎么让系统自动干活。温度高了自动开风机,土壤干了自动浇水,光照不够自动补光——真正的智慧农业,数据不是终点,控制才是。

一、自动化的核心价值

传统大棚种植最痛苦的是什么?是「人不能离」

夏天中午棚内温度飙升到 40℃,你必须冲进去开风机开天窗;凌晨湿度骤降,又得爬起来开加湿器。一个疏忽,一季的收成就打了水漂。

自动化控制要解决的就是这个痛点。它的核心价值有三层:

  1. 解放人力:24 小时自动值守,人不用绑在大棚里
  2. 精准控制:传感器采集的精度远超人的感知,28.5℃ 和 30℃ 的区别你感觉不到,但机器能
  3. 联动决策:温度和湿度不是孤立问题——开风机降温的同时会带走湿度,系统能自动计算平衡点,人就很难做到

二、控制闭环架构

自动控制的本质是一个「感知→决策→执行→反馈」的闭环:

┌─────────┐ 传感器数据 ┌─────────────┐ 控制指令 ┌─────────┐ │ 传感器 │ ───────────────→ │ 规则引擎 │ ──────────────→ │ 执行器 │ │ (温度等) │ │ (阈值判断) │ │ (风机等) │ └─────────┘ └─────────────┘ └─────────┘ ↑ │ │ ┌─────────┐ │ └───────────────────────│ 反馈 │←───────────────────────┘ 传感器持续采集验证效果 └─────────┘ 执行后传感器值变化

举个具体例子:温度传感器上报 32℃ → 规则引擎判断超阈值 → 下发「开风机」指令 → 风机启动 → 1 分钟后温度降到 29℃ → 规则引擎判断达标 → 关闭风机。这就是一个完整的控制闭环。

三、阈值触发规则设计

先列一个智慧农业的典型控制规则表:

控制场景触发条件执行动作恢复条件
高温降温温度 > 30℃开风机 + 开天窗温度 < 28℃
低温加热温度 < 15℃关天窗 + 开加热器温度 > 18℃
土壤干旱浇水土壤湿度 < 30%开水泵灌溉湿度 > 70%
湿度过高排湿湿度 > 90%开风机排湿湿度 < 80%
湿度过低加湿湿度 < 60%开喷雾/加湿器湿度 > 70%
光照不足补光光照 < 5000 Lux开补光灯光照 > 8000 Lux
CO2不足补充CO2 < 300ppm开CO2发生器CO2 > 500ppm

注意每个规则都有触发阈值恢复阈值,而且两者不同(这叫「滞回控制」)。比如温度高于 30℃ 开风机,要等温度降到 28℃ 才关——如果触发和恢复用同一个阈值,设备就会在边界上疯狂开关(振荡),电机烧了都不知道为啥。

四、规则引擎实现:三种方案对比

方案一:定时轮询(最简单,适合初期)

@ComponentpublicclassThresholdCheckScheduler{@AutowiredprivateInfluxDBServiceinfluxDBService;@AutowiredprivateControlServicecontrolService;// 每30秒检查一次阈值@Scheduled(fixedDelay=30000)publicvoidcheckThresholds(){// 查询最近一次所有传感器的读数List<SensorReading>latestReadings=influxDBService.queryLatestReadings();for(SensorReadingreading:latestReadings){ThresholdRulerule=ruleConfig.getRule(reading.getGreenhouseId(),reading.getSensorType());if(rule.isExceeded(reading.getValue())){controlService.execute(reading.getGreenhouseId(),rule.getAction());}}}}

优点是实现简单,缺点是有延迟(最多 30 秒),而且每条规则都要查库,传感器多了效率低。

方案二:MQTT 实时消费(推荐)

直接在消息消费时判断阈值,延迟最低:

@ComponentpublicclassRealTimeThresholdHandler{@AutowiredprivateControlServicecontrolService;@AutowiredprivateRuleConfigruleConfig;// 防抖计数器:Key = "greenhouseId:sensorType", Value = 连续超阈值次数privatefinalMap<String,Integer>exceedCounters=newConcurrentHashMap<>();// 冷却记录:Key = "greenhouseId:action", Value = 上次触发时间privatefinalMap<String,Long>cooldownMap=newConcurrentHashMap<>();privatestaticfinalintDEBOUNCE_COUNT=3;// 连续3次超阈值才触发privatestaticfinallongCOOLDOWN_MS=300_000;// 5分钟冷却publicvoidonSensorData(SensorDatadata){StringruleKey=data.getGreenhouseId()+":"+data.getSensorType();ThresholdRulerule=ruleConfig.getRule(ruleKey);if(rule==null||!rule.isExceeded(data.getValue())){// 未超阈值,重置防抖计数器exceedCounters.remove(ruleKey);return;}// 超阈值 → 防抖计数 +1intcount=exceedCounters.merge(ruleKey,1,Integer::sum);if(count<DEBOUNCE_COUNT){return;// 还不够次数,继续观察}// 检查冷却时间(避免频繁触发同一个设备)StringactionKey=data.getGreenhouseId()+":"+rule.getAction().getName();LonglastTrigger=cooldownMap.get(actionKey);if(lastTrigger!=null&&System.currentTimeMillis()-lastTrigger<COOLDOWN_MS){return;}// 触发控制cooldownMap.put(actionKey,System.currentTimeMillis());exceedCounters.remove(ruleKey);// 触发后重置计数器controlService.execute(data.getGreenhouseId(),rule.getAction());log.info("阈值触发: 大棚={}, 传感器={}, 当前值={}, 阈值={}, 动作={}",data.getGreenhouseId(),data.getSensorType(),data.getValue(),rule.getThreshold(),rule.getAction().getName());}}

这里有两个关键的保护机制

防抖(Debounce):传感器可能因为电磁干扰等原因偶尔读到一个异常值(比如温度突然跳到 50℃ 又瞬间回来)。如果读到一次异常就触发控制,就可能误开风机。解决方案是「连续 N 次超阈值才触发」——连续 3 次(如果是 5 秒一次采集,就是 15 秒内持续超标)才算真的超标。

冷却(Cooldown):控制操作执行后,环境变化需要时间。比如开水泵灌溉后,土壤湿度不会立刻从 25% 跳到 60%。如果不加冷却,接下来的 5 分钟内系统会反复检测到「湿度 < 30%,需要浇水」。冷却机制规定「同一设备同一动作 5 分钟内不再重复触发」,避免控制指令满天飞。

方案三:EMQX 规则引擎(Broker 内置)

如果你用的是 EMQX 企业版,它的规则引擎可以直接在 Broker 侧做简单的阈值判断:

-- EMQX 规则引擎 SQLSELECTpayload.temperatureastemp,payload.humidityashum,topicFROM"agriculture/+/+/sensor/#"WHEREpayload.temperature>30

超阈值后可以直接触发 HTTP 回调到你的控制服务。这个方案的好处是延迟极低(处理发生在 Broker 内部),适合对实时性要求极高的场景。缺点是逻辑不能太复杂,而且依赖 EMQX 企业版。

推荐组合拳:方案二 + 方案三。EMQX 规则引擎做第一层快速过滤,对超出明显安全范围的数据直接触发告警;SpringBoot 消费者做第二层精细化判断,考虑防抖、冷却、联动逻辑。

五、联动控制:别顾此失彼

温室环境是相互耦合的——你不能孤立地控制某一个参数。

举个典型场景:温度 33℃(超了)、湿度 55%(也低了)。如果只看温度,系统开风机降温——结果风机一吹,湿度从 55% 降到了 40%,掉进更低的坑里。

正确的联动做法是:

publicclassLinkedControlLogic{publicvoidhandleTemperatureHigh(SensorDatadata){doubletemp=data.getTemperature();doublehumidity=data.getHumidity();// 开风机降温controlService.sendCommand(data.getGreenhouseId(),"fan_on");// 联动:如果温度高且湿度低,同时开启加湿器if(humidity<60){log.info("联动:降温同时加湿,当前湿度={}%",humidity);controlService.sendCommand(data.getGreenhouseId(),"humidifier_on");}// 联动:开风机前检查天窗是否已开DeviceStatusskylight=deviceService.getStatus(data.getGreenhouseId(),"skylight");if(!skylight.isOpen()){controlService.sendCommand(data.getGreenhouseId(),"skylight_open");}}}

联动逻辑的核心是「不要只看一个变量」。在做任何控制决策时,都要检查组关联参数是否在安全范围内。

六、手动/自动模式切换

自动控制再聪明,也得给人留个「刹车」。有时候农户要进棚作业、要喷药、要采摘——这些场景下自动控制可能会帮倒忙。

Topic 设计:

agriculture/{farmId}/{greenhouseId}/mode Payload: {"mode": "auto"} 或 {"mode": "manual"}

控制服务在执行前必须检查当前模式:

publicvoidexecute(StringgreenhouseId,ControlActionaction){// 先查模式Stringmode=redisService.get("greenhouse:mode:"+greenhouseId);if("manual".equals(mode)){log.info("手动模式,跳过自动控制: 大棚={}, 动作={}",greenhouseId,action.getName());return;}// 自动模式,正常执行mqttCommandService.sendCommand(greenhouseId,action);// 记录控制日志controlLogService.record(ControlLog.builder().greenhouseId(greenhouseId).action(action.getName()).mode("auto").triggerCondition(action.getTriggerCondition()).threshold(action.getThreshold()).currentValue(action.getCurrentValue()).timestamp(System.currentTimeMillis()).result("success").build());}

手动模式优先级高于自动——这是铁律。机器可以辅助人,但不能凌驾于人。

七、控制日志:审计比控制还重要

每执行一次控制操作,都要留下完整的日志记录。不是为了形式主义,而是有实际价值:

CREATETABLEcontrol_log(idBIGINTPRIMARYKEYAUTO_INCREMENT,greenhouse_idVARCHAR(50)NOTNULL,actionVARCHAR(50)NOTNULLCOMMENT'fan_on/humidifier_on/pump_on等',modeVARCHAR(10)NOTNULLCOMMENT'auto/manual',trigger_conditionVARCHAR(200)COMMENT'触发条件描述',threshold_valueDECIMAL(10,2)COMMENT'阈值',current_valueDECIMAL(10,2)COMMENT'触发时的传感器值',execute_timeDATETIMENOTNULL,resultVARCHAR(20)NOTNULLCOMMENT'success/fail',fail_reasonVARCHAR(500)COMMENT'失败原因',INDEXidx_time(execute_time),INDEXidx_greenhouse(greenhouse_id,execute_time));

这些日志的用途:

  1. 事后排查:哪天作物状态不对,可以回溯「当时系统干了什么」
  2. 阈值优化:统计分析触发频率——如果降温风机一天开了 50 次,说明你阈值设得有问题
  3. 设备健康度:某水泵触发频率突然翻倍,可能是传感器失准或管路泄漏的预警信号

总结

自动控制的五条军规:

  1. 滞回控制:触发和恢复用不同阈值,避免设备振荡
  2. 防抖 + 冷却:连续 N 次超标才触发,触发后 N 分钟内不重复
  3. 联动判断:做任何控制前,检查关联参数
  4. 手动优先:手动模式一开,自动全部让路
  5. 控制必记日志:没有审计的控制是定时炸弹

数据采集做得再好,最终产生价值的还是「控制」。毕竟,农户要的不是漂亮的温湿度曲线,而是好收成。

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

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

立即咨询