Untuk bina sensor kualiti udara sendiri dengan ESP32, sambungkan sensor debu optik GP2Y1010AU0F ke pin ADC1 untuk trend PM2.5, dan sensor CO2 SCD30 ke bus I2C, kemudian paparkan kedua-dua bacaan pada OLED 0.96 inci. Satu sketch sahaja diperlukan β kod penuh ada di bawah. Alat ini tunjuk trend udara dalam rumah anda, bukan pengganti bacaan API rasmi.
Kenapa projek ini guna dua sensor?
Sensor debu GP2Y1010AU0F dan sensor CO2 SCD30 jawab dua soalan yang berbeza. Musim jerebu, soalannya “berapa banyak zarah halus masuk ke dalam rumah saya” β itu kerja sensor debu, yang mengesan pantulan cahaya inframerah pada zarah dalam udara. Bilik tertutup dengan aircond pula timbulkan soalan lain: “cukup ke udara segar di sini” β dan CO2 ialah penunjuk pengudaraan yang paling boleh dipercayai.
Kenali rupa setiap komponen. Sensor debu datang dalam casing aluminium dengan lubang bulat di tengah dan kabel 6 wayar merah berpalam JST putih. SCD30 pula breakout PCB hijau dengan blok sensor hitam β pad castellation-nya belum dipasang header, jadi anda perlu solder sendiri. Rujuk panduan kami tentang cara solder header pin kalau ini kali pertama. Otaknya NodeMCU-32S (micro-USB, cip USB CP2102), dan paparannya OLED 0.96 inci putih (PCB biru).
Senarai komponen
Satu perkara penting: sensor debu ini wajib ditemani satu perintang 150Ω dan satu kapasitor elektrolitik 220µF β nilai ini ditetapkan oleh datasheet Sharp sendiri, bukan pilihan. Kedua-duanya komponen bengkel biasa yang kebanyakan maker dah sedia ada dalam simpanan, jadi kami tak masukkan dalam senarai di atas. Kalau nak sentiasa ada stok komponen asas macam ini, component starter kit kami cara mudah untuk mulakannya.
Boleh tak alat ini bagi bacaan API macam laporan rasmi?
Indeks Pencemar Udara (API) Malaysia dikira oleh Jabatan Alam Sekitar daripada stesen pemantauan rujukan yang terkalibrasi. Ia bukan bacaan PM2.5 mentah β setiap pencemar utama (antaranya PM2.5, PM10, ozon, SO2, NO2 dan CO) diberi sub-indeks, dan sub-indeks tertinggi itulah yang jadi angka API. Sub-indeks PM2.5 pula dikira atas purata 24 jam, bukan bacaan saat itu.
Sensor optik inframerah macam GP2Y1010AU0F memberi trend relatif, bukan ukuran terkalibrasi. Bacaannya terpengaruh dengan kelembapan β dan Malaysia memang lembap β jadi jangan sesekali kutip angkanya sebagai “API rumah saya”.
Jadi apa gunanya? Banyak, sebenarnya. Anda boleh nampak udara bilik merosot bila jiran bakar sampah, sahkan sama ada tutup tingkap dan pasang air purifier betul-betul membantu, perhatikan trend sepanjang hari, atau kumpul data sebenar untuk projek sains sekolah. SCD30 pula cerita lain terus: ia penunjuk pengudaraan β bilik ni pengap atau tak β soalan berbeza daripada jerebu di luar. Jangan campurkan kedua-duanya.
Macam mana nak sambung wiring semua sensor?
ESP32 ada dua kumpulan pin ADC, dan pilihan pin sangat penting di sini. Pin ADC2 dikongsi dengan radio WiFi β bila WiFi aktif, bacaan ADC2 tersekat. Projek ini memang calon untuk WiFi nanti, jadi output analog sensor debu mesti masuk pin ADC1 (GPIO32 hingga GPIO39) β kita guna GPIO34.
Satu lagi: datasheet Sharp menunjukkan output sensor boleh cecah 3.4V ke atas semasa debu pekat, melebihi had input 3.3V ESP32. Penyelesaiannya pembahagi voltan mudah β 10kΩ bersiri, 20kΩ ke GND β supaya ADC hanya nampak dua pertiga voltan sebenar (maksimum sekitar 2.3V, selesa dalam julat ADC).
| Komponen | Pin / wayar | Sambung ke |
|---|---|---|
| Sensor debu (6 wayar, ikut susunan JST) | Wayar 1 (V-LED) | Perintang 150Ω → VIN (5V). Kapasitor 220µF dari wayar 1 ke GND, kaki negatif di GND |
| Wayar 2 (LED-GND) | GND | |
| Wayar 3 (LED) | GPIO25 | |
| Wayar 4 (S-GND) | GND | |
| Wayar 5 (Vo) | 10kΩ → GPIO34, kemudian 20kΩ dari GPIO34 ke GND | |
| Wayar 6 (Vcc) | VIN (5V) | |
| SCD30 | VDD | 3V3 |
| GND | GND | |
| TX/SCL | GPIO22 | |
| RX/SDA | GPIO21 | |
| OLED 0.96″ | GND | GND |
| VCC | 3V3 | |
| SCL | GPIO22 | |
| SDA | GPIO21 |

Perhatikan susunan header OLED kami dicetak GND, VCC, SCL, SDA β susunan luar biasa. Tersilap terbalikkan VCC dengan GND boleh terus merosakkan modul, jadi semak dua kali sebelum bekalkan kuasa.
SCD30 dan OLED duduk pada bus I2C yang sama (SDA=GPIO21, SCL=GPIO22 β pin I2C default ESP32) dengan alamat berbeza: 0x61 untuk SCD30, 0x3C untuk OLED, jadi tiada konflik. Biarkan pad SEL pada SCD30 kosong β itu yang memilih mod I2C. Nota teknikal: SCD30 menggunakan I2C clock stretching (30ms setiap bacaan, boleh mencecah 150ms sekali sehari) β 100kHz kelajuan default ESP32 ialah had maksimum SCD30 dan biasanya berjalan lancar; kalau bacaan kerap gagal, Sensirion syorkan 50kHz atau lebih rendah (tambah Wire.setClock(50000); selepas Wire.begin()).

Apa kod untuk baca PM2.5 dan CO2 serentak?
Sketch ini perlukan tiga library dari Arduino Library Manager: Adafruit SCD30 (terima dependency Adafruit BusIO dan Adafruit Unified Sensor bila ditanya), Adafruit GFX Library dan Adafruit SSD1306. Corak asasnya sama macam monitor suhu DHT11 + OLED kami.
Bahagian paling kritikal ialah denyut LED inframerah. Datasheet Sharp menetapkan kitaran 10ms dengan lebar denyut 0.32ms, dan sampel diambil 0.28ms selepas LED menyala. Silap timing ini punca nombor satu bacaan jadi karut.
// Monitor kualiti udara: debu (GP2Y1010AU0F) + CO2 (SCD30) + OLED
// Board: ESP32 Dev Module / NodeMCU-32S
#include <Wire.h>
#include <Adafruit_SCD30.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
const int PIN_LED_IR = 25; // wayar 3 sensor debu (kawalan IR LED, aktif LOW)
const int PIN_VO = 34; // wayar 5 -> pembahagi voltan -> GPIO34 (ADC1)
const float FAKTOR_DIVIDER = 1.5; // pembahagi 10k/20k: voltan sebenar = bacaan x 1.5
Adafruit_SCD30 scd30;
Adafruit_SSD1306 oled(128, 64, &Wire, -1);
float voltanBaseline = 3.3; // dijejak automatik: voltan terendah = udara paling bersih
float co2 = 0, suhu = 0, lembap = 0;
// Satu denyut ikut datasheet Sharp: LED ON -> 0.28ms -> sampel -> LED OFF -> genapkan 10ms
float bacaVoltanDebu() {
digitalWrite(PIN_LED_IR, LOW); // LOW = IR LED menyala
delayMicroseconds(280); // tunggu 0.28ms sebelum sampel
uint32_t mv = analogReadMilliVolts(PIN_VO); // bacaan ADC dalam milivolt (terkalibrasi)
digitalWrite(PIN_LED_IR, HIGH); // LED padam (lebar denyut ~0.32ms)
delayMicroseconds(9620); // lengkapkan kitaran ~10ms
return (mv * FAKTOR_DIVIDER) / 1000.0; // voltan sebenar pada pin Vo
}
float purataVoltanDebu() {
float jumlah = 0;
for (int i = 0; i < 30; i++) jumlah += bacaVoltanDebu(); // purata 30 denyut
return jumlah / 30.0;
}
void setup() {
Serial.begin(115200);
pinMode(PIN_LED_IR, OUTPUT);
digitalWrite(PIN_LED_IR, HIGH); // pastikan IR LED padam dulu
Wire.begin(21, 22); // SDA=21, SCL=22 (default ESP32)
if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // alamat I2C OLED
Serial.println("OLED tak dijumpai - semak wiring");
while (true) delay(10);
}
if (!scd30.begin()) { // alamat I2C SCD30 ialah 0x61
Serial.println("SCD30 tak dijumpai - semak solder dan wiring");
while (true) delay(10);
}
oled.clearDisplay();
oled.setTextSize(1);
oled.setTextColor(SSD1306_WHITE);
oled.setCursor(0, 0);
oled.println("Sensor memanas...");
oled.display();
delay(2000);
}
void loop() {
float voltanDebu = purataVoltanDebu();
// Baseline udara bersih: voltan terendah yang pernah dilihat
if (voltanDebu < voltanBaseline) voltanBaseline = voltanDebu;
// Anggaran debu: sensitiviti tipikal 0.5V per 0.1mg/m3 (datasheet Sharp)
float debu = (voltanDebu - voltanBaseline) / 0.005; // ug/m3 - ANGGARAN trend sahaja
if (debu < 0) debu = 0;
if (scd30.dataReady() && scd30.read()) {
co2 = scd30.CO2;
suhu = scd30.temperature;
lembap = scd30.relative_humidity;
}
oled.clearDisplay();
oled.setCursor(0, 0);
oled.print("Debu: "); oled.print(debu, 0); oled.println(" ug/m3");
oled.print("CO2 : "); oled.print(co2, 0); oled.println(" ppm");
oled.print("Suhu: "); oled.print(suhu, 1); oled.println(" C");
oled.print("RH : "); oled.print(lembap, 0); oled.println(" %");
oled.display();
Serial.printf("V=%.2fV debu=%.0fug/m3 CO2=%.0fppm\n", voltanDebu, debu, co2);
delay(2000);
}
Macam mana nak faham dan calibrate bacaan?
GP2Y1010AU0F mengeluarkan voltan tipikal sekitar 0.9V walaupun udara bersih (julat 0 hingga 1.5V ikut unit), dan naik lebih kurang 0.5V bagi setiap 0.1mg/m³ debu. Sebab itulah baseline udara bersih sangat penting: hidupkan alat dalam bilik paling bersih dulu supaya sketch dapat merekod voltan minimum sebagai titik sifar. Tanpa baseline, angka Β΅g/m³ anda tergantung di awang-awangan.
Baca trend, bukan digit. Kalau paparan menunjukkan bacaan dua kali ganda selepas tingkap dibuka waktu jerebu, itu isyarat sebenar; sama ada nilainya tepat 80 atau 95 Β΅g/m³ bukan soalan yang sensor kelas ini mampu jawab. Kelembapan tinggi juga menaikkan bacaan, jadi jangan panik dengan lonjakan waktu subuh yang lembap.
Untuk SCD30, datasheet Sensirion menyatakan ketepatan ±(30ppm + 3% bacaan) dalam julat 400 hingga 10,000ppm β cukup baik untuk keputusan pengudaraan. Ciri automatic self-calibration (ASC) pula ada syarat: sensor perlu berkuasa berterusan sekurang-kurangnya 7 hari dan menghidu udara segar (~400ppm) sekurang-kurangnya 1 jam setiap hari. Kalau unit anda duduk 24 jam dalam bilik tertutup, ASC tiada rujukan β buka tingkap seketika setiap hari, atau biarkan ASC dimatikan (default sensor).

Apa kesilapan biasa yang kami selalu nampak?
Corak yang sama berulang dengan GP2Y1010AU0F dan SCD30, jadi semak senarai ini sebelum anda syak sensor rosak.
Langkau perintang dan kapasitor. Tanpa rangkaian 150Ω/220µF itu, denyut IR LED tak stabil dan bacaan jadi rawak sepenuhnya. Ini bukan komponen “tambah baik” β ia sebahagian daripada litar sensor.
Output debu di pin ADC2. Semuanya elok semasa testing, kemudian bacaan mati mendadak bila WiFi dihidupkan. Pindahkan ke GPIO32 hingga 39 dan masalah hilang.
Terbalik VCC/GND pada OLED. Susunan GND, VCC, SCL, SDA memang mudah mengelirukan sesiapa yang biasa dengan modul susunan VCC dahulu β dan silap ini boleh membunuh modul serta-merta.
SCD30 tak dikesan pada 0x61. Hampir selalu puncanya solder joint sejuk pada pad castellation. Panaskan semula setiap sambungan dan cuba lagi.
Sensor debu dibekalkan 3.3V. Ia sensor 5V β bekalkan dari pin VIN semasa berkuasa USB, barulah voltan output bermakna.
Board langsung tak muncul di Arduino IDE. NodeMCU-32S guna cip CP2102, yang perlukan driver SiLabs. Ikut panduan ESP32 tak detect / upload gagal kami.
Soalan lazim
Boleh tak saya guna bacaan ini untuk lapor API?
Tak boleh. API ialah indeks terkira daripada stesen rujukan Jabatan Alam Sekitar, mengambil sub-indeks tertinggi antara beberapa pencemar dengan purata 24 jam untuk PM2.5. Sensor optik ini pula memberi trend relatif yang tak terkalibrasi β sangat berguna untuk rumah anda, tapi bukan angka API.
Kenapa bacaan debu naik turun walaupun bilik nampak bersih?
Tiga sebab biasa: kelembapan tinggi (titisan halus air turut memantul cahaya IR), baseline belum stabil, dan hingar semula jadi ADC. Purata 30 denyut dalam sketch sudah membantu β tambah purata bergerak kalau nak lebih tenang.
Perlu ke saya calibrate sensor ini?
Sensor debu perlukan baseline udara bersih sahaja β hidupkan di kawasan bersih dan sketch akan merekodnya sendiri. SCD30 pula datang terkalibrasi dari kilang; ASC pilihan tambahan yang hanya berfungsi kalau sensor kerap menghidu udara segar.
Boleh tak hantar bacaan ke telefon?
Boleh β sebab itulah kita pilih ESP32 yang ada WiFi terbina. Hantar bacaan ke platform seperti Blynk, Home Assistant atau MQTT broker. Pastikan output sensor debu kekal di pin ADC1 supaya WiFi dan ADC tak berebut.
Sesuai tak untuk projek sekolah atau FYP?
Sangat sesuai. Ia gabungkan bacaan analog berdenyut, bus I2C berkongsi dua peranti dan paparan masa nyata β dan data trend yang dikumpul semasa musim jerebu ialah bahan analisis sebenar untuk laporan. Cuma nyatakan dengan jujur dalam laporan: ini penunjuk trend, bukan instrumen rujukan.
Kemas kini terakhir Ogos 2026. Tersangkut? Chat dengan kami di WhatsApp.



NodeMCU ESP32 Wi-Fi + Bluetooth Development Board CH340/CP2012 - For IOT Project - ESP-32(CP2102)
PM2.5 Air Quality Sensor Module Digital Dust Detector DC01
SCD30 High Precision NDIR CO2 Carbon Dioxide Temperature Humidity Sensor Module I2C Interface Arduino Compatible
0.96β OLED Display Module Blue White Screen I2C IIC Serial 128X64 LCD Display Board - 0.96' OLED WHITE