基于STM32的智能宿舍管理系统设计与实现

一、项目概述
1.1 项目背景与目标
高校宿舍管理场景看起来简单,实际是一个典型的“多因素、强实时、低成本”系统。传统方式主要依赖人工巡查和经验判断,存在几个明显问题:
- 宿舍温湿度、光照、烟雾等环境参数无法持续采集,异常情况发现滞后
- 用电统计粗放,缺少实时功率、累计电量和超额预警能力
- 学生离开宿舍后设备仍长时间运行,存在明显能源浪费
- 管理数据零散,缺少历史记录与趋势分析,后续追溯困难
基于这些痛点,可以把宿舍管理系统拆成三类需求:
- 环境监测:实时采集温湿度、烟雾、光照、人体在位状态
- 能源管理:实时采集电压、电流、功率,并做电费估算与超额提醒
- 远程可视化:通过无线链路把数据上传到上位机,做图形化展示和历史存储
本文整理一套适合毕业设计展示的完整方案:以 STM32F103C8T6 为核心控制器,集成 DHT11、INA226、MQ-2、TEMT6000、PIR 等传感器,使用 ESP8266-01S 搭建 AP 模式无线链路,最后由 Python + PyQt5 上位机完成实时界面展示、SQLite 入库与异常报警。
1.2 技术栈选型
| 技术领域 | 具体选型 | 选择理由 |
|---|---|---|
| 主控芯片 | STM32F103C8T6 | 成本低、开发资料多、GPIO/ADC/I2C/UART 资源足够 |
| 温湿度检测 | DHT11 | 接口简单、成本低,适合宿舍场景演示 |
| 电流功率检测 | INA226 | I2C 接口、精度高,可直接测电流/电压/功率 |
| 烟雾检测 | MQ-2 | 成熟常见,适合做火灾隐患预警演示 |
| 光照检测 | TEMT6000 | 模拟量输出,接 STM32 ADC 即可 |
| 人体检测 | PIR 红外人体模块 | 低成本、逻辑清晰,适合联动节能控制 |
| 无线通信 | ESP8266-01S | 成本低、AT 指令成熟、WiFi 部署方便 |
| 网络模式 | AP + TCP | 本地直连上位机,便于宿舍场景演示和调试 |
| 上位机 | Python + PyQt5 | 开发效率高,适合毕业设计可视化展示 |
| 数据存储 | SQLite | 轻量级、零部署,适合本地历史数据管理 |
1.3 系统功能
- 实时采集温度、湿度、光照、烟雾浓度、人体检测状态
- 实时采集电压、电流、功率并估算累计电费
- OLED 本地显示关键参数,断网时仍可查看本地状态
- ESP8266 建立热点并通过 TCP 向上位机周期性发送数据
- 上位机实时刷新监测界面,支持历史数据存储与查询
- 当功率超阈值、烟雾异常或环境异常时,触发本地和上位机双重报警
- 基于人体在位状态做简单节能联动,为后续智能控制预留接口
二、系统架构设计
2.1 整体架构
系统采用“采集端 + 通信端 + 上位机”的三端协同结构,适合毕业设计答辩时讲清楚分层思路。
- 感知层:STM32 负责采集宿舍环境与用电参数,并做本地阈值判断
- 传输层:ESP8266 负责无线接入,建立 AP 热点和 TCP 服务器
- 应用层:PyQt5 上位机负责数据接收、界面展示、日志记录、SQLite 存储
推荐在 CSDN 中插入系统架构图:

2.2 数据流向
本系统的数据链路比较直观,可以概括为:

控制思路也可以进一步扩展:
- 上位机下发阈值参数
- STM32 更新本地阈值
- 后续可扩展风扇、继电器、照明等联动执行器
推荐在正文中插入数据流向图:

2.3 设计指标
为了让毕业设计更像工程项目,建议在文章中加入量化指标:
| 指标项 | 目标值 | 说明 |
|---|---|---|
| 数据采集周期 | 2s | 与上位机刷新周期保持一致 |
| 报警响应时间 | ≤1s | 功率超限、烟雾异常时快速提示 |
| WiFi 通信延迟 | <100ms | 宿舍内本地 AP 场景下可实现 |
| 连续稳定运行 | ≥24h | 满足毕设演示和可靠性测试 |
| 硬件成本 | <100 元 | 体现方案的低成本可落地性 |
三、硬件设计与连接
3.1 硬件清单
| 组件 | 型号 | 数量 | 说明 |
|---|---|---|---|
| MCU 主控 | STM32F103C8T6 最小系统板 | 1 | 系统核心控制器 |
| 温湿度传感器 | DHT11 | 1 | 宿舍温湿度采集 |
| 电流功率模块 | INA226 | 1 | 电压、电流、功率测量 |
| 烟雾传感器 | MQ-2 | 1 | 火灾隐患预警 |
| 光照传感器 | TEMT6000 | 1 | 宿舍亮度采集 |
| 人体检测模块 | PIR | 1 | 人体在位检测 |
| WiFi 模块 | ESP8266-01S | 1 | 本地热点与 TCP 传输 |
| 显示模块 | 0.96 寸 OLED | 1 | 本地数据显示 |
| LED 指示灯 | 红色 LED | 1 | 超额预警/告警 |
| 电源模块 | 5V/3.3V 稳压 | 1 | 给系统供电 |
3.2 引脚连接说明
| 模块 | STM32 引脚 | 接口类型 | 备注 |
|---|---|---|---|
| DHT11 DATA | PA7 | GPIO 单总线 | 外接 4.7K 上拉 |
| INA226 SCL/SDA | PB6 / PB7 | I2C1 | 监测电压电流功率 |
| MQ-2 AO | PA0 | ADC1_CH0 | 模拟量采集 |
| MQ-2 DO | PB1 | GPIO 输入 | 数字阈值告警 |
| TEMT6000 AO | PA1 | ADC1_CH1 | 光照模拟量采集 |
| PIR OUT | PB12 | GPIO 输入 | 检测人体活动 |
| OLED SCL/SDA | PB6 / PB7 | I2C1 | 与 INA226 共总线 |
| ESP8266 TX/RX | PA10 / PA9 | USART1 | 交叉连接 |
| 预警 LED | PB13 | GPIO 输出 | 超额或异常告警 |
3.3 关键硬件注意事项
⚠️ 重要提醒:
- ESP8266-01S 必须使用稳定的 3.3V 供电,峰值电流可达 300mA,不能直接从 STM32 板载 3.3V 弱供电口硬拖。
- MQ-2 模拟输出可能接近 5V,进入 STM32 ADC 前必须做分压处理。
- DHT11 的采样周期不要太快,建议 1 秒以上,否则容易读到重复数据或校验失败。
- INA226 的分流电阻选型会直接影响测量精度,建议使用低阻值、高精度分流电阻。
- 如果后续接入继电器控制大功率负载,必须做好电源隔离和反灌保护。
3.4 软件开发环境
# STM32 端
STM32CubeIDE / Keil MDK
# 上位机端
pip install PyQt5 pyqtgraph matplotlib
四、代码实现详解
4.1 主程序整体思路
STM32 端采用“前后台”结构最容易讲清楚:
- 初始化 GPIO、ADC、I2C、USART、定时器
- 初始化 DHT11、INA226、OLED、ESP8266
- 主循环按顺序采集各类传感器
- 将采集结果刷新到 OLED
- 每 2 秒打包一帧文本数据,通过 ESP8266 发送给上位机
- 根据阈值判断是否触发 LED 预警
核心主循环可以写成下面这种形式:
while (1)
{
Read_DHT11(&temp, &humi);
power = INA226_GetPower();
smoke = MQ2_ReadValue();
light = TEMT6000_ReadLux();
motion = PIR_ReadState();
OLED_ShowData(temp, humi, power, smoke, light, motion);
if (send_flag) {
SendSensorData(temp, humi, power, smoke, light, motion);
send_flag = 0;
}
Alarm_Check(power, smoke);
HAL_Delay(200);
}
4.2 DHT11 温湿度采集
DHT11 适合毕业设计入门实现,成本低、逻辑简单,核心是单总线时序控制。
头文件示例:
// dht11.h
#ifndef __DHT11_H
#define __DHT11_H
#include "stm32f1xx_hal.h"
uint8_t DHT11_ReadData(uint8_t *temp, uint8_t *humi);
#endif
实现示例:
// dht11.c
#include "dht11.h"
uint8_t DHT11_ReadData(uint8_t *temp, uint8_t *humi)
{
uint8_t buf[5] = {0};
// 这里省略详细时序,核心是启动信号、响应检测、40位数据读取和校验
// 成功后返回温湿度整数部分
*humi = buf[0];
*temp = buf[2];
if ((uint8_t)(buf[0] + buf[1] + buf[2] + buf[3]) == buf[4]) {
return 0;
}
return 1;
}
4.3 INA226 电流/功率采集
INA226 是这个项目里比较加分的模块,因为它不仅能看电流,还能算功率和总线电压,更容易体现“能源管理”而不只是“环境监测”。
// ina226.h
#ifndef __INA226_H
#define __INA226_H
#include "stm32f1xx_hal.h"
float INA226_GetVoltage(void);
float INA226_GetCurrent(void);
float INA226_GetPower(void);
#endif
// ina226.c
#include "ina226.h"
extern I2C_HandleTypeDef hi2c1;
float INA226_GetVoltage(void)
{
uint16_t raw = 0;
// 读取总线电压寄存器,换算为实际电压
return raw * 1.25f / 1000.0f;
}
float INA226_GetCurrent(void)
{
uint16_t raw = 0;
// 读取分流电压寄存器并结合分流电阻换算电流
return raw * 5.9f;
}
float INA226_GetPower(void)
{
return INA226_GetVoltage() * INA226_GetCurrent();
}
4.4 MQ-2 与 TEMT6000 模拟量采集
这两个模块都可以直接走 ADC,代码思路很清晰:采样、滤波、换算。
uint16_t ADC_ReadChannel(uint32_t channel)
{
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = channel;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 10);
return HAL_ADC_GetValue(&hadc1);
}
float TEMT6000_ReadLux(void)
{
uint16_t adc = ADC_ReadChannel(ADC_CHANNEL_1);
return adc * 0.5f;
}
float MQ2_ReadValue(void)
{
uint16_t adc = ADC_ReadChannel(ADC_CHANNEL_0);
return (adc / 4095.0f) * 100.0f;
}
4.5 PIR 人体检测与节能联动
PIR 模块输出的是数字量,非常适合做简单联动。比如:
- 检测到长时间无人时,标记宿舍为空闲状态
- 后续扩展控制照明、风扇、插座继电器
- 结合功率数据,做“有人/无人”用电行为分析
uint8_t PIR_ReadState(void)
{
return HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12) == GPIO_PIN_SET ? 1 : 0;
}
4.6 ESP8266 AP 模式通信
这个系统没有强依赖外网,最适合毕业设计现场演示的方式就是让 ESP8266 直接开热点,上位机连它的热点,然后走 TCP 收数。
初始化流程:
AT测试模块是否在线- 设置工作模式为 AP
- 配置 SSID 和密码
- 开启多连接
- 建立 TCP Server
// esp8266.c
void ESP8266_Init(void)
{
ESP_SendCmd("AT\r\n", "OK", 1000);
ESP_SendCmd("AT+CWMODE=2\r\n", "OK", 1000);
ESP_SendCmd("AT+CWSAP=\"SmartDorm\",\"12345678\",5,3\r\n", "OK", 3000);
ESP_SendCmd("AT+CIPMUX=1\r\n", "OK", 1000);
ESP_SendCmd("AT+CIPSERVER=1,8080\r\n", "OK", 1000);
}
数据发送建议使用文本协议,调试最方便:
void SendSensorData(float temp, float humi, float power, float smoke, float light, uint8_t motion)
{
char tx_buf[128];
sprintf(tx_buf,
"Temp:%.1fC,Humi:%.1f%%,Power:%.2fmW,GasConc:%.2f,Light:%.2f,Motion:%s\r\n",
temp, humi, power, smoke, light, motion ? "YES" : "NO");
ESP8266_SendData(tx_buf);
}
4.7 PyQt5 上位机接收与可视化
上位机建议采用多线程:
- 主线程负责界面
- 网络线程负责 TCP 接收
- 定时器负责界面刷新和数据库写入
TCP 接收核心示例:
import socket
from PyQt5.QtCore import QThread, pyqtSignal
class DataReceiver(QThread):
data_received = pyqtSignal(dict)
def run(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("192.168.4.1", 8080))
while True:
raw = sock.recv(1024).decode("utf-8").strip()
if raw:
data = self.parse_data(raw)
self.data_received.emit(data)
def parse_data(self, raw):
result = {}
for item in raw.split(","):
if ":" in item:
k, v = item.split(":", 1)
result[k] = v
return result
UI 层可以做以下几个区域:
- 温湿度卡片
- 功率/电费卡片
- 烟雾和人体状态卡片
- 系统日志窗口
- 历史数据查询窗口
如果追求展示效果,可以再加一块实时曲线区域,用 pyqtgraph 刷功率或温度变化趋势。
4.8 SQLite 历史数据存储
SQLite 足够支撑毕设演示,而且实现简单。
import sqlite3
conn = sqlite3.connect("sensor_data.db")
cur = conn.cursor()
cur.execute("""
CREATE TABLE IF NOT EXISTS sensor_data (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ts TEXT,
temp REAL,
humi REAL,
power REAL,
smoke REAL,
light REAL,
motion INTEGER
)
""")
conn.commit()
建议每 60 秒存一次,或者每接收一帧就写一次。前者更轻,后者数据更完整。
五、调试与优化
5.1 常见问题排查
-
ESP8266 无法稳定连接
- 先确认供电是否稳定
- 再确认串口波特率和 AT 固件版本
- 最后用串口助手单独测试 AT 指令是否正常
-
DHT11 偶发读取失败
- 检查上拉电阻
- 降低采样频率
- 避免中断或串口发送打断关键时序
-
MQ-2 数据波动大
- 预热时间不足
- 模拟量受电源噪声影响
- 建议增加多次采样平均滤波
-
上位机界面卡顿
- 不要在 UI 主线程里直接做阻塞式
recv - 把网络接收和界面刷新拆开
- 不要在 UI 主线程里直接做阻塞式
5.2 工程优化建议
- 传感器数据增加滑动平均滤波,减少抖动
- 通信协议增加帧头和校验字段,提高容错性
- 上位机增加断线重连机制,提升演示稳定性
- 阈值参数做成可配置项,而不是写死在代码里
- 把 AP 模式升级为 STA + MQTT,可以进一步接入云平台
六、项目总结与扩展
6.1 项目成果
这套系统的价值不在于“模块多”,而在于把 环境监测、能源管理、安全预警、上位机可视化 这四块真正串起来了。对毕业设计来说,它有几个明显优势:
- 软硬件链路完整,容易形成“系统设计与实现”的叙事
- 既有嵌入式采集,也有上位机界面,展示效果好
- 场景贴近校园宿舍,选题容易被老师理解
- 成本可控,硬件容易采购,调试门槛不高
6.2 可扩展方向
- 增加继电器,做照明/插座的节能联动控制
- 接入 CO2、甲醛等空气质量传感器,提升环境监测维度
- 将 AP + TCP 升级为 MQTT 云平台架构
- 引入语音模块,实现语音播报和语音查询
- 基于历史数据做异常检测或用电行为分析
6.3 写在最后
如果你现在正准备 STM32 相关毕业设计,这类“宿舍管理/环境监测/用电预警”方向是比较稳的选题:硬件复杂度适中、工程链路完整、可视化效果强,答辩时也比较容易讲清楚。
如果这篇文章对您有帮助,请点赞支持!如有问题或建议,欢迎在评论区交流。
更多推荐



所有评论(0)