4. 土壤湿度闭环灌溉控制实现

闭环控制对象与信号链

本节实现一个以土壤湿度为反馈量的闭环灌溉控制器。核心思路是:把湿度传感器输出的模拟电压换算成体积含水率,经滑动平均滤波抑制噪声,再送入带滞回的阈值比较器,决定电磁阀开或关。滞回的作用是避免湿度在阈值附近抖动时电磁阀频繁通断。

控制对象与信号链如下:传感器探头埋设在根区深度,输出 0.5~3.0 V 电压(对应 0~60% 体积含水率);ADC 采样后换算为湿度百分比;滤波窗口取 8 个采样点;启动阈值设为 35%,停止阈值设为 45%,即湿度低于 35% 开阀灌溉,高于 45% 关阀,中间区间保持当前状态。

闭环信号链 土壤湿度传感器 0.5~3.0 V ADC 采样换算 → 体积含水率 % 滑动平均滤波 窗口 N = 8 滞回比较器 开阀 35% / 关阀 45% 中间区保持 电磁阀驱动 继电器 / MOSFET 灌溉改变土壤含水率 → 反馈回传感器 滞回状态与湿度区间 0% 60% 湿度 < 35%:开阀灌溉 35%~45%:保持当前状态 湿度 > 45%:关阀停止 35% 45% 阀门 ON 阀门 OFF 湿度升至 45% 以上 湿度降至 35% 以下

采样换算与滤波实现

传感器输出经 12 位 ADC 采集,参考电压 3.3 V。按线性标定:含水率 θ(%) = (V − 0.5) / (3.0 − 0.5) × 60,其中 V 为传感器电压。滤波采用环形缓冲的滑动平均,窗口 8 点,每 1 秒采样一次,即滤波输出滞后约 4 秒,对灌溉这种慢过程完全可接受。

#define ADC_MAX      4095.0f
#define VREF         3.3f
#define V_DRY        0.5f
#define V_WET        3.0f
#define THETA_SPAN   60.0f
#define FILTER_N     8

static float buf[FILTER_N];
static int   idx = 0;
static int   cnt = 0;

/* 单次采样:ADC 原始值 → 电压 → 含水率(%) */
float read_moisture(void) {
    int raw = adc_read_channel(0);          /* 0..4095 */
    float v = raw / ADC_MAX * VREF;
    float theta = (v - V_DRY) / (V_WET - V_DRY) * THETA_SPAN;
    if (theta < 0.0f)  theta = 0.0f;
    if (theta > 60.0f) theta = 60.0f;
    return theta;
}

/* 滑动平均滤波 */
float filter_moisture(float x) {
    buf[idx] = x;
    idx = (idx + 1) % FILTER_N;
    if (cnt < FILTER_N) cnt++;
    float sum = 0.0f;
    for (int i = 0; i < cnt; i++) sum += buf[i];
    return sum / cnt;
}

滞回比较与阀门输出

滞回比较器用两个阈值和一个状态变量实现:当前阀门关闭时,只有湿度低于 35% 才开阀;当前阀门开启时,只有湿度高于 45% 才关阀。这样在 35%~45% 区间内阀门状态保持不变,避免频繁启停。

#define TH_ON   35.0f   /* 低于此值开阀 */
#define TH_OFF  45.0f   /* 高于此值关阀 */

static int valve_on = 0;

void control_step(float theta_f) {
    if (!valve_on && theta_f < TH_ON) {
        valve_on = 1;
        valve_set(1);            /* 继电器吸合,电磁阀通电 */
    } else if (valve_on && theta_f > TH_OFF) {
        valve_on = 0;
        valve_set(0);            /* 断电关阀 */
    }
    /* 35% ≤ θ ≤ 45%:保持原状态,不动作 */
}

/* 主循环:1 秒周期 */
void loop_1s(void) {
    float raw = read_moisture();
    float theta_f = filter_moisture(raw);
    control_step(theta_f);
}

参数选择与验证判据

滞回带宽(45% − 35% = 10%)应大于滤波后湿度的波动幅度,否则仍会抖动。若实测灌溉后湿度上升速率约 1.5%/分钟,则从 35% 升到 45% 约需 6~7 分钟,单次灌溉时长合理。验证时可用串口打印滤波后湿度与阀门状态,观察以下判据:

  • 湿度从 40% 缓慢下降穿越 35% 时,阀门应恰好开启一次,不出现反复通断。
  • 灌溉过程中湿度上升穿越 45% 时,阀门应关闭,且此后在 35%~45% 区间内保持关闭。
  • 人为在传感器附近浇水使湿度快速跳变,滤波输出应平滑过渡,不引起阀门误动作。
若现场电磁阀为 24 V 交流供电,继电器触点需加 RC 吸收或选用固态继电器,避免感性负载关断时干扰 ADC 采样;可在采样前短暂关闭阀驱动或增加采样延时。