โปรเจกต์ปานกลาง15 นาที

DIY Air Quality Monitor ด้วย ESP32: ตรวจจับ PM2.5, CO2 และอุณหภูมิ

สร้างเครื่องวัดคุณภาพอากาศ DIY ด้วย ESP32 ตรวจจับฝุ่น PM2.5, ก๊าซ CO2, อุณหภูมิ และความชื้น พร้อมเชื่อมต่อ Home Assistant และแจ้งเตือนอัตโนมัติ

Cyno IoT Team
14 มีนาคม 2569
DIY Air Quality Monitor with ESP32

ทำไมต้องสร้าง Air Quality Monitor เอง?

💡 ประโยชน์ของ Air Quality Monitor

  • ตรวจสอบคุณภาพอากาศในบ้าน - รู้ว่าอากาศที่หายใจเป็นอย่างไร
  • เตือนภัยล่วงหน้า - ได้รับการแจ้งเตือนเมื่ออากาศแย่ลง
  • ติดตามแนวโน้ม - เห็นการเปลี่ยนแปลงของคุณภาพอากาศตลอดเวลา
  • ประหยัดค่าใช้จ่าย - ถูกกว่าซื้อเครื่องวัดสำเร็จรูป
  • ปรับแต่งได้ - เพิ่มเซ็นเซอร์หรือฟีเจอร์ได้ตามต้องการ

โปรเจกต์นี้ได้รับแรงบันดาลใจจาก Project Aura ซึ่งเป็น DIY air quality monitor ที่นิยมในชุมชน IoT เราจะสร้างเวอร์ชันที่:

  • ตรวจจับ PM2.5 (ฝุ่นละอองขนาดเล็ก)
  • วัด ก๊าซ CO2 (คาร์บอนไดออกไซด์)
  • ติดตาม อุณหภูมิและความชื้น
  • เชื่อมต่อกับ Home Assistant สำหรับ automation
  • มี หน้าจอแสดงผล และ แจ้งเตือน อัตโนมัติ

⚠️ คำเตือน: เครื่องวัด DIY นี้เหมาะสำหรับการใช้งานส่วนบุคคลและการศึกษาเท่านั้น หากต้องการความแม่นยำระดับมืออาชีพ ควรใช้เครื่องวัดที่ได้รับการรับรองมาตรฐาน

อุปกรณ์ที่ต้องใช้

🎯 Core Components

  • ESP32 Development Board

    แนะนำ ESP32-WROOM-32 หรือ ESP32-S3

  • Plantower PMS5003

    เซ็นเซอร์ฝุ่น PM2.5/PM10 (Laser Particle Sensor)

  • SCD41 or SCD30

    เซ็นเซอร์ CO2 (Sensirion)

  • BME280 or DHT22

    เซ็นเซอร์อุณหภูมิและความชื้น

⚡ Power & Display

  • OLED Display 0.96" 128x64

    แสดงผลข้อมูล (I2C)

  • USB-C Power Adapter

    จ่ายไฟ 5V 2A ขึ้นไป

  • Jumper Wires & Breadboard

    สำหรับต่อวงจร

  • 3D Printed Case (optional)

    บรรจุอุปกรณ์

💰 ราคาโดยประมาณ

  • ESP32: ~150-200 บาท
  • PMS5003: ~350-500 บาท
  • SCD41: ~800-1,200 บาท (หรือ SCD30 ~1,500-2,000 บาท)
  • BME280: ~150-250 บาท
  • OLED Display: ~100-150 บาท
  • รวมทั้งหมด: ~1,550-2,300 บาท

การเชื่อมต่อวงจร

ต่อไปนี้คือการเชื่อมต่อระหว่างเซ็นเซอร์กับ ESP32:

// ==================== การเชื่อมต่อเซ็นเซอร์ ====================

// ===== PMS5003 (PM2.5 Sensor) =====
// PMS5003          ESP32
// VCC      →       5V
// GND      →       GND
// TX       →       GPIO16 (RX2)
// RX       →       GPIO17 (TX2)

// ===== SCD41 (CO2 Sensor) =====
// SCD41            ESP32
// VCC      →       3.3V
// GND      →       GND
// SDA      →       GPIO21 (I2C SDA)
// SCL      →       GPIO22 (I2C SCL)

// ===== BME280 (Temp & Humidity) =====
// BME280           ESP32
// VCC      →       3.3V
// GND      →       GND
// SDA      →       GPIO21 (I2C SDA)
// SCL      →       GPIO22 (I2C SCL)

// ===== OLED Display =====
// OLED             ESP32
// VCC      →       3.3V
// GND      →       GND
// SDA      →       GPIO21 (I2C SDA)
// SCL      →       GPIO22 (I2C SCL)

💡 Tip: เซ็นเซอร์ SCD41 และ BME280 ใช้ I2C bus เดียวกันได้ เพราะมี address ต่างกัน

โค้ด Arduino/PlatformIO

platformio.ini

; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino

; Serial Monitor options
monitor_speed = 115200

; Library dependencies
lib_deps = 
    adafruit/Adafruit BME280 Library @ ^2.2.2
    adafruit/Adafruit Unified Sensor @ ^1.1.9
    sparkfun/SparkFun SCD4x Arduino Library @ ^1.0.11
    adafruit/Adafruit SSD1306 @ ^2.5.7
    adafruit/Adafruit GFX Library @ ^1.11.3
    bblanchon/ArduinoJson @ ^6.21.3

; Upload settings
upload_speed = 921600

main.cpp

/**
 * DIY Air Quality Monitor ด้วย ESP32
 * ตรวจจับ PM2.5, CO2, อุณหภูมิ และความชื้น
 * เชื่อมต่อ Home Assistant ผ่าน MQTT
 * 
 * Hardware:
 * - ESP32 Development Board
 * - PMS5003 (PM2.5 Sensor)
 * - SCD41 (CO2 Sensor)
 * - BME280 (Temp & Humidity)
 * - OLED Display 0.96"
 */

#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <Adafruit_BME280.h>
#include <Adafruit_SSD1306.h>
#include <SparkFun_SCD4x_Arduino_Library.h>
#include <ArduinoJson.h>

// ==================== การตั้งค่า WiFi ====================
const char* WIFI_SSID = "YOUR_WIFI_SSID";
const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";

// ==================== การตั้งค่า MQTT (Home Assistant) ====================
const char* MQTT_BROKER = "homeassistant.local";  // หรือใช้ IP
const int MQTT_PORT = 1883;
const char* MQTT_USER = "homeassistant";          // ถ้ามี
const char* MQTT_PASSWORD = "your_password";      // ถ้ามี

// MQTT Topics
const char* MQTT_TOPIC_PM25 = "home/airquality/pm25";
const char* MQTT_TOPIC_PM10 = "home/airquality/pm10";
const char* MQTT_TOPIC_CO2 = "home/airquality/co2";
const char* MQTT_TOPIC_TEMP = "home/airquality/temperature";
const char* MQTT_TOPIC_HUMIDITY = "home/airquality/humidity";
const char* MQTT_TOPIC_AQI = "home/airquality/aqi";

// ==================== การตั้งค่าเซ็นเซอร์ ====================
#define PMS_RX_PIN 16
#define PMS_TX_PIN 17
#define OLED_WIDTH 128
#define OLED_HEIGHT 64
#define OLED_RESET -1

// ==================== การตั้งค่าการแจ้งเตือน ====================
#define PM25_WARNING_THRESHOLD 50    // µg/m³
#define PM25_DANGER_THRESHOLD 100    // µg/m³
#define CO2_WARNING_THRESHOLD 1000   // ppm
#define CO2_DANGER_THRESHOLD 2000    // ppm

// ==================== Global Objects ====================
WiFiClient espClient;
PubSubClient mqttClient(espClient);
Adafruit_BME280 bme;
SCD4x scd4x;
Adafruit_SSD1306 display(OLED_WIDTH, OLED_HEIGHT, &Wire, OLED_RESET);

// ==================== Data Structures ====================
struct SensorData {
  float pm25;        // PM2.5 (µg/m³)
  float pm10;        // PM10 (µg/m³)
  float co2;         // CO2 (ppm)
  float temperature; // อุณหภูมิ (°C)
  float humidity;    // ความชื้น (%)
  int aqi;           // Air Quality Index
  String status;     // สถานะคุณภาพอากาศ
};

SensorData currentData;
unsigned long lastSensorRead = 0;
const unsigned long SENSOR_READ_INTERVAL = 2000;  // 2 วินาที

// ==================== WiFi Functions ====================
void connectWiFi() {
  Serial.println("🔌 กำลังเชื่อมต่อ WiFi...");
  
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  
  int attempts = 0;
  while (WiFi.status() != WL_CONNECTED && attempts < 20) {
    delay(500);
    Serial.print(".");
    attempts++;
  }
  
  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("\n✅ เชื่อมต่อ WiFi สำเร็จ!");
    Serial.print("📡 IP: ");
    Serial.println(WiFi.localIP());
  } else {
    Serial.println("\n❌ ไม่สามารถเชื่อมต่อ WiFi ได้");
  }
}

// ==================== MQTT Functions ====================
void connectMQTT() {
  while (!mqttClient.connected()) {
    Serial.print("🔗 กำลังเชื่อมต่อ MQTT...");
    
    if (mqttClient.connect("ESP32_AirQuality", MQTT_USER, MQTT_PASSWORD)) {
      Serial.println("✅ เชื่อมต่อสำเร็จ!");
    } else {
      Serial.print("❌ ล้มเหลว (");
      Serial.print(mqttClient.state());
      Serial.println(")");
      delay(5000);
    }
  }
}

void publishMQTTData() {
  // สร้าง JSON payload
  StaticJsonDocument<256> doc;
  doc["pm25"] = currentData.pm25;
  doc["pm10"] = currentData.pm10;
  doc["co2"] = currentData.co2;
  doc["temperature"] = currentData.temperature;
  doc["humidity"] = currentData.humidity;
  doc["aqi"] = currentData.aqi;
  doc["status"] = currentData.status;
  
  String payload;
  serializeJson(doc, payload);
  
  // ส่งข้อมูลแต่ละตัว
  mqttClient.publish(MQTT_TOPIC_PM25, String(currentData.pm25).c_str());
  mqttClient.publish(MQTT_TOPIC_PM10, String(currentData.pm10).c_str());
  mqttClient.publish(MQTT_TOPIC_CO2, String(currentData.co2).c_str());
  mqttClient.publish(MQTT_TOPIC_TEMP, String(currentData.temperature).c_str());
  mqttClient.publish(MQTT_TOPIC_HUMIDITY, String(currentData.humidity).c_str());
  mqttClient.publish(MQTT_TOPIC_AQI, String(currentData.aqi).c_str());
  
  Serial.println("📤 ส่งข้อมูล MQTT แล้ว");
}

// ==================== Sensor Functions ====================
void initSensors() {
  Serial.println("🔧 กำลังเริ่มต้นเซ็นเซอร์...");
  
  // เริ่มต้น BME280
  if (!bme.begin(0x76)) {
    Serial.println("❌ ไม่พบ BME280!");
  } else {
    Serial.println("✅ BME280 พร้อมใช้งาน");
  }
  
  // เริ่มต้น SCD41
  Wire.begin();
  if (scd4x.begin() == false) {
    Serial.println("❌ ไม่พบ SCD41!");
  } else {
    Serial.println("✅ SCD41 พร้อมใช้งาน");
    scd4x.startPeriodicMeasurement();
  }
  
  // เริ่มต้น PMS5003
  Serial2.begin(9600, SERIAL_8N1, PMS_RX_PIN, PMS_TX_PIN);
  Serial.println("✅ PMS5003 พร้อมใช้งาน");
  
  // เริ่มต้น OLED
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println("❌ ไม่พบ OLED display!");
  } else {
    Serial.println("✅ OLED display พร้อมใช้งาน");
  }
}

void readSensors() {
  // อ่าน PMS5003
  if (Serial2.available()) {
    // PMS5003 data format: 32 bytes
    // ตำแหน่ง bytes: 4-5 (PM1.0), 6-7 (PM2.5), 8-9 (PM10)
    uint8_t buffer[32];
    if (Serial2.readBytes(buffer, 32) == 32) {
      if (buffer[0] == 0x42 && buffer[1] == 0x4d) {
        currentData.pm25 = (buffer[12] << 8) | buffer[13];
        currentData.pm10 = (buffer[14] << 8) | buffer[15];
      }
    }
  }
  
  // อ่าน SCD41 (CO2)
  if (scd4x.readMeasurement()) {
    currentData.co2 = scd4x.getCO2();
  }
  
  // อ่าน BME280 (อุณหภูมิและความชื้น)
  currentData.temperature = bme.readTemperature();
  currentData.humidity = bme.readHumidity();
  
  // คำนวณ AQI (Air Quality Index)
  calculateAQI();
}

void calculateAQI() {
  // ใช้ PM2.5 เป็นตัวคำนวณหลัก
  float pm25 = currentData.pm25;
  
  if (pm25 <= 12.0) {
    currentData.aqi = map(pm25, 0, 12, 0, 50);
    currentData.status = "ดีมาก";
  } else if (pm25 <= 35.4) {
    currentData.aqi = map(pm25, 12.1, 35.4, 51, 100);
    currentData.status = "ดี";
  } else if (pm25 <= 55.4) {
    currentData.aqi = map(pm25, 35.5, 55.4, 101, 150);
    currentData.status = "ปานกลาง";
  } else if (pm25 <= 150.4) {
    currentData.aqi = map(pm25, 55.5, 150.4, 151, 200);
    currentData.status = "ไม่ดีสำหรับกลุ่มเสี่ยง";
  } else if (pm25 <= 250.4) {
    currentData.aqi = map(pm25, 150.5, 250.4, 201, 300);
    currentData.status = "ไม่ดี";
  } else {
    currentData.aqi = map(pm25, 250.5, 500.4, 301, 500);
    currentData.status = "อันตราย";
  }
}

// ==================== Display Functions ====================
void updateDisplay() {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  
  // หัวข้อ
  display.setCursor(0, 0);
  display.println("Air Quality Monitor");
  
  // AQI และสถานะ
  display.setCursor(0, 16);
  display.setTextSize(2);
  display.print("AQI: ");
  display.println(currentData.aqi);
  
  display.setTextSize(1);
  display.setCursor(0, 36);
  display.println(currentData.status);
  
  // ข้อมูลอื่นๆ
  display.setCursor(0, 48);
  display.print("PM2.5: ");
  display.print(currentData.pm25, 1);
  display.print(" CO2: ");
  display.print(currentData.co2, 0);
  
  display.display();
}

// ==================== Alert Functions ====================
void checkAlerts() {
  // ตรวจสอบ PM2.5
  if (currentData.pm25 > PM25_DANGER_THRESHOLD) {
    sendAlert("PM2.5 อันตราย!", currentData.pm25);
  } else if (currentData.pm25 > PM25_WARNING_THRESHOLD) {
    sendAlert("PM2.5 สูงกว่าปกติ", currentData.pm25);
  }
  
  // ตรวจสอบ CO2
  if (currentData.co2 > CO2_DANGER_THRESHOLD) {
    sendAlert("CO2 อันตราย!", currentData.co2);
  } else if (currentData.co2 > CO2_WARNING_THRESHOLD) {
    sendAlert("CO2 สูงกว่าปกติ", currentData.co2);
  }
}

void sendAlert(String message, float value) {
  Serial.println("⚠️ แจ้งเตือน: " + message + " (" + String(value) + ")");
  
  // ส่ง alert ผ่าน MQTT
  StaticJsonDocument<128> doc;
  doc["alert"] = message;
  doc["value"] = value;
  doc["timestamp"] = millis();
  
  String payload;
  serializeJson(doc, payload);
  
  mqttClient.publish("home/airquality/alert", payload.c_str());
}

// ==================== Setup & Loop ====================
void setup() {
  Serial.begin(115200);
  Serial.println("🚀 เริ่มต้น Air Quality Monitor...");
  
  // เชื่อมต่อ WiFi
  connectWiFi();
  
  // เริ่มต้นเซ็นเซอร์
  initSensors();
  
  // ตั้งค่า MQTT
  mqttClient.setServer(MQTT_BROKER, MQTT_PORT);
  
  // แสดงข้อความเริ่มต้นบนหน้าจอ
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("Air Quality");
  display.println("Monitor");
  display.println("Starting...");
  display.display();
  
  delay(2000);
}

void loop() {
  // ตรวจสอบการเชื่อมต่อ
  if (WiFi.status() != WL_CONNECTED) {
    connectWiFi();
  }
  
  if (!mqttClient.connected()) {
    connectMQTT();
  }
  mqttClient.loop();
  
  // อ่านเซ็นเซอร์ทุก 2 วินาที
  unsigned long currentMillis = millis();
  if (currentMillis - lastSensorRead >= SENSOR_READ_INTERVAL) {
    lastSensorRead = currentMillis;
    
    // อ่านข้อมูลเซ็นเซอร์
    readSensors();
    
    // อัปเดตหน้าจอ
    updateDisplay();
    
    // ส่งข้อมูลผ่าน MQTT
    publishMQTTData();
    
    // ตรวจสอบและแจ้งเตือน
    checkAlerts();
    
    // แสดงข้อมูลใน Serial Monitor
    Serial.println("===== Air Quality Data =====");
    Serial.print("PM2.5: "); Serial.print(currentData.pm25); Serial.println(" µg/m³");
    Serial.print("PM10: "); Serial.print(currentData.pm10); Serial.println(" µg/m³");
    Serial.print("CO2: "); Serial.print(currentData.co2); Serial.println(" ppm");
    Serial.print("Temperature: "); Serial.print(currentData.temperature); Serial.println(" °C");
    Serial.print("Humidity: "); Serial.print(currentData.humidity); Serial.println(" %");
    Serial.print("AQI: "); Serial.println(currentData.aqi);
    Serial.print("Status: "); Serial.println(currentData.status);
    Serial.println("============================");
  }
}

📝 การติดตั้ง Library

ติดตั้ง libraries ที่จำเป็นใน PlatformIO:

pio lib install "Adafruit BME280 Library"
pio lib install "SparkFun SCD4x Arduino Library"
pio lib install "Adafruit SSD1306"

เชื่อมต่อ Home Assistant

หลังจากอัปโหลดโค้ดและเริ่มต้น ESP32 แล้ว เพิ่ม configuration ใน Home Assistant:

configuration.yaml

# MQTT Sensors for Air Quality Monitor
mqtt:
  sensor:
    - name: "Air Quality PM2.5"
      state_topic: "home/airquality/pm25"
      unit_of_measurement: "µg/m³"
      device_class: "pm25"
      
    - name: "Air Quality PM10"
      state_topic: "home/airquality/pm10"
      unit_of_measurement: "µg/m³"
      device_class: "pm10"
      
    - name: "Air Quality CO2"
      state_topic: "home/airquality/co2"
      unit_of_measurement: "ppm"
      device_class: "carbon_dioxide"
      
    - name: "Air Quality Temperature"
      state_topic: "home/airquality/temperature"
      unit_of_measurement: "°C"
      device_class: "temperature"
      
    - name: "Air Quality Humidity"
      state_topic: "home/airquality/humidity"
      unit_of_measurement: "%"
      device_class: "humidity"
      
    - name: "Air Quality Index"
      state_topic: "home/airquality/aqi"
      unit_of_measurement: "AQI"

# MQTT Alert Sensor
mqtt:
  sensor:
    - name: "Air Quality Alert"
      state_topic: "home/airquality/alert"
      value_template: "      value_template: "{{ lbrace;      value_template: "{{ lbrace; value_json.alert }}"
      json_attributes_topic: "home/airquality/alert"
      json_attributes_template: "      json_attributes_template: "{{ lbrace;      json_attributes_template: "{{ lbrace; value_json | tojson }}"

Automations (automations.yaml)

# แจ้งเตือนเมื่อคุณภาพอากาศแย่
- alias: "Alert when air quality is poor"
  trigger:
    - platform: numeric_state
      entity_id: sensor.air_quality_pm25
      above: 50
  action:
    - service: notify.mobile_app_phone
      data:
        title: "⚠️ Air Quality Alert"
        message: "PM2.5 is {{ states('sensor.air_quality_pm25') }} µg/m³"

# เปิดเครื่องฟอกอากาศเมื่อ CO2 สูง
- alias: "Turn on air purifier when CO2 is high"
  trigger:
    - platform: numeric_state
      entity_id: sensor.air_quality_co2
      above: 1000
  action:
    - service: switch.turn_on
      entity_id: switch.air_purifier

# ปิดเมื่อ CO2 ลดลง
- alias: "Turn off air purifier when CO2 is normal"
  trigger:
    - platform: numeric_state
      entity_id: sensor.air_quality_co2
      below: 800
  action:
    - service: switch.turn_off
      entity_id: switch.air_purifier

📊 สร้าง Dashboard

สร้าง Lovelace card ใน Home Assistant เพื่อแสดงผลข้อมูลคุณภาพอากาศ โดยใช้:

  • Gauge Card - แสดง AQI, PM2.5, CO2
  • History Graph - ดูแนวโน้มคุณภาพอากาศ
  • Markdown Card - แสดงคำแนะนำ
  • Entities Card - รวมข้อมูลทั้งหมด

การสอบเทียบเซ็นเซอร์

🔧 การสอบเทียบ PMS5003

  1. เปิดเครื่องในบริเวณที่มีอากาศบริสุทธิ์ (นอกบ้านหรือใกล้หน้าต่าง)
  2. ปล่อยให้ทำงาน 5-10 นาทีเพื่อให้เซ็นเซอร์ stabilise
  3. เปรียบเทียบค่ากับเครื่องวัดอ้างอิง (ถ้ามี)
  4. บันทึกค่า offset และปรับในโค้ด
  5. สอบเทียบซ้ำทุก 6-12 เดือน

🔧 การสอบเทียบ SCD41

  1. SCD41 สอบเทียบตัวเองอัตโนมัติ (Auto-calibration)
  2. ต้องเปิดอากาศบริเวณที่มีอากาศสะอาด (400 ppm CO2) เป็นเวลา 7 วัน
  3. หลีกเยี่ยงจากการวางใกล้แหล่ง CO2 (คน,สัตว์เลี้ยง,เครื่องจักร)
  4. หากต้องการใช้แบบ manual calibration ใช้ฟังก์ชัน performForcedCalibration()

💡 Tip: หากต้องการความแม่นยำสูง ควรสอบเทียบกับเครื่องวัดที่ได้รับการรับรองมาตรฐานอย่างน้อยปีละครั้ง

การออกแบบตู้บรรจุ

🎨 หลักการออกแบบ

  • การระบายอากาศ - ต้องมีรูระบายอากาศให้เพียงพอเพื่อให้อากาศไหลผ่านเซ็นเซอร์
  • ตำแหน่งเซ็นเซอร์ - PMS5003 ต้องวางในแนวดิ่งเพื่อให้ลูกศรชี้ขึ้น
  • ตำแหน่งหน้าจอ - OLED ควรอยู่ด้านหน้าที่มองเห็นชัด
  • การจัดการสายไฟ - ใช้ zip ties หรือ cable clips จัดระเบียบสาย
  • Ventilation - ใช้ fan ขนาดเล็ก (optional) เพื่อกระตุ้นการไหลเวียนของอากาศ

🖨️ 3D Printing Case

หากมีเครื่อง 3D printer สามารถดาวน์โหลด design จาก:

  • Thingiverse - ค้นหา "air quality monitor esp32"
  • Printables - มีหลายแบบให้เลือก
  • Cults3D - มีทั้งแบบง่ายและซับซ้อน

หรือใช้ กล่องพลาสติก หรือ ไม้ ตัดเอาง่ายๆ ก็ได้

สรุปและไอเดียต่อยอด

ในบทความนี้ เราได้สร้างเครื่องวัดคุณภาพอากาศ DIY ที่:

  • ตรวจจับ PM2.5, PM10, CO2, อุณหภูมิ และความชื้น
  • แสดงผลบน OLED display
  • เชื่อมต่อกับ Home Assistant ผ่าน MQTT
  • แจ้งเตือนอัตโนมัติเมื่อคุณภาพอากาศแย่
  • ใช้งานได้จริงและปรับแต่งได้

🎯 ไอเดียต่อยอด

  • เพิ่มเซ็นเซอร์ VOC - ตรวจจับก๊าซอินทรีย์ระเหย
  • เพิ่ม buzzer - ส่งเสียงแจ้งเตือน
  • เพิ่ม RGB LED - แสดงสถานะคุณภาพอากาศด้วยสี
  • ใช้ ESP32-CAM - แสดงผลเป็นกราฟิกบนเว็บ
  • เชื่อมต่อ Thingspeak - บันทึกข้อมูลระยะยาว
  • สร้างแอปมือถือ - ดูข้อมูลได้ทุกที่
  • ใช้แบตเตอรี่ + Solar - วางไว้นอกบ้านได้
← กลับไปหน้าบทความทั้งหมด