STM32+腾讯云IoT:烘干车间远程监控系统实战

发布时间:2026/10/21 6:57:43
STM32+腾讯云IoT:烘干车间远程监控系统实战 简介这份PDF面向嵌入式开发学习者与物联网项目实践者围绕基于STM32F103RCT6的烘干车间远程控制系统展开解决温湿度与空气质量监测、加热通风联动及远程操控等实际问题。内容从硬件选型入手涵盖DHT11、MQ135、ESP8266-WIFI、继电器、蜂鸣器与1.44寸SPI液晶屏的接线与驱动并给出自动/手动模式控制逻辑、按键功能与通信协议说明。软件部分包含STM32完整代码、KEIL工程配置、串口调试流程以及腾讯云IOT平台的产品与设备开发、物模型配置、MQTT主题订阅发布和微信小程序交互设计形成从设备端到云端的完整链路。资源为1个PDF文件约41.81MB目录按前言、硬件选型、云平台与小程序设计、硬件设计、代码流程及完整代码组织便于按模块查阅。已有204人学习适合课程设计、毕业设计或智能工厂改造参考可快速获取方案框架、代码参考与云端对接思路。1. 烘干车间上云这件事难点从来不在“连上网”烘干车间远程控制系统核心是把现场温湿度、设备启停状态通过 STM32 采集后经网络送到腾讯云 IoT再在云端做规则判断和远程下发。听起来像是个“联网 Demo”但真正落地时你会发现车间里 60℃ 以上的热风、电机启停带来的电源波动、多台设备共用一条 485 总线这些才是让系统三天两头掉线的元凶。这套方案适合做工业物联网方向的学生、刚转行嵌入式的开发者以及需要给小型烘干房做低成本远程监控的集成商。它不追求大厂级高可用但能把“数据上得来、命令下得去、断网能自愈”这三件事做扎实。下面按硬件选型、STM32 端采集与通信、腾讯云 IoT 接入、避坑排查、进阶技巧的顺序拆开讲每一步都给出可复现的配置和代码。2. 硬件选型与腾讯云 IoT 接入前必须想清楚的三个约束2.1 为什么主控选 STM32F103 而不是 ESP32 单芯片方案很多教程一上来就推 ESP32理由是“自带 Wi-Fi省一颗芯片”。但在烘干车间这个场景里我一般会坚持 STM32F103C8T6 加独立通信模组的组合。原因有三条第一车间内 380V 风机启停时电源纹波很大ESP32 的射频部分对电源噪声敏感实测在电机启动瞬间 Wi-Fi 重连概率明显上升第二STM32 的 ADC 和定时器资源更规整接 PT100 铂电阻和 SHT30 数字温湿度传感器时采样时序好控制第三一旦通信模组损坏只需更换模组主控里跑的控制逻辑和标定参数不用重烧。通信模组常见做法是选 EC200S 或 Air724UG 这类 4G Cat.1 模组走 MQTT 协议直连腾讯云 IoT。如果车间已有 Wi-Fi 覆盖且设备位置固定也可以选 ESP8266 做透传但要注意把模组供电和主控供电分开走线模组电源脚旁边并 100μF 和 0.1μF 电容。器件型号示例作用关键参数主控STM32F103C8T6采集与控制72MHz64KB Flash12位ADC温湿度SHT30环境温湿度±0.3℃精度I2C接口通信EC200S4G上云Cat.1MQTT/TCP继电器光耦隔离模块控制风机/加热3.3V触发250VAC/10A电源LM2596S24V转5V/3.3V3A输出需加散热片2.2 腾讯云 IoT 侧要提前建好的三个东西在写 STM32 代码之前先在腾讯云物联网开发平台上完成三件事否则后面调试会反复回头改。第一创建产品数据协议选“数据模板”这样云端能自动解析 JSON第二在产品下创建设备拿到三元组产品 ID、设备名称、设备密钥第三定义物模型至少建三个属性当前温度、当前湿度、设备运行状态再建一个行为远程启停。物模型的数据类型要和 STM32 端上报的 JSON 字段严格对应。比如温度定义为 float 类型单位摄氏度取值范围 -40 到 120运行状态定义为 bool0 表示停止1 表示运行。如果类型对不上云端会直接丢弃消息设备端却看不到任何报错这是新手最容易卡住的地方。提示三元组里的设备密钥只用于首次连接时计算 MQTT 密码不要把它硬编码在会分发的固件里。量产时建议每台设备单独烧录或走动态注册。2.3 MQTT 连接参数与三元组计算的最小验证腾讯云 IoT 的 MQTT 接入需要构造 clientId、username、password。常见做法是用 HMAC-SHA1 对特定字符串做签名。下面这段 Python 脚本用来在电脑上先验证三元组是否正确确认无误后再移植到 STM32 端。import hmac import hashlib import base64 import time # 替换为你的三元组 product_id 你的产品ID device_name 你的设备名 device_secret 你的设备密钥 # 时间戳毫秒级腾讯云要求与服务器时间偏差不超过5分钟 timestamp str(int(time.time() * 1000)) # 拼接签名原文注意顺序和分隔符 sign_str f{product_id}{device_name}{timestamp} # 用设备密钥做HMAC-SHA1 sign hmac.new(device_secret.encode(), sign_str.encode(), hashlib.sha1).digest() # Base64编码后再URL编码这里只做Base64实际连接时需URL编码 password base64.b64encode(sign).decode() client_id f{product_id}{device_name} username f{product_id}{device_name};{timestamp} print(clientId:, client_id) print(username:, username) print(password:, password)这段代码的逻辑是腾讯云要求 password 由设备密钥对“产品ID设备名时间戳”做 HMAC-SHA1 后 Base64 得到。时间戳必须用毫秒且和云端时间差不能超过 5 分钟否则会返回“认证失败”。在 STM32 端没有现成的 HMAC 库时可以移植一份精简的 SHA1 和 HMAC 实现注意把时间戳通过 4G 模组从网络获取不要用本地 RTC因为 RTC 走久了会漂。3. STM32 端采集、打包与 MQTT 上报的完整链路3.1 SHT30 采集与温度补偿的代码实现SHT30 走 I2CSTM32F103 的硬件 I2C 在电机干扰下容易死锁我一般用软件模拟 I2C把时钟拉到 100kHz 以下。下面是对 SHT30 发起单次测量并读取温度的代码片段。// 软件I2C引脚定义 #define SHT30_SCL_PIN GPIO_Pin_6 #define SHT30_SDA_PIN GPIO_Pin_7 #define SHT30_PORT GPIOB // SHT30地址7位地址0x44左移一位 #define SHT30_ADDR 0x88 // 单次测量高重复性无时钟拉伸 void SHT30_StartMeasure(void) { I2C_Start(); I2C_SendByte(SHT30_ADDR); I2C_WaitAck(); I2C_SendByte(0x2C); // 命令高字节 I2C_WaitAck(); I2C_SendByte(0x06); // 命令低字节高重复性 I2C_WaitAck(); I2C_Stop(); } // 读取温湿度原始值并转换 void SHT30_ReadTempHumi(float *temp, float *humi) { uint8_t buf[6]; I2C_Start(); I2C_SendByte(SHT30_ADDR | 0x01); // 读地址 I2C_WaitAck(); for (int i 0; i 5; i) { buf[i] I2C_ReadByte(); I2C_SendAck(1); // 前5字节发ACK } buf[5] I2C_ReadByte(); I2C_SendAck(0); // 最后一字节发NACK I2C_Stop(); uint16_t raw_temp (buf[0] 8) | buf[1]; uint16_t raw_humi (buf[3] 8) | buf[4]; // 转换公式来自SHT30数据手册 *temp -45.0f 175.0f * raw_temp / 65535.0f; *humi 100.0f * raw_humi / 65535.0f; }这里的关键参数是命令字 0x2C06表示高重复性测量且不启用时钟拉伸。如果车间电磁干扰特别强可以改用 0x2C10低重复性牺牲一点精度换更短的测量时间减少被干扰的概率。转换公式里的 -45 和 175 是 SHT30 的固定系数不要改。读回来的温度建议做滑动平均比如连续采 5 次去掉最大最小再平均否则上报曲线会像心电图。3.2 上报 JSON 的拼装与 MQTT 发布STM32 端拼 JSON 不建议用动态内存直接用一个 256 字节的静态数组用 snprintf 格式化。下面是把温度、湿度、运行状态拼成腾讯云物模型格式并发布的代码。// 腾讯云物模型上报主题需替换产品ID和设备名 #define TOPIC_PUB $thing/up/property/你的产品ID/你的设备名 void Report_Property(float temp, float humi, uint8_t run_state) { char json[256]; // 物模型要求字段名与云端定义一致 int len snprintf(json, sizeof(json), {\method\:\report\,\clientToken\:\%lu\, \params\:{\temperature\:%.1f,\humidity\:%.1f, \run_state\:%d}}, HAL_GetTick(), temp, humi, run_state); // MQTT发布QoS选1保证至少到达一次 MQTT_Publish(TOPIC_PUB, json, len, 1); }这段代码里 clientToken 用 HAL_GetTick() 生成保证每次请求有唯一标识云端返回时会带回这个值方便做请求响应匹配。QoS 选 1 而不是 0是因为烘干车间的网络会间歇性抖动QoS 0 丢了就丢了温度数据断档后云端规则引擎可能误判。但 QoS 1 会带来重复消息云端物模型对重复上报是幂等的所以不用担心。注意snprintf 的返回值是“本该写入的长度”如果超过 256 会截断。建议在发布前判断 len 是否小于 sizeof(json)否则丢弃这条数据并记录错误计数。3.3 云端命令下发与 STM32 端的解析远程启停通过订阅$thing/down/property/产品ID/设备名主题实现。云端下发的 JSON 里 params 字段包含要设置的值。STM32 端不需要完整的 JSON 解析库用字符串查找定位关键字段即可但要注意字段顺序不固定。// 收到下行消息的回调 void MQTT_OnMessage(char *topic, char *payload, int len) { // 查找run_state字段 char *p strstr(payload, run_state); if (p ! NULL) { // 跳过冒号读取数值 p strchr(p, :); if (p ! NULL) { int state atoi(p 1); if (state 1) { Relay_On(); } else { Relay_Off(); } // 执行后立即上报当前状态形成闭环 Report_Property(last_temp, last_humi, state); } } }这里用 strstr 和 atoi 是最省资源的做法但前提是云端下发的 JSON 格式稳定。如果后续物模型增加了嵌套结构建议换成 cJSON 的精简版。执行继电器动作后立刻上报一次状态是为了让云端和 App 确认命令已生效否则用户点了“启动”但界面还显示停止体验很差。4. 腾讯云 IoT 规则引擎与远程控制的联动配置4.1 数据流转到自定义后端的配置步骤如果只想在腾讯云控制台看数据物模型上报就够了。但要做报警推送或存数据库需要配置规则引擎。步骤是进入物联网开发平台选择产品点“规则引擎”新建规则填写 SQL 语句筛选数据再配置动作转发到消息队列或 HTTP 接口。SQL 语句示例SELECT * FROM $thing/up/property/产品ID/设备名 WHERE temperature 80。这条规则会把温度超过 80 度的上报数据筛选出来转发到你指定的 HTTP 接口。注意 SQL 里的主题要写完整且产品 ID 和设备名要和实际一致否则规则不触发。4.2 用云函数做温度超限告警的最小实现规则引擎的动作可以选“云函数”在云端写一段 JavaScript 处理告警。下面是一个最小实现判断温度超过阈值后调用企业微信机器人或短信接口。exports.main_handler async (event, context) { // event 里包含规则引擎转发过来的消息 const payload JSON.parse(event.body || {}); const temp payload.params ? payload.params.temperature : null; const device payload.deviceName || 未知设备; if (temp ! null temp 80) { // 这里替换为实际的告警发送逻辑 console.log(告警设备${device}温度${temp}℃超过阈值); // 实际项目中调用短信API或推送服务 return { code: 0, msg: 告警已发送 }; } return { code: 0, msg: 正常 }; };这段云函数的逻辑是规则引擎把匹配到的消息以 event 形式传入解析出温度和设备名超过 80 度就触发告警。阈值 80 是烘干车间的常见上限具体数值要根据物料工艺调整。云函数执行时间默认 3 秒如果调用外部 API 超时需要在云函数配置里把超时时间调大。4.3 设备影子与离线命令缓存烘干车间偶尔会断网如果此时用户下发“启动”命令设备不在线就丢了。腾讯云 IoT 的设备影子可以缓存期望值设备上线后主动拉取。配置方法是在物模型里把 run_state 设为“可读写”并启用影子。STM32 端上线后先订阅$thing/down/property/主题再发布一条空消息触发云端下发当前期望值。这个机制不能保证命令实时到达但能保证“最终一致”。对于烘干这种慢过程控制最终一致是可以接受的。如果要求毫秒级响应那就得在现场加本地控制面板云端只做监视。5. 调试与运维阶段最容易翻车的五个坑5.1 设备频繁掉线日志显示 MQTT 连接被断开现象设备上线后几分钟到几十分钟不等就掉线重新连接后又能撑一段时间。原因通常有两个一是 MQTT keepalive 设置过短STM32 端在忙其他任务时没及时发心跳二是 4G 模组的电源在电机启动瞬间被拉低模组复位。解决方法是把 keepalive 从默认 60 秒改成 120 秒同时在 STM32 端用独立定时器专门发心跳不依赖主循环。电源方面给 4G 模组单独加一颗 2200μF 电解电容并确保模组供电走线不经过电机驱动区域。5.2 云端收到数据但物模型显示“解析失败”现象规则引擎能看到原始消息但物模型属性里没有数据或者显示“数据类型不匹配”。原因一般是 JSON 字段名大小写和云端定义不一致或者数值类型对不上。比如云端定义 temperature 是 float设备端上报的是字符串 25.3就会解析失败。解决方法是先用腾讯云控制台的“在线调试”功能手动发一条模拟数据确认云端能正确解析后再对照修改设备端代码。5.3 继电器动作时 STM32 复位现象每次继电器吸合或断开STM32 就重启串口打印一堆乱码。原因是继电器线圈断电时产生反向电动势通过共地路径干扰了 MCU。解决方法是继电器线圈两端加续流二极管光耦隔离模块的输入和输出电源完全分开MCU 的电源入口加 TVS 管和磁珠。如果已经画了板子可以在继电器控制引脚和地之间并一个 100nF 电容做缓冲。5.4 温度读数比实际值偏高 5 到 10 度现象SHT30 读数和标准温度计对比总是偏高。原因是 SHT30 离 STM32 主控或电源模块太近自身发热影响了测量。解决方法是把 SHT30 用延长线引出远离发热器件至少 5 厘米同时降低采样频率比如从每秒一次改成每 10 秒一次减少自热。如果结构上无法远离可以在软件里做固定偏移补偿但补偿值要实测确定。5.5 设备密钥泄露导致被恶意连接现象云端日志里出现陌生 IP 的连接记录或者设备被强制下线。原因是设备密钥硬编码在固件里固件被提取后密钥泄露。解决方法是量产时每台设备使用独立密钥并通过动态注册方式获取已泄露的密钥在云端禁用并重新生成。对于小批量项目至少不要把密钥提交到代码仓库用单独的配置文件并在编译时注入。6. 把上报间隔从 10 秒压到 1 秒STM32 端的内存与功耗平衡技巧前面讲的都是功能打通这一章说一个实际运维中会遇到的进阶问题烘干工艺要求温度曲线越细越好上报间隔从 10 秒缩到 1 秒STM32 端怎么扛住。直接改定时器周期当然可以但会带来三个连锁反应MQTT 发布频率提高后 4G 模组功耗上升JSON 拼装频繁导致内存碎片以及云端消息量增大后规则引擎费用增加。我的做法是分层上报本地每 1 秒采集一次存到一个 30 条的环形缓冲区里每 10 秒把缓冲区里的数据做一次压缩只上报最大值、最小值和平均值只有当温度变化超过 2 度时才立即触发一次单点上报。这样云端看到的曲线既保留了细节消息量又只有原来的三分之一。// 环形缓冲区结构 #define BUF_SIZE 30 typedef struct { float temp[BUF_SIZE]; float humi[BUF_SIZE]; uint8_t head; uint8_t count; } SensorBuf; SensorBuf g_buf {0}; // 每1秒调用一次存入缓冲区 void Buffer_Push(float t, float h) { g_buf.temp[g_buf.head] t; g_buf.humi[g_buf.head] h; g_buf.head (g_buf.head 1) % BUF_SIZE; if (g_buf.count BUF_SIZE) g_buf.count; } // 每10秒调用一次计算统计值并上报 void Buffer_Report(void) { if (g_buf.count 0) return; float t_max -100, t_min 200, t_sum 0; float h_sum 0; for (int i 0; i g_buf.count; i) { float t g_buf.temp[i]; if (t t_max) t_max t; if (t t_min) t_min t; t_sum t; h_sum g_buf.humi[i]; } float t_avg t_sum / g_buf.count; float h_avg h_sum / g_buf.count; // 上报统计值字段名在云端物模型里提前定义好 Report_Statistics(t_max, t_min, t_avg, h_avg); g_buf.count 0; // 清空计数head不复位 }这段代码的关键是环形缓冲区不动态分配内存固定 30 条每条 8 字节总共 240 字节STM32F103 的 20KB RAM 完全放得下。上报统计值时云端物模型需要提前增加 t_max、t_min、t_avg、h_avg 四个属性否则解析会失败。变化触发上报的阈值 2 度是经验值烘干车间温度波动本身就有 1 到 2 度设太小会频繁触发设太大又漏掉真实变化。还有一个省电技巧如果设备用电池供电可以把 4G 模组设为空闲时进入休眠STM32 用 RTC 定时唤醒。但烘干车间一般有市电这个优化不是必须的。我自己的习惯是任何上报间隔的调整都要先在现场跑 24 小时用云端日志统计实际消息量和丢包率再决定是否固化参数。曾经有一次把间隔从 10 秒改成 2 秒结果当天云端消息量翻了五倍规则引擎费用超了预算后来用分层上报才压回来。这个教训让我养成了“先算账再改参数”的习惯。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询