基于STM32的智慧大棚自动浇水通风系统搭建全攻略

基于STM32的智慧大棚自动浇水通风系统搭建全攻略 我蹲在菜园子边上还没到五分钟就彻底看不下去了——前两天下雨的时候水浇得勤这两天太阳一晒土壤表面干得发白开裂黄瓜苗叶子从根蔫到尖整株都耷拉着。这两畦黄瓜我真是当祖宗伺候可农业这事儿吧靠人盯是盯不住的。当天晚上我翻工具箱找出那块吃灰很久的STM32F103C8T6开发板决定给菜园子搞一套能自动伺候植物的智慧大棚。这篇就把整套从零搭起来的方案完整写出来硬件选型、接线、代码、排查坑全部摊开讲搞嵌入式也好纯粹想折腾自家阳台的朋友都能直接照着抄。如果你是第一次听说“智慧大棚”这四个字简单说就是用传感器代替你的眼睛和手感用单片机代替你的判断用继电器代替你的手实现浇水、通风、补光全自动。不用天天蹲在地里盯着植物状态反而比你亲手伺候的时候更稳。这套系统门槛不高一块STM32F103C8T6最小系统板、几个常见传感器、两三个继电器就能跑起来成本控制在几十块钱以内关键是它真的能解决实际问题。1. 为什么给自家菜园子搞一套智慧大棚1.1 黄瓜苗蔫了问题到底出在哪那几棵黄瓜苗蔫掉的时候我心里其实清楚原因中午土壤温度接近35℃水分蒸发极快我早上出门前没浇水等下班回来早就过了补水窗口期。这里有三个问题叠加在一起浇水时机完全取决于我的日程而不是植物的实际需求土壤表面看着干了但深层可能还有水分靠肉眼判断误差很大中午最热的时候大棚里闷得像蒸笼没有自动通风温度湿度的波动能把幼苗整垮。传统做法就是定闹钟、看天气、摸土这些我都试过效果不稳定。阴天和晴天的需水量差好几倍固定时间浇水要么浇多了沤根要么浇少了蔫叶。黄瓜苗的生长环境有个比较舒服的区间气温20℃到30℃土壤相对湿度60%到80%空气湿度白天60%左右、夜间可以更高一些。这些数据光靠人拍脑袋记根本不可能全天候维持。所以我才决定用传感器加MCU的方式做闭环控制。土壤湿度传感器实时测根部附近的含水率温湿度传感器监控空气环境光敏模块判断光照强度STM32F103C8T6读数据、跑逻辑、给继电器发指令水泵和风扇自动启停。这套思路本质上就是农业物联网里最经典的边缘控制节点只不过我用一块几十块钱的开发板把它落地了。1.2 定时器方案和闭环控制方案我为什么选后者最开始我也图省事想过买个机械定时插座设定每天早晚各浇一次水完事。这方案不是不能用但问题在于它完全“开环”——不管土壤是不是已经够湿到点就浇不管大棚里是不是40℃高温风扇必须等定时器走到那个点才转。遇上连续阴雨天土壤湿度本来就高再按固定计划浇水根很快就泡烂了。闭环控制的核心区别在于加了“反馈”这一环先用量测到的数据做判断再决定执行器动不动作动作之后继续观察数据变化直到进入目标区间。拿浇水这个场景举例如果土壤湿度降到50%以下水泵启动等到湿度回升到70%水泵停止中间留了20%的滞回区间防止继电器频繁跳变。这个过程不需要人参与数据说话而且比固定的开关更贴近植物真实需求。具体到实现层面我只需要STM32的ADC采集土壤湿度传感器输出的模拟电压再用GPIO控制继电器模块的通断逻辑上就是一个带阈值的比较器。这套方案的好处是即使单片机程序跑飞了手动开关还能兜底系统不会直接瘫掉。从工程角度说先做本地闭环后面再考虑往手机端上报数据路是通的。1.3 为什么是STM32F103C8T6而不是Arduino或者ESP32如果纯粹图省事Arduino Uno也能做这个项目写代码简单社区例程也多。但Arduino的短板很明显主频低、Flash小、外设资源少后面想同时挂OLED显示、多个传感器、还要跑FreeRTOS任务调度内存就明显吃力。ESP32当然性能更强、自带WiFi蓝牙可如果你的需求就是“本地自动控制、稳定长跑、成本可控”直接用ESP32有点浪费而且它的功耗比STM32高后续如果做电池供电得额外考虑降压和功耗优化。STM32F103C8T6是意法半导体的经典Cortex-M3内核芯片72MHz主频、64KB Flash、20KB SRAM48脚LQFP封装。最让我看重的是它的外设资源3个USART、2个SPI、2个I2C、2个ADC模块、4个定时器做两三个传感器加四路继电器的控制场景绰绰有余。而且这个芯片特别“皮实”3.3V供电、常规IO操作、简单的时钟配置非常适合干活。再说一个现实问题现在市面上国产替代的兼容芯片已经很成熟了GD32F103、MM32F103、APM32F103这些型号基本做到了引脚兼容、寄存器兼容直接用Keil的ST标准外设库就能开发。我自己这块板子就是某宝上常见的STM32F103C8T6最小系统板板载8MHz晶振、复位电路、USB转串口和3.3V稳压Type-C供电就能跑开发调试都非常方便。如果你只是自用学习选国产替代芯片完全够用价格还能再便宜一半。2. 硬件选型与原理这套系统到底由哪些东西组成2.1 STM32F103C8T6最小系统板板卡选型与引脚规划STM32F103C8T6最小系统板通常长这样中央一颗48脚的芯片引出了几乎全部可用GPIO板子正面有USB接口、BOOT0选择跳线、复位按键、电源指示灯背面一般有LDO稳压芯片。红色或蓝色的PCB宽约2.2cm、长约5.6cm插面包板或者接杜邦线都很顺手焊排针用也不占地方。引脚资源上这颗芯片实际可用的GPIO有PA0到PA15、PB0到PB15、PC13到PC15其中PA9和PA10默认接USB串口。具体到我的项目我做了这样的分配功能引脚说明DHT11温湿度传感器PA0单总线数字信号需接4.7k上拉土壤湿度传感器PA1ADC采集模拟电压0到3.3V光敏模块PA2ADC采集模拟电压判断光照强度手动模式按键PA3按键切换自动/手动带下拉电阻串口调试PA9/PA10复用为USART1输出日志波特率115200OLED显示屏PB6/PB7I2C接口SDA/SCL继电器1 水泵PB12低电平触发继电器2 通风扇PB13低电平触发继电器3 补光灯PB14低电平触发继电器4 遮阳帘PB15低电平触发板载LEDPC13状态指示自动模式下模拟“运行心跳”这个分配是我反复试过之后定下来的PA口的ADC采样通道和PB口的定时器通道都避开了不会和调试下载器冲突。接线的时候如果IO口不够用可以把OLED改到PB10/PB11I2C2或者把光敏模块退化成数字输出接普通IO都是灵活的替代方案。2.2 传感器与执行器感知层和执行层怎么配接地气地讲智慧大棚分成“感知”和“执行”两层。感知层负责收集环境数据执行层负责按指令干活。我用的传感器有四个DHT11温湿度传感器三根引脚VCC、DATA、GND单总线通信温度精度±2℃湿度精度±5%RH采集频率限制在1Hz以内也就是每次读取要隔1秒以上。这个精度对农业环境来说够用了关键是便宜好用。如果你想让数据更准一点换DHT22精度能到±0.5℃和±2%RH价格翻一倍也才十几块。土壤湿度传感器市面上常见电容式和电阻式两种。电阻式靠两根金属探针测土壤导电率浸在水里容易电解腐蚀用不了几个月精度就会飘。电容式传感器测的是土壤介电常数电极不裸露寿命长很多强烈推荐直接上电容式。它输出的是模拟电压通常0到3V左右接到STM32的ADC引脚就能读我自己做完实操测试土壤完全干燥时读数大约1.4V田间持水量状态大约2.2V浸泡在水里接近3.0V。光敏模块用的是光敏电阻加LM393比较器既可以输出模拟电压也可以输出数字电平我把AO口接到ADC上这样能看着电压值增长趋势来判断早晚和阴晴。如果你后面想做补光灯精细调节建议直接换BH1750光照传感器I2C接口输出Lux数值数据规范得多代码也不复杂。执行层主要靠继电器模块。我用的是一路低电平触发继电器模块板载PNP三极管驱动线圈侧需要大概70mA的驱动电流这正好是STM32普通IO口驱动不了的量级所以必须经过继电器模块板载电路不能直接把继电器线圈接到MCU引脚上。模块上COM接电源正极NO常开接水泵或风扇的正极设备负极直接回电源负极形成完整的回路。水泵我选了5V微型直流潜水泵扬程约1.5米流量每分钟两三升给两畦黄瓜滴灌绰绰有余。通风扇用的是12V电脑机箱风扇风力足够大棚换气。补光灯用的是一根红蓝光LED植物灯条12V供电额定功率15W。这三样都通过继电器单独控制互相隔离哪个坏了换哪个不会殃及主控板。2.3 供电与接口设计菜园子环境下的稳定性问题供电是整个项目最容易翻车的地方。STM32F103C8T6最小系统板可以用USB的5V取电板载稳压降到3.3V给MCU这个没问题。但绝对不能直接用这5V去带继电器和泵否则USB供电电流一大就掉电重启单片机反复复位系统根本跑不稳。我实际采用的供电方案是一个12V 3A的开关电源作为总电源12V直接给通风扇、补光灯条同时经过一个DC-DC降压模块降到5V给STM32板子和继电器模块供电。水泵是5V的也从这个5V母线上取电。继电器模块控制的是设备侧的高电流路径信号侧只需要5V和GND共地处理之后STM32的GPIO就能安全控制继电器通断。这里有个细节要注意所有传感器和执行器的GND必须要和STM32的GND连在一起也就是“共地”。如果不共地传感器输出的电压根本没有参考点ADC读出来的数据会乱跳。信号线和动力线尽量分开走至少不要绑在同一束线束里否则继电器吸合瞬间的电流变化会通过寄生电容耦合到传感器信号线上导致读数异常。菜园子的环境可比实验室恶劣多了湿度大、尘土多、可能有虫子和露水接线端子一定不能用裸露的杜邦线直接怼进去。我用的是KF301端子排和XH2.54端子接头都用热缩管套住继电器和降压模块装在一个密封的防水盒里引线从盒底开孔再用硅胶封堵。这样既能防溅水也方便以后拆开检修。3. 实战搭配从零搭建智慧大棚的完整过程3.1 接线方案与引脚分配实操记录准备工作做完开始动手接线。先把STM32F103C8T6最小系统板固定在一块洞洞板或者亚克力底座上再把继电器模块、降压模块排布好规划走线路径避免信号线和电源线交叉。第一步接传感器。DHT11的DATA引脚通过一根10cm长的杜邦线接到PA0同时在DATA和3.3V之间接一个4.7kΩ上拉电阻因为DHT11的通信协议是开漏输出必须有上拉才能保证高电平有效。土壤湿度传感器的AOUT接到PA1VCC和GND分别接3.3V和GND。光敏模块的AO接到PA2VCC接3.3VGND接地。这里要注意所有传感器供电都从3.3V取电ADC读数的满量程是0到3.3V如果接到5V上超出量程会把ADC输入引脚烧坏。第二步接OLED显示屏。这块SSD1306驱动芯片的0.96寸OLED默认I2C地址是0x3C。SDA接PB7SCL接PB6VCC和GND接3.3V和GND。如果能点亮屏幕但显示乱码大概率是地址不对把地址改成0x3D再试。第三步接继电器控制线。从STM32引四根GPIO线到四个继电器模块的信号输入端分别是PB12到继电器1PB13到继电器2PB14到继电器3PB15到继电器4。继电器模块上一般有三个信号脚VCC、GND和IN对应接好5V、GND和GPIO。第四步接执行器回路。以水泵为例12V总电源正极接到继电器1的COM口继电器1的NO口接水泵正极水泵负极直接回12V电源负极。这样当继电器吸合时COM和NO导通水泵得电工作。风扇和补光灯同理分别接在继电器2和继电器3上遮阳帘或者一个备用设备接继电器4。全部接完之后先不慌上电用万用表蜂鸣档量一遍电源正负极有没有短路再检查每个模块的VCC和GND是否接反这是整个流程里最便宜也最救命的一步。3.2 代码逻辑初始化、采集、控制、显示一条链路开发环境我用的是Keil MDK芯片选择STM32F103C8下载器用的ST-Link V2也可以用DAP-LinkKeil的pack支持都很完善。工程里我直接用了标准外设库比HAL库直观读起来也更容易理解底层逻辑。整个代码分四块系统初始化、传感器采集、控制策略、显示和日志。系统初始化这块时钟配置用内部的8MHz HSI也可以但为了串口波特率准确我直接用外部8MHz晶振配置系统主频到72MHz。GPIO初始化时把PA0设为输入模式PA1和PA2设为模拟输入PA3设为下拉输入PB6和PB7设为开漏输出并启用I2C1PB12到PB15设为推挽输出初始状态全部置高保证上电瞬间继电器不吸合。核心的控制逻辑在主循环里逻辑如下每2秒读取一次DHT11温湿度每5秒读取一次土壤湿度ADC和光照ADC把数据格式化成字符串在OLED上显示根据采集结果执行控制策略通过串口发送日志土壤湿度的控制代码我这里给一个参考版本#define SOIL_DRY_THRESHOLD 1500 // 土壤湿度低于此值认为偏干单位mV #define SOIL_WET_THRESHOLD 2100 // 土壤湿度高于此值认为够湿 #define SOIL_HYSTERESIS 600 // 滞回区间防止频繁启停 void soil_control(uint16_t soil_voltage_mv) { // 自动模式下根据土壤电压控制水泵 if (g_manual_mode 0) { if (soil_voltage_mv SOIL_DRY_THRESHOLD) { relay_on(RELAY_PUMP); // 土壤偏干开泵浇水 } else if (soil_voltage_mv SOIL_WET_THRESHOLD) { relay_off(RELAY_PUMP); // 湿度够了停泵 } // 在两个阈值之间不改变水泵现有状态这就是滞回 } }DHT11的读取代码是时序敏感部分这里强调几个关键点主机拉低总线至少18ms发起起始信号然后释放总线等待从机拉低应答。读取数据时每个bit用高低电平的时序长度来区分0和1整个过程需要关闭中断或者用定时器保证时序准确。我实测下来使用标准库的延时函数配合GPIO翻转温度读数的稳定性还不错唯一要注意的是每次读取间隔必须大于1秒否则DHT11不响应。通风控制逻辑稍微复杂一点温度和湿度各管一路继电器。当温度超过30℃时开启风扇低于27℃时关闭空气湿度超过85%时也开启风扇低于75%时关闭这样可以兼顾降温和降湿的诉求。补光灯的控制则纯粹看光照阈值模拟电压低于900mV相当于傍晚光照不足时开启补光灯高于1200mV时关闭。这些阈值一开始也是我拍脑袋设的后来根据几天的运行数据慢慢调出来的所以代码里我把阈值都定义成了宏方便后面修改。3.3 调试与调参从能跑到跑得稳系统能通电、传感器能读数这只是第一步离“跑得稳”还差着十万八千里。我的调试流程分三阶段走经验就是千万别跳步。第一阶段是硬件自检。把每个传感器的原始数据都通过串口打印出来人眼核对一遍。DHT11读出来的温度应该和环境温度对得上土壤湿度传感器插在干土和湿土里的读数应该有明显差异光敏在遮光和见光时的电压也要有变化。这个阶段最容易发现线序接错、引脚配置错误、供电电压不对之类的问题。我自己就遇到过DHT11死活读不到数据的情况排查了半天发现是DATA引脚忘了接上拉电阻总线电平一直浮空。第二阶段是手动控制测试。用按键切换到手动模式按一下继电器1吸合再按一下断开逐个验证四路继电器和对应的执行器是否正常工作。同时用万用表量继电器的COM和NO端是否确实导通这一步能把接线错误彻底消灭在闭环测试之前。第三阶段是闭环测试。把所有控制逻辑放开让系统自动跑起来。我建议先跑24小时期间时不时去串口监视器看看日志记录下什么时候启动水泵、水泵工作了多久、土壤湿度从多少涨到多少。你会发现你设定的阈值和实际系统响应之间存在延迟比如土壤湿度从干变湿是个缓慢过程水泵可能要持续工作十几分钟才能让湿度越过阈值这时候如果滞回区间设得太小就会出现水泵一启动就停、停了又启动的“振荡”现象。最终我把阈值参数调成了这样土壤湿度低于1.5V时开泵高于2.1V时停泵实测下来水泵每次运行约8到15分钟间隔至少两小时以上继电器寿命和保护植物这两个目标都兼顾了。温度阈值风速也一样先粗略设一个值看两天的温度曲线再调整开停边界直到系统在一天内都不会出现某个变量反复横跳的情况。4. 常见问题与排查技巧实录4.1 传感器数据异常怎么查用过的人都知道STM32开发板配传感器最大的坑就是数据读出来明显不对但你又不知道是哪一环出了问题。我把自己踩过的坑按概率排了个序做成一个速查表。现象大概率原因排查方法DHT11一直返回0或固定数值上拉电阻缺失、DATA接错引脚、时序被中断干扰检查4.7k上拉核对引脚配置读取期间关闭串口中断土壤湿度读数乱跳供电不稳、电极腐蚀、电路共地不良用万用表量传感器VCC是否为稳定3.3V换电容式传感器确认与MCU共地光敏读数不受光照影响模块上的电位器调得太偏用小螺丝刀微调板载电位器让输出随光照变化ADC所有通道读数都是4095引脚配置成推挽输出而不是模拟输入检查GPIO配置模拟输入通道对应的ADC采样时间设长一点DHT11的时序问题值得多说一句。这个传感器的时序是微秒级别的在标准库环境下如果你在主循环里同时开了串口中断或者定时器中断时序就可能被破坏。我最后的解决办法是用一个专门的软件延时函数来完成DHT11的读取时序读取期间用临界区保护挂起其他中断读完再恢复。虽然这种方式比较粗暴但在这种小项目里完全够用。4.2 继电器误动作、水泵不转这些坑继电器是执行层最容易出问题的地方而且问题是间歇性的最难排查。我遇到过的一种情况是刚上电的时候一切正常继电器能吸合也能释放但跑了几个小时之后有一个继电器开始不动作了。用万用表量GPIO电压逻辑电平明明是正常的但继电器模块的指示灯就是不亮。后来查到原因在继电器模块的电源上。继电器模块虽然只需要20mA左右就能维持吸合但吸合瞬间的电流尖峰很大。当多个继电器同时动作时5V母线电压瞬间被拉低如果DC-DC降压模块的响应速度不够快就会导致部分继电器吸合失败。解决方案有两条路一是给继电器模块单独加一个470μF到1000μF的电解电容做储能缓冲二是把继电器的吸合动作错开代码里不要在同一毫秒内同时打开或关闭多个继电器。还有一个低级的坑继电器模块上通常标了“低电平触发”和“高电平触发”两种版本买的时候要看清。我一开始买的是低电平触发版代码里却写的输出高电平来开继电器结果怎么调都不对后来翻模块背面的丝印才反应过来是触发极性搞反了。4.3 环境适应性与长期运行的经验智慧大棚和实验室板子的最大区别在于它要在室外连续跑几周、几个月稳定性要求远高于“能跑demo”。我踩了几次坑之后总结了几条经验加看门狗。STM32F103内置独立看门狗IWDG在代码初始化时设置好超时时间主循环里定期喂狗。程序一旦因为干扰跑飞看门狗能把芯片拉回正常执行流程避免“系统死了但继电器还维持着上次状态”这种危险情况。这个成本几乎为零但收益巨大。传感器读取要做超时保护。DHT11如果响应超时程序不能卡在等待循环里否则主循环就死了。我采用的方法是连续读取失败3次就跳过本次采集保留上次的有效数据并串口输出告警而不是让整个系统停下来。串口日志要加时间戳。调试阶段你不可能全程盯着屏幕把日志时间戳加上事后翻日志才能还原当时系统在做什么。我用的是开机后累计的毫秒数格式是[uptime_ms] soil2100mv temp27.5C hum63% pumpOFF这行日志备考价值极高。还有一点是针对室外环境的定期重新标定土壤湿度阈值。土壤用久了会板结电导率会变化同一块地同一个传感器用了两个星期之后读数会漂移。最稳妥的办法是每两周人工对比一次“传感器读数”和“土壤实际状态”重新调整阈值宏定义然后重新烧录。后面如果嫌麻烦可以把阈值存到Flash里运行中通过串口命令在线修改不用重新编译固件。5. 这套配置还能怎么进阶写到这里基础版的智慧大棚已经能稳定运行了。如果你和我一样折腾完第一版总想再压榨点性能下面这几个方向是可以无缝追加的加一个ESP8266或者ESP01S做远程上报。STM32的USART2空着没用正好接ESP8266把传感器数据通过WiFi传到手机上的MQTT服务器或者云平台。STM32本地照样跑闭环控制ESP8266只负责透传数据两边互不干扰哪怕断网也不影响大棚正常工作。跑一个FreeRTOS操作系统。STM32F103C8T6有20KB SRAM跑一个精简版FreeRTOS完全没问题。把DHT11采集、ADC采集、控制逻辑、OLED刷新、串口日志各分一个任务任务之间用队列传递数据代码结构会清晰很多。网上关于STM32F103C8T6移植FreeRTOS的教程很多照着搭就行确实能感受到多任务带来的便利。后备电池和掉电保存。加一个DS1302实时时钟芯片和一个小容量EEPROM系统启动时从EEPROM读取上次保存的工作参数和工作状态掉电重启后能无缝恢复不用每次断电重新设阈值。这套组合在嵌入式项目里非常经典。最后说说我的真实感受。整套系统跑了两周之后我再也没蹲在菜园子里盯着黄瓜苗发过呆不是因为不在乎了而是因为数据和执行器替我盯得比人准。每天早上起来扫一眼OLED屏上的温湿度和土壤状态心里就有数。传统农业靠天吃饭但至少在这个小菜园子里现在靠的是一块STM32F103C8T6和几个传感器把一个“看天干活”的问题变成了“看数据干活”的问题。如果你家里也有几盆花、一小块菜地或者纯粹想找个嵌入式项目练手这套智慧大棚是一个很合适的起点。