简介:本资源是一套基于STM32F103系列单片机开发的植物生长箱环境控制系统完整工程,面向嵌入式初学者、农业物联网爱好者及高校课程设计/毕业设计学生,解决植物培育过程中温湿度、光照、土壤墒情与水位等多参数协同监测与智能调控难题。压缩包共265个文件,含49个C源文件(如stm32f10x_adc.c、gizwits_protocol.c)、47个头文件(h)、47个编译中间文件(o)及46个依赖描述(crf),涵盖底层驱动、传感器采集、WIFI通信(GizWits云平台对接)、OLED显示、蜂鸣报警与双模式控制逻辑;另含Keil工程文件(uvprojx)、hex固件、PCB/SCH原理图及3个实操演示mp4视频,整体大小129.17MB。已有88人学习下载,提供从硬件连接、传感器标定、阈值逻辑配置到手机APP远程切换手动/自动模式的全链路实现,配套OLED实时界面与多级报警机制,可直接编译烧录运行,是嵌入式软硬协同开发的典型实践案例。 去年帮朋友做了一台植物生长箱的控制器,前后折腾了三个版本才稳定下来。最初我也有个挺天真的想法:既然只是“测温度、湿度、开加热、开加湿”,拿STM32接几个传感器、几个继电器就完事了。实际做下来发现完全不是这么回事——补光灯一开,箱内温度马上往上蹿;雾化加湿一启动,湿度探头的数据延时严重;继电器频繁跳闸,不到一周触点就发黑。环境控制系统本质是一个强耦合、大惯性的闭环系统,不是简单的开关组合。
这篇博客我打算从架构设计、传感器采集、执行器驱动、控制策略、人机交互到实测排错,完整复盘这个“基于STM32的植物生长箱环境控制系统”项目。主控用的是STM32F103C8T6,配合SHT30温湿度、BH1750光照、MQ135等传感器,实现温度、湿度、光照、CO2的自动调节。如果你正准备做课程设计、想给阳台花房做一套自动化设备,或者在做小型环境监控产品,这篇内容可以当成一份可直接参考的实现方案。
1. 整体架构:先想清楚“测什么、控什么、怎么控”
1.1 控制对象拆解,别一上来就画电路
植物生长箱的控制对象比想象中多。温度、湿度、光照、CO2浓度、土壤湿度,这五个变量都不是独立的,例如补光会产生大量热量,风扇换气会带走湿度和温度,雾化加湿又会轻微降温。如果不先把这些耦合关系理清,直接画电路、写代码,后面调起来会非常痛苦。
我先把控制对象整理成一张表,后面所有设计都以这张表为基准:
| 被控量 | 传感器选型 | 执行器 | 时间常数 | 主要耦合影响 |
|---|---|---|---|---|
| 温度 | SHT30 + DS18B20 | PTC加热器、排风扇 | 约5~15分钟 | 补光灯发热显著升温 |
| 湿度 | SHT30 | 超声波雾化器 + 风机 | 约2~5分钟 | 加湿会轻微降温 |
| 光照 | BH1750 | 全光谱LED灯带 | 毫秒级 | LED发热,影响温度 |
| CO2 | MQ135 | 排气扇、新风阀 | 数分钟到数十分钟 | 换气同时改变温湿度 |
| 土壤湿度 | 电容式土壤探头 | 微型水泵、滴灌阀 | 数小时 | 浇水提高空气湿度 |
从这张表能得出几个关键结论:
- 温度是整个系统的核心,因为它受补光灯、风扇、雾化器三重干扰。
- 光照响应最快,适合做定时和PWM渐变控制。
- 土壤湿度时间常数最长,用定时浇水策略即可,不需要快速闭环。
架构设计上,我采用了以STM32F103C8T6为主控、传感器采集层和执行器驱动层分离的方案。采集层通过I2C、单总线、ADC把环境参数汇集到主控;执行器层用光耦把MCU和强电/大电流设备隔离;控制策略在MCU内部以1秒为周期运行。这个分层后面会让调试方便很多,某个环节出问题时不用整板排查。
1.2 主控选型:为什么F103C8T6够用
很多新手做项目会陷入一个误区:芯片越强越好。实际上,植物生长箱控制系统的计算压力很小,STM32F103C8T6的资源完全够用。
C8T6的核心配置:72MHz Cortex-M3、64KB Flash、20KB RAM、3个ADC、2个I2C、3个USART、1个SPI。这些资源在项目中是这样分配的:
- 3路ADC:一路给MQ135 CO2传感器,一路给土壤湿度探头,一路留作箱内壁温度冷端补偿或用不上的备用。
- I2C1:接SHT30温湿度和BH1750光照,共用一条总线。
- USART1:接ESP8266或上位机调试。
- USART2:预留485接口,以后扩展更多执行器。
- 定时器:TIM1输出三路PWM,一路给补光灯调光,一路给风扇调速,一路给PTC加热器调功。
有人会问,F407不更好吗?F407的RAM更大、主频更高,但在这个场景下用不上。C8T6的劣势主要是Flash小,如果我要上LVGL或FreeRTOS+大屏显示,64KB确实紧张,那就得换F407VET6或F103RCT6。如果只是做传感器采集、PID策略、OLED显示、按键交互,C8T6能稳稳跑起来,而且最小系统板便宜,焊坏了也不心疼。
1.3 软件架构:裸机时间片还是FreeRTOS
这是软件设计里必须想清楚的问题。我第一版贪图省事,直接在while(1)里顺序执行:读传感器、算PID、刷新显示、查按键。结果发现一个严重问题——读取SHT30时,I2C通信需要阻塞等待,这段时间按键扫描和显示刷新全部卡住,PWM输出也会出现微小的抖动。
后来我把软件改成“时间片轮询+状态机”架构:用SysTick产生1ms时基,把任务按优先级分到不同的时间间隔里执行。传感器读取1秒一次,PID计算1秒一次,显示刷新200毫秒一次,按键扫描10毫秒一次。这样做的效果立竿见影,整个系统响应变得很稳定。
那什么时候上FreeRTOS?如果你要接入ESP8266跑TCP/MQTT协议栈、同时处理多路串口数据、还需要管理多个异步任务,裸机时间片会很累。FreeRTOS的好处是把“读传感器”“控执行器”“跑协议栈”做成独立任务,用队列和信号量通信。它的缺点是任务切换会增加调试复杂度,内存也得多留一点。按这个项目的体量,我的建议是:单箱体控制用时间片就够了,多箱体联网再上RTOS。
时间片轮询的任务划分参考:
| 任务 | 周期 | 优先级 | 说明 |
|---|---|---|---|
| 按键扫描 | 10ms | 高 | 带消抖,检测短按/长按 |
| OLED刷新 | 200ms | 中 | 只刷新变化区域,避免整屏重绘 |
| 传感器采集 | 1s | 中 | I2C读取SHT30/BH1750、ADC采样 |
| 控制策略 | 1s | 高 | PID计算、滞回判断、仲裁输出 |
| 串口解析 | 事件触发 | 中 | 串口空闲中断接收,解析参数 |
| 看门狗喂狗 | 500ms | 高 | IWDG复位,防止程序跑飞 |
2. 传感采集层:环境参数测量的关键细节
2.1 温湿度采集:别用DHT11,换SHT30体验完全不同
我知道很多人的第一反应是DHT11,便宜、教程多。但在这个项目里,DHT11的误差实在让人难受:温度±2℃、湿度±5%RH,而且单总线协议时序非常敏感,一旦被中断打断,读数就会卡住或者返回错误。植物生长箱里温度变化本来就慢,传感器误差太大,PID根本调不准。
我最后用了SHT30,SHT30走I2C接口,精度高(典型±0.3℃、±2%RH),带CRC校验,可以挂在I2C总线上和光照传感器共用。它的I2C地址是0x44(ADDR引脚接低)。测量流程是:发送测量命令0x2C 0x06,等待15ms,读取6字节数据,前两字节是温度、后两字节是湿度、中间有CRC。
温度转换公式:
uint16_t temp_raw = (data[0] << 8) | data[1]; float temperature = -45.0f + 175.0f * temp_raw / 65535.0f;另一个实用技巧是DS18B20多点测温。SHT30只能测箱内空气温度,但植物叶片附近和根部附近的温度可能存在几度差异。如果你想让控制系统更精细,可以加几颗DS18B20挂在单总线上,分别测箱顶、箱底、根区温度。DS18B20的时序要求比DHT11宽松,仍建议在读取时关中断或用定时器辅助时序。
2.2 光照与CO2的测量:数字传感器和模拟传感器要区别对待
光照我用的是BH1750,I2C接口,直接读出来就是勒克斯值。它的测量范围是0~65535 lx,对植物补光场景完全够用。注意BH1750上电后需要先发送断电命令再发送连续高分辨率测量命令,然后等120ms左右再去读结果。实测中光照传感器要放在植物冠层高度,不能贴着补光灯管,否则读出来的是直射光强,不是植物接收到的有效光照。
CO2浓度是很多人忽略的参数。箱内植物在光合作用旺盛时会消耗CO2,如果箱子是密闭的,CO2浓度下降会导致光合速率骤降。我用了MQ135,它本质上是一个热丝式气敏电阻,对CO2、酒精、烟雾都有响应。MQ135有两大问题:第一是预热时间长,上电后需要至少24小时才能稳定;第二是绝对精度差,只能做趋势判断。
MQ135的用法是把模拟输出接到STM32的ADC引脚,通过采样电压反推气体浓度。关键在标定:在洁净空气中测出一个基准电压,工作时用当前电压与基准电压的比值(Rs/Ro)估算浓度变化。我的做法是只做两级判断,CO2浓度超过设定阈值就打开排气扇换气,低于阈值就关闭,不做精确的连续调节。
2.3 ADC多通道扫描+DMA:最容易踩坑的信号链路
“stm32 adc多通道扫描循环采样dma”是搜索量很大的关键词,说明这个坑踩的人很多。我在这个项目里用ADC1采集MQ135和土壤湿度两个通道,配置成扫描模式、连续转换模式、DMA循环传输。
重点说坑:扫描模式下ADC会按Rank顺序依次转换各个通道,但DMA缓冲区里的数据顺序是严格按照ADC转换完成顺序写入的,不是按你中断里读的顺序。如果你配置时把通道1设为Rank1、通道2设为Rank2,那DMA缓冲区的第0个元素就是通道1的数据,第1个元素是通道2的数据。看似简单,但很多人栽在CubeMX配置里通道顺序和实际接线不一致,结果土壤湿度的数据跑到CO2通道上去了。
核心配置代码片段:
// ADC1 初始化, 两个通道 sConfig.Channel = ADC_CHANNEL_0; // PA0 - MQ135 sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; HAL_ADC_ConfigChannel(&hadc1, &sConfig); sConfig.Channel = ADC_CHANNEL_1; // PA1 - 土壤湿度 sConfig.Rank = ADC_REGULAR_RANK_2; HAL_ADC_ConfigChannel(&hadc1, &sConfig); // DMA缓冲区, 数量必须等于通道数 uint16_t adc_buf[2]; HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc_buf, 2);采样时间建议设长一点,239.5周期比较稳。实测中如果使用ADC+DMA循环模式,adc_buf里的数据一直会被自动刷新,你只需要在需要时拷贝一份出来,避免在中断里处理时数据被更新成一半。另外,所有ADC采集的引脚电压都必须是0~3.3V,MQ135模块如果输出的是5V电平,中间需要用分压电阻或运放调理。
2.4 传感器布局与线缆抗干扰
这块是在实际运行后才发现的问题。第一版我把SHT30贴在箱体侧壁,和加热器只有20厘米距离。结果PTC一工作,湿度读数先剧烈下跌再缓慢恢复——其实是热量驱动了传感器周围空气形成局部对流,读数根本不能代表箱内平均环境。
正确的做法是:
- SHT30放在箱内中间高度,用有孔塑料壳罩住,避免气流直接吹到探头。
- 光照传感器水平放在植物冠层位置,保证补光灯照度和自然光都能覆盖。
- 传感器线缆和继电器线缆分开走线,尤其不能和220V交流线绑在一起。
- 给I2C信号线(SCL、SDA)加4.7kΩ上拉电阻到3.3V,线长超过50cm时考虑加TVS管。
3. 执行器驱动:把控制量变成真实环境变化
3.1 隔离与驱动电路怎么设计
执行器层面,有一个原则:强电和弱电必须隔离。MCU是3.3V逻辑,继电器、水泵、雾化器是220V或12V/24V系统,如果共用电源,继电器吸合瞬间的电流冲击很容易把MCU复位。
我用的方案是:光耦隔离 + 达林顿管/三极管驱动继电器。光耦选了PC817,输入侧串联1kΩ限流电阻,电流控制在5~10mA,输出侧接继电器线圈。继电器线圈两端必须反向并联一个1N4007续流二极管,否则关断瞬间的反向电动势会击穿三极管。
如果驱动12V LED灯带或风扇这类直流设备,更推荐用低边N-MOS管,比如AO3400,导通电阻极低,发热小。栅极要加10kΩ下拉电阻,防止MCU上电瞬间GPIO悬空导致灯带闪烁。
如果是PTC加热器这类纯阻性交流负载,还有第三种方案:用MOC3021光耦可控硅驱动+BT136双向可控硅实现过零调功。这种方案比继电器更适合频繁调节,因为继电器触点频繁通断,寿命会迅速下降。不过可控硅调功需要过零检测电路,电路复杂度高一些,如果加热器功率不大、控制周期较长,用继电器也能接受。
3.2 补光灯PWM调光与调温解耦
补光灯用PWM调光非常合适。我用的全光谱LED灯带是12V供电,总功率约20W,用AO3400做低边开关,PWM频率选500Hz。之所以不选更高频率,是因为500Hz足以避免人眼明显闪烁,MOS管开关损耗也小,LED驱动器本身能承受。
补光灯最大的问题是它一工作就会发热,对温度控制产生明显的正向扰动。第一版实测,20W LED在密闭箱体里能让温度在半小时内上升3~5℃。PID控制器会先抑制这个扰动,但响应有滞后,温度出现明显的过冲。
解决思路是在策略层加前馈补偿,而不是只靠PID反馈。简单来说:当补光灯从0%调到100%时,估算约增加多少热功率,然后在PID输出的基础上直接减去一个偏置量。这个偏置量可以通过实验得出,例如50%光照对应约1.5℃升温,就先补偿1.5℃的加热输出。这样PID只需要处理净偏差,温度稳定性大幅提升。
3.3 雾化加湿和水泵的驱动注意事项
超声波雾化器是典型的“电力凶猛”设备。我用的一款12V雾化模块,标称工作电流3A,启动瞬间电流能冲到5A以上。如果你把雾化器和STM32共用同一个12V电源,雾化器一起动,电压瞬降,MCU直接就复位了。这个坑我踩得很实在,后面单列一节讲排查过程。
驱动方式上,雾化器用继电器或大电流MOS开关都可以,但必须给它独立的电源供电,建议用单独一路12V/5A以上的适配器,和主控电源分别供电,只在单点共地。另外,雾化器工作的环境湿度大,电路板要做好三防漆或装在密闭盒子中,否则用不了多久,继电器引脚和焊盘就会氧化发黑。
4. 控制策略:温度PID、湿度滞回、光照定时曲线的融合
4.1 温度控制:PID不能直接套公式
温度控制是这个项目里最费心思的部分。网上的PID教程很多,但直接套用教程代码,大概率会出现两个问题:积分饱和导致过冲,微分项放大传感器噪声导致输出抖动。
我的做法是位置式PID,采样周期固定为1秒,输出限幅到0~100%,然后用时间比例方式控制PTC加热器:比如输出30%,就是在一个5秒的控制周期里,加热器开1.5秒、关3.5秒。这样继电器或可控硅不会频繁通断,加热也均匀。
PID参数的经验起点:
| 参数 | 值 | 调整思路 |
|---|---|---|
| Kp | 150 | 先只加P,直到系统出现小幅振荡,再减半 |
| Ki | 1.5 | 慢慢加,消除稳态偏差,加太快会过冲 |
| Kd | 0 | 温度传感器噪声大,微分项弊大于利 |
调参我强烈建议用串口把实时温度、目标温度和PID输出打出来,做成曲线。没有曲线光看数字,很难判断积分是不是过头了。后面我专门讲了怎么用串口加Python脚本画曲线,这台植物生长箱的最终温控精度是±0.8℃。
关于抗积分饱和,我的实现很简单:当PID输出已经达到上限100%时,如果误差方向仍然要求继续增加输出,就冻结积分项。这样当实际温度慢慢追上目标值时,不会因为积分已经积累了一大截而导致过冲。
4.2 湿度控制:滞回控制比PID更实用
湿度控制我开始也试了PID,后来放弃了,因为湿度系统有两个特点:一是加湿器产生的水雾扩散需要时间,传感器读数变化严重滞后;二是湿度下降慢,但加湿过冲很快,PID很容易把加湿器开开关关。
最终方案是滞回控制:设定目标湿度60%RH,带回差±5%RH。当湿度低于55%RH时启动加湿,升至65%RH时关闭。滞回带避免继电器和雾化器频繁启停,雾化器的工作寿命和用电安全都更有保障。
加湿还有一个前馈技巧:雾化器关闭后,箱内雾气还会继续扩散,湿度读数通常会继续上升1~2%RH。所以我把关闭阈值设为目标值+5%RH,而不是目标值,实测中湿度基本稳定在目标值±4%RH内。
4.3 光照模拟:日出日落曲线比直接开关更聪明
植物生长需要光照周期,但突然开灯、突然关灯对植物来说是一种胁迫。我用STM32的TIM1 PWM输出控制LED亮度,配合一个简单的定时器任务,生成日出日落渐变曲线。
实现逻辑:设定每天6:00日出、18:00日落,从6:00开始,每隔5分钟亮度增加一个步长,约1小时后达到目标亮度;18:00后开始逐步降低亮度,持续1小时后关闭。这样总共12小时光周期,其中10小时是稳定光照。
光照强度本身也可以做成一个闭环:如果白天自然光透过窗户进入箱体,BH1750读到光照已经足够,就自动降低LED的PWM占空比,节省电能。不过这个闭环要加一个限制:LED亮度下限不低于20%,避免植物光周期紊乱。
4.4 多执行器优先级仲裁
当控制目标冲突时,必须有一个仲裁机制。我遇到过的最典型场景是:补光灯需要全开,但箱内温度已经接近上限。这时如果继续全开补光,温度肯定超限;如果直接关灯,植物光照又不足。
仲裁规则是:温度安全 > 湿度下限 > 光照需求 > CO2换气。具体实现中,当温度超过上限时,不直接切断补光灯,而是把补光亮度降到最低档,同时开启排风扇。如果温度继续上升,再逐步降低补光亮度。这样系统不会剧烈震荡,也不会让植物一下子处于全暗环境。
实际运行一个月下来,这套仲裁策略很稳定,没有出现过温度越限导致设备保护性关停的情况。
5. 人机交互与数据管理:控制系统需要“看得见”
5.1 OLED显示与菜单结构
显示部分我用了最常见的0.96寸OLED,SSD1306驱动,I2C接口。OLED本身刷新慢,不适合频繁整屏刷新,所以我把界面分成三个固定页面,只在切换页面或数据变化超过阈值时才更新局部区域。
三个页面是这样设计的:
- 状态页:实时显示温度、湿度、光照强度、CO2等级、设备状态图标。
- 参数页:显示并修改温度目标值、湿度目标值、光照时段、PID参数。进入参数页后,短按按键切换参数项,长按进入编辑,旋转编码器或按键调整数值。
- 手动页:强制开启/关闭加热器、加湿器、补光灯,方便现场测试。
如果你觉得OLED单色屏不够直观,项目想走高级路线,可以换带触摸的SPI彩屏,这时候C8T6的Flash就不够了,需要换大容量芯片,并移植LVGL。LVGL在这个体量的项目里能做出一屏多窗、曲线显示、触摸菜单,体验会好很多,但开发量会翻倍。
5.2 参数掉电保存:用内部Flash模拟EEPROM
PID参数、目标温湿度这些数据,如果每次断电都要重新设置,用户会崩溃。STM32F103没有内置EEPROM,但有Flash,可以在启动时从Flash读取参数,修改时写入Flash。
写Flash有两个必须注意的坑:
- Flash写入前必须先擦除整个扇区,F103是每页1KB,擦除会使该页数据全部变0xFF。
- Flash擦写寿命在10万次以下,频繁写入会损耗寿命,所以不能每次修改参数都立刻写Flash,应该先缓存,等所有参数修改完后由用户按“保存”键统一写入。
写入函数的核心流程:解锁Flash、擦除目标页、按地址写入数据、重新上锁。我在Flash末尾专门划分了一页(1KB)用来存储参数结构体,参数不多时足够用。启动时读出来的参数做合法性校验,如果读出来全是0xFF或校验失败,就用默认参数,防止初始化跑飞。
5.3 串口调试协议与上位机辅助调参
调PID没有实时曲线几乎是盲调。我的项目里用USART1连ESP8266做远程监控,同时用USART1的分时复用(或者单独用USART2)接USB转TTL,和PC通信。
串口接收不定长数据,用到了“HAL库串口空闲中断+DMA”的组合。传统按字节中断接收很简单,但解析不定长协议时CPU占用高,且容易漏数据。HAL库高版本提供了HAL_UARTEx_ReceiveToIdle_DMA()接口,开启DMA接收,空闲中断表示一帧数据结束,这时把DMA缓冲区里的数据提取出来解析,效率高很多。
我自定义了一个非常简单的帧格式:
帧头(0xAA 0x55) + 命令字(1字节) + 数据长度(1字节) + 数据 + 校验和(1字节)上位机我用Python写了不到100行的脚本,读取串口传来的数据,用matplotlib实时画温度/PID输出曲线。调PID时,改一次参数保存到Flash,观察曲线和稳态误差,再微调。这个流程比看串口打印数字高效得多。
6. 实测调试验证:从PID震荡到稳定运行
6.1 排查一:ADC多通道采样数据错位
现象:OLED上显示的CO2浓度和土壤湿度值互相串了,而且数值跳变严重。一开始我怀疑是传感器坏了,但单独采集每个通道时读数又正常。
排查过程:
- 先用万用表量MQ135模块输出端,电压稳定在1.2V左右,说明传感器本身没问题。
- 检查CubeMX里ADC Channel配置,确认Rank1是通道0、Rank2是通道1。
- 在
HAL_ADC_ConvCpltCallback里打印adc_buf[0]和adc_buf[1],发现adc_buf[0]对应的竟然是PA1引脚的电压。
根因:CubeMX生成代码时,Rank顺序和DMA缓冲区顺序本身是关联的,但我在手动初始化时中断了DMA请求,重新配置后通道顺序没同步,导致缓冲区数据顺序和物理通道错位。
解决:重新配置后,用固定电压源分别接到PA0和PA1验证DMA缓冲区第0和第1个元素,确认对应关系后再接传感器。建议每个项目都做一次通道标定,不要想当然。
6.2 排查二:雾化器一启动MCU就重启
现象:手动开启加湿器,OLED黑屏,STM32自动复位。
排查过程:
- 断开雾化器,MCU运行正常,加湿器一接上就复位,怀疑是电源问题。
- 用万用表测12V电源输出,雾化器启动瞬间电压掉到8V以下,3.3V稳压输出也被拉垮。
- 单独给雾化器供电,MCU不再复位。
根因:雾化器启动电流太大(5A级别),和MCU共用电源导致电压瞬降。这是典型的电源设计问题,不是固件问题。
解决:雾化器独立12V/5A电源,MCU系统3.3V由单独的低压差稳压器供给,两个电源只在主地单点连接。控制信号通过PC817光耦隔离,雾化器给主控的干扰被彻底切断。改造后测试,连续启动雾化器几百次,MCU再没复位过。
6.3 排查三:PID输出造成继电器频繁吸合
现象:温度稳定后,用万用表监听继电器,发现它每隔几秒就“咔哒”一次,明显是在频繁切换。
排查过程:
- 打印PID输出值,发现输出在0%和3%之间反复跳动,稳态偏差在0.1℃以内,但输出不断反复。
- 分析代码:位置式PID的输出在误差接近零时,积分项已经稳定,但比例项会随着0.1℃的微小误差波动,导致输出起伏。
- 确认是输出死区缺失和微分噪声放大的问题。
解决:给控制输出加了2%的死区,即PID输出小于2%时按0处理;同时把微分项完全禁用。改进后,温度维持在目标值附近,继电器动作频率大幅降低,基本稳定在几分钟才动作一次。
6.4 24小时连续运行验证
整机调试完成后,我做了一次24小时连续运行测试,记录若干关键时间点的数据:
| 时间 | 温度(℃) | 湿度(%RH) | 光照(lx) | 备注 |
|---|---|---|---|---|
| 08:00 | 25.1 | 61.2 | 0 | 升温段 |
| 09:00 | 26.3 | 60.5 | 12500 | 日出完成 |
| 12:00 | 25.8 | 62.1 | 13200 | 稳定段 |
| 15:00 | 26.2 | 59.8 | 12800 | 稳定段 |
| 18:30 | 25.0 | 58.3 | 6200 | 日落渐变 |
| 21:00 | 24.8 | 57.1 | 0 | 夜间模式 |
温度最大波动约±0.8℃,湿度在目标值±4%RH范围内,光照曲线平滑。整体功耗在补光全开时约45W,夜间约5W,对家用植物生长箱来说完全可以接受。
最后的经验和扩展想法
项目做到这个程度,控制系统本身已经能稳定工作了。如果还想继续扩展,我建议从三个方向入手:一是接入ESP8266通过WiFi上报数据,手机端就能看到箱内实时状态和曲线,不用每次跑到设备旁边看OLED;二是用K210这类带摄像头模组的芯片做植物叶片状态识别,通过图像判断植物是否缺光、缺水或生病;三是通过485总线扩展更多执行器,比如自动施肥泵、多路补光灯和多个箱体的集中管理。
整套系统做下来,我最大的体会是“环境控制不等于PID万能”。PID解决的是单变量闭环问题,但植物生长箱里的温度、湿度、光照、CO2彼此耦合,真正让系统稳定的,是架构层面的解耦设计和仲裁策略。传感器采集、执行器驱动、控制策略这三层的边界一旦划清楚,后面的调试会轻松很多。最后再分享一个小技巧:项目调试时养成保存参数版本的习惯,每改一次PID参数就在Flash里存一个备份,出问题能快速回退,别问我怎么知道的。
本文还有配套的精品资源,点击获取