网站横幅广告代码,深圳网络seo推广,阿帕奇建设网站博客,文字logo设计生成器本教程将指导您制作一台专业级的空气质量检测仪。这个项目使用经济实惠的ESP8266和PMS5003传感器#xff0c;配合OLED显示屏#xff0c;不仅能实时显示PM2.5数值#xff0c;还能通过手机APP随时查看数据。总成本70元#xff0c;相比几百的用的便宜#xff0c;用的心理踏实…本教程将指导您制作一台专业级的空气质量检测仪。这个项目使用经济实惠的ESP8266和PMS5003传感器配合OLED显示屏不仅能实时显示PM2.5数值还能通过手机APP随时查看数据。总成本70元相比几百的用的便宜用的心理踏实。
功能特点
实时检测PM2.5和PM10浓度OLED屏幕直观显示数据WiFi无线连接支持远程数据查看手机APP实时监控支持数据历史记录和趋势分析24小时持续监测
成品
网页
APP
硬件需求 ESP8266开发板如NodeMCU、Wemos D1 mini等10元 PMS5003/PMS7003系列颗粒物传感器 50元 0.96寸OLED显示屏I2C接口128x64分辨率9元 若干杜邦线
接线说明
PMS传感器接线5V供电
VCC → ESP8266的VIN5V GND → ESP8266的GND TX → D6GPIO12 RX → D5GPIO14
OLED显示屏接线
VCC → 3.3V GND → GND SDA → D2GPIO4 SCL → D1GPIO5
准备工作
Arduino IDE配置
安装ESP8266开发板支持 安装必要的库
WiFiManager用于WiFi配置 PubSubClientMQTT客户端 Adafruit GFX和Adafruit SSD1306OLED驱动 ArduinoJsonJSON数据处理
使用说明
首次使用
给设备上电后会创建一个名为AP的WiFi热点 用手机连接该热点 在弹出的配置页面中设置WiFi信息 设备会自动连接配置好的WiFi
正常使用
设备每3秒更新一次显示屏数据 每10秒向MQTT服务器发送一次数据 OLED屏幕显示实时PM2.5数值
代码
#include ESP8266WiFi.h
#include WiFiManager.h
#include PubSubClient.h
#include SoftwareSerial.h
#include Wire.h
#include Adafruit_GFX.h
#include Adafruit_SSD1306.h
#include ArduinoJson.h// OLED显示屏设置
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, Wire, OLED_RESET);// PMS传感器串口设置
#define PMS_RX 12 // D6
#define PMS_TX 14 // D5
SoftwareSerial pmsSensor(PMS_RX, PMS_TX);// MQTT设置
const char* mqtt_server 47.115.210.16;
const int mqtt_port 1883;
const char* mqtt_username cc1fb73f-ec43-3b37-522;
const char* mqtt_password b5c6d62;
const char* mqtt_client_id mqtt_d59ea842-b79;
const char* mqtt_topic devices/telemetry;// 时间设置
unsigned long lastMQTTPublish 0;
const long MQTT_PUBLISH_INTERVAL 10000; // MQTT发布间隔10秒
const long DISPLAY_UPDATE_INTERVAL 3000; // 显示更新间隔3秒WiFiClient espClient;
PubSubClient client(espClient);// PMS数据结构
struct PMS_data {uint16_t pm1_0;uint16_t pm2_5;uint16_t pm10_0;uint16_t pm1_0_std; // 添加标准颗粒物浓度uint16_t pm2_5_std;uint16_t pm10_0_std;bool valid;
} pms_data;void setup() {Serial.begin(115200);Serial.println(\n启动中...);// 初始化I2CWire.begin(4, 5); // SDA GPIO4 (D2), SCL GPIO5 (D1)// 初始化OLEDif(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {Serial.println(OLED初始化失败);} else {Serial.println(OLED初始化成功);display.clearDisplay();display.setTextColor(SSD1306_WHITE);showInitScreen();}// 初始化PMS传感器Serial.println(初始化PMS传感器...);pmsSensor.begin(9600);pms_data.valid false;// 配置WiFiWiFiManager wifiManager;if(!wifiManager.autoConnect(AP)) {Serial.println(配置失败重启);ESP.restart();}// 配置MQTTclient.setServer(mqtt_server, mqtt_port);
}void loop() {static unsigned long lastDisplayUpdate 0;unsigned long currentMillis millis();if (!client.connected()) {reconnectMQTT();}client.loop();if (currentMillis - lastDisplayUpdate DISPLAY_UPDATE_INTERVAL) {if (readPMSdata()) {updateDisplay();}lastDisplayUpdate currentMillis;}if (pms_data.valid currentMillis - lastMQTTPublish MQTT_PUBLISH_INTERVAL) {publishData();lastMQTTPublish currentMillis;}
}bool readPMSdata() {uint8_t buffer[32];uint16_t sum 0;// 清空接收缓冲区while(pmsSensor.available()) {pmsSensor.read();}// 等待数据delay(1000);if (pmsSensor.available() 32) {return false;}// 检查帧头if (pmsSensor.read() ! 0x42 || pmsSensor.read() ! 0x4D) {return false;}// 读取剩余数据pmsSensor.readBytes(buffer, 30);// 计算校验和sum 0x42 0x4D;for (int i 0; i 28; i) {sum buffer[i];}// 验证校验和if (sum ! ((buffer[28] 8) | buffer[29])) {Serial.println(校验和错误);return false;}// 打印原始数据以供调试Serial.println(Raw data:);for(int i 0; i 30; i) {Serial.printf(%02X , buffer[i]);if((i 1) % 8 0) Serial.println();}Serial.println();// 标准颗粒物浓度pms_data.pm1_0_std (buffer[4] 8) | buffer[5]; // 数据1PM1.0标准pms_data.pm2_5_std (buffer[6] 8) | buffer[7]; // 数据2PM2.5标准pms_data.pm10_0_std (buffer[8] 8) | buffer[9]; // 数据3PM10标准// 大气环境浓度pms_data.pm1_0 (buffer[10] 8) | buffer[11]; // 数据4PM1.0大气环境pms_data.pm2_5 (buffer[12] 8) | buffer[13]; // 数据5PM2.5大气环境pms_data.pm10_0 (buffer[14] 8) | buffer[15]; // 数据6PM10大气环境Serial.println(解析后的数据:);Serial.printf(标准颗粒物浓度 - PM1.0: %d, PM2.5: %d, PM10: %d\n, pms_data.pm1_0_std, pms_data.pm2_5_std, pms_data.pm10_0_std);Serial.printf(大气环境浓度 - PM1.0: %d, PM2.5: %d, PM10: %d\n, pms_data.pm1_0, pms_data.pm2_5, pms_data.pm10_0);// 验证数据合理性暂时注释掉范围检查看看实际数据// if (pms_data.pm2_5 1000 || pms_data.pm1_0 1000 || pms_data.pm10_0 1000) {// Serial.println(数据超出合理范围);// return false;// }pms_data.valid true;// 打印调试信息Serial.printf(PM1.0: %d, PM2.5: %d, PM10: %d\n, pms_data.pm1_0, pms_data.pm2_5, pms_data.pm10_0);return true;
}void updateDisplay() {display.clearDisplay();// 标题 - 确保不会折行display.setTextSize(1);display.setTextColor(SSD1306_WHITE);const char* title AIR QUALITY;int16_t titleWidth strlen(title) * 6;display.setCursor((SCREEN_WIDTH - titleWidth) / 2, 2);display.print(title);// 单条分隔线display.drawLine(0, 12, SCREEN_WIDTH, 12, SSD1306_WHITE);// PM2.5值显示String pm25Str String(pms_data.pm2_5);int16_t valueX SCREEN_WIDTH - (pm25Str.length() * 12) - 8; // 右边距离8像素int16_t valueY 22;// PM2.5标签display.setTextSize(1);display.setCursor(8, valueY 4);display.print(PM2.5);// PM2.5数值反色显示int16_t boxWidth pm25Str.length() * 12 4;int16_t boxHeight 18;display.fillRect(valueX - 2, valueY - 1, boxWidth, boxHeight, SSD1306_WHITE);display.setTextColor(SSD1306_BLACK);display.setTextSize(2);display.setCursor(valueX, valueY);display.print(pm25Str);// PM10显示保持在一行内display.setTextColor(SSD1306_WHITE);display.setTextSize(1);// PM10标签和值int16_t pm10Y 48;display.setCursor(8, pm10Y);display.print(PM10);String pm10Str String(pms_data.pm10_0);int16_t pm10ValueX SCREEN_WIDTH - (pm10Str.length() * 6) - 35; // 预留单位的空间display.setCursor(pm10ValueX, pm10Y);display.print(pm10Str);// 单位display.setCursor(SCREEN_WIDTH - 30, pm10Y);display.print(ug/m3);display.display();
}void publishData() {StaticJsonDocument200 doc;doc[pm25] pms_data.pm2_5;doc[pm10] pms_data.pm10_0;char buffer[200];serializeJson(doc, buffer);if (client.publish(mqtt_topic, buffer)) {Serial.println(MQTT数据发送成功);Serial.println(buffer);} else {Serial.println(MQTT数据发送失败);}
}void reconnectMQTT() {while (!client.connected()) {Serial.println(尝试MQTT连接...);if (client.connect(mqtt_client_id, mqtt_username, mqtt_password)) {Serial.println(MQTT已连接);} else {Serial.print(MQTT连接失败, rc);Serial.println(client.state());delay(2000);}}
}void showInitScreen() {display.clearDisplay();// 计算文本位置以实现居中显示int16_t startY (SCREEN_HEIGHT - 32) / 2; // 32是两行文本的总高度(16px每行)display.setTextSize(2);// 显示 Air PM2.5const char* line1 Air PM2.5;int16_t line1Width strlen(line1) * 12; // 每个字符宽度约12像素display.setCursor((SCREEN_WIDTH - line1Width) / 2, startY);display.println(line1);// 显示 Monitorconst char* line2 Monitor;int16_t line2Width strlen(line2) * 12;display.setCursor((SCREEN_WIDTH - line2Width) / 2, startY 16);display.println(line2);display.display();delay(2000);
}传感器手册