资讯动态

项目一:基于 STM32F103C8T6 + FreeRTOS 的低功耗环境监测节点:多传感器采集 → OneNet 上云 → Android 远程监控

发布时间:2026/9/6 4:59:00 来源:尧图企业网站定制
项目一基于 STM32F103C8T6 FreeRTOS 的低功耗环境监测节点多传感器采集 → OneNet 上云 → Android 远程监控分类物联网 / 嵌入式标签STM32、FreeRTOS、低功耗、MQTT、OneNet、Android一、项目简介本项目从零到一实现一个软硬件全栈的便携式环境监测节点STM32 实时采集温度、湿度、光照、PM2.5通过 ESP8266 以MQTT 接入 OneNet 云平台断网时数据本地落盘、联网自动补传配套Android App远程实时查看与历史数据分析。整机锂电池供电设计了双模式低功耗架构周期自动唤醒 常亮 一键关机。适用场景室内空气质量监测、智能家居传感器节点、嵌入式 / 物联网学习参考。亮点不依赖现成 IoT SDK用 AT 指令 手写 MQTT 报文打通云平台不迷信直接调 API 进休眠用防御式处理把 STANDBY 真正睡进去并靠复位标志区分周期唤醒与手动开机两种姿态。项目实拍图改善中## 二、系统整体架构┌──────────────────────────── STM32F103C8T6 侧 ─────────────────────────────┐ │ FreeRTOS 多任务 │ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────────────┐ │ │ │ SensorTask │ │DisplayTask │ │NetworkTask │ │ LowPower_Task │ │ │ │ 每2s采集 │ │ OLED刷新 │ │ WiFi 上云 │ │ 收信号→进入STANDBY │ │ │ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ └─────────┬──────────┘ │ │ I2C1(mutex互斥) 软I2C USART2 │ │ │ SHT30 BH1750 OLED(SSD1306) ESP8266 │ │ │ USART3 SPI1 W25Q64 离线缓存 │ │ PMS5003 ────────── 断网本地存储 / 联网补传 ────────── │ └───────────────┬───────────────────────────────────────────────────────────┘ │ MQTT 上报 (JSON, Token 鉴权) ▼ ┌──────────────┐ │ OneNet 云 │◄── HTTP API 定时查询不占用设备 MQTT 连接 └──────┬───────┘ ▼ Android AppJetpack Compose Room MVVM层次职责技术选型感知层温度 / 湿度 / 光照 / PM2.5SHT30、BH1750、PMS5003控制层任务调度、外设管理、低功耗STM32F103C8T6 FreeRTOS HAL存储层离线数据缓存、断网补传W25Q64SPI Flash网络层WiFi 上云ESP8266 OneNet MQTT应用层远程实时 / 历史查看AndroidJetpack Compose Room三、硬件设计3.1 硬件清单模块型号接口说明主控STM32F103C8T6 最小系统板—ARM Cortex-M3 72MHz温湿度SHT30I2C1PB6/PB7精度 ±0.3℃ / ±2%RH光照BH1750I2C1PB6/PB70~65535 Lux与 SHT30 共用总线PM2.5攀藤 PMS5003USART3PB10/PB11激光式需 5V 供电显示0.96 寸 OLED 128×64软件 I2CPB8/PB9SSD1306 驱动WiFiESP8266 ESP-01SUSART2PA2/PA3AT 固件存储W25Q64SPI1PA4~PA7离线数据帧缓存电源TP4056 MT3608 603450 电池—锂电充放电、3.7V→5V 升压交互KEY1PB1/ PA0EXTI / WKUP休眠切换与唤醒3.2 供电拓扑USB 5V ── TP4056充电── 603450 锂电池 3.7V ── MT3608 升压 ── 5V ── STM32 板 PMS5003 └── 3.3V ── 传感器 / OLED / ESP8266踩坑提醒PMS5003 需要5V供电由升压模块单独供给传感器模块本身 3.3V与 STM32 电平兼容。ESP8266 的 RST 引脚必须接10K 上拉电阻到 3.3V不可悬空。四、软件架构FreeRTOS 任务划分任务优先级周期 / 触发职责start_task6上电一次初始化互斥锁、W25Q64、低功耗模块创建子任务后自删除LowPower_Task6信号量触发收到休眠信号后进入 STANDBYNetworkTask5常亮 10min / 周期一次性ESP8266 初始化 → 连 WiFi → MQTT → 上传 / 补传SensorTask4每 2sSHT30 → BH1750 → PMS5003 顺序采集DisplayTask2每 1sOLED 刷新周期模式下自动不点屏核心代码目录Int/ ├── freertos_demo.c 任务创建与主逻辑常亮 / 周期双运行姿态 ├── sht30.c / bh1750.c I2C 传感器驱动 ├── pms5003.c USART3 中断收帧 帧校验解析 ├── esp8266.c AT 指令封装初始化 / 配网 / TCP ├── onenet_mqtt.c 手写 OneNet MQTT 报文CONNECT/PUBLISH/PINGREQ ├── w25q64.c SPI Flash 离线数据缓存 ├── low_power.c 双模式低功耗管理 ├── oled.c 软件 I2C OLED 驱动 └── Key.c / LED.c 遗留轮询按键 / 指示灯主交互已迁移至 EXTI 中断五、功能清单1. 环境数据采集SensorTask周期 2sSHT30读取温度 / 湿度含无应答重试。BH1750与 SHT30共享 I2C1靠 FreeRTOS 互斥锁避免总线冲突。PMS5003USART3 中断逐字节接收解析 32 字节数据帧并校验输出 PM1.0 / PM2.5 / PM10。2. 本地 OLED 显示DisplayTask周期 1s软件 I2C 驱动 0.96 寸 OLED实时显示温度 / 湿度 / PM2.5 / 光照。周期模式自动不点屏——进一步省电、夜间无光污染。3. 按键交互KEY1 单按 / 长按 PA0 唤醒KEY1 单按3s进入周期模式——STANDBY 睡眠并设 30 分钟 RTC 闹钟到点自动唤醒采集上传一轮后回睡。KEY1 长按≥3s进入关机——STANDBY 睡眠且不设闹钟仅 PA0 可唤醒等同电源键。PA0WKUP 硬件唤醒脚唤醒后进入常亮模式。实现上 KEY1 走EXTI 双边沿中断按下沿记时刻、松开沿按时长区分单按 / 长按200ms 软件消抖中断中xSemaphoreGiveFromISR通知低功耗任务完全替代老代码的轮询按键。4. WiFi 上云NetworkTask OneNet MQTTAT 指令封装完成 ESP8266 初始化 / 配网 / TCP 连接。手写 MQTT 报文CONNECT含鉴权→ CONNACK → PUBLISHJSON 数据→ 保活 PINGREQ未使用现成 IoT SDK。常亮模式每 10 分钟完整上报一轮空闲时让 ESP8266 进入 light-sleep 省电。5. 离线数据缓存与断网补传W25Q64上传失败或未连上云时当前数据帧温度 / 湿度 / 光照 / PM2.5 / 时间戳写入 SPI Flash。下次连上云后先补传历史离线帧、再上报当前帧保证数据不丢。6. 双模式低功耗核心亮点详见第六节周期模式STANDBY 待机 → RTC 闹钟 30 分钟唤醒 → 复位后判定唤醒源 → 静默完成采集 补传 当前上报后自动回睡联网与上传设有90s 预算超时也落盘回睡防止死等。常亮模式冷启动 / PA0 唤醒进入OLED 常亮、10 分钟持续上报等待 KEY1 手动切换。关机长按 KEY1无闹钟睡眠仅 PA0 唤醒。7. Android App 远程监控实时仪表盘温度 / 湿度 / 光照 / PM2.5 四张数据卡片Compose UI ViewModel Repository Room 网络层MVVM 架构。历史分析趋势曲线图 统计值最小值 / 平均值 / 最大值 可滚动数据表格 时间范围筛选1 小时 / 6 小时 / 12 小时 / 24 小时 / 7 天 / 30 天。本地化存储Room 数据库落库保留 7 天自动清理。数据获取通过OneNet HTTP API 定时查询设备最新数据——上报走 MQTT、查询走 HTTP不额外占用设备 MQTT 连接内部做 Studio 新 API / 旧版 API 多端点降级容错。六、关键技术实现6.1 共享 I2C 总线上的 FreeRTOS 互斥SHT30 与 BH1750 挂在同一条 I2C1 上且采集任务并发运行。若不保护两个任务交替操作总线会产生半截事务I2C 的 START/STOP 时序敏感导致数据错乱。解决方式是总线即临界区g_I2C_MutexxSemaphoreCreateMutex();// start_task 中创建// 每次访问 I2C 总线前加锁整段事务完成后释放xSemaphoreTake(g_I2C_Mutex,portMAX_DELAY);SHT30_Read(temp,humi);xSemaphoreGive(g_I2C_Mutex);这也是把 OLED 从硬件 I2C 挪到**软件 I2CPB8/PB9**的原因——把硬件 I2C1 留给两个传感器共用用总线锁而不是把外设独占给某个任务来解决问题。6.2 STANDBY 低功耗难点在怎么睡得进去STANDBY 是 STM32 功耗最低的模式MCU 待机电流降至 μA 级。很多人以为调HAL_PWR_EnterSTANDBYMode()就能睡但在FreeRTOS HAL下经常睡不进去——问题在于执行__WFI()的瞬间若有中断 pending会立刻返回。本项目做了防御式清场staticvoidPrepareInterruptCleanup(void){SysTick-CTRL0U;/* 停 FreeRTOS 时基 */TIM2-CR1~TIM_CR1_CEN;/* 停 HAL 时基1ms tick */__HAL_RCC_USART2_CLK_DISABLE();/* 关闭会产生中断的外设时钟 */__HAL_RCC_USART3_CLK_DISABLE();__HAL_RCC_I2C1_CLK_DISABLE();__HAL_RCC_SPI1_CLK_DISABLE();NVIC_DisableIRQ(...);/* 屏蔽相关中断 */NVIC_ClearPendingIRQ(...);/* 并清空 pending 标志 */}/* 进休眠前的收尾 */__disable_irq();HAL_PWR_EnterSTANDBYMode();/* 安全网万一 WFI 因残留中断未进入 STANDBY主动复位恢复干净状态 */__enable_irq();NVIC_SystemReset();进休眠前还会 OLED 关屏、W25Q64 进待机真正做到关灯拔插头。6.3 STANDBY 唤醒后 系统复位如何区分为什么醒F1 的 STANDBY 唤醒不会回到原执行点而是系统复位。那如何区分30 分钟闹钟到点还是用户按 PA0 开机利用复位后依然保留的电源标志位if(__HAL_PWR_GET_FLAG(PWR_FLAG_SB))// STANDBY 唤醒复位标志{if(__HAL_RTC_ALARM_GET_FLAG(hrtc,RTC_FLAG_ALRAF))g_wakeup_reasonWAKEUP_REASON_RTC;// 周期模式静默一轮后回睡elseg_wakeup_reasonWAKEUP_REASON_KEY;// PA0 / 冷启动常亮模式__HAL_RTC_ALARM_CLEAR_FLAG(hrtc,RTC_FLAG_ALRAF);}NetworkTask/DisplayTask启动时依据g_wakeup_reason决定运行姿态RTC 唤醒 →周期模式OLED 不点屏90s 预算内完成连网 → 补传 → 上报 → 回睡。KEY / 冷启动 →常亮模式清掉上次残留的 RTC 闹钟防止常亮期间被莫名拉回睡眠OLED 点亮进入 10 分钟循环。闹钟依赖 RTC 走LSI——STANDBY 下 LSI 继续运行闹钟使用 32 位二进制秒计数唤醒可靠。整体复位即重启 标志位判别 双运行姿态的设计是比单纯进 STANDBY 更高一层的系统级思路。6.4 断网补传时序上传路径统一为连接稳定后先回放 W25Q64 离线帧全部成功再上报当前帧任一次补传失败立即停止回放并把当前帧追加落盘保证数据不丢、不重复污染。6.5 Android 端数据容错App 层查询 OneNet 做多端点降级Studio 新 API → 旧版 API并对新版返回结构做针对性解析适配实时数据经协程Channel推给 Compose 层历史数据走 Room实时与历史两条链路解耦。七、实测效果串口调试输出与当前固件 printf 一致[SHT30] T25.7 C H58.3 %RH [BH1750] Light6.7 Lux [PMS5003] PM1.012 PM2.517 PM1017 [ESP8266] Init OK [WiFi] Connected [OneNet] MQTT OK [W25Q64] Offline data done [OneNet] Upload OK: T25.7 H58.3 L6.7 PM2.517 [Network] Periodic cycle done, sleeping... [LowPower] Entering STANDBY (periodic), wake in 1800 s [Main] Woke from STANDBY, reasonRTC [Network] Periodic cycle done, sleeping...Android App 界面实时数据界面历史数据界面八、开发环境与工具项版本Keil MDKV5ARMCC V5配置与驱动STM32CubeMX STM32F1 HAL 库RTOSFreeRTOSAndroidKotlin Jetpack Compose Room云平台OneNet StudioMQTT 1883 / HTTP APIToken 鉴权硬件工具T12 焊台模块化搭建九、项目亮点软硬件全栈打通MCU 采集 → ESP8266 上云 → OneNet MQTT → Android App 远程监控一条完整数据链路。低功耗双模式架构STANDBY RTC 30 分钟周期唤醒唤醒后靠复位标志判别周期 / 常亮双姿态KEY1 单按 / 长按区分周期休眠与关机PA0 硬件唤醒。解决STANDBY 睡不进去的工程难题停时基、断外设时钟、清 pending 中断、失败安全网复位——把低功耗从调 API变成懂机制。RTOS 资源管理意识共享 I2C 总线用互斥锁保护任务与外设资源合理划分。手写 MQTT 协议接入云平台CONNECT / PUBLISH / PINGREQ不依赖现成 IoT SDK。可靠性设计SPI Flash 离线缓存 断网补传 联网超时预算数据不丢、不死等。驱动级硬核I2C 时序、软件 I2C、USART 中断收帧与帧校验、AT 指令状态机均底层手写。工程化习惯CubeMX 分层结构、中文注释与开发笔记沉淀、Git 版本管理、实测截图留档、README 齐全。十、后续可优化方向整机待机电流的实测与进一步降耗分模块电源关断。设备端 OTA 固件升级。App 由 HTTP 轮询升级为 MQTT 长连接订阅降低实时延迟。一云多节点 / 多设备统一管理。注项目仍在持续改善中·项目完整代码及文档仅供参考学习转载 / 使用请注明出处。文章目录项目一基于 STM32F103C8T6 FreeRTOS 的低功耗环境监测节点多传感器采集 → OneNet 上云 → Android 远程监控一、项目简介三、硬件设计3.1 硬件清单3.2 供电拓扑四、软件架构FreeRTOS 任务划分五、功能清单1. 环境数据采集SensorTask周期 2s2. 本地 OLED 显示DisplayTask周期 1s3. 按键交互KEY1 单按 / 长按 PA0 唤醒4. WiFi 上云NetworkTask OneNet MQTT5. 离线数据缓存与断网补传W25Q646. 双模式低功耗核心亮点详见第六节7. Android App 远程监控六、关键技术实现6.1 共享 I2C 总线上的 FreeRTOS 互斥6.2 STANDBY 低功耗难点在怎么睡得进去6.3 STANDBY 唤醒后 系统复位如何区分为什么醒6.4 断网补传时序6.5 Android 端数据容错七、实测效果串口调试输出与当前固件 printf 一致Android App 界面八、开发环境与工具九、项目亮点十、后续可优化方向

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价