(HAL库)基于STM32F103C8T6的物联网温控PID系统实战:从DHT11到阿里云
1. 项目背景与硬件选型去年参加完蓝桥杯嵌入式比赛后总觉得学到的知识应该落地成实际项目。当时手头正好有块STM32F103C8T6开发板想着做个能实时监控环境温度并自动调节的智能系统应该挺有意思。这个蓝色小板子虽然只有64KB Flash和20KB RAM但用来跑温控PID算法绰绰有余。核心硬件清单我精简到了最实用的组合主控芯片STM32F103C8T6性价比之王HAL库支持完善温湿度传感器DHT11便宜够用精度±2℃无线模块ESP8266-01SAT指令固件直接透传MQTT执行机构L298N驱动的小风扇5V加热片PWM调速控制人机交互0.96寸OLED两个按键状态显示和参数设置这里有个选型经验分享DHT11虽然精度一般但对于室内环境监控完全够用。如果追求更高精度可以换DHT22或DS18B20不过要注意DHT22的响应速度会慢一些。ESP8266我选的是01S版本比普通01多了PCB天线实测穿墙能力提升明显。2. 开发环境搭建2.1 CubeMX基础配置打开STM32CubeMX新建工程时记得选对芯片型号。有次我手滑选了C6T6下载程序时一直报错排查半天才发现型号选错。具体配置步骤如下时钟树配置HSE_VALUE 8000000 PLLMUL x9 系统时钟 72MHz APB1 36MHz (定时器时钟x2)建议先用Clock Configuration界面自动生成再手动微调。我习惯把APB1定时器时钟设为72MHzx2倍频这样PWM分辨率更高。GPIO分配PA0 - DHT11数据线 PA2/PA3 - USART2 (ESP8266) PB6/PB7 - I2C1 (OLED) PA8 - TIM1_CH1 (PWM输出) PB14/PB15 - 电机方向控制定时器配置 TIM1通道1生成PWM关键参数Prescaler 71 Counter Period 19999 Pulse 1000 (初始占空比5%)2.2 开发工具链推荐用VSCodePlatformIO组合比Keil更友好安装PlatformIO插件新建STM32项目修改platformio.ini[env:bluepill_f103c8] platform ststm32 board bluepill_f103c8 framework stm32cube upload_protocol stlink有个坑要注意PlatformIO默认的HAL库版本可能较旧建议手动指定最新版platform_packages framework-stm32cube2.0.03. DHT11驱动开发3.1 传感器通信协议DHT11采用单总线协议时序要求严格。第一次调试时因为没加延时读回来的全是乱码。后来用逻辑分析仪抓波形才发现响应信号需要20ms低电平。关键时序参数主机拉低≥18ms主机拉高20-40us从机响应80us低电平数据位026-28us高电平数据位170us高电平实测代码里需要微调延时void DHT11_Rst(void) { DHT11_IO_OUT(); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); HAL_Delay(20); // 实测18ms不够稳定 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET); delay_us(30); // 28us有时会丢响应 }3.2 数据校验技巧DHT11返回40bit数据前32bit分温湿度最后8bit是校验和。建议增加以下错误处理uint8_t DHT11_Read_Data(uint16_t *temp, uint16_t *humi) { if((buf[0]buf[1]buf[2]buf[3])!buf[4]) { return 1; // 校验失败 } // 温度值处理技巧整数部分用buf[2]小数部分固定为0 *temp (buf[2]8) | 0x00; *humi (buf[0]8) | 0x00; return 0; }4. ESP8266连接阿里云4.1 阿里云IoT平台配置创建产品时功能定义要添加两个属性温度float-20~100℃湿度float0~100%设备三元组获取后建议用宏定义保存#define PRODUCT_KEY k11lrEXZkfv #define DEVICE_NAME temp #define DEVICE_SECRET e033ec75050e41da5c29b92faa2201d64.2 MQTT连接优化原始AT指令容易出错我封装了重试机制uint8_t mqtt_connect() { for(int i0; i3; i) { sprintf(cmd, ATMQTTCONN0,\%s.iot-as-mqtt.cn-shanghai.aliyuncs.com\,1883,1\r\n, PRODUCT_KEY); if(sendATCmd(cmd, OK, 2000)) { return 0; } HAL_Delay(1000); } return 1; }数据上传格式建议用JSON阿里云文档要求的格式比较特殊char* build_json(uint16_t temp, uint16_t humi) { static char json[100]; sprintf(json, {\\\params\\\:{\\\temp\\\:%d.%d,\\\humi\\\:%d.%d}}, temp8, temp0xFF, humi8, humi0xFF); return json; }5. PID算法实现5.1 增量式PID实现位置式PID容易积分饱和我改用增量式算法typedef struct { float Kp,Ki,Kd; float err[3]; // 环形队列保存最近三次误差 float output; } PID_IncTypeDef; float PID_Incremental(PID_IncTypeDef *pid, float actual) { pid-err[2] pid-err[1]; pid-err[1] pid-err[0]; pid-err[0] pid-target - actual; float delta pid-Kp*(pid-err[0]-pid-err[1]) pid-Ki*pid-err[0] pid-Kd*(pid-err[0]-2*pid-err[1]pid-err[2]); pid-output delta; return pid-output; }5.2 参数整定经验通过多次实测得出这些经验值先调Kp让系统有明显震荡加入Ki消除静差取Kp值的1/10Kd最后加改善动态响应我的温控系统最终参数pid.Kp -30.0; // 负号表示温度高时加大冷却 pid.Ki 0.5; // 消除静差 pid.Kd 2.0; // 抑制超调6. 系统整合与优化6.1 主程序架构采用时间片轮询方式避免阻塞void main() { // 初始化代码... uint32_t oled_tick 0; uint32_t sensor_tick 0; while(1) { uint32_t now HAL_GetTick(); if(now - sensor_tick 2000) { // 2秒采集一次 DHT11_Read(); sensor_tick now; } if(now - oled_tick 500) { // OLED刷新 OLED_Display(); oled_tick now; } PID_Calculate(); // 实时运行PID } }6.2 抗干扰设计DHT11数据线加上拉电阻4.7K电机电源与MCU完全隔离ESP8266供电单独加1000μF电容7. 效果展示与改进方向实际测试在20㎡房间内能将温度控制在设定值±0.5℃范围内。通过阿里云物联网平台可以实时查看数据曲线还能远程修改目标温度。后续改进计划增加手机APP控制界面改用ESP32作主控内置WiFi模块加入历史数据存储功能这个项目最让我惊喜的是PID算法的实际效果——原本以为需要复杂的数学模型实际上通过简单参数整定就能获得不错的控制效果。