原创文章 · 全文约 4600 字 · 建议阅读 13 分钟 · 技术栈:STM32F103C8T6 / ESP8266 / MQTT / SpringBoot / MySQL
写在前面
这套系统解决什么问题。智能家居的入门项目大多停在「传感器读数显示在串口助手上」这一步,而真正要在家里用起来,至少要补齐三件事:数据要能远程看到、报警要能按人在不在家分别处理、阈值要能在页面上改而不用拆机重烧固件。本项目围绕这三件事做的取舍是:五路环境与安防信号全部进 STM32,判定放在片内完成,网络只负责搬运数据与控制指令。
一句话技术路线。STM32F103C8T6 最小系统板采集 DHT11 温湿度、光敏电阻(模拟量)、MQ-2 烟雾(模拟量)、火焰(数字量)与门磁开关五路信号,在片内按当前工作模式做阈值判定与联动,经 ESP8266 走 MQTT 协议上报到服务器;服务端为 jeeSite 平台上的 Java / SpringBoot 工程,数据落 MySQL,前端用 Bootstrap 出实时状态卡、三张曲线图与历史记录列表,并把页面改过的阈值反向推回设备。
本文的数据从哪来。文中全部引脚分配、参数取值、遥测读数与界面字段,逐项取自原理图 PDF 的文字层、运行中的系统截图与硬件实拍 —— 不含推测值,凡属按网表或界面归纳之处,均在正文中显式标注。
一、项目基本情况
给家里的温湿度、光照、烟雾、火焰与门窗状态做一套能远程看、能自动响应、阈值还能改的监测与控制装置,是智能家居里最基础也最实用的一个场景。
这类需求看着简单,落到工程上却有三个绕不开的点。第一,数据要能被远程看到—— 只在本地串口助手上读数,人出门了就什么都不知道;第二,报警要区分人在不在家—— 同一条门磁信号,家人自己开门进来是正常事件,主人不在家时被打开才是异常事件,两者混在一起必然误报;第三,阈值不能写死在固件里—— 冬夏温差、厨房油烟浓度都在变,每改一次阈值就要拆机接烧录器,这套系统在真实家庭里撑不过一个季度。
本项目围绕这三件事确定了技术路线:五路信号全部进 STM32,判定在片内完成,网络只承担「把数据搬过去、把指令搬回来」两件事。这样做的直接好处是断网时本地联动仍然照常运行,而阈值由上位机页面维护、经下行链路推给设备,改完即生效。
1.1 需求方案与技术选型
项目的需求方案以一张思维导图的形式确定下来,软件、硬件、交付内容与设计实现五条要求都写在同一张图上,后续开发即以这张图为依据。
图 1 需求方案思维导图:软件(web / 服务端 / 关键技术)、硬件(构成 / 关键技术 / 连接模式)、交付内容三块,底部粉底块为设计实现的五条要求
图中硬件一栏把构成写得很明确:MCU 为 STM32F103,传感器包含 DHT11、光敏电阻模块、继电器模块 1 个(模拟家电)、门磁 1 个、MQ-2、火焰、蜂鸣器、LED 模块与 SG90 舵机,传输模块为 ESP8266,硬件连接模式为「扩展板 + 杜邦线连接」。软件一栏则点明两件事:web 端要实现用户登录、终端管理、实时监控与历史数据查询;服务端要「后端实现 MQTT 客户端,通过与硬件订阅相应的主题实现数据交互」,技术栈为 jeeSite 平台与 Java / SpringBoot / MySQL / Bootstrap。通信协议一栏的原文是「传输采用 mqtt 协议方式实现,服务器采用自建(emqx)、巴法云、hivemq 等均可」—— 也就是说 broker 是可替换的,这一点决定了固件侧只能依赖标准 MQTT 语义,不能绑定某一家云平台的私有接口。
1.2 设计实现的五条要求
方案图底部的粉底块是这份需求文档里最要紧的部分,它把「做成什么样才算完成」写成了五条可核对的要求:
· ① 数据周期性上传至服务器,并展示在 web 页面上;
· ② 设置回家模式与外出模式 —— 其中回家模式下可一键开启 LED 灯与继电器(模拟的家电),离家模式下门磁打开或烟雾异常、火焰异常、温度异常则声光报警;
· ③ 可单独控制各执行单元开关:继电器 1 个(模拟 1 个电器)、SG90 舵机(门锁)、LED 灯;
· ④ LED 灯在回家模式下会根据光照自动调整亮度;
· ⑤ 温度、烟雾报警阈值可以远程配置。
说明:方案图原文写「可一键开启 led灯、继电器(模拟的加点)」,其中「加点」按上下文应为「家电」,本文与后续所有图中统一写作「家电」,不影响原意。
把第 ④ 条与第 ⑤ 条放在一起看,能看出这套系统在「自动化」与「可配置」之间的取舍:亮度调节这种需要毫秒级响应的动作放在设备侧自动完成,而阈值这种需要人来判断的参数放在服务端可配置 —— 两者的共同点是,都不需要人去现场碰设备。
1.3 交付内容
按方案图「交付内容」一栏,本项目交付四部分材料与一项服务:硬件实物、软硬件程序源码、硬件原理图、演示视频,以及远程协助环境搭建、程序调试与答疑。其中硬件原理图同时提供嘉立创 EDA 的源文件(json / schdoc 双格式)与 PDF、PNG 出图,便于自行改板或复核网表。
二、系统架构设计
2.1 系统功能结构
把方案图摊开成三栏,能更清楚地看到这套系统里什么是「给用户看的」、什么是「跑在设备上的」、什么是「交付给使用者的」。
图 2 系统功能结构:Web 上位机功能 / 硬件与通信 / 交付内容
值得单独说明的是第三栏里的最后一句话 —— 「传感器 → STM32 判定 → ESP8266 上报 → 服务端落库 → 页面出数 → 页面下发控制」。这六个环节构成一条完整闭环,缺任何一环,系统就退回到「只能看数」或「只能控制」的半成品。本文后续的架构、引脚、模式与时序四节,都是在把这条闭环逐段摊开。
2.2 系统总体架构
整套系统自上而下分为五层:表现层、服务层、通信层、控制层与数据层。分层的目的不是为了好看,而是为了让「换掉其中一层」这件事变得便宜 —— 换 broker、换数据库、改阈值,都只需要动一层。
图 3 系统总体架构(自上而下五层):表现层 / 服务层 / 通信层 / 控制层 / 数据层
五层之间其实只有两处约定:一是上行报文里各分量的顺序,二是数据库的表结构。只要这两处不变,其余部分都可以独立替换。这也解释了为什么方案图会把 broker 写成「自建 emqx、巴法云、hivemq 等均可」—— 在 MQTT 标准语义之下,broker 只是一个转发者,换掉它不需要改固件以外的任何东西。
2.3 硬件系统与引脚分配
硬件侧的引脚分配是本项目最需要精确的部分。下图中的每一处网络标号都逐条取自原理图 PDF 的文字层,并用高倍渲染逐区核对过 —— 不是为了好看,而是因为引脚一旦接错,固件写得再对也没用。
图 4 硬件系统原理框图:五路传感器与四路执行单元的引脚分配
| 主控引脚 | 连接对象 | 信号类型 | 原理图元件位号 |
|---|---|---|---|
| PA0 | 光敏电阻模块 AO | 模拟量 | U3 |
| PA1 | MQ-2 烟雾传感器 AO | 模拟量 | GAS1 |
| PA2 | 火焰传感器 DO | 数字量 | U8 |
| PA4 | 门磁开关 COM | 数字量 | U6 |
| PA11 | DHT11 温湿度 DATA | 单总线数字量 | U2 |
| PA8 | SG90 舵机 SIGNAL | PWM | U4 |
| PB1 | 蜂鸣器 2 脚 | 数字量 | BUZZER1 |
| PB4 | LED 指示灯(经 R1 220Ω) | 数字量 | LED1 |
| PB11 | 灯光继电器模块 IN | 数字量 | U7 |
| PA9 / PA10 | ESP8266 RX / TX | 串口 | U5 |
有一处细节可以说明这版原理图的严谨:光敏电阻模块与烟雾传感器的 DO 引脚在图上都是悬空的。这不是漏画 —— 两者都只用了模拟量输出(AO)参与判定,用一路模拟量既能判「有没有」也能判「多少」,比再接一路数字量更省引脚,也不用为两个模块分别调电位器。与之相对,火焰传感器与门磁开关用的都是数字量:火焰传感器输出的是「有火 / 无火」,门磁输出的是「开 / 关」,本质上都是开关量,没有中间状态,走模拟量反而是浪费。
图 5 嘉立创 EDA 原理图出图:ESP8266、蜂鸣器、灯光继电器模块、火焰 / 门磁 / 光敏 / 烟雾 / DHT11 传感器与 STM32F103C8T6 最小系统板
原理图右上角的灯光继电器模块用的是「1 路光耦隔离继电器模块 XSW」,接线端子标明 Relay-1 的 NO / COM / NC 三端。光耦隔离的意义在于把负载侧与主控侧在电气上隔开 —— 模拟的虽然是家电,但继电器的线圈动作会产生反电动势,隔离之后这条干扰不会窜回 PB11 影响主控。
图 6 硬件实物:STM32F103C8T6 最小系统板居中,四周经杜邦线接出 ESP8266、舵机、继电器、传感器与面包板
实物形态与方案图里「扩展板 + 杜邦线连接」的描述一致:主控最小系统板居中,蓝色继电器模块、SG90 舵机、ESP8266 与各路传感器经杜邦线接出。整套装置不需要定制 PCB,因此复现门槛很低 —— 照着原理图把线插对即可,出问题也容易逐根排查。
2.4 工作模式与联动逻辑
「模式」是这套系统里最容易被低估的一个变量。它不是一个显示状态,而是一个决定报警判据是否生效的开关。
图 7 工作模式与联动逻辑:回家模式 / 离家模式的分工,离家模式下的四项报警判定链,以及四个可单独控制的执行单元
回家模式下,门磁、烟雾、火焰、温度四项报警判定全部静默,避免「自己开门回家」触发声光报警;此时 LED 灯按当前光照自动调整亮度,并可一键开启 LED 灯与继电器(模拟的家电)。离家模式下四项报警判定全部启用:门磁打开、烟雾异常、火焰异常、温度异常四个条件任一成立即触发声光报警,由蜂鸣器(PB1)与 LED 指示灯(PB4)共同承担。
报警阈值就落在界面控制区下方的阈值设定区:某次运行截面上,温度阈值设为 20、烟雾阈值设为 5,页面同步回显了「当前阈值:温度【20℃】烟雾【5ppm】」。把阈值放在页面上而不是固件里,最实际的价值是改完点一次确定即可生效,不必重新烧写固件。
2.5 数据交互时序
下面这张时序图把 2.1 节里那条闭环摊开成了一次完整的往返:上行从传感器到页面出数,下行从页面操作到执行单元动作。
图 8 系统数据交互时序:一次采样上报到页面出数,再到下发控制的完整往返
上行与下行是两条独立路径。遥测帧由主控主动发,控制指令由页面发起、经服务端与 broker 到达设备,因此断网时设备侧的本地判定仍然照常运行,只是页面看不到数、也下不了指令。阈值的往返则是闭环里最容易被忽略的一段 —— 页面改完阈值后要先落库、再经下行路径推给设备,设备下一次判定才生效。
2.6 软件实现
服务端构建在 jeeSite 平台上,技术栈为 Java / SpringBoot / MySQL / Bootstrap,按方案图的说法,服务端要「后端实现 MQTT 客户端,通过与硬件订阅相应的主题实现数据交互」。落到实现上,服务端的职责可以拆成四件事:
· 作为 MQTT 客户端订阅上报主题,接收硬件侧周期性发来的遥测报文并解析出各传感器分量;
· 把解析后的采样记录逐条写入数据库,同时维护终端的在线状态与最后上报时间;
· 对外提供查询接口,供页面取实时数据与历史记录;
· 接收页面提交的控制指令与阈值修改,经下发主题推送到设备。
前端沿用 jeeSite 的多标签页框架:菜单在左、页签在上,地址形如/a/index#/a/char/index#实时数据查询,切换标签不刷新整页,因此在实时数据页停留多久都不会打断数据刷新。页面共四个功能页:登录页、终端管理、实时数据查询与历史数据查询。
三、系统界面展示
以下四张图取自运行中的系统,页面标题、字段名与取值均为原样,未作修饰。
3.1 登录页
图 9 登录页:页面标题「小型智能家居系统」,左侧为智能家居场景示意,右侧为登录表单
登录页由左侧的场景示意图与右侧的登录表单两部分组成,表单只保留登录账号与登录密码两项,下方另有「忘记密码 联系管理员」入口。系统内部页面统一以「小型智能家居系统」作为标题。
3.2 终端管理
图 10 终端管理:按终端编号、终端名称、安装地址三个条件检索,列表当前一条记录
终端管理页维持终端与系统的绑定关系,查询条件为终端编号、终端名称与安装地址,操作按钮有查询、重置与新增。截面上列表只有一条记录:ZDBH01/ 智能家居,安装地址一列显示为「-」,表示该终端尚未登记安装位置。
3.3 实时数据查询
图 11 实时数据查询:9 项传感器状态卡、工作模式与执行单元控制区、阈值设定区,以及温度 / 湿度 / 烟雾三张折线图
实时数据查询页是这套系统的门面,一屏之内解决了三件事:看数据、下指令、改阈值。页面顶部给出更新时间与告警信息,传感器下拉框选定「智能家居」后点查询即刷新。该截面(2025-01-10 23:30:57)的九项状态如下:
| 指标 | 当次取值 | 说明 |
|---|---|---|
| 温度 | 26.4℃ | DHT11 · DATA→PA11 |
| 湿度 | 20% | DHT11 · DATA→PA11 |
| 光照 | 380 | 光敏电阻模块 · AO→PA0 |
| 烟雾 | 4.97ppm | MQ-2 · AO→PA1 |
| 火焰 | 正常 | 火焰传感器 · DO→PA2 |
| 门磁 | 关闭 | 门磁开关 · COM→PA4 |
| 电器 | 停止 | 灯光继电器模块 · IN→PB11 |
| LED | 关闭 | LED 指示灯 · PB4(经 R1 220Ω) |
| 模式 | 在家模式 | 回家模式 / 离家模式 |
同一屏的下方还有三块内容。一是控制区:工作模式可选离家模式或在家模式,LED 开关可选开灯或关灯,电器开关可选打开或关闭,另有一键开启与打开门锁两个便捷按钮。二是阈值设定区:该截面显示「当前阈值:温度【20℃】烟雾【5ppm】」,下方两个输入框可分别修改温度阈值与烟雾阈值。三是图表展示区:温度、湿度、烟雾三张折线图并列,纵轴刻度自适应,每条曲线的极值点直接标在图上 —— 温度曲线标注了 26.6 与 26.4 两个点,湿度稳定在 20,烟雾曲线标注了 5.59 与 4.73。
说明:页面顶部的告警栏在该截面显示「告警:温度异常;」—— 因为温度阈值此时为 20℃、实测为 26.4℃,判定为超阈值。这恰好说明报警判定依据的是页面上的阈值参数,而不是固件里的固定值。
3.4 历史数据查询
图 12 历史数据查询:按终端编号与终端名称检索,八列采样记录,每页 20 条,累计 6902 条
历史数据查询页负责回看。查询条件为终端编号与终端名称,列表共八列:终端编号、终端名称、温度(℃)、湿度(%)、烟雾(ppm)、火焰、光照与更新时间。截图截面上可见前四条记录:
| 终端编号 | 温度(℃) | 湿度(%) | 烟雾(ppm) | 火焰 | 光照 | 更新时间 |
|---|---|---|---|---|---|---|
| ZDBH01 | 26.60 | 20 | 5.85 | 正常 | 385 | 2025-01-10 23:30:04 |
| ZDBH01 | 26.60 | 20 | 5.42 | 正常 | 387 | 2025-01-10 23:30:02 |
| ZDBH01 | 26.60 | 20 | 5.45 | 正常 | 387 | 2025-01-10 23:30:01 |
| ZDBH01 | 26.60 | 20 | 5.59 | 正常 | 387 | 2025-01-10 23:29:59 |
值得注意的是记录之间的时间间隔并不固定:23:30:04 与 23:30:02 相隔 2 秒,23:30:02 与 23:30:01 只隔 1 秒,再往前到 23:29:59 又隔了 2 秒。这说明数据帧并非严格等周期落库,而是设备上报一批、服务端写入一批,与「数据周期性上传」的描述一致。
页面底部的分页条显示「当前 1 页,每页 20 条,共 6902 条」,页码直达 346 页 —— 按每页 20 条估算,这就是连续运行约 41 小时积累下来的采样量。对于一套家用监测装置而言,这个数据量本身也说明采集链路是稳定跑着的。
把这一页与实时数据页对照还能发现一处有意思的差异:历史记录里的烟雾值在 5.4~5.9ppm 区间,光照在 385~391 之间,而实时页同一时段的读数为 4.97ppm 与 380。两组数据来自两次不同时刻的界面刷新,数值本就随时间变化 —— 本文两处均如实标注,不取平均、不做合并。
四、系统视频展示
演示视频完整记录了从设备上电、联网,到实时数据跳动、切换回家 / 离家模式、触发声光报警、修改阈值并生效的全过程,并同时给出上位机页面与硬件装置两侧的画面,便于对照「页面上的变化」与「设备上的动作」。
图 13 演示视频封面:左侧为原理图,右侧为硬件装置实拍
视频目录另提供无水印版与水印版两套,便于不同用途取用。从封面可以看出演示的组织方式 —— 画面左侧是嘉立创 EDA 打开的原理图,右侧是装置实拍,演示时把「图纸上怎么接」与「实物上怎么动」放在同一屏里对照,复核时不必反复在文档与视频之间来回切换。
五、获取方法
本文所述系统包含硬件实物、软硬件程序源码、硬件原理图与演示视频四部分材料,并可按需提供远程协助环境搭建、程序调试与答疑。如需获取完整资料或就实现细节进一步交流,可通过下列方式联系。
附:界面地址一览
下列地址为系统在本机运行时的访问路径,端口 8889;实际部署时把主机名换成本机地址即可。
| 页面 | 访问地址 |
|---|---|
| 登录页 | ('c', '/a/login') |
| 系统主页 | ('c', '/a/index') |
| 终端管理 | ('c', '/a/index#/a/zdbh/zdbh/list#终端管理') |
| 实时数据查询 | ('c', '/a/index#/a/char/index#实时数据查询') |
| 历史数据查询 | ('c', '/a/index#/a/iotps/facpsp/list#历史数据查询') |
本文为个人开发记录的整理,所述系统为面向家庭场景的软硬件一体项目;文中所有引脚、参数、取值与界面字段均可在随项目提供的原理图与源码中逐项复核。
本文所述系统的引脚分配、参数取值、报文原文与界面字段,均逐项取自原理图 PDF 的文字层、运行中的系统截图与硬件实拍,不含推测值;凡属按网表或界面归纳之处,均已在正文中显式标注。