十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于物联网的粉尘监测预警系统:从传感器选型到实战闭环

基于物联网的粉尘监测预警系统:从传感器选型到实战闭环 简介面向毕业设计与物联网实战的作业场所粉尘危害监测预警系统以粉尘浓度监测与预警为核心场景适合物联网、嵌入式或底层系统方向的小白与进阶学习者也可直接用于毕设、课程设计、大作业或工程实训。压缩包共952个文件约5.07MB以png、js、css、html为主涵盖界面截图、前端逻辑、页面骨架与样式配置另有json、map、md等文件辅助配置和说明整体是一个可直接运行验证的项目工程。源码经过严格测试能快速跑通粉尘监测预警流程借助内容预览中的layui、皮肤样式、toast等前端组件读者可清晰了解界面层封装思路并在此基础上修改复刻扩展更多传感器接入或告警功能。已有32人学习下载对于需要积累物联网项目经验或准备毕业设计的开发者来说具备较好的借鉴与二次开发价值。1. 粉尘监测预警系统是物联网毕业设计里少有的能完整闭环的选题在木材加工、石材切割这类作业场所粉尘浓度超标不能靠肉眼判断更不能靠人工巡检兜底——等看见扬尘时浓度往往已经远超限值。基于物联网的作业场所粉尘危害监测预警系统就是把这个过程做成闭环传感器采集浓度主控板读数无线网络上传服务端按阈值分级判定触发声光警报和短信通知历史数据留存追溯。它适合物联网工程、电子信息、自动化专业的毕业设计也适合想拿完整实战项目参加技能竞赛的同学。感知、传输、存储、报警、展示每一层都有可检验的交付物答辩时不缺内容现场演示也直观是物联网毕业设计选题里少见的“全链路”题目。2. 系统架构与硬件选型先把感知、传输、应用三层算清楚再下单2.1 三层架构与数据流向从粉尘浓度到预警消息中间经过哪几步做粉尘监测预警系统最忌讳拿到板子就写代码。先问自己三个问题粉尘浓度用什么传感器测数据怎么传到机房报警消息发给谁。这三个问题恰好对应感知层、传输层、应用层任何一层选错后期都要返工。感知层是数据源头。监测预警系统的可信度完全取决于传感器读数粉尘传感器必须按作业场所的实际浓度范围选不能随便拿个室内空气质量模块凑数。传输层负责把数据从车间送到服务端常见方案有 WiFi、4G Cat.1、NB-IoT 和 LoRa按现场有没有网、有没有电、点位多不多来定。应用层包括数据接收、入库、阈值判定、报警推送和可视化看板这部分直接决定系统能不能真正用起来。我的习惯是先把数据流画在纸上再动手买板子粉尘传感器 → 主控板 → 无线模块 → MQTT Broker → 后端服务 → 数据库 → 预警服务 → 声光报警 / 短信通知 / Web 看板这个流程画完每个环节用什么硬件、走什么接口心里就有数了。跳过这一步行事焊完板子再想架构后面大概率拆了重来。整个系统里最容易被低估的是“断电恢复”车间里三相设备启动、大功率电机频繁启停电源闪断很常见数据链路一旦断了不能自动恢复整套系统在用户眼里就是废的。2.2 粉尘传感器选型激光散射方案才是预警系统的默认答案粉尘浓度传感器按原理分两类一类是红外散射一类是激光散射。二者都基于光散射测量颗粒物浓度但红外传感器光源波长宽、抗干扰差读数在湿度大的环境里会明显偏高分辨率通常只有 1 µg/m³ 档量程也窄多数在 0~500 µg/m³ 附近。激光散射传感器使用半导体激光器作为光源单色性好配合光电二极管和算法的卷积处理分辨率和重复性都好一截量程可以做到 0~1000 µg/m³部分型号还能同时输出 PM2.5、PM10 和 TSP 三组数据。作业场所粉尘监测预警系统里传感器部署在车间、仓库、装卸区环境比室内复杂得多我一般直接用激光散射方案。常见的 PMS 系列传感器就是这类串口输出占空比低带风扇主动采样响应时间在 10 秒以内。参数上重点看三个量程、分辨率、数据输出方式。量程覆盖到 1000 µg/m³ 以上才不用频繁切换分辨率低于 1 µg/m³ 的模块基本不可用输出方式最好选 UART 串口I2C 在长线场景容易受干扰。还有一点容易忽略传感器标称浓度是“标准颗粒物质量浓度”跟作业场所要测的“总尘”或“呼尘”不是一回事。毕设阶段直接用 PM2.5/PM10 作为预警指标完全够用但如果后面要对接职业卫生限值就需要在算法里加一个换算系数或者直接选带 TSP 输出的模块。红外传感器便宜不是完全不能碰做课程设计、演示原理可以做监测预警系统不推荐湿度稍大读数就飘现场维护的人会觉得这套系统就是个摆设。2.3 主控与通信通道ESP32 直连 WiFi 还是 4G Cat.1现场条件一票否决主控板选择相对简单。毕设场景下大多数同学选 ESP32原因很直接双核、主频高、自带 WiFi 和蓝牙ADC 引脚够用价格也压得下来。ESP8266 更便宜但单核、GPIO 少后期要同时接传感器、继电器、蜂鸣器、状态灯的时候捉襟见肘。如果现场点位少、只做单点监测ESP8266 也能跑要做多点或者带屏幕直接上 ESP32省得第二次换板子重写代码。通信通道才是真正一票否决的选型点而且几乎没有后悔药。室内环境有企业 WiFiESP32 直连是最省事的方案数据直接走 MQTT 上云代码量最小调试也最方便。但车间不是写字楼厂房深处、金属货架密集区域、地下室仓库WiFi 信号衰减非常快连上了也经常断。这种情况下我一般选 4G Cat.1 模块插物联网卡走运营商网络不依赖现场 WiFi缺点是每张卡有流量费代码里还要处理网络注册、拨号、Socket 重连。如果作业场所面积大、点位分散还有一种做法是 LoRa 组网每个监测点用 LoRa 节点把数据发到网关网关再走 4G 或以太网上云。LoRa 穿透力强厂房里穿两三堵墙没问题但网关节点要自己维护组网复杂度上了一个台阶。毕设阶段通常不需要上 LoRaESP32 加 WiFi或者 ESP32 加 Cat.1 模块都能把链路讲清楚。选型阶段还要算好供电。传感器、主控、通信模块加起来电流不小ESP32 峰值电流能到 300mA 以上4G 模块在弱信号环境下更夸张。用 USB 供电的毕设演示没问题真正放现场至少要 12V/2A 的适配器并通过 DC-DC 降压给主控供电。锂电池供电要看功耗预算后面第 6 章再展开。3. 搭建数据链路与预警判定MQTT 上云、分级阈值、多重报警3.1 传感器数据读取PySerial 解析串口粉尘帧不要自己拼协议在 PC 或者树莓派上先做数据读取验证是最稳的起步方式。PMS 系列粉尘传感器是串口输出波特率常见 9600数据帧固定 32 字节帧头是 0x42 0x4D。解析逻辑不复杂但校验一定要做否则一条错帧就会让后面的 PM2.5、PM10 全部错位。import serial import struct ser serial.Serial(/dev/ttyUSB0, 9600, timeout2) buffer bytearray() while True: buffer ser.read(ser.in_waiting or 64) head buffer.find(b\x42\x4d) if head 0 and len(buffer) head 32: frame buffer[head:head 32] del buffer[:head 32] # 帧校验帧头到数据末尾之和拆成高字节和低字节与帧尾两字节比对 checksum sum(frame[:30]) if (checksum 8) frame[30] and (checksum 0xFF) frame[31]: # 第 4~5 字节是 PM2.5 标准值第 6~7 字节是 PM10 标准值大端序 pm25 struct.unpack(H, frame[4:6])[0] pm10 struct.unpack(H, frame[6:8])[0] # 浓度单位是 µg/m³ print(fPM2.5{pm25} PM10{pm10}) else: print(checksum mismatch, skip frame)逻辑说明先把串口读到的字节累积到 buffer通过查找 0x42 0x4D 定位帧头。找到后确认缓冲区里至少有 32 字节再取出一整帧处理。校验和是整个帧前 30 字节的累加和正确解析后 PM2.5 和 PM10 都是无符号 16 位大端整数单位是 µg/m³。参数说明timeout2是每次读串口的超时时间单位秒设太短容易读不完整设太长会让循环卡住ser.read(ser.in_waiting or 64)表示把当前缓冲区里已有的数据全部读出来如果没有数据就尝试读最多 64 字节这样脚本在任何平台跑都不会空转。这段代码里的循环是纯 CPU 轮询精度足够毕设数据采集不需要上中断。3.2 数据入库与设备管理MQTT Broker FastAPI MySQL 的最小链路传感器数据上云我一般用 MQTT不直接走 HTTP。原因很简单MQTT 是发布订阅模式设备端只负责推送服务端只需要订阅主题设备多了也不怕而且 MQTT Broker 自带会话保持设备断线重连后能续上消息HTTP 轮询做不到这个效果。主题设计按点位和设备区分例如dust/{device_id}/data设备端上报 JSON 负载包含设备编号、PM2.5、PM10、湿度、时间戳。后端订阅这个主题收到消息后写入数据库同时交给预警服务做判断。import json import time import pymysql import paho.mqtt.client as mqtt def save_to_db(payload): # 每次新建连接简单直接毕设阶段够用 conn pymysql.connect(hostlocalhost, useriot, passwordiot123456, databasedust) try: with conn.cursor() as cur: sql INSERT INTO readings (device_id, pm25, pm10, humidity, created_at) VALUES (%s, %s, %s, %s, %s) cur.execute(sql, ( payload[device_id], payload[pm25], payload[pm10], payload[humidity], time.strftime(%Y-%m-%d %H:%M:%S) )) conn.commit() finally: conn.close() def on_message(client, userdata, msg): payload json.loads(msg.payload.decode()) save_to_db(payload) # 这里只是把数据写库预警判定单独走函数保持逻辑隔离 client mqtt.Client() client.on_message on_message client.connect(broker.example.com, 1883, 60) client.subscribe(dust//data) client.loop_forever()逻辑说明on_message回调里做两件事解析 JSON、写数据库。dust//data中的是 MQTT 通配符表示匹配任意设备编号这样新增设备不用改代码。写库用INSERT语句created_at直接用服务器时间避免设备端时钟不准导致报表时间错乱。参数说明connect的第三个参数 60 是 keepalive 秒数设备端心跳间隔大于这个值会被 Broker 判定离线所以 ESP32 上 MQTT 心跳一般设 30~45 秒。loop_forever()是阻塞式网络循环异常掉线会自动退出实际部署时外面要再加一层重试逻辑。这里有个容易被忽略的设计点数据表和预警记录表要分开。readings只存原始浓度数据预警表单独记录触发时间、点位、级别、确认状态这样数据回溯和报警记录互不干扰答辩时也能说清楚系统设计的分层思想。3.3 预警判定不能只看单次读数连续超标、分级阈值与去毛刺粉尘浓度本身波动大车间里一台叉车开过、一阵风吹过都可能让读数瞬间冲高。预警判定如果写成“超过 1000 就报警”这套系统一天能报几百次现场的人最后会把报警器拆了。所以判定逻辑要处理两件事分级和去毛刺。我一般设三级阈值对应黄、橙、红三种状态。比如 PM10 浓度超过 400 µg/m³ 触发黄色提醒超过 700 触发橙色预警超过 1000 触发红色报警。每级还要配一个“持续确认”规则最近 5 条数据里至少 4 条超过阈值才真正报警单次毛刺自动滤掉。def judge_alert(recent_records, limit, confirm_count4): if len(recent_records) 5: return None over sum(1 for r in recent_records if r[pm10] limit) if over confirm_count: return alert return None # 使用示例 records get_recent_readings(001, minutes5) level judge_alert(records, limit700)逻辑说明judge_alert接收最近 5 条记录统计超过阈值的条数超过 4 条才返回报警信号。这个“5 条里 4 条”的规则并不是拍脑袋定的它等效于在时间维度上做了一个 80% 占空比的窗口响应延迟在 MQTT 上报间隔合理的前提下大约 1~2 分钟既不会漏报也滤掉了大部分瞬时干扰。参数说明limit就是分级阈值不同点位可以单独配置。比如电焊工位旁边 PM10 背景浓度本身就高阈值可以适当上调而办公区、控制室这种清洁区域要从严。confirm_count4是确认次数现场粉尘越剧烈这个值要调得越大否则还是会被偶发高浓度欺骗。实际工程项目里还会加一个“报警恢复”状态机触发报警后必须连续 3 条数据低于阈值的 80% 才恢复绿色。否则报警状态一直卡在高位后续再触发新报警会被合并掉。这个逻辑会稍微增加代码量但演示效果和实际体验都提升一大截。4. Web 监控大屏与答辩演示把预警闭环做成评委看得懂的效果4.1 实时大屏ECharts 折线加 WebSocket 推送刷新间隔别瞎取后端数据有了预警逻辑有了现在要把系统“看见”。Web 监控大屏是物联网毕业设计最直观的交付物看着屏幕上折线实时跳动、颜色从绿变红评委比看任何文字都容易理解。实时性用 WebSocket 做不用 HTTP 轮询浏览器一个连接挂着服务端推送一条数据更新一次图表。const recent []; const chart echarts.init(document.getElementById(dustChart)); function updateChart(data) { recent.push({ time: new Date().toLocaleTimeString(), pm25: data.pm25, pm10: data.pm10 }); // 只保留最近 200 个点避免浏览器内存无限增长 if (recent.length 200) recent.shift(); chart.setOption({ xAxis: { type: category, data: recent.map(p p.time) }, yAxis: { type: value, name: µg/m³, max: 1200 }, series: [ { name: PM2.5, type: line, smooth: true, data: recent.map(p p.pm25) }, { name: PM10, type: line, smooth: true, data: recent.map(p p.pm10) }, { // 阈值参考线黄色预警线 700 name: 预警线, type: line, markLine: { silent: true, data: [{ yAxis: 700, label: { formatter: 预警线 700 } }] } } ] }); } const socket new WebSocket(ws://your-server/ws/dust); socket.onmessage function (event) { const data JSON.parse(event.data); updateChart(data); };逻辑说明ECharts 的setOption是增量更新不是全量重绘所以每次只把新的时间戳和数据塞进去性能足够。recent.shift()控制数组长度长时间挂着也不会把浏览器拖垮。预警参考线用markLine画在 700 µg/m³折线一越线视觉上立刻有冲击力。参数说明图表数据刷新频率取决于 MQTT 上报间隔。传感器主动模式下每秒出一次数据但不需要每一条都推到浏览器我一般让设备端每 10 秒上报一次WebSocket 收到后直接更新浏览器端不需要再设setInterval。如果用的是被动读取模式服务端拿到数据就往 WebSocket 广播前端也不用管轮询。把刷新间隔做成可配置项演示时能调得更顺滑平时能调得更省流量答辩时这个细节也能讲两句。4.2 历史报表导出CSV 加 utf-8-sigExcel 打开不乱码预警系统不能只看实时画面还得能回答“昨天下午三点浓度为什么超了”。历史查询和报表导出是这个问题的标准解法。后端用 FastAPI 写一个导出接口按点位和时间段查询数据库生成 CSV 返回给前端下载。import csv import io from fastapi.responses import StreamingResponse app.get(/export) def export_readings(device_id: str, start: str, end: str): rows query_readings(device_id, start, end) buffer io.StringIO() writer csv.writer(buffer) writer.writerow([device_id, pm25, pm10, humidity, created_at]) writer.writerows(rows) # utf-8-sig 带 BOMExcel 直接打开不会乱码 return StreamingResponse( io.BytesIO(buffer.getvalue().encode(utf-8-sig)), media_typetext/csv, headers{Content-Disposition: fattachment; filenamedust_{device_id}.csv} )逻辑说明StreamingResponse把 CSV 内容作为附件流返回浏览器收到后自动下载不需要前端生成文件。utf-8-sig编码是给 Excel 用的直接utf-8导出的文件Windows 上 Excel 打开中文表头大概率乱码这个细节不说可能有同学要踩。表格的主题、字段、格式都是有讲究的。字段里除了 PM2.5、PM10还要带湿度和时间戳湿度对粉尘读数有解释作用文件名带上设备编号和时间范围归档方便。答辩演示时可以现场导出一次报表展示 Excel 打开的效果比口头说“支持历史查询”有说服力得多。4.3 现场演示脚本90 秒走完“正常→报警→恢复”全流程系统做完了最后一步是设计演示流程。很多同学忽略这个结果答辩现场传感器读数一直在一个范围波动等了五分钟都没触发报警气氛很尴尬。提前规划演示脚本把整个闭环的效果串起来。我的做法是准备一个透明亚克力密封箱传感器放在箱子里演示时先让读数稳定在 30~50 µg/m³录一段正常画面。然后点一小段蚊香放进箱子或者用面粉通过筛网轻轻抖入粉尘浓度会在 20 秒内快速爬升达到黄色预警线触发第一次声光报警。这时不要停再抖一点面粉浓度超过红色阈值短信通知发出来Web 大屏上的折线越过预警线颜色变红。最后把箱子打开通风浓度回落系统自动恢复绿色。整个过程大约 90 秒分三个阶段正好对应预警逻辑里的黄、橙、红三级。演示的关键点是提前在箱子侧面留一个小孔用于插传感器线缆或者温度探针不要让粉尘散到答辩教室。另外一个细节蚊香的烟是气溶胶粒径和粉尘有差异但触发传感器足够了动作干脆不拖泥带水。演示前至少完整跑两遍确保报警阈值设置合理不会出现还没抖面粉就报警的情况。5. 粉尘监测系统避坑指南血泪换来的 5 条现场经验每一条都能毁掉一次演示5.1 传感器读数负值、零点漂移校零、预热与软件截断现象传感器刚上电时读数直接显示 “-5” 或 “-12”运行一小时后慢慢回到零附近或者前一天还正常第二天开机整体偏高 20 到 30 个单位。原因激光散射传感器出厂时内置算法依赖光强基准上电瞬间激光器和光电二极管没有达到热平衡配合不同批次器件的一致性差异就会在零点附近出现负偏。另外传感器镜头上有积尘也会让零点缓慢漂移。解决上行前预热 5 分钟让激光器达到工作温度模块上电后清零算法做一次初始校准软件侧对负值直接截断为 0避免图表上出现负浓度这种一眼假的数据。如果点位环境灰尘大还要定期用压缩空气吹镜头或者干脆换带防尘滤网的传感器外壳。5.2 湿度一高浓度就爆表凝露误报怎么区分和规避现象连续阴雨天没有作业活动系统却在凌晨频繁触发黄色预警报表里 PM10 数值大面积超过 600甚至飙到 900 以上。原因激光散射原理在空气相对湿度超过 70% 时水汽会包裹颗粒物导致颗粒物等效粒径变大、散射截面增强读数虚高一倍不止。凌晨湿度最大所以误报集中在夜间。解决数据链路里同时接入温湿度传感器在预警判定逻辑里加湿度补偿或者湿度超过 75% 时把粉尘读数标记为“受湿度影响”降低预警级别。还有一种做法是传感器安装在有遮挡、通风良好的位置不要让雨水或者高湿气流直接吹到传感器风道上。这个坑最大的危害是让人对系统失去信任误报比不报更致命。5.3 厂房深处 4G 信号弱数据延迟和本地缓存现象ESP32 加 4G 模块部署在厂房角落Web 大屏上数据每隔几分钟才更新一次点击“实时刷新”时长时间没有新数据。原因厂房金属结构对无线信号屏蔽严重4G 模块进入弱信号区上行数据重传次数增加。更隐蔽的是通信模块在弱信号下会主动降低发射功率导致连接频繁超时。解决优先给通信模块接外置吸盘天线天线吸在窗户玻璃上或者厂房立柱顶棚效果立竿见影。如果信号依旧差换用 Cat.1 模块里接收灵敏度更高的型号。数据链路侧加本地缓存主控板每读到一组数据就写入 SD 卡网络恢复后再补传这样即使断网半小时数据也是完整的。5.4 粉尘毛刺触发连环报警滑动窗口与确认周期现象运行一星期后系统在中午和傍晚各触发一次红色报警但现场当时并没有明显扬尘工人也反馈没看到异常。原因粉尘浓度的瞬时脉冲比如一辆叉车驶过卷起的地面积尘或者附近有电焊烟尘飘过单次读数瞬间超过阈值。如果预警逻辑是“单条数据超阈值就报警”这种毛刺就会直接触发。解决把单点判断改成滑动窗口最近 5 条数据里至少 4 条超过阈值才报警报警后还要连续 3 条低于阈值的 80% 才恢复。之所以设置“恢复延迟”是因为浓度下降和粉仓沉降都需要时间瞬时回落后又立刻升高的情况很常见。5.5 断电重启后数据错乱时钟丢失与数据去重现象现场偶然断电系统来电重启后Web 大屏的时间轴出现凌晨一点、上午十点交替跳动报表里同一分钟出现两条相同数据。原因主控板没有实时时钟芯片重启后时间从编译固件时的初始时间开始跑或者干脆用了复位时间同时 MQTT 会话恢复后Broker 里积压的旧消息和新消息一起被消费导致重复入库。解决设备端增加时间校准重启后通过 MQTT 向服务端请求一次 NTP 时间再用这个时间戳标记数据数据库里对设备编号和设备时间戳做联合唯一索引重复消息提交时直接跳过。这个坑最容易在最后一周被翻出来因为平时都在实验室调试根本没经历过断电。6. 验证与升级把“演示能跑”变成“连续运行不掉链子”6.1 对标测试与修正系数系统能跑通闭环只是第一步真正要说服评委和现场使用人员要用数据说话。找一个手持式粉尘浓度仪作为参考把两个设备放在同一位置连续采集一小时每 10 秒记录一组读数然后做线性回归。采集时间段参考仪器 PM10 (µg/m³)自建节点 PM10 (µg/m³)偏差百分比10:00-10:10455215.6%10:10-10:2078836.4%10:20-10:301561623.8%10:30-10:403203416.6%10:40-10:505405725.9%低浓度段偏差大是正常现象激光散射传感器在颗粒物稀少时光子计数统计涨落更明显。把参考仪器的读数作为纵轴自建节点的读数作为横轴求一个线性拟合系数得到y a*x b把系数写进服务端每次入库前先修正再判断阈值。修正后系统读数与参考仪器的偏差能控制在 10% 以内这个结论直接写进答辩报告里比“做了个系统”有说服力得多。6.2 低功耗与多监测点联动下一步升级方向是低功耗。当前方案里传感器风扇和通信模块是耗电大户测量周期改成测量 30 秒、休眠 300 秒平均电流能降一个数量级锂电池加太阳能板就可以支撑。如果作业场所没有市电这个方案就是唯一解也正好接上“无源物联网”的方向把环境能量采集和低功耗传感结合起来是连续两年国赛和毕业论文里的热门选题。多监测点联动也是一条可走的路。每个粉尘监测点独立报警已经够用但把 10 个点位的浓度空间分布叠加到一张厂区地图上就能判断粉尘是从哪个工位扩散出来的这已经从“监测预警系统”延伸到了“溯源分析系统”工作量不大展示效果却上了一个档次。回看这个系统最大的教训是不要等到答辩前一周才做联动调试传感器、通信、后端、前端每一个环节单独都正常连起来才暴露问题而这些问题的排查耗时远超预期。把它当成一个完整的交付物来做每连接一层就验证一层现场演示时才不会掉链子。希望帮到你。本文还有配套的精品资源点击获取
返回列表