เครือข่ายตรวจวัดคุณภาพอากาศ เทศบาลเมืองตาก
ระบบ IoT 2 สถานี ส่งข้อมูลทุก 10 นาที ผ่าน WiFi → Cloud Server → Dashboard สาธารณะ
สถานีตรวจวัด 2 จุด
เซ็นเซอร์: PMS7003 + BME688 + SCD30
Firmware: v5.5.2 · WiFi + OTA + Serial CLI
สถานะ: 🟢 Online
เซ็นเซอร์: PMS7003 + BME688
Firmware: v5.5.2 · WiFi + OTA + Serial CLI
สถานะ: 🟢 Online
→ ตาก TB1 อยู่ใจกลางเมือง ส่วน TB2 อยู่ชานเมือง — ค่า PM2.5 อาจต่างกัน เปรียบเทียบได้ว่าแหล่งมลพิษมาจากไหน
ข้อ 2: ระยะห่างระหว่าง 2 สถานีประมาณเท่าไร? (ใช้พิกัดคำนวณ)
→ ดูวิชาคณิตศาสตร์ — สูตร Haversine Distance
เซ็นเซอร์ที่ใช้จริง ในระบบตรวจวัดคุณภาพอากาศ
ระบบติดตั้งจริงที่โรงเรียน ใช้ ESP32-WROVER + 3 เซ็นเซอร์ วัดค่า 10+ พารามิเตอร์ ส่งข้อมูลทุก 10 นาที 24/7
ช่วงวัด: 0–500 µg/m³
Resolution: 1 µg/m³
Interface: UART 9600 bps
ขา: RX=GPIO25, TX=GPIO26
ความแม่นยำ: T ±0.5°C, H ±3%RH
ช่วงวัด P: 300–1100 hPa
Interface: I2C Address 0x77
ขา: SDA=GPIO21, SCL=GPIO22
ช่วงวัด: 400–10,000 ppm
ความแม่นยำ: ±30 ppm ±3%
Interface: I2C Address 0x61
ขา: SDA=GPIO14, SCL=GPIO12
ตัวอย่างข้อมูลจริงจากเซ็นเซอร์ สถานี TH-TAK-TB1-001 (ทศ.1 กิตติขจร) — ฤดูหนาว ม.ค. 2569 (ใช้ในแบบฝึกหัดทุกรายวิชา)
| เวลา | PM2.5 (µg/m³) |
PM10 (µg/m³) |
CO₂ (ppm) |
Temp (°C) |
Humidity (%RH) |
Pressure (hPa) |
Gas Res. (Ω) |
|---|---|---|---|---|---|---|---|
| 06:00 | 68.3 | 82.1 | 487 | 18.2 | 78.4 | 1012.3 | 42,180 |
| 07:00 | 72.5 | 89.4 | 523 | 19.1 | 75.6 | 1012.1 | 38,950 |
| 09:00 | 55.2 | 68.7 | 445 | 24.3 | 62.1 | 1011.8 | 51,200 |
| 12:00 | 32.8 | 41.2 | 412 | 31.5 | 48.3 | 1010.5 | 67,400 |
| 15:00 | 28.4 | 35.6 | 408 | 33.2 | 42.7 | 1009.8 | 72,100 |
| 18:00 | 45.1 | 56.3 | 456 | 27.8 | 58.9 | 1010.2 | 55,800 |
| 21:00 | 61.7 | 75.2 | 498 | 22.4 | 71.5 | 1011.1 | 45,300 |
| 00:00 | 58.9 | 71.8 | 478 | 20.1 | 76.2 | 1011.9 | 43,600 |
| ตัวแปร | ชื่อเต็ม | คำอธิบาย | หน่วย | เซ็นเซอร์ |
|---|---|---|---|---|
| PM2.5 | Particulate Matter ≤ 2.5 µm | มวลฝุ่นละอองเส้นผ่านศูนย์กลาง ≤ 2.5 ไมครอน (เล็กกว่าเส้นผม 30 เท่า) เข้าสู่ปอดและกระแสเลือดได้ | µg/m³ | PMS7003 |
| PM10 | Particulate Matter ≤ 10 µm | มวลฝุ่นละอองขนาด ≤ 10 ไมครอน (ฝุ่นหยาบ) ค้างในจมูกและคอ | µg/m³ | PMS7003 |
| CO₂ | Carbon Dioxide | ก๊าซคาร์บอนไดออกไซด์ บอกคุณภาพการระบายอากาศ กลางแจ้ง ≈ 410 ppm ในห้องเรียนไม่ควรเกิน 1,000 ppm | ppm | SCD30 |
| Temp | Temperature | อุณหภูมิอากาศ ณ ตำแหน่งเซ็นเซอร์ | °C (เซลเซียส) | BME688 |
| Humidity | Relative Humidity | ความชื้นสัมพัทธ์ — ปริมาณไอน้ำจริง เทียบกับปริมาณสูงสุดที่อากาศรับได้ ณ อุณหภูมินั้น | %RH | BME688 / SCD30 |
| Pressure | Atmospheric Pressure | ความดันบรรยากาศ ที่ระดับน้ำทะเล ≈ 1013.25 hPa จ.ตาก (สูง ~130 ม.) ≈ 1000–1012 hPa | hPa | BME688 |
| Gas Res. | MOX Sensor Resistance | ความต้านทานเซ็นเซอร์ก๊าซ Metal Oxide — ค่าสูง = อากาศดี ค่าต่ำ = มี VOC มาก | Ω (โอห์ม) | BME688 |
→ ปรากฏการณ์ Temperature Inversion — กลางคืนอากาศเย็นกดทับอากาศร้อน มลพิษไม่ลอยสูงขึ้น
ข้อ 2: Gas Resistance ตอน 15:00 (72,100 Ω) สูงกว่า 07:00 (38,950 Ω) หมายความว่าอย่างไร?
→ ค่า Resistance สูง = อากาศสะอาดกว่า (ตรงข้ามกับ PM2.5 ที่ค่าสูง = แย่)
ข้อ 3: ทำไม CO₂ ตอน 07:00 (523 ppm) สูงที่สุด?
→ รถยนต์รอส่งนักเรียนช่วงเช้า + อากาศไม่ถ่ายเท → CO₂ สะสม
สูตรคำนวณ AQI (Air Quality Index)
ระบบของเราคำนวณ AQI 6 มาตรฐานสากล — ทุกสูตรมีคำอธิบายตัวแปรครบถ้วน พร้อมตัวอย่างจากข้อมูลจริง
ดีมาก
ปานกลาง
กลุ่มเสี่ยง
มีผลต่อสุขภาพ
อันตรายมาก
วิกฤต
US EPA AQI — มาตรฐานสหรัฐอเมริกา มาตรฐานหลักที่ใช้ทั่วโลก และเป็นค่าหลักของระบบเรา
| สัญลักษณ์ | ชื่อเต็ม (EN) | ชื่อภาษาไทย | คำอธิบายละเอียด | หน่วย | ค่าตัวอย่าง |
|---|---|---|---|---|---|
| \(AQI\) | Air Quality Index | ดัชนีคุณภาพอากาศ | ผลลัพธ์ที่ต้องการคำนวณ — ตัวเลข 0–500 ยิ่งสูงยิ่งอากาศแย่ ใช้สื่อสารกับประชาชนแทนค่าทางวิทยาศาสตร์ | ไม่มีหน่วย (ดัชนี) | 149.5 |
| \(C_p\) | Pollutant Concentration | ค่าความเข้มข้นมลพิษ | ค่าที่เซ็นเซอร์วัดได้จริง — อ่านจาก PMS7003 โดยตรง สำหรับ PM2.5 ต้องตัดทศนิยมเหลือ 1 ตำแหน่ง | µg/m³ | 55.2 |
| \(BP_{Hi}\) | Breakpoint High | จุดแบ่งช่วง ขอบบน | ขอบบนของช่วง Breakpoint ที่ \(C_p\) ตกอยู่ — เปิดตาราง Breakpoint หาว่า 55.2 อยู่ช่วง 35.5–55.4 | µg/m³ | 55.4 |
| \(BP_{Lo}\) | Breakpoint Low | จุดแบ่งช่วง ขอบล่าง | ขอบล่างของช่วง Breakpoint ที่ \(C_p\) ตกอยู่ | µg/m³ | 35.5 |
| \(I_{Hi}\) | Index High | ค่า AQI ขอบบน | ค่า AQI ที่ตรงกับ \(BP_{Hi}\) — ดูจากคอลัมน์ AQI ในตาราง Breakpoint | ไม่มีหน่วย | 150 |
| \(I_{Lo}\) | Index Low | ค่า AQI ขอบล่าง | ค่า AQI ที่ตรงกับ \(BP_{Lo}\) — ค่า AQI ต่ำสุดของช่วงนั้น | ไม่มีหน่วย | 101 |
📋 ตาราง Breakpoint สำหรับ PM2.5 — US EPA (ปรับปรุง 2024)
| AQI Category | \(BP_{Lo}\) (µg/m³) | \(BP_{Hi}\) (µg/m³) | \(I_{Lo}\) | \(I_{Hi}\) | สี |
|---|---|---|---|---|---|
| Good (ดี) | 0.0 | 9.0 | 0 | 50 | 🟢 |
| Moderate (ปานกลาง) | 9.1 | 35.4 | 51 | 100 | 🟡 |
| Unhealthy for Sensitive Groups | 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 | 🟤 |
ข: เวลา 07:00 PM2.5 = 72.5 µg/m³ → ช่วง 55.5–125.4, AQI ≈ 163 🔴
ค: ถ้าต้องการ AQI ≤ 100 ค่า PM2.5 สูงสุดเท่าไหร่? → 35.4 µg/m³
// ฟังก์ชันคำนวณ AQI — ใช้จริงบน Dashboard
function
calcAQI(Cp, breakpoints) {
for (const bp
of breakpoints) {
if (Cp >= bp.BPLo && Cp <= bp.BPHi) {
return Math.round( ((bp.IHi - bp.ILo) /
(bp.BPHi - bp.BPLo)) * (Cp - bp.BPLo) + bp.ILo ); } } }
// ตัวอย่าง:
calcAQI(55.2, EPA_PM25_BP);
// → 150
EPA NowCast™ Algorithm คำนวณ AQI แบบเรียลไทม์ ให้น้ำหนักข้อมูลล่าสุดมากกว่า — ใช้จริงบน Dashboard
| สัญลักษณ์ | ชื่อ (EN) | ชื่อไทย | คำอธิบายละเอียด | หน่วย | ค่าตัวอย่าง |
|---|---|---|---|---|---|
| \(NowCast\) | NowCast Concentration | ค่าความเข้มข้นแบบ NowCast | ผลลัพธ์: ค่าเฉลี่ยถ่วงน้ำหนัก ใช้แทน \(C_p\) ในสูตร AQI เพื่อตอบสนองต่อการเปลี่ยนแปลงเร็วขึ้น | µg/m³ | 54.5 |
| \(c_i\) | Hourly Concentration | ค่าเฉลี่ยรายชั่วโมง | ค่า PM2.5 เฉลี่ยรายชั่วโมง ย้อนหลัง \(i\) ชั่วโมง — \(c_1\) = ชม.ล่าสุด | µg/m³ | c₁=55, c₂=48, c₃=62 |
| \(N\) | Number of Hours | จำนวนชม.ย้อนหลัง | จำนวนชั่วโมงที่ใช้ — PM2.5 ใช้ N=12, PM10 ใช้ N=12, Ozone ใช้ N=8 | ชั่วโมง | 12 |
| \(w\) | Weight Factor | ตัวคูณน้ำหนัก | ค่า 0.5 ถึง 1.0: ข้อมูลเปลี่ยนมาก → w ต่ำ → เชื่อข้อมูลล่าสุด; ค่าคงที่ → w ≈ 1 → เฉลี่ยเท่ากัน | ไม่มีหน่วย | 0.774 |
| \(w^{i-1}\) | Weight for hour i | น้ำหนักของชม.ที่ i | ชม.ล่าสุด \(w^0=1\), ชม.ก่อน \(w^1\), ชม.ก่อนหน้า \(w^2\) — ยิ่งเก่ายิ่งน้ำหนักน้อย | ไม่มีหน่วย | 1, 0.774, 0.599 |
Thai PCD AQI — กรมควบคุมมลพิษ เกณฑ์ไทย ใช้สูตรเดียวกัน แต่ตาราง Breakpoint ต่างจาก EPA
| ระดับ | \(BP_{Lo}\) PM2.5 | \(BP_{Hi}\) PM2.5 | \(I_{Lo}\) | \(I_{Hi}\) | คำแนะนำ |
|---|---|---|---|---|---|
| ดีมาก | 0 | 15 | 0 | 25 | ทำกิจกรรมกลางแจ้งได้ปกติ |
| ดี | 16 | 25 | 26 | 50 | ออกกำลังกายกลางแจ้งได้ |
| ปานกลาง | 26 | 37.5 | 51 | 100 | กลุ่มเสี่ยงลดกิจกรรมกลางแจ้ง |
| เริ่มมีผลฯ | 37.6 | 75 | 101 | 200 | ใส่หน้ากาก N95 |
| มีผลต่อสุขภาพ | 75.1 | ∞ | 201 | — | หลีกเลี่ยงกิจกรรมกลางแจ้ง |
WHO 2021 Guidelines — องค์การอนามัยโลก เกณฑ์เข้มงวดที่สุด — เป้าหมายที่โลกควรมุ่งสู่
| มลพิษ | ค่าเฉลี่ย | WHO 2021 | EPA Standard | Thai PCD | ค่าจากเซ็นเซอร์เรา |
|---|---|---|---|---|---|
| PM2.5 | เฉลี่ย 24 ชม. | 15 µg/m³ | 35 µg/m³ | 37.5 µg/m³ | 52.86 µg/m³ |
| PM2.5 | เฉลี่ยรายปี | 5 µg/m³ | 9 µg/m³ | 15 µg/m³ | — |
| PM10 | เฉลี่ย 24 ชม. | 45 µg/m³ | 150 µg/m³ | 120 µg/m³ | 65.0 µg/m³ |
| CO₂ | ในห้องเรียน | 1,000 ppm | — | — | 462 ppm |
→ บทเรียน: ค่าเท่ากัน แต่ "ระดับอันตราย" ต่างตามมาตรฐาน — นักเรียนต้องรู้ว่าดูมาตรฐานไหน
→ WHO เข้มงวดที่สุด เพราะอ้างอิงจากงานวิจัยผลกระทบสุขภาพระยะยาว
สถิติจาก ข้อมูลเซ็นเซอร์จริง
ใช้ PM2.5 ทั้ง 8 รายการ: 68.3, 72.5, 55.2, 32.8, 28.4, 45.1, 61.7, 58.9 (µg/m³)
| สัญลักษณ์ | ชื่อ | คำอธิบาย | ค่าตัวอย่าง |
|---|---|---|---|
| \(SD\) หรือ \(s\) | Standard Deviation | ผลลัพธ์: ยิ่งสูง ข้อมูลยิ่งกระจาย — บอก "ค่าอากาศผันผวนแค่ไหน" | 15.81 |
| \(x_i - \bar{x}\) | Deviation | ระยะห่างระหว่างข้อมูลตัวที่ i กับค่าเฉลี่ย | 68.3−52.86 = 15.44 |
| \(n - 1\) | Degrees of Freedom | ใช้ \(n-1\) แทน \(n\) สำหรับกลุ่มตัวอย่าง (Bessel's Correction) | 8−1 = 7 |
เกณฑ์ตีความ: |r| > 0.7 = สูง, |r| 0.3–0.7 = ปานกลาง, |r| < 0.3 = ต่ำ
แบบฝึกหัดเพิ่มเติม: ลองคำนวณ r ระหว่าง PM2.5 กับ Humidity — คาดว่าจะสัมพันธ์ทิศทางไหน? (ตอบ: +, เพราะอากาศชื้นทำให้ฝุ่นลอยตัวยาก)
Kalman Filter — กรองสัญญาณรบกวนจากเซ็นเซอร์
เซ็นเซอร์ PMS7003 มี noise สูง — Kalman Filter ช่วยกรองให้นิ่งขึ้น ใช้จริงบน ESP32
| สัญลักษณ์ | ชื่อ (EN) | คำอธิบาย | หน่วย | ค่าในระบบ |
|---|---|---|---|---|
| \(\hat{x}_{k|k}\) | Updated Estimate | ผลลัพธ์สุดท้าย — ผสมค่าทำนาย + ค่าเซ็นเซอร์ ถ่วงน้ำหนักด้วย K | µg/m³ | 52.51 |
| \(z_k\) | Measurement | ค่าดิบจากเซ็นเซอร์ ณ เวลา \(k\) — มี noise ปน | µg/m³ | 55 |
| \(K_k\) | Kalman Gain | "เชื่อใคร?" K→1 เชื่อเซ็นเซอร์, K→0 เชื่อค่าทำนาย | ไม่มีหน่วย | 0.5025 |
| \(Q\) | Process Noise | "ค่าจริงเปลี่ยนเร็วแค่ไหน" Q สูง→กรองเบา, Q ต่ำ→กรองหนัก | (µg/m³)² | 0.01 |
| \(R\) | Measurement Noise | "เซ็นเซอร์คลาดเคลื่อนแค่ไหน" R สูง→ไม่เชื่อเซ็นเซอร์, R ต่ำ→เชื่อเซ็นเซอร์ | (µg/m³)² | 1.0 |
| \(z_k - \hat{x}_{k|k-1}\) | Innovation | "ผิดไปเท่าไหร่" ระหว่างเซ็นเซอร์กับค่าทำนาย | µg/m³ | 55−50 = 5 |
// C++ จริงบน ESP32 — Kalman Filter Class
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, 50.0);
float filtered = pm25Filter.update(55.2); // → 52.51
บทเรียน วิทยาศาสตร์ — หลักการทำงานของเซ็นเซอร์
PMS7003 — Laser Scattering
ยิงแสง Laser → ฝุ่นกระเจิงแสง → Photodetector วัดแสงกระเจิง → คำนวณขนาดอนุภาค
| ตัวแปร | ชื่อ | คำอธิบาย | หน่วย |
|---|---|---|---|
| \(I\) | Scattered Intensity | ความเข้มแสงกระเจิง | W/m² |
| \(d\) | Particle Diameter | เส้นผ่านศูนย์กลางอนุภาค | µm |
| \(\lambda\) | Wavelength | ความยาวคลื่น Laser (~650 nm) | nm |
SCD30 — NDIR CO₂
ยิงแสง IR ผ่านอากาศ → CO₂ ดูดกลืน IR ที่ 4.26 µm → วัด IR ที่เหลือ → คำนวณ CO₂
| ตัวแปร | ชื่อ | คำอธิบาย | หน่วย |
|---|---|---|---|
| \(A\) | Absorbance | ค่าการดูดกลืนแสง | ไม่มีหน่วย |
| \(\varepsilon\) | Molar Absorptivity | สัมประสิทธิ์ดูดกลืน เฉพาะ CO₂ ที่ 4.26 µm | L·mol⁻¹·cm⁻¹ |
| \(c\) | Concentration | ความเข้มข้น CO₂ — ตัวที่ต้องการหา! | mol/L |
| \(l\) | Path Length | ระยะทางแสงเดินผ่าน | cm |
BME688 — MEMS 4-in-1
Temp จาก Resistive, Humidity จาก Capacitance, Pressure จาก Membrane, Gas จาก Metal Oxide
| ตัวแปร | ชื่อ | คำอธิบาย | ค่า |
|---|---|---|---|
| \(h\) | Altitude | ความสูง (ผลลัพธ์) | เมตร |
| \(T_0\) | Ref. Temperature | อุณหภูมิอ้างอิง | 288.15 K |
| \(P_0\) | Sea-level Pressure | ความดันระดับน้ำทะเล | 1013.25 hPa |
| \(P\) | Measured Pressure | ความดันจาก BME688 | hPa |
บทเรียน คณิตศาสตร์ จากข้อมูลจริง
ทุกโจทย์ใช้ข้อมูลจากเซ็นเซอร์ — ไม่ใช่ตัวเลขสมมุติ
สมการเชิงเส้นจากสูตร AQI (ม.2-3) เปลี่ยนสูตร AQI ให้อยู่ในรูป y = mx + b
\(m = \frac{150-101}{55.4-35.5} = 2.462\), \(b = 101-2.462 \times 35.5 = 13.6\)
→ \(\boxed{AQI = 2.462 \times PM2.5 + 13.6}\)
ข้อ 1: PM2.5 = 40 → AQI = \(2.462 \times 40 + 13.6 = \boxed{112.1}\) 🟠
ข้อ 2: ต้องการ AQI ≤ 100 → \(x = \frac{86.4}{2.462} = \boxed{35.1\;\mu g/m^3}\)
อัตราส่วน ร้อยละ และสัดส่วน (ม.1-2) ใช้ข้อมูล PM2.5 คำนวณสัดส่วนเกินเกณฑ์
ก: อัตราส่วนวันเกินเกณฑ์ = 22:30 = 11:15
ข: ร้อยละ = \(\frac{22}{30} \times 100 = \boxed{73.3\%}\)
ค: ถ้า ม.ค. 31 วัน เกิน 73.3% → วันอากาศดี = \(31-(31\times0.733) = \boxed{8}\) วัน
ระยะทางระหว่าง 2 สถานี — Haversine Formula (ม.4-6) ใช้พิกัด GPS คำนวณระยะทางบนผิวโลก
| สัญลักษณ์ | ชื่อ | คำอธิบาย | ค่าตัวอย่าง |
|---|---|---|---|
| \(d\) | Distance | ระยะทางระหว่าง 2 จุด (ผลลัพธ์) | ≈ 2.68 km |
| \(R\) | Earth's Radius | รัศมีโลก | 6,371 km |
| \(\phi_1, \phi_2\) | Latitudes | ละติจูดของ 2 สถานี (เป็นเรเดียน) | 16.884°, 16.905° |
| \(\Delta\phi\) | Lat difference | \(\phi_2 - \phi_1\) ผลต่างละติจูด | 0.021° |
| \(\Delta\lambda\) | Lon difference | ผลต่างลองจิจูด | −0.020° |
\(\Delta\phi = 0.0207°\), \(\Delta\lambda = -0.0196°\)
→ ระยะห่างประมาณ 2.68 km — เหมาะสำหรับเปรียบเทียบคุณภาพอากาศใจกลางเมืองกับชานเมือง
บทเรียน Coding & IoT — โค้ดจริงจากระบบ
เขียนโปรแกรม ESP32 อ่านค่า PM2.5 วิทยาการคำนวณ ม.1-3 — C++, IoT, Bit Manipulation
// โค้ดจริงจากระบบ v5.5.2 (ย่อเพื่อการเรียนรู้)
#include
<HardwareSerial.h>
HardwareSerial pms(2);
// ใช้ Serial2 ของ ESP32
void setup() {
Serial.begin(115200);
// Serial Monitor pms.begin(9600, SERIAL_8N1, 25,
26);
// เชื่อม PMS7003
}
void loop() {
if (pms.available() >=
32) {
uint8_t buf[32];
pms.readBytes(buf, 32);
if (buf[0]==0x42 && buf[1]==0x4D) {
// ตรวจ Header
int pm25 = (buf[12] << 8) | buf[13]; // รวม 2 bytes Serial.printf("PM2.5=%d µg/m³\n", pm25); } } delay(1000); }
| คำสั่ง / ค่า | ชื่อ | คำอธิบาย |
|---|---|---|
| 0x42, 0x4D | Header Bytes | เลขฐานสิบหก เป็น "สัญญาณเริ่มต้น" ของ packet ข้อมูล |
| << 8 | Bit Shift Left | เลื่อนบิตซ้าย 8 ตำแหน่ง = คูณ 256 — รวม High + Low byte เป็นเลข 16 บิต |
| | | Bitwise OR | รวม 2 bytes เข้าด้วยกัน เช่น 0x00 << 8 | 0x37 = 55 |
| buf[12], buf[13] | Data Position | ตำแหน่ง byte 12-13 ใน packet 32 bytes = ค่า PM2.5 atmospheric |
Python — วิเคราะห์ข้อมูลเซ็นเซอร์ วิทยาการคำนวณ ม.4-6 — pandas, matplotlib, สถิติ
# วิเคราะห์ข้อมูล PM2.5 จากเซ็นเซอร์โรงเรียน
import pandas
as pd
import matplotlib.pyplot
as plt
# ข้อมูลจริงจากสถานี TB1 — ม.ค. 2569
data = {
'time': ['06:00','07:00','09:00','12:00','15:00','18:00','21:00','00:00'],
'pm25': [68.3,
72.5, 55.2,
32.8, 28.4,
45.1, 61.7,
58.9], 'temp':
[18.2, 19.1,
24.3, 31.5,
33.2, 27.8,
22.4, 20.1] } df
= pd.DataFrame(data)
# สถิติพื้นฐาน
print(f"ค่าเฉลี่ย PM2.5: {df['pm25'].mean():.2f} µg/m³") print(f"ค่ามัธยฐาน: {df['pm25'].median():.2f} µg/m³") print(f"SD: {df['pm25'].std():.2f} µg/m³")
# หาสหสัมพันธ์ PM2.5 กับ Temperature
r = df['pm25'].corr(df['temp']) print(f"Pearson r = {r:.3f}") # → -0.943
# วาดกราฟ
fig, ax = plt.subplots(figsize=(10,
5)) ax.plot(df['time'], df['pm25'],
'o-', color='#ea580c', label='PM2.5') ax.axhline(y=37.5, color='red', linestyle='--', label='เกณฑ์ PCD') ax.set_title('PM2.5 รายชั่วโมง — สถานี TB1 กิตติขจร') ax.legend() plt.show()
ข้อ 2: คำนวณจำนวนชั่วโมงที่ PM2.5 เกินเกณฑ์ Thai PCD (37.5 µg/m³)
ข้อ 3: ใช้
scipy.stats.pearsonr() หาค่า
p-value ของ r = −0.94
บทเรียน ภาษา — คำศัพท์จาก Dashboard สองภาษา
| English Term | ภาษาไทย | คำอธิบาย / ตัวอย่างประโยค |
|---|---|---|
| Particulate Matter (PM) | ฝุ่นละอองขนาดเล็ก | The PM2.5 concentration is 55.2 µg/m³, exceeding the WHO guideline. |
| Air Quality Index (AQI) | ดัชนีคุณภาพอากาศ | Today's AQI is 150, which is unhealthy for sensitive groups. |
| Relative Humidity (%RH) | ความชื้นสัมพัทธ์ | The sensor reads 78.4% relative humidity, indicating moist conditions. |
| Atmospheric Pressure | ความดันบรรยากาศ | Atmospheric pressure dropped to 1009 hPa before the storm. |
| Temperature Inversion | การกลับทิศของอุณหภูมิ | Temperature inversion traps pollutants near the ground at night. |
| Real-time Monitoring | การตรวจวัดแบบเรียลไทม์ | Our school operates a real-time air quality monitoring network. |
| Threshold / Standard | เกณฑ์ / มาตรฐาน | WHO's annual threshold for PM2.5 is 5 µg/m³. |
| Calibration | การสอบเทียบ | The CO₂ sensor requires calibration every 6 months. |
| Internet of Things (IoT) | อินเทอร์เน็ตของสรรพสิ่ง | IoT sensors collect data automatically and send it to the cloud. |
| Volatile Organic Compounds | สารอินทรีย์ระเหยง่าย (VOC) | The BME688 gas sensor detects volatile organic compounds in the air. |
ม.4-6: เขียน Paragraph อธิบายว่า "Why is the air quality worse in the morning?" โดยใช้ข้อมูลจริงอ้างอิง
บทเรียน สุขภาพ กับคุณภาพอากาศ
School Protocol — แนวปฏิบัติตามระดับ AQI (ใช้จริง)
| AQI | ระดับ | กิจกรรมพลศึกษา | กิจกรรมกลางแจ้ง | การปกป้อง |
|---|---|---|---|---|
| 0–50 | 🟢 ดีมาก | ทุกกิจกรรม ปกติ | ✅ อนุญาต | ไม่จำเป็น |
| 51–100 | 🟡 ปานกลาง | ลดความหนัก | ⚠️ จำกัด ≤ 30 นาที | กลุ่มเสี่ยงใส่หน้ากาก |
| 101–150 | 🟠 เริ่มมีผลฯ | กิจกรรมเบาเท่านั้น | ❌ งด | ทุกคนใส่ N95 |
| 151–200 | 🔴 มีผลต่อสุขภาพ | ย้ายเข้าอาคาร | ❌ ห้าม | เครื่องฟอกอากาศ |
| 201+ | 🟣 อันตรายมาก | ❌ งดทั้งหมด | ❌ ปิดหน้าต่าง | พิจารณาหยุดเรียน |
→ AQI 163 = 🔴 → ย้ายเข้าอาคาร เปลี่ยนเป็นโยคะ ยืดเหยียด
สถานการณ์ 2: TB1 แสดง AQI 45 🟢 แต่ TB2 แสดง AQI 120 🟠 — โรงเรียน 2 ควรงดกิจกรรมกลางแจ้งไหม?
→ ใช่! แต่ละสถานีต้องดูค่าตัวเอง ไม่ใช้ค่าเฉลี่ยรวม
บทเรียน ศิลปะ & Data Visualization
แปลงข้อมูลเป็นภาพ — สื่อสารคุณภาพอากาศให้ชุมชนเข้าใจง่าย
สี กับ AQI — Color Theory ในชีวิตจริง
ทฤษฎีสี: เขียว = ปลอดภัย (สัญชาตญาณ), แดง = อันตราย (ตัดกัน/Complementary)
Accessibility: ต้องเพิ่มตัวเลข+ข้อความ ไม่ใช้แค่สี เพราะผู้ที่ตาบอดสีแดง-เขียว (8% ของผู้ชาย) จะแยกไม่ออก
Data Visualization — เปลี่ยนตัวเลขเป็นภาพ
Bar Chart: เปรียบเทียบ TB1 vs TB2 ในเวลาเดียวกัน
Heatmap: แสดง PM2.5 ทุกชั่วโมง x ทุกวัน → เห็นวันไหนแย่ที่สุด
Infographic: สรุป 1 หน้า สำหรับประชาสัมพันธ์ชุมชน
ม.4-6: ออกแบบ Dashboard UI mockup บนกระดาษหรือ Figma สำหรับแอปพลิเคชันคุณภาพอากาศเทศบาลเมืองตาก คำนึงถึง: สี, ขนาดตัวอักษร, ลำดับข้อมูล, Accessibility
เกณฑ์ให้คะแนน: ความถูกต้องของข้อมูล (30%) · การออกแบบสวยงาม (30%) · สื่อสารเข้าใจง่าย (40%)
ระบบ AI Tutor เสริมการเรียนรู้
Ollama + Qwen 2.5 — สอนคณิตศาสตร์แบบ 1:1 ปรับระดับอัตโนมัติ มี Gamification
🤖 ตัวอย่างบทสนทนากับ AI Tutor
สวัสดีครับ! วันนี้เราจะเรียนเรื่อง การคำนวณ AQI จากค่า PM2.5 ซึ่งใช้ข้อมูลจริงจากเซ็นเซอร์ของโรงเรียน 🌬️
ก่อนอื่น — เคยเห็นค่า PM2.5 บน Dashboard ของโรงเรียนไหมครับ?
เคยครับ วันนี้เห็นค่า 55 ครับ
ดีมาก! 55 µg/m³ ค่อนข้างสูงนะ 🤔
สูตร AQI: \(AQI = \frac{I_{Hi}-I_{Lo}}{BP_{Hi}-BP_{Lo}} \times (C_p - BP_{Lo}) + I_{Lo}\)
Step 1: ลองหาก่อนว่า 55 อยู่ในช่วง Breakpoint ไหนครับ?
อยู่ในช่วง 35.5-55.4 ครับ
ถูกต้อง! 🎉 +10 XP เก่งมากครับ!
\(BP_{Lo}=35.5\), \(BP_{Hi}=55.4\), \(I_{Lo}=101\), \(I_{Hi}=150\)
Step 2: ลองแทนค่าในสูตรดูครับ — ไม่ต้องกลัวผิด! 💪
🎮 Gamification
Levels: 🌱 ฝึกหัด → ⭐ นักคิด → 🔥 นักแก้โจทย์ → 💎 อัจฉริยะ → 👑 ปรมาจารย์
Daily Streak: เข้าเรียนทุกวัน = Streak Bonus
Leaderboard: จัดอันดับในห้อง/ระดับชั้น
📚 เทคนิคการสอนของ AI
Socratic Method: ไม่เฉลยทันที — ถามนำให้คิดเอง
Adaptive Difficulty: ตอบถูกมาก = ยากขึ้นอัตโนมัติ
RAG: สอนจากเนื้อหาที่ครูเตรียมไว้เท่านั้น
Lesson Lock: ห้ามสอนนอกเรื่องที่กำหนด
บทเรียน สังคมศึกษา — SDGs, สิ่งแวดล้อม & ธรรมาภิบาล
เชื่อมโยงระบบตรวจวัดคุณภาพอากาศกับเป้าหมายการพัฒนาที่ยั่งยืน (SDGs) และหน้าที่พลเมือง
เป้าหมายการพัฒนาที่ยั่งยืน (SDGs) ที่เกี่ยวข้อง
SDG 3 + 13 — สุขภาพ & สิ่งแวดล้อม
จ.ตาก: ฤดูหมอกควัน (ม.ค.–เม.ย.) มี PM2.5 เกินเกณฑ์เฉลี่ย 70% ของวัน
สาเหตุหลัก: การเผาพื้นที่เกษตร การเผาป่า ไฟข้ามแดนจากเมียนมา
SDG 11 — เมืองยั่งยืน & ธรรมาภิบาล
ระบบของเรา: เทศบาลเมืองตากใช้ข้อมูลจากเซ็นเซอร์ตัดสินใจนโยบาย เช่น ประกาศเตือน ปิดเรียน ห้ามเผา
UNESCO GNLC: เครือข่ายเมืองแห่งการเรียนรู้ตลอดชีวิต ยอมรับ เทศบาลเมืองตาก ปี 2025
ม.4-6: จัดทำ "ข้อเสนอแนะเชิงนโยบาย" เสนอต่อเทศบาลเมืองตาก โดยใช้ข้อมูลจากเซ็นเซอร์ทั้ง 2 สถานีวิเคราะห์ เช่น "ควรมีจุดจ่ายหน้ากาก N95 ที่ใดในเมือง?"
กิจกรรมกลุ่ม: อภิปราย "สิทธิในการหายใจอากาศสะอาด" เป็นสิทธิมนุษยชนหรือไม่? เทศบาลมีหน้าที่อะไร?