02-G5+nodeMCU
(2017/12/31)
比照之前G3+nodeMCU,再來做一次G5+NodeMCU,G5也就是PMS5003ST攀藤測PM2.5的感測器,可以偵測PM2.5、甲醛及溫濕度的值。
一、NodeMCU+G5+LCD顯示器:
接線說明:
一個nodeMCU+擴展板、一個LCD顯示器(SDA接D2、SCL接D1)、一個G5(pin5(Tx)接Rx)
LCD要接5V的電,不然電太弱會看不清楚
從下面這資料,好像用大氣環境下的為主
首先,它可以採樣測定的空氣懸浮微粒有三種規格 0.3-1.0um/1.0-2.5um/2.5-10um,也就是說我們可以拿到 PM1.0/PM2.5/PM10 的測定資料(ug/m3)。而且PMS3003 的 datasheet 寫到他有兩套檢定空氣品質濃度的方法,分別是可以獲得「大氣環境下」和「標準顆粒物」兩組資料值,所以程式裡面每一次從 sensor 那邊得到的資料就會有2組,6個測定值。這裡我會在意的是「大氣環境下」測得的這組,所以,以下顯示的是大氣環境下這組的數據。
利用下面程式可以得到PM1.0、PM2.5、PM10分別在CF=1為標準顆粒物、atmosphere為大氣環境下
CF=1 根据美国TSI公司的仪器校准
大气环境下 根据中国气象局的数据校准
程式說明:
G5程式採上一單元參考一的程式,LCD程式採用TUNIOT的程式,以下紅色字的部分(參考01TUNIOT入門課程)
進入TUNIOT網站:http://easycoding.tn/tuniot/demos/code/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2); //注意是0x27或0x3F
static unsigned int pm_cf_10; //定义全局变量
static unsigned int pm_cf_25;
static unsigned int pm_cf_100;
static unsigned int pm_at_10;
static unsigned int pm_at_25;
static unsigned int pm_at_100;
static unsigned int particulate03;
static unsigned int particulate05;
static unsigned int particulate10;
static unsigned int particulate25;
static unsigned int particulate50;
static unsigned int particulate100;
static float HCHO;
static float Temperature;
static float Humidity;
void getG5(unsigned char ucData)//获取G5的值
{
static unsigned int ucRxBuffer[250];
static unsigned int ucRxCnt = 0;
ucRxBuffer[ucRxCnt++] = ucData;
if (ucRxBuffer[0] != 0x42 && ucRxBuffer[1] != 0x4D)//数据头判断
{
ucRxCnt = 0;
return;
}
if (ucRxCnt > 38)//数据位判断//G5S为32,G5ST为38
{
pm_cf_10=(int)ucRxBuffer[4] * 256 + (int)ucRxBuffer[5]; //大气环境下PM2.5浓度计算
pm_cf_25=(int)ucRxBuffer[6] * 256 + (int)ucRxBuffer[7];
pm_cf_100=(int)ucRxBuffer[8] * 256 + (int)ucRxBuffer[9];
pm_at_10=(int)ucRxBuffer[10] * 256 + (int)ucRxBuffer[11];
pm_at_25=(int)ucRxBuffer[12] * 256 + (int)ucRxBuffer[13];
pm_at_100=(int)ucRxBuffer[14] * 256 + (int)ucRxBuffer[15];
particulate03=(int)ucRxBuffer[16] * 256 + (int)ucRxBuffer[17];
particulate05=(int)ucRxBuffer[18] * 256 + (int)ucRxBuffer[19];
particulate10=(int)ucRxBuffer[20] * 256 + (int)ucRxBuffer[21];
particulate25=(int)ucRxBuffer[22] * 256 + (int)ucRxBuffer[23];
particulate50=(int)ucRxBuffer[24] * 256 + (int)ucRxBuffer[25];
particulate100=(int)ucRxBuffer[26] * 256 + (int)ucRxBuffer[27];
HCHO=((int)ucRxBuffer[28] * 256 +(int)ucRxBuffer[29])/1000.000;
Temperature = ((int)ucRxBuffer[30] * 256 +(int)ucRxBuffer[31])/10.000;//包含温度
Humidity = ((int)ucRxBuffer[32] * 256 +(int)ucRxBuffer[33])/10.000;//包含湿度
if (pm_cf_25 > 999)//如果PM2.5数值>1000,返回重新计算
{
ucRxCnt = 0;
return;
}
ucRxCnt = 0;
return;
}
}
void setup() {
Serial.begin(9600);
lcd.begin();
}
void loop() {
while (Serial.available())
{
getG5(Serial.read());
}
Serial.print(" PM_CF1.0:");Serial.print(pm_cf_10);Serial.print(" ug/m3");//硬件串口输出数据
Serial.print(" PM_CF2.5:");Serial.print(pm_cf_25);Serial.print(" ug/m3");
Serial.print(" PM_CF10 :");Serial.print(pm_cf_100);Serial.println(" ug/m3");
Serial.print(" PM_AQI1.0:");Serial.print(pm_at_10);Serial.print(" ug/m3");
Serial.print(" PM_AQI2.5:");Serial.print(pm_at_25);Serial.print(" ug/m3");
Serial.print(" PM_AQI10:");Serial.print(pm_at_100);Serial.println(" ug/m3");
Serial.print(" PM_count03:");Serial.print(particulate03);Serial.print(" pcs/0.01cf");
Serial.print(" PM_count05:");Serial.print(particulate05);Serial.print(" pcs/0.01cf");
Serial.print(" PM_count10:");Serial.print(particulate10);Serial.print(" pcs/0.01cf");
Serial.print(" PM_count25:");Serial.print(particulate25);Serial.print(" pcs/0.01cf");
Serial.print(" PM_count100:");Serial.print(particulate100);Serial.println(" pcs/0.01cf");
Serial.print(" HCHO:");Serial.print(HCHO,3);Serial.println(" mg/m3");
Serial.print(" TS:");Serial.print(Temperature,1);Serial.println(" C"); //包含温度
Serial.print(" HS:");Serial.print(Humidity,1);Serial.println(" %RH"); //包含湿度
Serial.println("*********************************************");
lcd.setCursor(0, 0);
lcd.print(String("At")+pm_at_10 + String(",")+pm_at_25 + String(",")+pm_at_100+String("F:")+HCHO );
lcd.setCursor(0, 1);
lcd.print( String(" T:")+Temperature + String(" H:")+Humidity );
delay(2000);
}
二、NodeMCU+G5+OLED顯示器:
接線說明:
一個nodeMCU+擴展板、一個OLED顯示器(SDA接D2、SCL接D1)、一個G5(pin5(Tx)接Rx)
OLED接3.3V的電,即可
程式說明:
G5程式採上一單元參考一的程式,OLED程式採用TUNIOT的程式,以下紅色字的部分(參考01TUNIOT入門課程)
進入TUNIOT網站:http://easycoding.tn/tuniot/demos/code/
#include <Wire.h>
#include "SSD1306.h"
SSD1306 display(0x3C, 4, 5);
static unsigned int pm_cf_10; //定义全局变量
static unsigned int pm_cf_25;
static unsigned int pm_cf_100;
static unsigned int pm_at_10;
static unsigned int pm_at_25;
static unsigned int pm_at_100;
static unsigned int particulate03;
static unsigned int particulate05;
static unsigned int particulate10;
static unsigned int particulate25;
static unsigned int particulate50;
static unsigned int particulate100;
static float HCHO;
static float Temperature;
static float Humidity;
void getG5(unsigned char ucData)//获取G5的值
{
static unsigned int ucRxBuffer[250];
static unsigned int ucRxCnt = 0;
ucRxBuffer[ucRxCnt++] = ucData;
if (ucRxBuffer[0] != 0x42 && ucRxBuffer[1] != 0x4D)//数据头判断
{
ucRxCnt = 0;
return;
}
if (ucRxCnt > 38)//数据位判断//G5S为32,G5ST为38
{
pm_cf_10=(int)ucRxBuffer[4] * 256 + (int)ucRxBuffer[5]; //大气环境下PM2.5浓度计算
pm_cf_25=(int)ucRxBuffer[6] * 256 + (int)ucRxBuffer[7];
pm_cf_100=(int)ucRxBuffer[8] * 256 + (int)ucRxBuffer[9];
pm_at_10=(int)ucRxBuffer[10] * 256 + (int)ucRxBuffer[11];
pm_at_25=(int)ucRxBuffer[12] * 256 + (int)ucRxBuffer[13];
pm_at_100=(int)ucRxBuffer[14] * 256 + (int)ucRxBuffer[15];
particulate03=(int)ucRxBuffer[16] * 256 + (int)ucRxBuffer[17];
particulate05=(int)ucRxBuffer[18] * 256 + (int)ucRxBuffer[19];
particulate10=(int)ucRxBuffer[20] * 256 + (int)ucRxBuffer[21];
particulate25=(int)ucRxBuffer[22] * 256 + (int)ucRxBuffer[23];
particulate50=(int)ucRxBuffer[24] * 256 + (int)ucRxBuffer[25];
particulate100=(int)ucRxBuffer[26] * 256 + (int)ucRxBuffer[27];
HCHO=((int)ucRxBuffer[28] * 256 +(int)ucRxBuffer[29])/1000.000;
Temperature = ((int)ucRxBuffer[30] * 256 +(int)ucRxBuffer[31])/10.000;//包含温度
Humidity = ((int)ucRxBuffer[32] * 256 +(int)ucRxBuffer[33])/10.000;//包含湿度
if (pm_cf_25 > 999)//如果PM2.5数值>1000,返回重新计算
{
ucRxCnt = 0;
return;
}
ucRxCnt = 0;
return;
}
}
void setup() {
Serial.begin(9600);
display.init();
}
void loop() {
while (Serial.available())
{
getG5(Serial.read());
}
Serial.print(" PM_CF1.0:");Serial.print(pm_cf_10);Serial.print(" ug/m3");//硬件串口输出数据
Serial.print(" PM_CF2.5:");Serial.print(pm_cf_25);Serial.print(" ug/m3");
Serial.print(" PM_CF10 :");Serial.print(pm_cf_100);Serial.println(" ug/m3");
Serial.print(" PM_AQI1.0:");Serial.print(pm_at_10);Serial.print(" ug/m3");
Serial.print(" PM_AQI2.5:");Serial.print(pm_at_25);Serial.print(" ug/m3");
Serial.print(" PM_AQI10:");Serial.print(pm_at_100);Serial.println(" ug/m3");
Serial.print(" PM_count03:");Serial.print(particulate03);Serial.print(" pcs/0.01cf");
Serial.print(" PM_count05:");Serial.print(particulate05);Serial.print(" pcs/0.01cf");
Serial.print(" PM_count10:");Serial.print(particulate10);Serial.print(" pcs/0.01cf");
Serial.print(" PM_count25:");Serial.print(particulate25);Serial.print(" pcs/0.01cf");
Serial.print(" PM_count100:");Serial.print(particulate100);Serial.println(" pcs/0.01cf");
Serial.print(" HCHO:");Serial.print(HCHO,3);Serial.println(" mg/m3");
Serial.print(" TS:");Serial.print(Temperature,1);Serial.println(" C"); //包含温度
Serial.print(" HS:");Serial.print(Humidity,1);Serial.println(" %RH"); //包含湿度
Serial.println("*********************************************");
display.clear();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_16);
display.drawString(0, 0, String("At")+pm_at_10 + String(",")+pm_at_25 + String(",")+pm_at_100);
display.display();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_16);
display.drawString(0, 16, String("F:")+HCHO);
display.display();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_16);
display.drawString(0, 32, String(" T:")+Temperature + String(" H:")+Humidity);
display.display();
delay(2000);
}
經過一夜房間的數據與小米清淨機的比較,但不知兩者間有沒有關係?
三.加入上網功能,並將PM2.5相關數據上傳到thingspeak
接線說明:同NodeMCU+G5+OLED顯示器
上網程式請參考02TUNIOT網路應用課程及02-G3+NodeMCU
Thingspeak網站(https://thingspeak.com/),Thingspeak的使用,請參考 01DHT11溫濕度
本例是將大氣環境下的pm1.0、pm2.5、pm10及甲醛、溫濕度的值(共6個field),上傳到Thingspeak去
進入TUNIOT網站:http://easycoding.tn/tuniot/demos/code/
轉為Arduino語言,並修改程式內容
#include <Wire.h>
#include "SSD1306.h"
SSD1306 display(0x3C, 4, 5);
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
WiFiClient client;
String thingSpeakAddress= "http://api.thingspeak.com/update?";
String writeAPIKey;
String tsfield1Name;
String request_string;
HTTPClient http;
static unsigned int pm_cf_10; //定义全局变量
static unsigned int pm_cf_25;
static unsigned int pm_cf_100;
static unsigned int pm_at_10;
static unsigned int pm_at_25;
static unsigned int pm_at_100;
static unsigned int particulate03;
static unsigned int particulate05;
static unsigned int particulate10;
static unsigned int particulate25;
static unsigned int particulate50;
static unsigned int particulate100;
static float HCHO;
static float Temperature;
static float Humidity;
void getG5(unsigned char ucData)//获取G5的值
{
static unsigned int ucRxBuffer[250];
static unsigned int ucRxCnt = 0;
ucRxBuffer[ucRxCnt++] = ucData;
if (ucRxBuffer[0] != 0x42 && ucRxBuffer[1] != 0x4D)//数据头判断
{
ucRxCnt = 0;
return;
}
if (ucRxCnt > 38)//数据位判断//G5S为32,G5ST为38
{
pm_cf_10=(int)ucRxBuffer[4] * 256 + (int)ucRxBuffer[5]; //大气环境下PM2.5浓度计算
pm_cf_25=(int)ucRxBuffer[6] * 256 + (int)ucRxBuffer[7];
pm_cf_100=(int)ucRxBuffer[8] * 256 + (int)ucRxBuffer[9];
pm_at_10=(int)ucRxBuffer[10] * 256 + (int)ucRxBuffer[11];
pm_at_25=(int)ucRxBuffer[12] * 256 + (int)ucRxBuffer[13];
pm_at_100=(int)ucRxBuffer[14] * 256 + (int)ucRxBuffer[15];
particulate03=(int)ucRxBuffer[16] * 256 + (int)ucRxBuffer[17];
particulate05=(int)ucRxBuffer[18] * 256 + (int)ucRxBuffer[19];
particulate10=(int)ucRxBuffer[20] * 256 + (int)ucRxBuffer[21];
particulate25=(int)ucRxBuffer[22] * 256 + (int)ucRxBuffer[23];
particulate50=(int)ucRxBuffer[24] * 256 + (int)ucRxBuffer[25];
particulate100=(int)ucRxBuffer[26] * 256 + (int)ucRxBuffer[27];
HCHO=((int)ucRxBuffer[28] * 256 +(int)ucRxBuffer[29])/1000.000;
Temperature = ((int)ucRxBuffer[30] * 256 +(int)ucRxBuffer[31])/10.000;//包含温度
Humidity = ((int)ucRxBuffer[32] * 256 +(int)ucRxBuffer[33])/10.000;//包含湿度
if (pm_cf_25 > 999)//如果PM2.5数值>1000,返回重新计算
{
ucRxCnt = 0;
return;
}
ucRxCnt = 0;
return;
}
}
void setup() {
Serial.begin(9600);
display.init();
WiFi.disconnect();
delay(3000);
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_16);
display.drawString(0, 0, "START ... Connecting");
display.display();
WiFi.begin("Xiaomi_6F5A","12345678");
delay(10000);
if (!(WiFi.status() == WL_CONNECTED)) {
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_24);
display.drawString(0, 30, "Can\'t connect to wifi ...");
display.display();
} else {
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_16);
display.drawString(0, 16, "I am connected! My IP address is");
display.display();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_16);
// display.drawString(0, 32, (WiFi.localIP()));
display.display();
}
delay(3000);
}
void loop() {
while (Serial.available())
{
getG5(Serial.read());
}
Serial.print(" PM_CF1.0:");Serial.print(pm_cf_10);Serial.print(" ug/m3");//硬件串口输出数据
Serial.print(" PM_CF2.5:");Serial.print(pm_cf_25);Serial.print(" ug/m3");
Serial.print(" PM_CF10 :");Serial.print(pm_cf_100);Serial.println(" ug/m3");
Serial.print(" PM_AQI1.0:");Serial.print(pm_at_10);Serial.print(" ug/m3");
Serial.print(" PM_AQI2.5:");Serial.print(pm_at_25);Serial.print(" ug/m3");
Serial.print(" PM_AQI10:");Serial.print(pm_at_100);Serial.println(" ug/m3");
Serial.print(" PM_count03:");Serial.print(particulate03);Serial.print(" pcs/0.01cf");
Serial.print(" PM_count05:");Serial.print(particulate05);Serial.print(" pcs/0.01cf");
Serial.print(" PM_count10:");Serial.print(particulate10);Serial.print(" pcs/0.01cf");
Serial.print(" PM_count25:");Serial.print(particulate25);Serial.print(" pcs/0.01cf");
Serial.print(" PM_count100:");Serial.print(particulate100);Serial.println(" pcs/0.01cf");
Serial.print(" HCHO:");Serial.print(HCHO,3);Serial.println(" mg/m3");
Serial.print(" TS:");Serial.print(Temperature,1);Serial.println(" C"); //包含温度
Serial.print(" HS:");Serial.print(Humidity,1);Serial.println(" %RH"); //包含湿度
Serial.println("*********************************************");
display.clear();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_16);
display.drawString(0, 0, String("At")+pm_at_10 + String(",")+pm_at_25 + String(",")+pm_at_100);
display.display();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_16);
display.drawString(0, 16, String("F:")+HCHO);
display.display();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_16);
display.drawString(0, 32, String(" T:")+Temperature + String(" H:")+Humidity);
display.display();
if (client.connect("api.thingspeak.com",80)) {
writeAPIKey = "key=DBHMUBZGACL1P8U8";
// tsfield1Name = "&field1=10";
request_string = thingSpeakAddress;
// request_string += "key=";
request_string += writeAPIKey;
request_string += "&";
request_string += "field1";
request_string += "=";
request_string += pm_at_10;
request_string += "&";
request_string += "field2";
request_string += "=";
request_string += pm_at_25;
request_string += "&";
request_string += "field3";
request_string += "=";
request_string += pm_at_100;
request_string += "&";
request_string += "field4";
request_string += "=";
request_string += HCHO;
request_string += "&";
request_string += "field5";
request_string += "=";
request_string += Temperature;
request_string += "&";
request_string += "field6";
request_string += "=";
request_string += Humidity;
http.begin(request_string);
http.GET();
http.end();
delay(5000);
}
}
呈現結果: