ผู้เขียนบทความ : นายศิกวัส สตรอว์ COE#15
คณะวิศวกรรมศาสตร์ : สาขาวิศวกรรมคอมพิวเตอร์
วิชา : โปรแกรมคอมพิวเตอร์ขั้นสูง 1/2566
1.ความเป็นมา
ในปัจจุบันอัตราเพิ่มขึ้นของมลพิษ หมอกควันและฝุ่นละออง ในอากาศมีแนวโน้มเพิ่มสูงขึ้นอย่าง
รวดเร็ว โดยเฉพาะอย่างยิ่ง บริเวณที่มีมนุษย์อาศัยอยู่อย่างหนาแน่น เช่น เขตชุมชนเมือง โรงเรียน เป็นต้น ซึ่ง
หากค่าฝุ่นละอองมีค่าความเข้มข้นเกินกว่าค่า มาตรฐานที่กำหนด อาจส่งผลกระทบต่อสุขภาพของผู้อยู่อาศัย
ทั้งในระยะสั้นและระยะยาว โดยเฉพาะฝุ่นละอองขนาดเล็กไม่เกิน 2.5 ไมครอน (PM 2.5) จะสามารถ
แพร่กระจายเข้าสู่ระบบทางเดินหายใจ กระแสเลือด และแทรกซึมเข้าสู่กระบวนการทำงานของ อวัยวะต่าง ๆ
ของร่างกาย และยังเพิ่มความเสี่ยงเป็นโรคในระบบทางเดินหายใจ หลอดเลือด และอาจก่อให้เกิดโรคมะเร็งได้
2.วัตถุประสงค์
2.1 เพื่อสร้างเครื่องกรองอากาศสำหรับใช้ภายในรถยนต์
2.2 เพื่อสร้างอากาศที่ดีเพื่อลดความเสี่ยงในด้านสุขภาพ
2.3 เพื่อพัฒนาทักษะการเขียนโปรแกรม Arduino IDE
2.4 เพื่อการสร้างอากาศที่ดีในพื้นที่ปิดเพื่อลดปัญหาด้านสุขภาพ
2.5 เพื่อเรียนรู้การใช้อุปกรณ์และเซ็นเซ็นเซอร์ต่างๆ
2.6 เพื่อเรียนรู้การออกแบบวงจรและการสร้างวงจร
3.ขอบเขต
3.1 สามารถกรองอากาศได้
3.3 สามารถวัดค่าได้ตั้งแต่ PM 10 PM2.5 และ PM 1.0
3.4 สามารถแสดงข้อมูลค่าฝุ่นได้ในหน้าจอ OLED
3.5 สามารถแสดงข้อมูลค่าฝุ่นบนเว็บไซต์ NETPIE
3.7 ใช้การจ่ายไฟโดย USB สะดวกกับการใช้งานในรถยนต์
4.ประโยชน์ที่คาดว่าจะได้รับ
4.1 ช่วยลดความเสี่ยงด้านสุขภาพของผู้โดยสาร ช่วยลดความเสี่ยงต่อโรคทางเดินหายใจและโรคระบบหัวใจจาก
มลพิษในอากาศ.
4.2 พัฒนาทักษะการเรียนรู้เรียนรู้เกี่ยวกับโปรแกรม Arduino IDE และวงจรอิเล็กทรอนิกส์.
4.3 สร้างอากาศที่ดีนำไปใช้ในรถยนต์หรือพื้นที่ปิดเพื่อสร้างอากาศสะอาด.
4.4 เรียนรู้การใช้อุปกรณ์และเซ็นเซอร์ศึกษาการใช้งานเซ็นเซอร์และอุปกรณ์อิเล็กทรอนิกส์.
5.ความรู้ที่เกี่ยวข้อง
5.1 NETPIE
คือ เว็บไซต์ที่สร้างมาเพื่อรองรับของมูลจากของอุปกรณ์ IOT โดยใช้ Protocal MQTT วิธีใช้งานขั้นแรกให้สมัคร accont ของ NETPIE ที่เว็บไซต์ที่คำว่า Sign up ด้านขวาบน
หลังจากนั้นเมื่อทำการ Login เสร็จแล้วให้ทำการกดที่คำว่า + Create ที่ด้านขวาบนของเว็บไซต์ หลังจากนั้นให้ตั้งชื่อและใส่คำอธิบายได้ตามใจชอบ และกด save
เมื่อเข้ามาแล้วให้ทำการกดที่คำว่า device ด้านซ้ายและกด create ที่ด้านขวาบน การตั้งชื่อนั้นควรตั้งตามสิ่งที่เราจะรับเข้ามา อย่างเช่นอุปกรณ์ของผมใช้เซ็นเซอร์วัดค่าฝุ่นผมเลยตั้งชื่ออุปกรณ์ว่า DustSensor และกด save
เมื่อเราได้ Device แล้ว ให้เรานำตัว token ต่างๆไปใช้ในโปรแกรมได้เลย และหลังจากนี้ส่วนใหญ่จะขึ้นอยู่กับฝั่งโค้ดที่เขียนแล้วว่าจะ publish ออกมาอย่างไรซึ่งรูปแบบที่ผมใช้คือเอามาจากตัว netpie เอง โดยจะเขียนในรูปแบบนี้โดยสามารถเขียนแบบนี้ได้เลยเพียงแค่นำตัวแปรมาให้แก้ไข
String data = "{\"data\": {\"PM1.0\":" + String(pm_data.PM_AE_UG_1_0) +
",\"PM2.5\":" + String(pm_data.PM_AE_UG_2_5) +
",\"PM10\":" + String(pm_data.PM_AE_UG_10_0) + "}}";
Serial.println(data);
data.toCharArray(msg, (data.length() + 1));
client.publish("@shadow/data/update", msg);
หลังจากนั้นค่าต่างๆที่ได้มาให้นำไปเขียนใน schema ในรูปแบบนี้เพื่อที่จะให้ข้อมูลสามารถนำไปขึ้นบนหน้า FreeBoard ได้
{
"additionalProperties": false,
"properties": {
"PM1.0": {
"operation": {
"store": {
"ttl": "7d"
}
},
"type": "number"
},
"PM2.5": {
"operation": {
"store": {
"ttl": "7d"
}
},
"type": "number"
},
"PM10": {
"operation": {
"store": {
"ttl": "7d"
}
},
"type": "number"
}
}
}
หลังจากนั้นให้ทำการ Create FreeBoard ขึ้นมาโดยที่เข้าไปยัง Menu Console –> Freeborad และกด Create ตั้งชื่ออะไรก็ได้โดยที่ผมตั้ง PMvalue หลังจากนั้นให้กด save และเข้าไปยังหน้า Freeboard
เมื่อเข้ามายัง FreeBoard แล้วให้กดปุ่ม ADD ใน DATASOURCE และใส่ข้อมูลจาก Device
หลังจากนั้นให้กดที่คำว่า ADD PANE ทางด้านซ้ายและเลือกรูปแบบตามต้องการโดยที่ผมใช้รูปแบบ Gauge และใส่ขอมูลจาก Data sorce ดังนี้ และกด save ทำให้ครบทุกค่าที่มีและจัดรูปแบบตามที่ต้องการได้เลย
5.2 อุปกรณ์และวงจร ของระบบเครื่องกรองอากาศ
ประกอบด้วย ESP32 ,พัดลม12v ,เซ็นเซอร์ PMS5003 , จอ OLED SSD1306 0.96 นิ้ว ,LM2596 stepdown 12v to 5v ,หัวแปลง USB 5v to DC jack 5.5mm x 2.1mm 12v ,dc jack 5.5mm x 2.1mm ตัวเมีย และ RELAY 5v
5.3 โค้ดการทำงาน
ทำการเพิ่ม libary ต่างๆเข้ามา
#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <PMS.h>
ซึ่งมี libary สำคัญของตัว PMS5003 คือตัว libary PMS.h โดยจะมีวิธีใช้ให้เรียกการใช้งานเป็นเงื่อนไขในการเรียกถ้ามีการอ่านให้ทำการ … ซึ่งผมเมื่อมีการอ่านค่าเกิดขึ้นให้ทำการส่งค่าต่างๆและนำค่าต่างๆมาใช้ดังโด้ดด้านล่าง
if (pms.read(pm_data)) {
updatePMData();
โดยเรียกฟังก์ชั่นนี้ซึ่งเป็นฟังก์ชั่นที่ผมสร้างมาเองโดยแค่ให้อัปเดตค่าที่ให้มาได้เลย โดยที่ปกติแล้วไม่จำเป็นต้องทำเป็นฟังก์ชั่นสามารถเรียกตรงๆได้ตามความสะดวกในการใช้งาน
void updatePMData() {
Serial.print("PM1.0: ");
Serial.print(pm_data.PM_AE_UG_1_0);
Serial.print(" ug/m³, PM2.5: ");
Serial.print(pm_data.PM_AE_UG_2_5);
Serial.print(" ug/m³, PM10: ");
Serial.print(pm_data.PM_AE_UG_10_0);
Serial.println(" ug/m³");
}
ประกาศขาของอุปกรณ์ทุกตัวที่ใช้
#define OLED_I2C_ADDRESS 0x3C
#define SDA_PIN 21
#define SCL_PIN 22
#define RELAY_PIN 27
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
ตั้งค่าต่างๆของ WIFI และ NETPIE
const char* ssid = "Humyaitoo";
const char* password = "miracle3";
const char* mqtt_server = "mqtt.netpie.io";
const int mqtt_port = 1883;
const char* mqtt_client = "a0989e0c-5a5d-48be-b9a4-b5d133bd1eef";
const char* mqtt_username = "puZqNo1gSB46Hpu2QGAb78X1RpWrJ349";
const char* mqtt_password = "XkgngvLgdnfaJUDopyPVrfVybbaktekL";
ทำการสร้าง CLASS และเริ่มการทำงานโดยจากใน Code นั้นจะทำการเชื่อมต่อ WIFI จนกว่าจะเข้าได้โดยที่แสดงข้อมูลทั้งในหน้าจอและบน Serial monitor โดยใช้ชื่อฟังก์ชั่นว่า begin เพื่อที่จะนำไปเรียกใน Setup ตอนหลัง
class PMDisplay {
public:
PMDisplay() : display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire), client(espClient) {}
void begin() {
if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_I2C_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.display();
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
display.setCursor(10, 10);
display.print("Initializing....");
display.display();
Serial.begin(115200);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
display.setCursor(20, 20);
display.print("WiFi connected..!");
display.setTextSize(1);
display.setCursor(20, 40);
display.print(WiFi.localIP());
display.display();
delay(4000);
client.setServer(mqtt_server, mqtt_port);
Serial2.begin(9600);
delay(4000);
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, LOW);
}
โดยต่อมาจะมีฟังก์ชั่นการวนลูปซึ่งเป็นการอ่านค่าจากตัว PMS5003 sensor เพื่อนำค่าฝุ่นมาแสดงโดยสร้างฟังก์ชั่นโดยใน CODE จะมี code ที่เป็น Setup การใช้งานจาก netpie ตามที่กล่าวไปในหัวข้อ 5.1 และยังใช้ฟังก์ชั่นจากตัว libary ของ PMS โดยที่เขียนดังนี้ if (pms.read(pm_data))
void repeat() {
if (pms.read(pm_data)) {
updatePMData();
String data = "{\"data\": {\"PM1.0\":" + String(pm_data.PM_AE_UG_1_0) +
",\"PM2.5\":" + String(pm_data.PM_AE_UG_2_5) +
",\"PM10\":" + String(pm_data.PM_AE_UG_10_0) + "}}";
Serial.println(data);
data.toCharArray(msg, (data.length() + 1));
client.publish("@shadow/data/update", msg);
updateDisplay();
delay(1000);
}
if (pm_data.PM_AE_UG_1_0 > 50 || pm_data.PM_AE_UG_2_5 > 50 || pm_data.PM_AE_UG_10_0 > 50) {
digitalWrite(RELAY_PIN, HIGH);
} else {
digitalWrite(RELAY_PIN, LOW);
}
if (!client.connected()) {
reconnect();
}
client.loop();
}
โดยในฟังก์ชั่นข้างต้นนั้นได้ทำการเรียกฟังก์ชั่นย่อยอีก 2 ตัวซึ่งเป็นการเรียกเพื่อการอัปเดตข้อมูลของค่าฝุ่น PM จาก Sensor PMS โดยเงื่อนไขว่าถ้าเกิดการอ่านค่าจากเซ็นเซอร์ PMS ให้ทำการแสดงข้อมูลฝุ่นลงหน้าจอ OLED(1) และ Serial monitor(2)
void updateDisplay() {
display.clearDisplay();
display.setCursor(10, 10);
display.print("PM1.0: ");
display.print(pm_data.PM_AE_UG_1_0);
display.print(" ug/m³");
display.setCursor(10, 30);
display.print("PM2.5: ");
display.print(pm_data.PM_AE_UG_2_5);
display.print(" ug/m³");
display.setCursor(10, 50);
display.print("PM10: ");
display.print(pm_data.PM_AE_UG_10_0);
display.print(" ug/m³");
display.display();
}
void updatePMData() {
Serial.print("PM1.0: ");
Serial.print(pm_data.PM_AE_UG_1_0);
Serial.print(" ug/m³, PM2.5: ");
Serial.print(pm_data.PM_AE_UG_2_5);
Serial.print(" ug/m³, PM10: ");
Serial.print(pm_data.PM_AE_UG_10_0);
Serial.println(" ug/m³");
}
และยังได้สร้างเงื่อนไขไว้ด้านล่างอีกด้วย เมื่อค่าฝุ่นที่อ่านได้นั้น อย่างใดอย่างหนึ่งเกิน 50 หน่วยให้ทำการเปิดลีเลย์ ซึ่งจะส่งผลให้พัดลมหมุนเพื่อกรองอากาศ
if (pm_data.PM_AE_UG_1_0 > 50 || pm_data.PM_AE_UG_2_5 > 50 || pm_data.PM_AE_UG_10_0 > 50) {
digitalWrite(RELAY_PIN, HIGH);
} else {
digitalWrite(RELAY_PIN, LOW);
}
และยังมีเงื่อนไขการเข้าสู่ระบบของ MQTT เมื่อเกิดการหลุดให้ทำการเข้าสู่ระบบอีกครั้งโดยการเรียกฟังก์ชั่น
if (!client.connected()) {
reconnect();
}
void reconnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
if (client.connect(mqtt_client, mqtt_username, mqtt_password)) {
Serial.println("connected");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
switch (client.state()) {
case -4:
Serial.println("MQTT_CONNECTION_TIMEOUT");
break;
case -3:
Serial.println("MQTT_CONNECTION_LOST");
break;
case -2:
Serial.println("MQTT_CONNECT_FAILED");
break;
case -1:
Serial.println("MQTT_DISCONNECTED");
break;
default:
Serial.println("MQTT_UNKNOWN_ERROR");
break;
}
Serial.println("Retrying in 5 seconds...");
delay(5000);
}
}
}
หลังจาก Setup ทั้งหมดขึ้นมาแล้วให้ทำการเรียกตัวฟังก์ชั่นจาก Class โดยที่เขียนดังนี้
PMDisplay pmDisplay;
void setup() {
pmDisplay.begin();
}
void loop() {
pmDisplay.repeat();
}
(โค้ดเต็มของระบบเครื่องกรองอากาศ)
#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <PMS.h>
#define OLED_I2C_ADDRESS 0x3C
#define SDA_PIN 21
#define SCL_PIN 22
#define RELAY_PIN 27
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
const char* ssid = "Humyaitoo";
const char* password = "miracle3";
const char* mqtt_server = "mqtt.netpie.io";
const int mqtt_port = 1883;
const char* mqtt_client = "a0989e0c-5a5d-48be-b9a4-b5d133bd1eef";
const char* mqtt_username = "puZqNo1gSB46Hpu2QGAb78X1RpWrJ349";
const char* mqtt_password = "XkgngvLgdnfaJUDopyPVrfVybbaktekL";
class PMDisplay {
public:
PMDisplay() : display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire), client(espClient) {}
void begin() {
if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_I2C_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.display();
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
display.setCursor(10, 10);
display.print("Initializing....");
display.display();
Serial.begin(115200);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
display.setCursor(20, 20);
display.print("WiFi connected..!");
display.setTextSize(1);
display.setCursor(20, 40);
display.print(WiFi.localIP());
display.display();
delay(4000);
client.setServer(mqtt_server, mqtt_port);
Serial2.begin(9600);
delay(4000);
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, LOW);
}
void repeat() {
if (pms.read(pm_data)) {
updatePMData();
String data = "{\"data\": {\"PM1.0\":" + String(pm_data.PM_AE_UG_1_0) +
",\"PM2.5\":" + String(pm_data.PM_AE_UG_2_5) +
",\"PM10\":" + String(pm_data.PM_AE_UG_10_0) + "}}";
Serial.println(data);
data.toCharArray(msg, (data.length() + 1));
client.publish("@shadow/data/update", msg);
updateDisplay();
delay(1000);
}
if (pm_data.PM_AE_UG_1_0 > 50 || pm_data.PM_AE_UG_2_5 > 50 || pm_data.PM_AE_UG_10_0 > 50) {
digitalWrite(RELAY_PIN, HIGH);
} else {
digitalWrite(RELAY_PIN, LOW);
}
if (!client.connected()) {
reconnect();
}
client.loop();
}
private:
Adafruit_SSD1306 display;
WiFiClient espClient;
PubSubClient client;
PMS pms{Serial2};
PMS::DATA pm_data;
char msg[100];
void reconnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
if (client.connect(mqtt_client, mqtt_username, mqtt_password)) {
Serial.println("connected");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
switch (client.state()) {
case -4:
Serial.println("MQTT_CONNECTION_TIMEOUT");
break;
case -3:
Serial.println("MQTT_CONNECTION_LOST");
break;
case -2:
Serial.println("MQTT_CONNECT_FAILED");
break;
case -1:
Serial.println("MQTT_DISCONNECTED");
break;
default:
Serial.println("MQTT_UNKNOWN_ERROR");
break;
}
Serial.println("Retrying in 5 seconds...");
delay(5000);
}
}
}
void updatePMData() {
Serial.print("PM1.0: ");
Serial.print(pm_data.PM_AE_UG_1_0);
Serial.print(" ug/m³, PM2.5: ");
Serial.print(pm_data.PM_AE_UG_2_5);
Serial.print(" ug/m³, PM10: ");
Serial.print(pm_data.PM_AE_UG_10_0);
Serial.println(" ug/m³");
}
void updateDisplay() {
display.clearDisplay();
display.setCursor(10, 10);
display.print("PM1.0: ");
display.print(pm_data.PM_AE_UG_1_0);
display.print(" ug/m³");
display.setCursor(10, 30);
display.print("PM2.5: ");
display.print(pm_data.PM_AE_UG_2_5);
display.print(" ug/m³");
display.setCursor(10, 50);
display.print("PM10: ");
display.print(pm_data.PM_AE_UG_10_0);
display.print(" ug/m³");
display.display();
}
};
PMDisplay pmDisplay;
void setup() {
pmDisplay.begin();
}
void loop() {
pmDisplay.repeat();
}
6.ผลการดำเนินงาน
ผังการทำงานของระบบ
วิธีการใช้งานอุปกรณ์ เมื่อเสียบสายไฟแล้วอุปกรณ์จะขึ้น Initializing…. บนหน้าจอ OLED ให้ทำการเปิด Wifi เพื่อเข้าสู่ระบบ
เมื่อเชื่อมต่อ WIFI ได้แล้วจะขึ้นคำว่า WiFi connected..! และแสดงที่อยู่ IP
หลังจากนั้นจะเข้าสู่ Loop หลักคือการทำงานระบบจะทำการแสดงค่าของฝุ่นไปยัง NETPIE และ หน้าจอ OLED
เมื่อค่าฝุ่นเกินค่าที่กำหนดไว้ (50) ให้ทำการเปิดพัดลมเพื่อกรองอากาศ ****(เมื่อต้องการกรองอากาศจำเป็นต้องใส่ Filter ไว้ด้านฝั่งลมเข้าของตัวพัดลมซึ่งจะขึ้นอยู่กับ spec ของตัว Filter ว่าเอาไว้กรองอะไร)
การทดลอง
การทดลองที่ 1 การทดสอบเมื่อค่าฝุ่นมีการเปลี่ยนแปลงเกินกำหนดพัดลมจะติดกี่ครั้ง โดยจะใช้แป้งในการทดสอบเป็นตัวทดแทนฝุ่นเพื่อให้ได้มาซึ่งผลการทำงาน
การบันทึกผลการทดสอบการใช้งาน ผลที่ได้คือ ความถูกต้องของระบบอัตโนมัติ คือร้อยละ 100
การทดลองที่ 2 ทดสอบความล่าช้าในการอ่านค่าและการเปิดพัดลม เป็นการทดสอบโดยใช้วิธีเดียวกับข้อแรกทุกอย่างแต่แทนที่จะนับว่าพัดลมติดหรือเปล่าให้นับความล่าช้าในการอ่านข้อมูลว่าเกิน 10 วินาทีหรือไม่ เมื่อเกินจะนับว่าไม่สำเร็จเมื่อไม่เกินจะนับว่าสำเร็จ
การบันทึกผลการทดสอบพบว่าส่วนใหญ่นั้นจะอ่านได้ภายใน 6-7 วินาทีซึ่งทำให้ไม่มีครั้งไหนเลยที่เกินเวลาที่ตั้งใจไว้คือ 10 วินาทีทำให้สรุปได้ว่าความเร็วในการอ่านนั้นจากการทดลอง 20 ครั้ง ไม่เคยเกิน 10 วินาทีเลย ซึ่งทำให้คิดเป็นร้อยละ 100
7.สรุปผลและข้อเสนอแนะ
7.1 สรุปผล
จากผลการทดสอบระบบเครื่องกรองอากาศสามารถทำงานได้อย่างมีประสิทธิภาพตรงตามเงื่อนไข ตามที่ได้ทดสอบ ได้แก่
1) การตอบโต้ต่อค่าฝุ่นที่สูงเกินค่าที่กำหนดได้อย่างถูกต้อง
2) สามารถเปิดพัดลมได้ตลอดไม่มีข้อผิดเพี้ยน
7.2 ข้อเสนอแนะ
1.สามารถใช้ในสถานที่นอกจากรถยนต์ได้แต่ต้องเป็นสถานที่ที่มีขนาดเล็กและเป็นที่ปิด
2.สามารถกรองได้หลายอย่างขึ้นอยู่กับตัว Filter ที่ใช้
8.อ้างอิง
1.กองการจัดการคุณภาพอากาศและเสียง กรมควบคุมมลพิษ. ดัชนีคุณภาพ อากาศ (Air Quality Index : AQI) [ออนไลน์] 2566. [สืบค้นวันที่ 15 ตุลาคม 2566]. จาก http://air4thai.pcd.go.th/webV2/aqi_info.php
2.NETPIE. คู่มือการใช้งาน NETPIE [ออนไลน์] 2563. [สืบค้นวันที่ 10 ตุลาคม2566]. จาก https://docs.netpie.io/
3.CyberTice. สอนใช้งาน Arduino PM2.5 เซ็นเซอร์ตรวจจับฝุ่นละออง วัดคุณภาพอากาศ Laser Dust Sensor PMS5003. [ออนไลน์] 2563. [สืบค้นวันที่ 10 ตุลาคม 2566]. จาก https://bit.ly/3SkarAl
4.CyberTice. การใช้งานจอแสดงผล OLED SSD1306 [ออนไลน์] 2563. [สืบค้นวันที่ 10 ตุลาคม 2566]. จาก https://bit.ly/46STBNp