尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
基于Arduino与ESP8266的温湿度及PM2.5环境监测系统设计
拿到这个标题第一反应就是典型的“毕业设计/课程设计热门款”加“个人DIY环境监测入门标配”。但说真的把它做好做稳并不简单很多照着网上教程接线的人最后都卡在数据飘、连不上网、读数对不齐这几个地方。我这篇不打算只给一份能用就行的方案而是把设计思路、传感器选型、电路处理、代码框架、联网调试这些环节全部拆开讲一遍顺便把踩过的坑也说清楚希望能帮你少走几趟弯路。这个项目能完成的事情其实很直观一块Arduino或者直接上带WiFi的ESP8266/ESP32开发板接上温湿度传感器和PM2.5传感器定期采集数据通过WiFi上传到服务器或者局域网里的小程序/网页最终实现用手机随时查看房间、工位、大棚或者工作室的空气状况。适合的对象也很明确刚学完单片机基础、想尝试“硬件上云”的开发者以及需要给现有环境做个低成本监测方案而没有头绪的爱好者。1. 项目整体设计与硬件选型1.1 先想清楚要测什么、传到哪、怎么看不要一上来就买一堆模块先把需求拆成三个问题测什么参数、要不要显示、数据给谁看。这个项目标题里固定了温湿度、PM2.5、WiFi联网三样那最基本的目标就是定时测出这三项数据让数据能通过WiFi送出去。至于送到哪我建议第一版先送局域网内的PC或手机端调试跑通后再对接公网云平台。这里有一个容易被忽略的设计取舍Arduino Uno本身不带WiFi要联网就得外挂ESP8266模块两个MCU之间还得走串口通信复杂度一下就上去了。如果标题里没有强制“必须用Arduino Uno”我强烈建议直接用NodeMCU或ESP32这类自带WiFi的开发板。它们仍然是Arduino生态Arduino IDE直接开发但省去了主控与WiFi模块之间的握手逻辑稳定性能好很多。下面所有内容都以“ESP8266 NodeMCU Arduino IDE”为主线同时也会说明和Uno的区别这样你无论手头有什么都能套用。1.2 传感器选型温湿度选DHT22还是SHT30PM2.5选激光还是红外温湿度模块是这类的老熟人了DHT11和DHT22几乎每个教程都会出现。我的建议很直接预算不是特别紧就上DHT22成本和DHT11的差价也就是一杯饮料的钱但精度和稳定性差距肉眼可见。DHT11的湿度误差可以达到±5%放在空气质量场景里数据波动大到没法看DHT22能做到±2%左右温度精度也能到±0.5°C家用监测足够。再往上可以选SHT30I2C接口不用自己写时序读数据更稳就是需要一点库配置经验。PM2.5传感器比较坑因为网上便宜的红外式模块夏普GP2Y1010AU0F为代表模拟输出需要运放电路处理而且对灰尘的辨识度一般做做定性趋势还可以当真数据有点勉强。如果要做可信的数值上传建议选激光散射式的串口模块比如PMS5003、PMS7003。这类模块内置风扇串口直接输出颗粒物质量浓度单位ug/m3有PM1.0、PM2.5、PM10三组数据精度靠谱得多。虽然贵几十块但省掉一堆信号调理电路开发时间省回来完全划算。WiFi这块如果按“Arduino UnoESP8266”的老路线你需要给ESP8266刷AT固件然后用SoftwareSerial发指令什么“ATCIPSTART”“ATCIPSEND”调试起来很折磨人。直接用NodeMCU开发板就轻松多了固件、引脚、电源都排好了按照我们常说一句别自己造车轮。1.3 供电与结构很多不稳定的源头是电传感器和WiFi模块混在一起时电源问题会被放大。PM2.5激光传感器内部有个风扇启动瞬间电流能到100mA以上ESP8266在发射WiFi时电流也会突然飙升峰值可能接近300-400mA。如果全部靠Arduino的3.3V引脚供电电压很容易被拉低程序就会莫名其妙重启数据也会出现跳变。我的经验是外接5V/2A适配器通过USB进NodeMCU板传感器的VCC尽量从5V引脚取只要传感器支持5V输入并把每个传感器模块上的板载稳压降到3.3V给逻辑部分用。DHT22可以用5V供电PMS5003的VCC用5V供电完全没有问题。这样就不用纠结电流不够的问题了。如果坚持用电池供电至少要选18650两节或一个5V/2A的移动电源芯片方案不要指望USB口带得动全部外设。结构上PM2.5传感器要保证进出风口不被遮挡最好固定在设备外壳的侧边让空气可以自然流入DHT22要避免贴到发热元件也不能放在阳光直晒的位置。我自己见过一个案例把DHT22放在ESP8266正上方结果温度永远比其他房间温度高3度一看就是被板子烤的。2. 电路搭建与传感器细节解析2.1 接线图与引脚分配假设你用NodeMCU开发板引脚分配可以这样DHT22 Data脚 - D4GPIO2供电接5VGND接GNDData与5V之间建议加一个4.7kΩ到10kΩ上拉电阻有些模块板载已带不用重复加。PMS5003串口发送数据到NodeMCU的D3GPIO0和D2GPIO4。注意方向PMS5003的TXD接NodeMCU的RX引脚PMS5003的RXD接NodeMCU的TX引脚。如果板上引脚名不好区分就记住交叉接。如果加OLED屏幕128x64I2CSDA接D1GPIO5SCL接D2GPIO4。这里有个比较关键的坑NodeMCU的部分引脚在启动时保持特定电平不能乱接。比如GPIO2和GPIO0如果在启动时被拉低会进入下载模式导致板子无法正常启动。DHT22接在D4GPIO2一般没问题因为DHT的Data线空闲时是高的但如果有些模块带LED指示灯影响电平就要注意。最保险的办法是把传感器接到D5、D6这类普通IO口避开启动敏感的GPIO0/2/15。PMS5003是3.3V TTL串口NodeMCU也是3.3V逻辑可以直接相连。如果你用Arduino Uno5V逻辑就要用电平转换芯片不能直接接否则会烧模块。2.2 温湿度传感器的时序原理和拉高问题DHT22/DHT11的数据引脚用的是单总线协议时序要求比较严格。程序发送一个低电平起始信号传感器应答后开始连续输出40位数据。最常见的问题是如果延时精度不够或者线路过长导致边沿变缓读出来的数据就可能一直是0、NaN或校验错误。DHT类库现在主流是DHT-sensor-library用起来很简单但底层也是靠sleep和digitalRead去模拟时序对中断不友好的环境会很脆。如果你在代码里同时开启了WiFiESP8266的底层库会频繁使用中断这确实可能干扰DHT的时序。我试过的稳定方案是读取DHT数据前先短暂关闭WiFiWiFi.disconnect()或者使用DHT的异步读取方式再或者换成带I2C接口的SHT30彻底绕开时序问题。这算是在这个项目上最有价值的避坑点之一。2.3 PM2.5激光传感器串口数据解析PMS5003输出的是被动模式下的串口数据包每帧32字节以0x42 0x4D开头ASCII字符“BM”后面跟着帧长度、各粒径浓度数据、CRC校验。标准做法是写一个状态机在串口缓冲里找帧头读到32字节后校验再从第5、7、9字节提取PM1.0、PM2.5、PM10浓度值16位整数。很多教程直接给一个简单版解析函数只在空闲时间读容易出现数据错位。建议处理方式在串口事件里逐字节读取缓存到数组每拿到一个新字节就尝试匹配帧头累计到预期长度后做校验。这样的状态机代码几十行而已但稳定度提升很大再也不会被一个乱码字节毁掉整帧数据。如果你选的是GP2Y1010AU0F这种模拟输出模块那就要用ADC采样而且必须配合脉冲驱动和运放复杂度完全不在一个量级。不是玩玩而已的话我劝你直接换PMS系列省心太多。3. 软件设计与核心代码实现3.1 程序整体框架状态机式还是轮询式考虑到WiFi、传感器、显示三个任务并发最自然的写法是轮询主循环里分时处理比如每2秒读一次PM2.5每5秒读一次DHT每10秒上传一次数据。这样避免了把传感器读取放在中断里导致的各种莫名崩溃。当然也可以用定时器或millis()控制节奏而不是delay()。delay()会阻塞整个循环WiFi底层协议栈无法及时收包连接和重连都会变得迟钝。你自己想一下WiFi模块也需要“呼吸”来维持连接你把它的氧气全堵了它当然要罢工。建议所有时间控制都基于millis()的状态判断把“现在该干什么”写在主循环里。3.2 温湿度读取代码DHT22以DHT-sensor-library为例核心代码很短#include DHT.h #define DHTPIN 4 // 注意这是D2引脚对应的GPIO4根据你实际接线改 #define DHTTYPE DHT22 DHT dht(DHTPIN, DHTTYPE); void setup() { Serial.begin(115200); dht.begin(); } void loop() { float h dht.readHumidity(); float t dht.readTemperature(); if (isnan(h) || isnan(t)) { Serial.println(DHT read failed); return; } Serial.printf(Temp: %.1f C, Hum: %.1f%%\n, t, h); delay(2000); }在实际项目里建议把readTemperature(false)写完整默认返回值就是摄氏度。如果你的传感器是DHT11把DHTTYPE改成DHT11就行。注意读失败的次数可能不少至少要做3次重试连续失败超过5次再报警不要读到一次失败就认为传感器坏了。3.3 PM2.5读取代码PMS5003状态机解析下面是简化了但很实用的状态机代码能直接放进你的项目#include SoftwareSerial.h #define PMS_RX 5 // 接PMS5003 TXD - NodeMCU D1(GPIO5) #define PMS_TX 4 // 接PMS5003 RXD - NodeMCU D2(GPIO4)如果不发命令可以不接 SoftwareSerial pms(PMS_RX, PMS_TX); uint8_t buf[32]; int bufIndex 0; bool frameStarted false; void setup() { Serial.begin(115200); pms.begin(9600); } void loop() { while (pms.available()) { uint8_t byte pms.read(); if (bufIndex 0 byte ! 0x42) continue; if (bufIndex 1 byte ! 0x4D) { bufIndex 0; continue; } buf[bufIndex] byte; if (bufIndex 32) { handleFrame(buf); bufIndex 0; } } } void handleFrame(uint8_t* data) { // 校验 uint16_t sum 0; for (int i 0; i 30; i) sum data[i]; uint16_t check (data[30] 8) | data[31]; if (check ! sum) { Serial.println(PM2.5 checksum error); return; } uint16_t pm25 (data[5] 8) | data[6]; uint16_t pm10 (data[7] 8) | data[8]; Serial.printf(PM2.5: %d ug/m3, PM10: %d ug/m3\n, pm25, pm10); }解析这部分的要点在于必须把SoftwareSerial的波特率设为9600PMS5003默认。代码里没有发任何指令只读取被动推送的数据够用了。如果你想要传感器进入主动模式或者设置唤醒等需要单独发指令这里不多扩展。校验位很容易被忽视但加上了之后能防止大量假数据别省。3.4 WiFi连接与数据上传ESP8266连WiFi最简单的方法是使用ESP8266WiFi.h库连接代码大家都会但有几个细节决定稳不稳定。第一连接要带超时控制不能无限while(WiFi.status() ! WL_CONNECTED)否则路由器故障时程序就死在那了。我习惯写成最多尝试20次每次500ms仍然失败就重启或继续主循环等下一次上传周期再重连。第二HTTP上传用HTTPClient库向服务器POST JSON数据。下面是一个简单可用的上传函数#include ESP8266WiFi.h #include ESP8266HTTPClient.h #include ArduinoJson.h const char* ssid 你的WiFi名字; const char* password 你的WiFi密码; const char* serverUrl http://192.168.1.100:8080/api/data; void uploadData(float temp, float humi, int pm25) { if (WiFi.status() ! WL_CONNECTED) { if (!connectWiFi()) return; } HTTPClient http; http.begin(serverUrl); http.addHeader(Content-Type, application/json); StaticJsonDocument256 doc; doc[temp] temp; doc[humi] humi; doc[pm25] pm25; String body; serializeJson(doc, body); int code http.POST(body); if (code 0) { Serial.printf(Upload OK, code%d\n, code); } else { Serial.printf(Upload failed, error%s\n, http.errorToString(code).c_str()); } http.end(); } bool connectWiFi() { WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); int tries 0; while (WiFi.status() ! WL_CONNECTED tries 20) { delay(500); tries; } return WiFi.status() WL_CONNECTED; }注意serverUrl第一版想简单调试可以先在电脑上装个“处理接收数据的本地服务端”后面再接入云平台。用什么服务端完全看你自己熟悉什么只要能接收HTTP POST并显示数据就行。如果你要对接常见的物联网云平台一般在平台上创建产品、添加设备拿到三个关键参数设备ID、API Key、数据模板。然后把你上面的上传函数改一下URL和JSON字段名即可。不要一上来就上云先用局域网IP调试通再接入平台排查起来会轻松很多。4. 数据显示与报警联动从“能传”到“能用”4.1 加入OLED屏实现本地显示虽然标题核心是WiFi联网但现场没有屏幕调试时太痛苦。我习惯在项目里加一块0.96寸OLED实时显示当前温湿度和PM2.5顺便显示WiFi连接状态。I2C接口只用两根线代码也不复杂。显示用U8g2库或Adafruit_SSD1306库都可以。U8g2功能多但字号、缓冲区设置比较烧脑SSD1306库更轻量。我给出的建议是先只显示一行“WiFi OK/NO”再显示“T25.3C H60%”最后显示“PM2.535”。OLED的刷新不要太频繁每秒一次够用了反正人眼刷新也看不出多大差别。OLED的I2C地址一般是0x3C如果你接好后屏幕不亮用I2C扫描程序查一下地址确认你的接线有没有问题。这算基础但每次都能拦截一半以上的硬件通病。4.2 超限报警与消息推送数据传到服务器或者公网平台后报警逻辑通常放云端或服务端处理比放在单片机里更灵活。我的常用做法在服务端配置阈值比如PM2.5超过75ug/m3就触发报警。服务端收到数据后判断一次超过阈值就通过Webhook方式把消息推到钉钉、企业微信、或某个“公众号模板消息”服务。这样设备端只负责上传阈值可以随时改而不用刷固件。如果什么都不想搭建也可以在ESP8266代码里直接判断超过阈值就让蜂鸣器响。蜂鸣器不要直接接GPIO电流不够也容易伤引脚用一个三极管或者模块驱动才行。4.3 数据存储与历史曲线只显示实时数值是“能用”能查历史数据才是“好用”。最简单的方案是用一个极简的后端接收JSON数据后写入数据库或CSV文件。如果你不想自己写后端就直接用物联网平台平台里都带数据存储和折线图功能能省很多事。但要注意免费版的数据存储频率和条数有限制上传间隔别低于1分钟。我做过一个实际场景在自己书房放了一个小盒子每5分钟上传一次数据跑了三个月功率大概就几瓦。用平台自带的历史曲线对比天气变化能发现下雨前湿度曲线会缓慢抬升这些规律用来判断房间的通风条件非常有用。5. 调试过程中的常见问题与避坑实录5.1 DHT传感器读数为NaN或0这个问题排名第一原因一般有三个接线错误、上拉电阻缺失、WiFi中断干扰时序。排查步骤用最简单的DHT例程不打开WiFi只读传感器确认硬件没问题。如果例程正常、上电后依然间歇性报错把DHT的Data线靠近电源线减少干扰。如果开WiFi后才出问题按前面说的读取DHT前短暂暂停WiFi或者换SHT30。检查数据线是否过长超过50cm很容易失败。5.2 PM2.5数据一直不变或为0大概率是串口接线不对或波特率不对或者是信号线被其他库占用。PMS5003上电后有大约30秒稳定时间风扇转起来刚上电的数据可能偏低等一会儿再看。如果你的传感器买到的是被动模式版本可能不会连续输出数据需要发主动模式指令0x42 0x4D 0xE1 0x00 0x00 0x01 0x70网上搜得到标准命令。5.3 WiFi频繁断连重连先排除供电问题。测一下NodeMCU的3.3V引脚电压如果低于3.2V就该检查电源适配器了。再检查路由器信道和信号强度2.4G信号最好保持在-60dBm以上。固件里加上自动重连机制发现WiFi.status() ! WL_CONNECTED就重新连接而不是只连接一次。另外在代码里不要用delay阻塞太久。上传HTTP时如果服务器响应慢整个循环会被卡住底层WiFi协议栈无法维持连接。建议给HTTP请求设置http.setTimeout(3000)不要让它无限等。5.4 数据跳变严重干扰主要来自电源和线路布局。DHT22的信号线不要跟PMS5003的串口线绑在一起两者分开放用屏蔽线更好。PM2.5模块的风扇会产生振动虽然数字传感器不受影响但模拟传感器会被噪声害死。另外传感器最好用短而粗的线连接电源地平面我见过有人用杜邦线飞了20cm数据完全没法看。电源上可以在模块电源引脚就近并联一个100uF电解电容和0.1uF瓷片电容这个组合能滤掉大部分毛刺。5.5 数据上传频率与服务器压力如果你用的是免费云平台上传频率太密容易触发限流。我建议环境监测场景下每分钟上传一次足够。如果做实时性要求高的场景也要控制在10秒以上毕竟传感器响应和空气变化没快到毫秒级。5.6 问题速查表现象大概率原因解决动作DHT返回NaN时序被干扰/接线不良重插线、短接线、读取前暂停WiFiPM2.5为0串口交叉错/波特率错检查TXD/RXD、串口9600WiFi连不上路由器2.4G关闭/密码错确认SSID与密码、开启2.4G设备反复重启电源电流不够换2A适配器峰值电流要够数据偶尔上传失败HTTP超时/网络抖动增加重试超时缩短采集值严重偏高传感器靠近热源移开散热元件改善通风6. 扩展思路与实际项目落地感想如果你走完上面这些流程你已经拥有一个完整可用的环境监测节点。再往下扩展我可以给你几个方向多节点组网每个房间放一个子站ESP8266连同一个路由器数据上传到同一个服务端按设备ID区分。硬件升级把ESP8266换成ESP32增加蓝牙和更大内存可以接入更多传感器甚至做本地离线分析。联动控制检测到PM2.5超标通过继电器打开空气净化器检测到土壤湿度低加水泵灌溉。这些都是同一套数据链路的不同出口。离线缓存在断网时把数据存到Flash或SD卡联网后再补传这个在信号差的场景下非常好用。我个人实际使用中最强烈的体会是这个项目的难点从来不在代码本身而在“稳定”这两个字。一个能跑三分钟的Demo和一台能连续运行三个月不垮的监测设备之间隔着的是对电源、干扰、时序、重连机制的认真对待。尤其是WiFi上传部分解决掉“掉线”和“数据错位”这两个问题成就感会特别明显。希望这篇复盘能帮你把这个经典的Arduino联网设计从“跑通”做到“靠谱”。如果你按这个思路做出来欢迎回来分享你踩到的其他坑。
RELATED

相关推荐

Qt节点式视觉工具链:QGraphicsScene流程编辑器源码解析

Qt节点式视觉工具链:QGraphicsScene流程编辑器源码解析

做视觉项目这些年,我越来越觉得“工具链搭建”和“流程编排”是个绕不开的坎。尤其是做工业检测类的上位机软件,常常需要把相机采集、图像预处理、特征提取、缺陷判定、结果输出这些步骤串起来。最朴素的实现是写死一段流程函数,今天要加一个…

📅 2026/10/24 6:00:58
龙软地质建模开源复现:从钻孔数据到三维地层的全流程闭环

龙软地质建模开源复现:从钻孔数据到三维地层的全流程闭环

简介:龙软地质软件是一款面向地质勘查、矿山设计与采矿工程技术人员的专业工具,聚焦三维地质建模、矿体可视化分析与开采方案辅助设计,有效解决地层结构解析、钻孔数据整合、地质图件绘制及稳定性模拟等核心问题。资源包共121个文件&#xff…

📅 2026/10/24 5:55:58
区块链遇上基础模型:BTFM 2026交叉领域国际会议全解析

区块链遇上基础模型:BTFM 2026交叉领域国际会议全解析

开年到现在,我朋友圈里讨论度最高的一次会议,大概就是刚放出征稿通知的EI会议——2026年区块链技术与基础模型国际学术会议(BTFM 2026)。这个会全称挺长,圈内一般直接喊BTFM 2026,核心议题一句话就能讲清楚…

📅 2026/10/24 5:55:58
MORE NEWS

更多资讯

📰

快降重理工科降AI技术:实证数据与推导逻辑的保护机制详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

YimMenu:GTA V 防崩溃菜单,怎么编译注入、哪些功能敢开

YimMenu:GTA V 防崩溃菜单,怎么编译注入、哪些功能敢开 【免费下载链接】YimMenu YimMenu, a GTA V menu protecting against a wide ranges of the public crashes and improving the overall experience. 项目地址: https://gitcode.com/GitHub_Tren…

📰

Visual Studio 添加万能头文件 bits/stdc++.h:从原理到配置全程指南

做算法题的朋友应该都有这个习惯:从题单里复制一道题目,打开 Visual Studio,第一件事不是读题,而是先伸手去敲开头那串#include。iostream、algorithm、vector、map、string、queue……少敲一个心里都不踏实,敲完了还要…

📰

Windows平台frpc客户端架构选择与性能优化指南

1. frpc客户端架构差异解析在Windows平台上部署frp内网穿透服务时,我们常会遇到两个不同架构的客户端版本:frpc_win_amd64和frpc_win_arm64。这两个版本的核心区别在于CPU指令集架构的兼容性设计。1.1 x86_64与ARM64架构对比AMD64(又称x86_64…

📰

PaddleHelix 分子模型上手指南:GeoGNN 与 SD VAE 两个核心组件从原理到跑通

PaddleHelix 分子模型上手指南:GeoGNN 与 SD VAE 两个核心组件从原理到跑通 【免费下载链接】PaddleHelix Bio-Computing Platform Featuring Large-Scale Representation Learning and Multi-Task Deep Learning “螺旋桨”生物计算工具集 项目地址: https://git…

📰

企业级数据可视化BI 仪表板数据中台监控平台的选择分析

三类场景决策模型产品推荐场景1:简单BI展示推荐使用ECharts原因:免费快速场景2:企业级BI平台推荐使用Highcharts原因:可扩展可维护有完整生态不同场景类型选择的真正的差异是什么?1. 使用 ECharts是用“代码能力”2. 使…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬