
简介一份基于Atmel SAM L21 J18B低功耗单片机的嵌入式植物浇水控制应用工程面向智能农业、物联网及嵌入式系统学习者适合需要实现土壤湿度监测、自动灌溉和远程监控的开发者参考。资源以zip压缩包形式提供整体约38.06MB压缩包内文件清单未在下载页单独展示工程围绕MATLAB数据分析与微控制器协同工作涵盖ADC采样、传感器数据处理、RTC定时控制、RTOS任务调度及低功耗电源管理等多个设计环节。目前已有45人浏览学习既可作为课程设计、电子竞赛的完整参考项目也可用作产品原型开发的切入点。借助包内内容读者可理解从硬件选型、电路布局到嵌入式程序编写再到MATLAB算法建立与联调的完整流程并可据此扩展湿度预测模型、无线通信控制等功能形成更智能的浇水方案。1. 办公室绿植的无人值守方案低功耗单片机该选谁办公室窗台上的绿植周末两天没人浇水周一回来叶子就蔫了。真正的难点不是让水泵转起来而是让电池撑过整个夏天。基于 ATSAML21J18B 单片机开发板的嵌入式植物浇水控制应用解决的就是这个组合问题先用低功耗 Cortex-M0 采集土壤湿度再用状态机决策水泵启停最后让系统大部分时间睡在微安级电流里。ATSAML21J18B 属于 Microchip SAM L21 系列48MHz 主频、256KB Flash、32KB SRAM待机功耗约 4µA。开发板和应用落到工程上就是一张外设连接表、一套可抄的 C 状态机代码以及一组实测的浇水参数三者配合才能做到「平时不耗电、该浇才浇」。谁适合用这个方案做过单片机点亮 LED、想往低功耗方向深入的嵌入式工程师以及做智能家居、小型农业监测、需要省电采样策略的从业者。示例代码以 ATSAML21J18B 的 HAL 为准不绑定具体开发板型号。2. ATSAML21J18B 开发板的选型理由与最小硬件连接2.1 为什么选这颗单片机待机功耗是植物浇水应用的第一指标植物浇水是典型的慢变系统土壤湿度一天内的变化不超过几十个百分点采样周期取 5 分钟完全够用。这意味着单片机 99% 的时间都在空闲状态决定续航的不是主频而是待机电流。SAM L21 系列在 48MHz 活动模式下电流约 35µA/MHz进入 Standby 后配合 RTC 保持计时整机电流约 3.9µA两节 AA 电池可以跑一年以上。单片机内核典型待机电流适合场景ATSAML21J18BCortex-M03.9µA电池供电传感节点、本方案STM32L431Cortex-M43.4µA需要 DSP、浮点运算ESP32Xtensa LX610µA 以上需要 Wi-Fi、云端联动从外设角度看这颗芯片自带 12 位 ADC、两组 SERCOM可配置为 UART/I2C/SPI、RTC 和看门狗植物浇水应用需要的模块全部内置不需要再挂额外芯片。选它能省掉「低功耗单片机 外部前端」的组合把传感、决策、驱动三件事放在一颗芯片上完成BOM 和调试链路都更短。2.2 外设分配表土壤湿度、水泵驱动与调试串口的引脚规划开发板引出引脚有限接线前先做一张分配表比边接边试可靠得多。以下是一套常见的规划传感器、执行器和人机接口互不冲突外设引脚复用功能说明土壤湿度传感器PA02AIN012 位 ADC 输入接传感器模拟输出水泵 MOS 管驱动PB10GPIO 输出经 AO3400 驱动 3.3V 微型水泵UART 调试PA10 / PA11SERCOM3115200-8-N-1打印湿度与状态OLED 显示可选PA16 / PA17SERCOM1 I2C显示湿度百分比与电池电压传感器输出端到 PA02 之间串一个 1kΩ 电阻再并联 100nF 电容滤掉电源纹波带来的读数抖动。水泵不要用 GPIO 直接驱动3.3V 单片机引脚输出电流有限接一个 N-MOSAO3400用 PB10 控制栅极泵由电池正极供电。调试串口留在开发板上还有个好处量产前跳掉仅保留 PA02 和 PB10 两根信号线进主控整机故障率会明显下降。2.3 最小工程Microchip Studio 下的裸机框架这类应用不建议上 RTOS任务只有「采样、决策、浇水、计时」四个裸机状态机更好排查。开发环境用 Microchip Studio 或 MPLAB X新建工程时用 Atmel START 生成初始化代码把 ADC0、RTC、SERCOM3、WDT 勾上生成后入口就是 atmel_start_init。主函数只做两件事初始化然后进入由 RTC 唤醒的主循环。#include atmel_start.h #include hal_adc_sync.h #include hal_gpio.h #define PUMP_PIN PIN_PB10 volatile uint8_t wakeup_flag 0; void RTC_0_Handler(void) { wakeup_flag 1; /* RTC 定时唤醒置位后主循环处理 */ RTC_0_rtc_clear_interrupt(); } int main(void) { atmel_start_init(); /* 时钟、GPIO、ADC、RTC、WDT 初始化 */ gpio_set_pin_direction(PUMP_PIN, GPIO_DIRECTION_OUT); gpio_set_pin_level(PUMP_PIN, false); /* 上电默认关泵防止误喷 */ while (1) { if (wakeup_flag) { wakeup_flag 0; watering_poll(); /* 采样湿度并按状态机决策 */ } sleep_mode_enter(); /* 进入 Standby见第 4 章 */ } }atmel_start_init 由 Atmel START 生成负责把时钟配置到 48MHz、使能需要用到的外设和中断。PUMP_PIN 对应数据手册上的 PB10上电先拉低是安全设计否则复位瞬间水泵可能因为引脚浮空而误转。watering_poll 的实现放在第 3 章。sleep_mode_enter 不是标准库函数是我们在第 4.2 节封装的 Standby 进入函数。Microchip 官方例程库和不少嵌入式开源项目都提供 SAM L21 的 low-power 例程对着烧录一遍就能确认这套框架的基本形态。3. ATSAML21J18B 的土壤湿度采样与浇水控制状态机实现3.1 电容式湿度传感器的 ADC 采样与均值滤波参数市面常见的土壤湿度传感器分两类。电阻式靠两根金属探针测土壤导电率便宜但直流极化会让探针几个月内氧化读数漂移明显电容式用 PCB 铜箔做极板测介电常数不与土壤金属离子直接接触寿命长。对无人值守的浇水控制应用电容式是更稳的选择。电容式传感器输出 0~3.3V 模拟电压干燥时电压偏高约 2.6V湿润时偏低约 1.2V正好落在 ATSAML21J18B 的 12 位 ADC 量程内。ADC 采样不能只读一次。传感器输出经过输出电阻和滤波电容形成一阶低通单次读数的噪声通常在 ±30 counts直接用于阈值判断会出现干湿抖动。常见做法是每个采样点读 8 次、间隔 10ms取平均作为有效值static uint16_t read_soil_moisture(void) { uint16_t raw 0; uint32_t sum 0; uint8_t i; for (i 0; i 8; i) { adc_sync_read_channel(ADC_0, 0, (uint8_t *)raw, 2); sum raw; delay_ms(10); /* 等传感器输出进入平稳区 */ } return (uint16_t)(sum / 8); }adc_sync_read_channel 是 SAM L21 HAL 的同步读接口第三个参数是输出缓冲区第四个参数是字节数12 位结果占 2 字节。8 次采样合计约 80ms只在唤醒后执行一次对整机待机电流影响很小。如果传感器线缆超过 20cm把间隔提到 20ms、滤波电容从 100nF 加大到 1µF读数会平滑很多代价是响应变慢但对分钟级系统无所谓。3.2 浇水决策状态机双阈值迟滞与二次确认判断「该不该浇水」最忌讳单阈值湿度在阈值附近波动时水泵会频繁启停。解决方案是双阈值迟滞——低于 THRESH_DRY 判定干燥高于 THRESH_WET 判定湿润两个阈值之间留 600 counts 左右的死区。另一个工程习惯是二次确认第一次采到干燥后不立即浇水等下一个采样周期再确认一次拦截掉传感器被叶片遮住或探头悬空造成的假读数。typedef enum { ST_IDLE, ST_CONFIRM, ST_PUMPING, ST_COOLDOWN } state_t; state_t state ST_IDLE; uint8_t dry_confirm 0; uint32_t pump_start_ms 0; void watering_poll(void) { uint16_t m read_soil_moisture(); switch (state) { case ST_IDLE: if (m THRESH_DRY) { /* 第一次干燥进入确认态 */ state ST_CONFIRM; dry_confirm 1; } break; case ST_CONFIRM: if (m THRESH_DRY) { /* 第二个周期仍干燥开始浇水 */ gpio_set_pin_level(PUMP_PIN, true); pump_start_ms now_ms(); state ST_PUMPING; } else { dry_confirm 0; /* 湿度回升撤销浇水决定 */ state ST_IDLE; } break; case ST_PUMPING: if (now_ms() - pump_start_ms PUMP_ON_MS) { gpio_set_pin_level(PUMP_PIN, false); state ST_COOLDOWN; /* 进入抑制期等水分扩散 */ } break; case ST_COOLDOWN: /* 状态不变由 RTC 计时到期后统一切回 ST_IDLE */ break; } }状态切换的关键在 ST_CONFIRM它把「一次干燥采样」和「两次干燥采样」区分开拦截掉大部分瞬时干扰。ST_PUMPING 里 PUMP_ON_MS 是硬上限即使传感器失效、读数一直偏低水泵最多转 30 秒就停不会出现淹花盆的故障。now_ms 是 SysTick 中断里累加的 uint32 毫秒计数溢出周期约 49.7 天对这个应用足够。ST_COOLDOWN 的状态切换放在 RTC 中断回调里做不在 watering_poll 里延时等待。提示ST_COOLDOWN 在 WDT 复位后会丢失。把上次浇水时刻写入 RTC 或 Flash 备份区复位后重新核算抑制期否则刚浇完水系统重启下一轮采样又会判定干燥。3.3 浇水时长与复检逻辑的参数表参数标定按「花盆大小、基质类型、泵流量」三个变量折算。以口径 15cm、装填泥炭土的花盆为例微型隔膜泵流量约 300mL/min浇透需要 120~180mL 水对应泵运行 30 秒左右。节奏参数常见设定如下参数推荐值设定依据THRESH_DRY180012 位 ADC 码值泥炭土完全干燥时的实测中值THRESH_WET1200浇透后静置 10 分钟的读数PUMP_ON_MS30000目标浇水量 ÷ 泵流量COOLDOWN_MS3600000浇水后 1 小时内不重复启动SAMPLE_PERIOD3000005 分钟唤醒一次采样两个阈值不是固定的。同一块泥炭土压实前后干湿读数差 300 counts换成椰糠基质整体偏低。正确标定方式是先把传感器埋入正常湿度土壤用串口连续打印读数取 24 小时内干湿极值的 20% 与 80% 分位当阈值第 5 章给出具体步骤。4. 嵌入式低功耗调度RTC 唤醒与看门狗恢复4.1 用 RTC 周期中断代替 delay 定时采样主循环里不能用 delay 等 5 分钟那样单片机停在活动模式电流会到毫安级。SAM L21 的 RTC 支持周期中断由外部 32.768kHz 晶振或内部 OSC32K 提供计数时钟配置好周期后自动唤醒。下面是 Atmel START 生成的代码里修改周期值的示意接口名称在不同 HAL 版本有差异逻辑不变static void rtc_arm(uint32_t seconds) { struct rtc_module *rtc RTC_0; rtc_disable(rtc); /* 改配置前必须先失能 */ rtc_set_period(rtc, RTC_PERIOD_CYC32_CPRD, seconds); rtc_enable(rtc); }rtc_set_period 的第三参数是秒数换算后的计数周期值。RTC 使能后每隔 SAMPLE_PERIOD 触发一次中断中断服务函数里只置位 wakeup_flag 就返回不采样、不驱动泵把中断上下文控制在 1µs 量级。采样任务放主循环做避免长时间占用中断导致其他外设中断丢失。SAMPLE_PERIOD 换算成的周期值超过 16 位时要确认 HAL 内部用的是 32 位周期寄存器SAM L21 支持这个模式但代码里要显式声明。4.2 进入 Standby 的封装与唤醒后的外设恢复ATSAML21J18B 的 Standby 模式由 PM 的 SLEEPCFG 寄存器控制置位后执行 WFI 指令进入。进入前要把 ADC、SERCOM 逐个关掉否则外设时钟仍维持实际睡眠电流会比数据手册值高出一截。常见封装如下void sleep_mode_enter(void) { adc_sync_disable(ADC_0); /* 关 ADC省掉采样电路静态电流 */ PM-SLEEPCFG.bit.SLEEPMODE PM_SLEEPCFG_SLEEPMODE_STANDBY_Val; __WFI(); /* 唤醒后按数据手册建议重新使能外设 */ adc_sync_enable(ADC_0); }SLEEPMODE 的具体枚举值由头文件里的 PM_SLEEPCFG_SLEEPMODE_STANDBY_Val 宏给出不同型号编码不一样。唤醒后外设时钟不是自动恢复的Atmel START 生成的初始化是一次性的所以 WFI 之后要立即重新使能 ADC并在下一次采样前等约 1ms 让内部参考源建立——直接采样会拿到前几次转换的残留值。想验证睡眠电流是否达标用万用表串入电池供电回路读数应该落在 4~10µA 之间如果高出几个数量级多半是有外设没关干净。注意SLEEPMODE 的枚举编码在 SAM D21 与 SAM L21 上不同移植到其他系列以前务必对照数据手册的 PM 章节。4.3 看门狗兜底与复位后的安全状态状态机再严谨也挡不住寄存器被干扰跳飞。给整个系统加看门狗超时自动复位是出厂前的必备步骤。SAM L21 的 WDT 配置如下void wdt_init(void) { WDT-CTRLA.bit.ENABLE 0; /* 写配置前先失能 */ WDT-CONFIG.reg WDT_CONFIG_PER(0xA); /* 超时约 8 秒以手册表为准 */ WDT-CTRLA.bit.ENABLE 1; }WDT_CONFIG_PER 的参数与超时秒数的对应关系在不同系列上不一样0xA 在 SAM L21 上对应 8 秒级别量产前以数据手册的 WDT 超时表为准。主循环每轮喂一次狗喂狗放在进入睡眠之前保证「唤醒 → 处理 → 睡眠」的完整循环里狗不会被饿死。如果程序在浇水过程中卡死WDT 复位后 main 从头执行上电默认关泵的动作保证复位瞬间泵一定是停止状态不会带着卡死前的高电平继续转。5. 植物浇水控制应用的阈值校准与整机验证5.1 用串口打印湿度曲线标定双阈值开发板接上串口每 30 秒打印一次采样值printf(moisture%u\r\n, read_soil_moisture());花盆浇透后静置到表层发白整个过程记录 24 小时得到干燥极值和湿润极值按 (max - min) × 20% 与 × 80% 算出 THRESH_DRY 和 THRESH_WET写回参数表再跑一天观察状态切换是否符合预期。注意串口波特率要与开发板电路匹配115200 下输出量很小不会对低功耗测试造成干扰。5.2 三个常见误用与对应处理探头埋太浅读数受表层蒸发影响大湿度曲线剧烈抖动加大死区到 800 counts 依然误触发把探头埋到 5cm 以下即可解决。浇水后立即复检水会顺着传感器外壳流下造成「刚浇完就很湿」的假信号复检必须等 COOLDOWN 到期后再做。供电电压变化传感器输出是比例式的电池从 3.7V 掉到 3.2V同一湿度下的 ADC 码值会偏高软件里用 VCC / 4095 换算成百分比再比较。5.3 交付前的验证清单与复位保护验证项方法通过标准待机电流万用表串入电池供电回路睡眠状态下 ≤ 10µAWDT 复位恢复浇水时强制重启复位后泵必须处于关断状态连续运行无人值守跑 48 小时串口记录全部事件浇水次数与预期一致无一次误动作跑完 48 小时后如果日志与实际浇水次数对不上优先检查 COOLDOWN 状态有没有被复位清掉——这是裸机状态机最容易丢的一个状态。把上次浇水的时间戳存在 RTC 的计时寄存器里设备启动时先读回来核算剩余抑制期再决定是否允许进 ST_CONFIRM。这个复位保护比任何阈值标定都重要。本文还有配套的精品资源点击获取