自动灌溉系统:AI 什么时候浇水,比老农还准?

灌溉是农业最高频的操作,也是浪费最严重的环节。老农的经验是「看着土干了就浇」,一浇就是大水漫灌,蒸发掉的比渗进土里的多。这篇从简单的定时/阈值出发,做到结合天气预报、土壤趋势和作物生长周期的智能决策。


灌溉的三个层次

级别 策略 优点 缺点
L1 规则控制 定时 / 阈值 简单可靠 不管明天是否下雨,照浇不误
L2 环境联动 阈值 + 天气预报 + 渗透模型 省水 30%+ 需要外部数据
L3 AI 决策 模型预测最优灌溉方案 理论上最优 需要大量历史数据

90% 的场景做到 L2 已经碾压人工经验。我们先搞 L1 和 L2。


L1:规则控制——定时 + 阈值

最基础的模式,实现也最简单。

定时灌溉

每天早上 6 点、傍晚 18 点各浇一次,每次 10 分钟。

// Spring Boot 定时任务
@Component
public class ScheduledIrrigation {
    @Autowired
    private DeviceCmdService cmdService;
    
    @Scheduled(cron = "0 0 6,18 * * ?")  // 每天 6:00 和 18:00
    public void timedIrrigate() {
        cmdService.sendCmd("pump_01", CmdRequest.builder()
            .cmd("irrigate")
            .params(Map.of("duration", 600, "valve", 1))
            .build());
    }
}

阈值灌溉

土壤湿度低于 25% 且持续超过 30 分钟,自动开阀;高于 45% 自动关阀。

这个逻辑方在告警引擎里扩展——告警不仅发通知,还能触自动作:

public void evaluate(SensorData data) {
    // ... 前面告警评估 ...
    
    // 灌溉触发
    if ("soil_moisture".equals(rule.getField()) && triggered) {
        evaluateIrrigation(data);
    }
}

private void evaluateIrrigation(SensorData data) {
    // 获取该设备关联的灌溉执行器
    String pumpId = deviceLinkService.getActuator(data.getDev(), "pump");
    if (pumpId == null) return;
    
    Boolean pumpStatus = deviceStateCache.get(pumpId + ":irrigating");
    
    if (data.getSoilMoisture() < 25.0 && pumpStatus != Boolean.TRUE) {
        cmdService.sendCmd(pumpId, Map.of("cmd", "irrigate", "duration", 600));
        deviceStateCache.put(pumpId + ":irrigating", true);
    } else if (data.getSoilMoisture() > 45.0 && pumpStatus == Boolean.TRUE) {
        cmdService.sendCmd(pumpId, Map.of("cmd", "off"));
        deviceStateCache.put(pumpId + ":irrigating", false);
    }
}

ESP32 端的执行器代码(加个 PWM 调速控制电磁阀开度,而不是一味全开):

// 电磁阀控制——PWM 渐进式开关,减少水锤效应
#define VALVE_PIN 12

void startIrrigation(int durationSec, int flowPercent) {
    // 1. 先低压预开 3 秒(防冲击)
    ledcWrite(0, map(30, 0, 100, 0, 255));
    delay(3000);
    
    // 2. 升到目标开度
    ledcWrite(0, map(flowPercent, 0, 100, 0, 255));
    
    // 3. 持续 durationSec 后自动关
    vTaskDelay(pdMS_TO_TICKS(durationSec * 1000));
    ledcWrite(0, 0);
    Serial.println("灌溉完成");
}

L2:环境联动——看天浇水

昨天浇过水,今天下暴雨,你这 10 分钟的水就算白浇了(还可能导致涝根)。接一个天气预报 API,浇前判断:

@Service
public class SmartIrrigationService {
    @Autowired
    private WeatherService weatherService;
    @Autowired
    private TDengineService tdengine;
    
    public boolean shouldIrrigateNow(String deviceId) {
        // 1. 当前土壤湿度
        double soilMoisture = tdengine.getLatest(deviceId, "soil_moisture");
        if (soilMoisture > 40) return false;  // 够湿,不需要
        
        // 2. 未来 6 小时天气预报
        WeatherForecast forecast = weatherService.getForecast(deviceId, 6);
        if (forecast.getRainProbability() > 60 && forecast.getRainMm() > 2) {
            log.info("未来 6h 降雨概率 {}%,预计雨量 {}mm,跳过灌溉", 
                     forecast.getRainProbability(), forecast.getRainMm());
            return false;
        }
        
        // 3. 今天已浇水量
        double todayIrrigation = irrigationLogService.getTodayTotal(deviceId);
        double maxDaily = getCropDailyWaterLimit(deviceId);
        if (todayIrrigation >= maxDaily) {
            log.info("今日已浇 {}L,达上限 {}L,跳过", todayIrrigation, maxDaily);
            return false;
        }
        
        // 4. 土壤渗透率——刚浇完不久土还没渗下去
        LocalDateTime lastIrrigation = irrigationLogService.getLastTime(deviceId);
        if (lastIrrigation != null 
            && ChronoUnit.MINUTES.between(lastIrrigation, LocalDateTime.now()) < 60) {
            return false;
        }
        
        return true;
    }
}

天气预报数据源:和风天气 API 免费版每天 1000 次调用,对几十个大棚绰绰有余。精度在县城级别,大棚场景够用——反正你需要的只是「未来 6 小时会不会下雨」这个布尔值。

@Service
public class WeatherService {
    private final String API_KEY = "你的和风天气Key";
    private final String API_URL = "https://devapi.qweather.com/v7/weather";
    
    public WeatherForecast getForecast(String deviceId, int hours) {
        // 根据设备经纬度查询
        Device device = deviceService.getByDeviceId(deviceId);
        String url = String.format(
            "%s/%shourly?location=%s,%s&key=%s",
            API_URL, hours > 6 ? "24h" : "3h",
            device.getLng(), device.getLat(), API_KEY);
        
        // 解析返回,取未来 hours 小时内的降水概率和降水量
        // ...
    }
}

L3:AI 决策(简介)

做到 L2 已经省水 30%+。L3 用机器学习做灌溉模型,输入特征:

  • 过去 7 天土壤湿度趋势、温度趋势
  • 未来 48 小时天气预报
  • 作物生长阶段(苗期/生长期/结果期,需水量不同)
  • 土壤类型(沙土渗水快、黏土保水强)

输出:灌溉时长最佳时间点

这个模型需要至少一个生长季的数据才能训练。建议先用 L2 跑一个季度,攒够数据再上 LSTM/Transformer,预测未来 24 小时的土壤湿度变化曲线:

# 输入: (7天 * 288点/天 = 2016个历史数据点 + 天气预报)
# 输出: 未来 24 小时的土壤湿度预测曲线
model = Sequential([
    LSTM(64, return_sequences=True, input_shape=(2016, features)),
    Dropout(0.2),
    LSTM(32),
    Dense(288),  # 24h * 12points/h
])

但在那之前,L2 已经够用了。别在只有两个大棚的时候就上 Transformer——等你有了 200 个大棚的数据再说。


执行器安全——如果阀门坏了怎么办?

远程控制最怕的是:开了阀门,结果忘了关(或关了但没关紧),水一直流,淹了棚。

三保险机制:

  1. 硬件上限开关:ESP32 控制继电器时,代码里设最大持续时长(比如 30 分钟),超时强制切断
  2. 流量传感器:在主管道串一个霍尔流量计,如果检测到流量异常(开阀了但没水流/关阀了还有水流),立刻告警
  3. 人工急停:小程序里一个大大的红色「紧急停止」按钮,点一下关所有阀门
// ESP32 超时保护
#define MAX_IRRIGATION_SEC  1800  // 30 分钟硬上限

unsigned long valveOpenSince = 0;

void loop() {
    if (valveStatus == OPEN && valveOpenSince > 0) {
        if ((millis() - valveOpenSince) / 1000 > MAX_IRRIGATION_SEC) {
            Serial.println("⚠️ 灌溉超时,强制关闭!");
            closeValve();
        }
    }
}

成本与效果

  • 一个电磁阀:12V DC 常闭型,30 元
  • 一个霍尔流量计:YF-S201,8 元
  • 继电器模块:2 路 5V,6 元

一户菜农一个棚,灌溉水费一年大约 2000 元。上这套系统(硬件投入 300 元),省水 30%,一年回本还有余。


下一篇:《大棚环境控制:温湿度、光照、CO₂ 的全自动调节》——通风扇、遮阳网、补光灯、CO₂ 气肥,四套执行器的联动策略和 PID 控制。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐