尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

基于STM32的温室大棚温湿度监测控制系统设计与实现

发布时间:2026/9/18 10:51:15

资讯中心
01
ARTICLE

基于STM32的温室大棚温湿度监测控制系统设计与实现

基于STM32的温室大棚温湿度监测控制系统设计与实现
简介一份完整的温室大棚温湿度控制系统毕业设计文档适合电气、电子信息类专业学生及设施农业自动化方向的工程实践者参考。文档以STC89C51与AT89C51微控制器为核心结合DHT11温湿度传感器从系统总体结构出发先后展开单片机最小系统、震荡电路、复位电路、中断系统等硬件设计并详细说明DHT11的引脚定义、电源连接和单线双向串行接口等应用要点同时对软件控制算法、数据处理与存储方式做了系统梳理还讨论了国内外温室控制领域的发展现状、趋势与挑战。资源包仅包含1个doc文件整体大小2.29MB内有开题报告、章节目录和完整系统设计流程结构清晰便于查阅目前已有1201人学习下载。对正在准备温室环境监测或单片机应用类毕业设计的读者来说这份文档既能提供整体框架参考也可帮助理解温湿度采集电路的连接细节与接口实现思路节省方案调研和论文组织的时间。1. 从环境监测到闭环控制一套可落地的温室大棚温湿度系统该怎么做做嵌入式或者农业物联网的同学十有八九都接过“温室大棚温湿度控制”这类需求。表面看就是读两个传感器、控制风机和湿帘但真正往深了做你会发现难点根本不在传感器驱动上而在于系统怎么在“环境变化慢但干扰源多”的温室场景里做到稳定、省电、可远程维护。本篇文章要聊的这套基于STM32的温湿度监测控制系统核心是把传感器采集、控制策略、执行机构驱动和人机交互串成一个闭环而不是简单做个体积小巧的测温仪。这套系统在工程上通常分为现场采集与控制终端、上位机监控界面两层。STM32负责底层数据采集、控制逻辑和报警处理上位机通过串口或无线模块拿到数据做展示与参数下发。对5年以上的开发者来说这篇文章有价值的部分集中在控制策略的选取、传感器滤波与校准、以及系统抗干扰设计这些容易被忽略的细节上。我们直接按“传感器选型 → 电路与驱动 → 控制策略 → 调试验证”这条主线展开。2. 温湿度传感器选型与STM32接口设计从DHT11到SHT30的迁移路径很多课设和毕业设计里选DHT11因为便宜、资料多、代码到处都是。但在温室大棚场景下DHT11的±2℃温度和±5%RH湿度精度以及1Hz的最高采样率往往不能满足昼夜温差大、湿度变化剧烈的控制需求。更关键的是DHT11的单总线协议对时序要求极严在STM32上还要关中断去模拟时序稍有不慎就读取失败。2.1.1 传感器选型对比DHT11、DHT22与SHT30的实测差异参数DHT11DHT22 (AM2302)SHT30温度精度±2℃±0.5℃±0.3℃湿度精度±5%RH±2%RH±2%RH采样周期1s2s0.5mstyp通信接口单总线单总线I2C最高1MHz典型价格2-5元10-15元8-20元如果你的系统是毕业设计或者演示用途DHT22是性价比最高的选择精度够、代码成熟。如果做实际落地项目优先选SHT30因为I2C接口可以直接挂载到STM32的硬件I2C外设上不需要像单总线那样模拟时序抗干扰能力也更强。另外SHT30内置了加热元件可以在高湿环境下清除传感器表面的凝露这对大棚环境非常重要。2.1.2 基于STM32的SHT30驱动代码框架SHT30的I2C地址默认是0x44命令格式为两个字节比如0x2C 0x06表示开启周期测量模式。下面给出一个最小驱动示例使用STM32的HAL库。#include stm32f1xx_hal.h #include math.h #define SHT30_ADDR_WRITE 0x88 // 0x44 1 #define SHT30_ADDR_READ 0x89 extern I2C_HandleTypeDef hi2c1; uint8_t SHT30_ReadTempHum(float *temp, float *hum) { uint8_t cmd[2] {0x2C, 0x06}; // 周期测量模式重复性高 uint8_t buf[6] {0}; uint16_t raw_temp 0, raw_hum 0; // 发送测量命令 if (HAL_I2C_Master_Transmit(hi2c1, SHT30_ADDR_WRITE, cmd, 2, 100) ! HAL_OK) return 1; // 等待测量完成周期模式下约需16ms HAL_Delay(20); // 读取6字节数据 if (HAL_I2C_Master_Receive(hi2c1, SHT30_ADDR_READ, buf, 6, 100) ! HAL_OK) return 1; // 校验CRC简化版实际应做CRC8校验 raw_temp (buf[0] 8) | buf[1]; raw_hum (buf[3] 8) | buf[4]; *temp (float)raw_temp * 175.0f / 65535.0f - 45.0f; *hum (float)raw_hum * 100.0f / 65535.0f; return 0; }这段代码的逻辑分三步发送命令、延时等待、读取数据。需要注意HAL_I2C_Master_Transmit的第二个参数是设备地址左移一位后的值因为HAL库内部会再右移一位。如果你用的是寄存器版本的驱动务必确认地址是否带读写位这是最常见的移植错误。实际工程中建议加上CRC8校验函数SHT30的数据手册里有完整的多项式算法示例。3. 控制策略设计位置式PID与滞回控制的取舍温湿度控制系统光把数据读上来没用关键在控制算法。大棚环境是一个典型的大惯性系统温度变化缓慢但执行机构风机、湿帘、天窗的动作又是离散的。很多初学者直接上PID结果发现系统振荡得很厉害原因在于大棚的滞后性远大于普通电机控制场景。3.1.1 为什么不用纯PID滞后系统与积分饱和问题在大棚里风机开启后温度要过好几分钟才会明显下降传感器检测到变化再反馈到控制器这个纯滞后时间往往超过系统时间常数的三分之一。传统PID在这种系统里积分项会持续累积误差等到温度真的降下来时控制量已经超调过头了。这就是所谓的积分饱和现象。解决思路有两种一是对PID输出做限幅并设置积分分离二是干脆不用PID改用滞回控制。对于继电器控制的风机或湿帘滞回控制更实用。它的原理很简单设定一个目标温度T_target允许误差范围ΔT当温度高于T_targetΔT时开启风机低于T_target-ΔT时关闭风机。这样避免执行机构频繁动作延长继电器寿命。3.1.2 滞回控制参数表与代码实现以温度控制为例参数设置如下参数典型值说明目标温度25℃根据作物种类调整滞回上限27℃高于此值启动降温设备滞回下限23℃低于此值关闭降温设备采样周期5s传感器读取间隔控制周期30s控制逻辑执行间隔采样周期和控制周期是两个不同的概念。传感器可以每5秒读一次用于显示和记录但控制逻辑每30秒执行一次就行避免执行机构在临界点附近频繁启停。typedef struct { float target; float hysteresis_upper; float hysteresis_lower; uint8_t cool_state; // 0停止1运行 } TempController; void Temp_Control_Loop(TempController *ctl, float current_temp) { if (ctl-cool_state 0) { if (current_temp ctl-hysteresis_upper) { ctl-cool_state 1; // 开启风机、湿帘 HAL_GPIO_WritePin(FAN_GPIO_Port, FAN_Pin, GPIO_PIN_SET); } } else { if (current_temp ctl-hysteresis_lower) { ctl-cool_state 0; HAL_GPIO_WritePin(FAN_GPIO_Port, FAN_Pin, GPIO_PIN_RESET); } } }这段代码的核心在于状态判断的顺序先判断当前状态再决定是否切换。如果反过来用传感器数值直接判断开关那么在滞回区间内会频繁抖动。另外滞回下限和上限之间的区间就是缓冲区缓冲区越大执行机构动作越少但对目标温度的偏离就越大。大棚场景下2-4℃的缓冲区间比较合理。如果一定要用PID建议使用增量式PID并将输出限制在0到100%之间。同时加入积分分离只在误差小于某个阈值比如2℃时启用积分防止快速升温阶段积分饱和。4. 执行机构驱动与系统可靠性设计继电器、PWM与异常保护控制策略计算出来之后最终要驱动风机、湿帘泵、补光灯这些执行机构。STM32的GPIO输出的电流很小不能直接驱动交流设备中间必须经过继电器或者固态继电器。这个环节最容易出问题的不是电路连接而是电磁干扰导致MCU死机或重启。4.1.1 继电器驱动电路与隔离方案最稳妥的方案是使用光耦隔离的继电器模块。STM32的GPIO连接到光耦输入端光耦输出端驱动继电器线圈继电器触点再控制220V交流设备。典型接线参数器件推荐型号/参数备注光耦EL357N或PC817隔离GPIO与继电器继电器5V/10ASRD-05VDC感性负载需并联续流二极管驱动三极管S8050或ULN2003S8050需配合1kΩ基极限流电阻续流二极管1N4007反向并联在继电器线圈两端ULN2003可以替代分立三极管一个芯片能驱动7路继电器适合控制设备较多的大棚系统。无论用哪种方案GPIO到光耦之间都要串联一个300Ω到1kΩ的限流电阻防止灌入电流过大损坏MCU引脚。4.1.2 电磁干扰导致复位看门狗与软件滤波继电器吸合的瞬间线圈电感会产生反向电动势虽然续流二极管能吸收一部分但仍可能通过电源线或地线干扰MCU。最有效的处理手段有三个第一继电器模块和STM32最小系统分开供电继电器用5V电源MCU用3.3V LDO供电第二在MCU的电源引脚附近并联100nF陶瓷电容和10μF电解电容第三开启STM32的独立看门狗每500ms喂一次狗防止程序跑飞后系统长时间无响应。除了硬件防护软件上也要加入滤波算法。传感器可能会因为电磁干扰读取到异常跳变值比如温度从25℃瞬间变成60℃。使用中位值平均滤波法效果很好连续采集5次数据去掉最大值和最小值剩下求平均。uint16_t SHT30_ReadFilteredTemp(void) { uint16_t samples[5]; uint16_t temp; int i, j; uint16_t sum 0; for (i 0; i 5; i) { // 假设该函数返回原始温度值 samples[i] read_sht30_raw_temp(); HAL_Delay(50); } // 简单选择排序去掉一个最大值和一个最小值 for (i 0; i 4; i) { for (j i 1; j 5; j) { if (samples[j] samples[i]) { temp samples[i]; samples[i] samples[j]; samples[j] temp; } } } for (i 1; i 4; i) { sum samples[i]; } return sum / 3; }这个滤波函数会阻塞主循环250ms左右如果在实时性要求高的场合建议把采样放到定时器中断里只保留一个滑动窗口缓冲区。计算平均时只取窗口中间几个值既平滑又不会滞后太多。4.1.3 系统故障自检机制一个能拿得出手的温控系统必须包含故障自检。最常见的故障类型是传感器断线读不到数据、继电器粘连控制信号关闭但设备仍在工作、温湿度超限。传感器断线很好检测连续读取5次如果返回错误码或数据全为0xFF就判定传感器离线系统进入安全模式——关闭所有执行机构并在OLED屏幕和上位机上同时报警。继电器粘连比较难检测需要加一个电流互感器或者接触器辅助触点检测成本偏高。折中方案是设置一个最长运行时间比如风机连续运行超过15分钟就强制停止一次防止湿帘泵过度工作损坏电机。void System_Fault_Check(void) { static uint32_t last_cool_time 0; static uint32_t cool_start_time 0; uint32_t now HAL_GetTick(); if (relay_state.fan 1) { if (cool_start_time 0) { cool_start_time now; } else if (now - cool_start_time 15 * 60 * 1000) { // 风机运行超过15分钟强制关闭并报警 relay_state.fan 0; HAL_GPIO_WritePin(FAN_GPIO_Port, FAN_Pin, GPIO_PIN_RESET); last_cool_time now; fault_code | FAULT_COOL_OVERRUN; } } else { cool_start_time 0; } }这个保护逻辑有一个小坑直接在系统主循环里调用HAL_GetTick()判断时间差如果系统使用硬件定时器进中断处理控制逻辑需要注意临界区资源的竞争。建议把fault_code定义为volatile类型确保在中断和主循环之间传递时不会被优化掉。5. 上位机通信协议与实时监控设计用Modbus RTU避免自创协议温湿度监控系统至少要提供一个可视化界面。最常见的方案是STM32通过串口连接PC上位机或者通过ESP8266模块将数据上报到云平台。这里推荐使用Modbus RTU协议而不是自己定义一套简单的帧格式原因在于Modbus RTU是一种工业级标准协议调试工具丰富且兼容Modbus Poll、Node-RED等现成的上位机软件。5.1.1 上位机通信协议帧格式定义一个标准的Modbus RTU帧包含地址码、功能码、数据域和CRC校验。对于温湿度监控只需要用到03功能码读保持寄存器和06功能码写单个寄存器。寄存器地址内容数据类型权限0x0000当前温度放大10倍uint16只读0x0001当前湿度放大10倍uint16只读0x0002目标温度uint16读写0x0003控制模式0手动1自动uint16读写0x0004继电器状态bit0风机bit1湿帘uint16只读数据放大10倍是工程常用技巧因为Modbus寄存器是16位整数直接传输浮点数需要拆分成两个寄存器比较麻烦。上位机拿到数值后除以10即可还原小数精度完全够用。5.1.2 基于FreeModbus的移植要点不建议从零手写Modbus协议栈直接移植开源FreeModbus库效率最高。FreeModbus对多款STM32都有适配例程核心需要实现三个接口函数// 获取系统Tick用于协议超时计时 uint32_t xMBPortTimersGetTickCountMs(void) { return HAL_GetTick(); } // 启动定时器用于3.5T字符超时判断 void vMBPortTimersEnable(void) { __HAL_TIM_SET_COUNTER(htim6, 0); HAL_TIM_Base_Start_IT(htim6); } // 关闭定时器 void vMBPortTimersDisable(void) { HAL_TIM_Base_Stop_IT(htim6); }这三个函数中最容易出错的是vMBPortTimersEnable里的定时器重设逻辑。MB_BCON_TIMER频率必须和波特率匹配比如9600波特率时定时器中断周期约为3.5个字符时间需要根据MCU主频计算预分频值和自动重装载值。很多人在这个环节直接复制例程不改参数导致上位机通信时好时坏。Modbus主站向从站发送一帧请求后从站的响应时间通常在50ms以内。超过100ms没有任何响应上位机侧就要做超时重试机制连续3次超时则判定从站离线弹出报警提示。从站侧则要利用看门狗防止协议卡死导致系统假死。5.1.3 定时器中断里完成温湿度采集与控制决策为了保证控制实时性主循环里只处理Modbus协议任务温湿度读取和控制逻辑放到定时器中断里。这里有个设计权衡SHT30的I2C读取需要等待约20ms如果在中断里做会长时间阻塞其他中断。推荐方案是把控制逻辑拆成状态机在定时器中断里只做“读取标志位”和“发送启动转换命令”数据的处理放到主循环中。void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { static uint32_t cnt 0; if (htim-Instance TIM6) { cnt; if (cnt % 5 0) { // 每5个周期触发一次1s sensor_measure_flag 1; } if (cnt % 30 0) { // 每30个周期触发一次6s control_loop_flag 1; } } }通过设置两个不同周期的标志位既避免了在中断里执行耗时操作又保证了采集和控制各自按合适的频率运行。主循环判断标志位后才真正去读传感器数据和计算控制输出。这套机制在实时性和代码可维护性之间取得了平衡也是我通常会在生产环境使用的方式。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。