เริ่มจากคำถามเดียว
วันนี้อากาศเหมาะกับกิจกรรมกลางแจ้งไหม แล้วให้แต่ละวิชาช่วยตอบด้วยข้อมูลคนละมุม
ข้อมูลจริงตาม cadence ที่ตรวจพบของแต่ละสถานี · แยกค่าทันทีออกจากค่าเฉลี่ย 24 ชั่วโมง · UNESCO GNLC 2025 · SDG 3 · 4 · 11 · 13
วันนี้อากาศเหมาะกับกิจกรรมกลางแจ้งไหม แล้วให้แต่ละวิชาช่วยตอบด้วยข้อมูลคนละมุม
แยกค่าทันทีออกจากค่าเฉลี่ย 24 ชม. ตรวจ coverage แล้วจึงใช้ SD, AQI และ Heat Index ในบทเรียน
ข้อมูลล่าสุดยังใหม่พอสำหรับกิจกรรมสดและ dashboard ในคาบเรียน
ปลายทางไม่ใช่แค่ทำกราฟ แต่ให้นักเรียนเสนอ protocol, policy และการสื่อสารต่อชุมชนได้
ระบบ IoT 4 สถานีที่เปิดใช้งาน ประเมินรอบส่งจาก median gap ล่าสุดของแต่ละสถานี (สถานีตัวอย่าง: 5 นาที/ครั้ง) ผ่าน WiFi → Cloud Server → Dashboard สาธารณะ
หน้าเว็บตรวจข้อมูลใหม่ทุก 60 วินาที · ค่าทันทีใช้ดูการเปลี่ยนแปลง ส่วน AQI/WHO ใช้ค่าเฉลี่ย 24 ชั่วโมงเมื่อ coverage ≥75%
pm_readings_v2 เรียงตามเวลาและสุ่มลดจุดเพื่อให้กราฟลื่น;
Diurnal Pattern คือค่าเฉลี่ย PM2.5/CO₂ แยกตามชั่วโมงของวันนี้;
กราฟ 7 วันใช้วันเต็ม 7 วันล่าสุดและไม่รวมวันปัจจุบัน;
AQI คำนวณจากค่าเฉลี่ยเคลื่อนที่ 24 ชั่วโมงเมื่อ coverage ≥75% และแยก US EPA 2024 กับ Thai PCD;
Heat Index ใช้ขั้นตอน NWS simple formula/Rothfusz ภายใต้สมมติฐานร่มและลมอ่อน;
Pearson r ใช้เฉพาะคู่ข้อมูล valid ในช่วง 24 ชั่วโมงล่าสุด เป็นสถิติเชิงพรรณนา ไม่ใช่หลักฐานเหตุ-ผล;
CO₂ เป็นตัวชี้วัดประกอบเรื่องการระบายอากาศ ไม่ใช่คะแนนคุณภาพอากาศภายในทั้งหมด
เปรียบเทียบ US EPA AQI, Thai AQI และแนวทาง WHO — ฐาน PM2.5 เฉลี่ย 24 ชม. = 5.7 µg/m³ · coverage 100%
| สัญลักษณ์ | ชื่อ | คำอธิบาย | หน่วย | ค่าจริง |
|---|---|---|---|---|
| \(C_p\) | Concentration | ค่า PM2.5 จากเซ็นเซอร์ (ค่าเฉลี่ย 24h) | µg/m³ | 5.7 |
| \(BP_{Lo}\) | Breakpoint Low | ขอบล่างของช่วงที่ \(C_p\) ตกอยู่ | µg/m³ | 0 |
| \(BP_{Hi}\) | Breakpoint High | ขอบบนของช่วงที่ \(C_p\) ตกอยู่ | µg/m³ | 9 |
| \(I_{Lo}\) | Index Low | ค่า AQI ที่ตรงกับ \(BP_{Lo}\) | — | 0 |
| \(I_{Hi}\) | Index High | ค่า AQI ที่ตรงกับ \(BP_{Hi}\) | — | 50 |
| \(AQI\) | Air Quality Index | ผลลัพธ์ 0–500 | — | 31 |
| Category | BPLo | BPHi | ILo | IHi | สี |
|---|---|---|---|---|---|
| Good | 0.0 | 9.0 | 0 | 50 | ● |
| Moderate | 9.1 | 35.4 | 51 | 100 | ● |
| Unhealthy for Sensitive | 35.5 | 55.4 | 101 | 150 | ● |
| Unhealthy | 55.5 | 125.4 | 151 | 200 | ● |
| Very Unhealthy | 125.5 | 225.4 | 201 | 300 | ● |
| Hazardous | 225.5 | 325.4 | 301 | 500 | ● |
ข้อมูล PM2.5 จำนวน 288 รายการ จากสถานี โรงเรียน เทศบาล 1 กิตติขจร
สาธิต Kalman Filter 1D กับค่าจริงจาก PMS7003 เพื่อเรียนรู้การกรองสัญญาณ; ค่าพารามิเตอร์ Q/R ด้านล่างเป็นสมมติฐานการสอน ไม่ใช่ค่าที่สอบเทียบแล้ว
| สัญลักษณ์ | ชื่อ (EN) | คำอธิบาย | ค่าในระบบ |
|---|---|---|---|
| \(z_k\) | Measurement | ค่าดิบจากเซ็นเซอร์ PMS7003 ณ เวลา k | 5.5 |
| \(K_k\) | Kalman Gain | "เชื่อใคร?" K→1 เชื่อเซ็นเซอร์, K→0 เชื่อค่าทำนาย | 0.5025 |
| \(Q\) | Process Noise | "ค่าจริงเปลี่ยนเร็วแค่ไหน" Q สูง = กรองเบา | 0.01 (สมมติ) |
| \(R\) | Measurement Noise | "เซ็นเซอร์คลาดเคลื่อนแค่ไหน" R สูง = ไม่เชื่อเซ็นเซอร์ | 1.0 (สมมติ) |
| \(\hat{x}_{k|k}\) | Updated Estimate | ผลลัพธ์สุดท้าย — ค่ากรองแล้ว | — |
// C++ ตัวอย่างสำหรับห้องเรียน — ต้อง validate ก่อนใช้จริง
class KalmanFilter {
float x_est, P_est, Q, R;
public:
KalmanFilter(float q, float r, float x0=0)
: Q(q), R(r), x_est(x0), P_est(1) {}
float update(float z) {
float P_pred = P_est + Q; // Predict
float K = P_pred/(P_pred+R); // Gain
x_est += K * (z - x_est); // Update
P_est = (1-K) * P_pred; // Covariance
return x_est;
}
};
// พารามิเตอร์สาธิต ไม่ใช่ผลสอบเทียบ
KalmanFilter pm25Filter(0.01, 1.0, 5.7);
float filtered = pm25Filter.update(5.5);
// → 5.59 µg/m³| ระดับ | Heat Index (°C) | อาการ | คำแนะนำ |
|---|---|---|---|
| 🟢 ต่ำกว่า Caution | < 27 | ต่ำกว่าช่วงเตือนของตาราง NWS | ยังต้องดูแดด ลม ระยะเวลา และอาการ |
| 🟡 Caution | 27–32 | อ่อนเพลีย ถ้าออกกำลังนาน | ดื่มน้ำบ่อย พักเป็นช่วง |
| 🟠 Extreme caution | 32–41 | ตะคริว เพลียแดด | ลดกิจกรรม ย้ายเข้าร่ม |
| 🔴 อันตราย | 41–54 | ลมแดด | งดกิจกรรม เข้าอาคาร |
| 🟣 อันตรายมาก | > 54 | อันตรายถึงชีวิต | อยู่ในอาคารเท่านั้น |
ทุกโจทย์ใช้ข้อมูลจากเซ็นเซอร์จริง — ไม่ใช่ตัวเลขสมมุติ
| สัญลักษณ์ | ชื่อ | ค่าจริง |
|---|---|---|
| \(R\) | รัศมีโลก | 6,371 km |
| \(\phi_1\) | โรงเรียน เทศบาล 1 กิตติขจร | 16.867284°, 99.127582° |
| \(\phi_2\) | โรงเรียนเทศบาล 2 วัดดอนมูลชัย | 16.903990°, 99.105876° |
| \(d\) | ระยะทาง | 4.690 km |
// ตัวอย่างอ่าน PMS7003 — ตรวจ frame length และ checksum ก่อนใช้ค่า
#include <HardwareSerial.h>
HardwareSerial pms(2); // Serial2
uint8_t frame[32];
size_t pos = 0;
void setup() {
Serial.begin(115200);
pms.begin(9600, SERIAL_8N1, 25, 26);
}
void loop() {
while (pms.available()) {
uint8_t b = pms.read();
if (pos == 0 && b != 0x42) continue;
if (pos == 1 && b != 0x4D) { pos = (b == 0x42) ? 1 : 0; continue; }
frame[pos++] = b;
if (pos == 32) {
uint16_t frameLen = (frame[2] << 8) | frame[3];
uint16_t sum = 0;
for (int i = 0; i < 30; i++) sum += frame[i];
uint16_t expected = (frame[30] << 8) | frame[31];
if (frameLen == 28 && sum == expected) {
uint16_t pm25 = (frame[12] << 8) | frame[13];
Serial.printf("PM2.5=%d µg/m³\n", pm25);
// ค่าทันที: 6 µg/m³
}
pos = 0;
}
}
}| คำสั่ง | ชื่อ | คำอธิบาย |
|---|---|---|
| 0x42, 0x4D | Header Bytes | สัญญาณเริ่มต้น packet ของ PMS7003 (ASCII "BM") |
| << 8 | Bit Shift Left | เลื่อนบิตซ้าย 8 ตำแหน่ง = คูณ 256 รวม High+Low byte |
| frame[12], frame[13] | Data Position | ตำแหน่ง byte 12-13 = ค่า PM2.5 atmospheric ใน packet 32 bytes |
| Σ byte 0–29 | Checksum | ต้องเท่ากับ byte 30–31 และ frame length ต้องเป็น 28 มิฉะนั้นต้องทิ้ง frame |
# ดึงข้อมูลจาก API และแยกค่าทันทีกับค่าเฉลี่ย 24 ชั่วโมง
import pandas as pd
import requests, matplotlib.pyplot as plt
url = "https://tb1.ac.th/tak-aqm/integration_lessons.php?api=chart&station=TH-TAK-TB1-001"
r = requests.get(url, timeout=15)
r.raise_for_status()
df = pd.DataFrame(r.json())
df['reading_time'] = pd.to_datetime(df['reading_time'])
df['pm25'] = pd.to_numeric(df['pm2_5_compensated'], errors='coerce')
df['temperature'] = pd.to_numeric(df['temperature'], errors='coerce')
df['temperature'] = df['temperature'].where(df['temperature'].between(-40, 85))
df = df[df['pm25'].between(0, 1000)].sort_values('reading_time')
df = df.set_index('reading_time')
df['pm25_24h'] = df['pm25'].rolling('24h', min_periods=216).mean()
# สถิติ
print(f"Mean: {df['pm25'].mean():.2f}") # → 5.68
print(f"SD: {df['pm25'].std():.2f}") # → 0.23
print(f"r: {df['pm25'].corr(df['temperature']):.3f}")
# → 0.258
# Z-score screening — ใช้ค้นจุดที่ควรตรวจ ไม่ใช่ข้อสรุปสาเหตุ
df['z_score'] = (df['pm25'] - df['pm25'].mean()) / df['pm25'].std(ddof=1)
anomalies = df[df['z_score'].abs() > 2]
print(f"Anomalies: {len(anomalies)}")
# วาดกราฟ
fig, ax = plt.subplots(figsize=(10, 4))
ax.plot(df.index, df['pm25'], color='#93C5FD', alpha=.45, label='instantaneous')
ax.plot(df.index, df['pm25_24h'], color='#2563EB', label='rolling 24h')
ax.axhline(y=37.5, color='red', ls='--', label='Thai 24h reference')
ax.axhline(y=15, color='green', ls='--', label='WHO 24h guideline')
plt.tight_layout(); plt.show()ตารางนี้ดัดแปลงเพื่อการเรียนรู้จาก AirNow School Activity Guidance ไม่ใช่คำสั่งของโรงเรียน ต้องผ่านผู้บริหาร ครูพยาบาล และหน่วยงานสาธารณสุขก่อนนำไปใช้จริง
| AQI | ระดับ | กิจกรรมสั้น | กิจกรรมยาว/หนัก | สิ่งที่ต้องติดตาม |
|---|---|---|---|---|
| 0–50 ⬅️ | 🟢 Good | ทำได้ตามแผน | ทำได้ตามแผน | ตรวจ AQI และอาการ |
| 51–100 | 🟡 Moderate | ทำได้ตามแผน | ผู้ไวต่อมลพิษเฝ้าดูอาการ | แผนโรคหืด/ยาประจำตัว |
| 101–150 | 🟠 Sensitive groups | ทำได้ โดยเฉพาะกิจกรรมสั้น | เพิ่มพักและลดความหนัก | ติดตามไอ หายใจลำบาก แน่นหน้าอก |
| 151–200 | 🔴 Unhealthy | เพิ่มพักและลดความหนัก | พิจารณาย้ายในอาคาร/เลื่อนเวลา | ติดตามอาการของทุกคน |
| 201–500 | 🟣 Very unhealthy+ | ย้ายในอาคารหรือเลื่อน | ย้ายในอาคารหรือเลื่อน | ตรวจคุณภาพอากาศภายในด้วย |
Ollama + Qwen 2.5 — สอนคณิตศาสตร์แบบ 1:1 ด้วยข้อมูลจริงจาก Dashboard
บทเรียน สังคมศึกษา — SDGs, สิ่งแวดล้อม & ธรรมาภิบาล
SDG 3 + 13 — สุขภาพ & สิ่งแวดล้อม
ข้อมูลวันนี้: PM2.5 เฉลี่ย = 5.7 µg/m³
โจทย์วิจัยท้องถิ่น: ตรวจข้อมูลย้อนหลังรายเดือนร่วมกับจุดความร้อน ลม และฝน ก่อนสรุปรูปแบบฤดูกาลของจังหวัดตาก
SDG 11 — เมืองยั่งยืน & ธรรมาภิบาล
ระบบของเรา: ใช้ข้อมูลเซ็นเซอร์เป็นหลักฐานสนับสนุนหลังตรวจ coverage/คุณภาพ ไม่ใช่ฐานตัดสินนโยบายเพียงแหล่งเดียว
UNESCO GNLC 2025: เทศบาลเมืองตากได้รับการรับรอง
ม.4-6: จัดทำ "ข้อเสนอแนะเชิงนโยบาย" โดยรายงานข้อมูลจาก 4 สถานีที่เปิดใช้งาน พร้อมข้อจำกัด coverage ตัวแปรกวน และแหล่งอ้างอิงภายนอก