🎓 Materi Workshop Interaktif

Predictive Analytics
Kualitas Udara Berbasis IoT

Belajar membangun sistem monitoring udara realtime dari sensor fisik hingga dashboard web — lengkap dengan Machine Learning Decision Tree.

Download Materi

⏱️ Durasi 2 Jam
🎯 Pemula – Menengah
🔧 ESP32 + PHP + MySQL
🤖 Decision Tree ML
Scroll ke bawah
🎯 Tujuan

Apa yang Akan Kamu Pelajari?

Setelah workshop ini selesai, kamu akan bisa membangun sistem IoT end-to-end dari nol.

📡
Konsep IoT
Memahami alur data dari sensor fisik ke dashboard web secara realtime.
🔌
Hardware ESP32
Menghubungkan ESP32 + MQ135 + DHT11 dan memprogram pengiriman data.
🖥️
REST API PHP
Membangun backend API sederhana dengan PHP Native dan MySQL.
🤖
Decision Tree
Menerapkan algoritma klasifikasi untuk memprediksi kualitas udara.
📊
Dashboard Web
Menampilkan grafik dan data realtime menggunakan Chart.js dan AJAX.
🔬
Analisis Data
Membaca tren, pola harian, dan statistik dari data sensor historis.
🗺️ Arsitektur

Alur Sistem GoIoT

Begini cara semua komponen saling terhubung.

🔌
ESP32
MQ135 + DHT11
HTTP POST
JSON
🖥️
PHP Server
XAMPP / Apache
SQL Query
🗄️
MySQL
sensor_data
JSON API Response
📊
Dashboard
Browser / Chart.js
Fetch setiap
5 detik
🤖
Decision Tree
Klasifikasi ML
⏱️ Jadwal

Rundown Workshop 2 Jam

Setiap sesi dirancang fokus dan padat agar semua materi tersampaikan.

00:00
Sesi 1
🌐 Pengenalan IoT & Arsitektur Sistem
Konsep IoT, komponen hardware, dan gambaran besar alur sistem GoIoT.
15 menit
00:15
Sesi 2
🔌 Setup Hardware & Pemrograman ESP32
Wiring sensor, instalasi library Arduino, dan kode pengiriman data via HTTP POST.
20 menit
00:35
Sesi 3
🖥️ Backend PHP & Database MySQL
Setup XAMPP, buat database, konfigurasi API endpoint penerima dan pengirim data.
20 menit
00:55
Sesi 4
🤖 Algoritma Decision Tree
Konsep ML, pohon keputusan GoIoT, implementasi PHP, dan latihan prediksi interaktif.
25 menit
01:20
Sesi 5
📊 Dashboard & Visualisasi Data
Arsitektur frontend, fetch API dengan async/await, update Chart.js realtime.
25 menit
01:45
Sesi 6
🚀 Demo, Tanya Jawab & Penutup
Demo end-to-end, simulasi tanpa hardware, ide pengembangan lanjutan.
15 menit

1

Pengenalan IoT & Arsitektur

⏱️ 15 menit  |  🌐 Konsep dasar dan gambaran sistem

💡 Apa itu IoT?

Internet of Things (IoT) adalah konsep menghubungkan perangkat fisik ke internet agar bisa mengumpulkan, mengirim, dan menerima data secara otomatis — tanpa campur tangan manusia setiap saat.

🔌
ESP32
Mikrokontroler WiFi built-in. Otak dari seluruh sistem. Harga ~Rp 50.000.
💨
MQ135
Sensor gas & polutan udara. Output nilai analog yang dikonversi ke ppm.
🌡️
DHT11
Sensor suhu (°C) dan kelembaban (%). Komunikasi digital 1-wire.
🖥️
PHP + MySQL
Backend server menerima data, menjalankan ML, dan menyimpan ke database.
📈
Chart.js
Library JavaScript untuk grafik interaktif di browser.
💡
Kenapa ESP32? WiFi & Bluetooth built-in, 2 core processor, ADC 12-bit (0–4095), kompatibel Arduino IDE, dan harganya sangat terjangkau dibanding Arduino + WiFi shield terpisah.

📊 Perbandingan Mikrokontroler Populer

ESP32 (WiFi built-in)Sangat Direkomendasikan
Arduino Uno (tanpa WiFi)Butuh modul tambahan
Raspberry Pi (Linux)Overkill untuk sensor sederhana

2

Setup Hardware & ESP32

⏱️ 20 menit  |  🔌 Wiring, library, dan kode Arduino

🔌 Skema Wiring

💨 ESP32 → MQ135

5V/Vin
VCC
GND
GND
Pin 34 (ADC)
AOUT

🌡️ ESP32 → DHT11

3.3V
VCC (Pin 1)
GND
GND (Pin 4)
Pin 4 (DATA)
DATA (Pin 2)
📌
Pasang resistor 10kΩ antara pin VCC dan DATA pada DHT11 (pull-up resistor). Tanpa ini, pembacaan bisa tidak stabil.
Note: Untuk DHT11 yang masih bentuk module
📦 Library Arduino yang Dibutuhkan
📚
DHT sensor library
by Adafruit — untuk membaca suhu dan kelembaban dari DHT11/DHT22.
📚
Adafruit Unified Sensor
Dependensi wajib untuk library DHT Adafruit.
📚
ArduinoJson
by Benoit Blanchon — serialize/deserialize JSON untuk komunikasi HTTP.
💻 Kode ESP32 — Konfigurasi WiFi & Server
esp32_sensor.ino — Konfigurasi
// ── Ganti dengan data WiFi dan IP server kalian ──
const char* WIFI_SSID     = "NAMA_WIFI_ANDA";
const char* WIFI_PASSWORD = "PASSWORD_WIFI_ANDA";
const char* SERVER_URL    = "http://192.168.1.100/goiot/api/sensor.php";
//                                  ^^^^^^^^^^^
//                      Ganti dengan IP komputer kalian
//                      Cek dengan: ipconfig (Windows)

// ── Pin & Interval ──
#define MQ135_PIN   34    // ADC Pin
#define DHT_PIN     4     // Data Pin DHT11
const unsigned long SEND_INTERVAL = 10000; // 10 detik
💻 Membaca Sensor & Kirim Data
esp32_sensor.ino — readAndSendData()
void readAndSendData() {
  // Baca MQ135 — ADC 12-bit: nilai 0 sampai 4095
  int rawMQ135 = analogRead(MQ135_PIN);
  
  // Konversi ke ppm (kalibrasi linear sederhana)
  float mq135 = map(rawMQ135, 0, 4095, 0, 500);

  // Baca suhu dan kelembaban dari DHT11
  float suhu       = dht.readTemperature();
  float kelembaban = dht.readHumidity();

  // Validasi — DHT11 kadang gagal baca
  if (isnan(suhu) || isnan(kelembaban)) {
    Serial.println("[ERROR] Gagal baca DHT11!");
    return;
  }

  // Kirim ke server PHP
  sendToServer(mq135, suhu, kelembaban);
}

void sendToServer(float mq135, float suhu, float kelembaban) {
  // Buat JSON payload
  StaticJsonDocument<200> doc;
  doc["mq135"]      = mq135;
  doc["suhu"]       = suhu;
  doc["kelembaban"] = kelembaban;

  String payload;
  serializeJson(doc, payload); // → {"mq135":85.2,"suhu":28.0,"kelembaban":65.0}

  // HTTP POST
  HTTPClient http;
  http.begin(SERVER_URL);
  http.addHeader("Content-Type", "application/json");
  int httpCode = http.POST(payload);
}

✅ Checklist Sesi 2

Wiring MQ135 dan DHT11 sudah benar
Library DHT, Adafruit Sensor, ArduinoJson sudah terinstall
SSID, Password, dan SERVER_URL sudah diganti
Upload berhasil, Serial Monitor menampilkan data sensor

3

Backend PHP & Database

⏱️ 20 menit  |  🖥️ XAMPP, MySQL, dan REST API

🗄️ Setup Database
1️⃣
Buka phpMyAdmin
Akses localhost/phpmyadmin di browser.
2️⃣
Buat Database
Klik New → beri nama goiot → klik Create.
3️⃣
Import SQL
Tab Import → pilih file database.sql → klik Go.
💻 Struktur Tabel
database.sql
CREATE TABLE sensor_data (
  id          INT AUTO_INCREMENT PRIMARY KEY,
  mq135       FLOAT NOT NULL,    -- Nilai polutan (ppm)
  suhu        FLOAT NOT NULL,    -- Suhu Celsius
  kelembaban  FLOAT NOT NULL,    -- Kelembaban %
  prediksi    VARCHAR(20),       -- Baik / Sedang / Buruk
  timestamp   DATETIME DEFAULT CURRENT_TIMESTAMP
);
💻 Konfigurasi Database
config/database.php
define('DB_HOST', 'localhost');
define('DB_USER', 'root');   // default XAMPP
define('DB_PASS', '');       // default XAMPP (kosong)
define('DB_NAME', 'goiot');
💻 Endpoint Penerima Data (api/sensor.php)
api/sensor.php — Alur Proses
// 1. Terima JSON dari ESP32
$body       = json_decode(file_get_contents('php://input'), true);
$mq135      = (float) $body['mq135'];
$suhu       = (float) $body['suhu'];
$kelembaban = (float) $body['kelembaban'];

// 2. Jalankan Decision Tree → dapat label prediksi
$prediksi = DecisionTree::predict($mq135, $suhu, $kelembaban);

// 3. Simpan ke database
$model->insert($mq135, $suhu, $kelembaban, $prediksi['label']);

// 4. Kirim response JSON ke ESP32
echo json_encode(['status' => 'success', 'prediksi' => $prediksi]);
🔗 Semua Endpoint API
MethodURLFungsi
POST/api/sensor.phpTerima data dari ESP32
GET/api/data.php?type=latest1 data terbaru (realtime)
GET/api/data.php?type=statsStatistik ringkasan
GET/api/data.php?type=chartData grafik 24 jam
GET/api/data.php?type=analysisAnalisis 7 hari
GET/api/predict.php?mq135=120&suhu=30&kelembaban=70Prediksi manual

✅ Checklist Sesi 3

Database goiot sudah dibuat dan tabel sudah ada
config/database.php sudah dikonfigurasi
Akses http://localhost/goiot tidak error
API ?type=latest mengembalikan JSON yang benar

4

Algoritma Decision Tree

⏱️ 25 menit  |  🤖 Machine Learning untuk klasifikasi udara

Decision Tree adalah algoritma ML yang membuat keputusan seperti diagram alur. Setiap node adalah pertanyaan, setiap cabang adalah jawaban, dan setiap daun adalah hasil akhir. Analogi: seperti kunci determinasi biologi.

🌳 Pohon Keputusan GoIoT
🔍 MQ135 < 100 ppm?
YA
TIDAK
🌡️ Suhu < 30°C?
🔍 MQ135 < 130 ppm?
YA
TIDAK
YA
TIDAK
✅ BAIK
95% confidence
⚠️ SEDANG
80% confidence
⚠️ SEDANG
85% confidence
🚨 BURUK
88–95% confidence
📋 Tabel Aturan Klasifikasi
MQ135 (ppm)Suhu (°C)Kelembaban (%)HasilConfidence
< 100< 30✅ Baik95%
< 100≥ 30⚠️ Sedang80%
100 – 129< 70⚠️ Sedang85%
100 – 129≥ 70⚠️ Sedang70%
≥ 130🚨 Buruk88–95%
💻 Implementasi PHP
model/DecisionTree.php
public static function predict(float $mq135, float $suhu, float $kelembaban): array {

  if ($mq135 < 100) {
    // Polutan rendah — cek suhu sebagai faktor sekunder
    if ($suhu < 30) {
      return self::result('Baik', 95.0, 'MQ135 rendah dan suhu normal');
    } else {
      return self::result('Sedang', 80.0, 'MQ135 rendah tapi suhu tinggi');
    }

  } elseif ($mq135 < 130) {
    // Polutan sedang — kelembaban memperburuk kondisi
    if ($kelembaban < 70) {
      return self::result('Sedang', 85.0, 'MQ135 sedang, kelembaban normal');
    } else {
      return self::result('Sedang', 70.0, 'MQ135 sedang + kelembaban tinggi');
    }

  } else {
    // Polutan tinggi — langsung Buruk
    return self::result('Buruk', 95.0, 'MQ135 melewati batas aman');
  }
}
🧪 Latihan Interaktif — Prediksi Manual
🎮 Coba prediksi sendiri sebelum lihat jawabannya!
Kasus 1: Udara pagi hari yang segar
Kasus 2: Siang hari di area padat kendaraan
Kasus 3: Dekat pabrik saat hujan
Kasus 4: Masukkan nilai sendiri!

✅ Checklist Sesi 4

Memahami cara kerja Decision Tree (node, cabang, daun)
Bisa menelusuri pohon keputusan secara manual
Latihan prediksi interaktif sudah dicoba semua
Memahami mengapa threshold 100 dan 130 ppm dipilih

5

Dashboard & Visualisasi Data

⏱️ 25 menit  |  📊 Frontend, AJAX, dan Chart.js

🏗️ Arsitektur Frontend
Semua fungsi dipanggil otomatis setiap 5 detik
index.php (HTML)
→ loads
dashboard.js
Controller utama
├─ fetchLatest() → kartu sensor realtime
├─ fetchStats() → kartu statistik
├─ fetchChartData() → grafik 24 jam
├─ fetchTableData() → tabel historis
└─ fetchAnalysis() → analisis 7 hari
💻 Auto-Refresh dengan setInterval
dashboard.js — Inisialisasi
document.addEventListener('DOMContentLoaded', () => {
  initCharts();              // Buat chart kosong dulu
  fetchAll();                // Fetch data pertama kali
  setInterval(fetchAll, 5000); // Ulangi setiap 5 detik
});

async function fetchAll() {
  // Jalankan semua fetch secara paralel (lebih cepat)
  await Promise.all([
    fetchLatest(),
    fetchStats(),
    fetchChartData(),
    fetchTableData(),
    fetchAnalysis(),
  ]);
}
💻 Fetch Data dari API (async/await)
dashboard.js — fetchLatest()
async function fetchLatest() {
  try {
    // Panggil API — async/await lebih mudah dibaca dari .then()
    const res  = await fetch(`${API_BASE}/data.php?type=latest`);
    const json = await res.json();

    if (json.status !== 'success' || !json.data) return;

    const d = json.data;

    // Update elemen HTML berdasarkan id
    document.getElementById('val-mq135').textContent = parseFloat(d.mq135).toFixed(1);
    document.getElementById('val-suhu').textContent  = parseFloat(d.suhu).toFixed(1);

  } catch (e) {
    console.error('fetchLatest error:', e);
  }
}
🔧 Troubleshooting Umum
MasalahPenyebabSolusi
Data tidak tampilPath API salahCek API_BASE di dashboard.js
Grafik kosongBelum ada data 24 jamInsert data dummy dari database.sql
ESP32 tidak konekIP server salahCek ipconfig, pastikan satu jaringan
DHT11 errorWiring / resistor kurangCek pin dan pasang resistor 10kΩ
500 Error APIKoneksi DB gagalCek config/database.php

✅ Checklist Sesi 5

Dashboard terbuka di http://localhost/goiot
Kartu sensor menampilkan data (bukan --)
Grafik 24 jam menampilkan data
Section analisis 7 hari tampil dengan benar

6

Demo, Tanya Jawab & Penutup

⏱️ 15 menit  |  🚀 Demo end-to-end dan pengembangan lanjutan

🎬 Urutan Demo End-to-End
1️⃣
Serial Monitor
Tunjukkan data sensor terbaca dan terkirim di Arduino Serial Monitor.
2️⃣
Dashboard Live
Kartu realtime berubah setiap 10 detik sesuai data ESP32.
3️⃣
phpMyAdmin
Tabel sensor_data bertambah baris baru secara otomatis.
4️⃣
Test API
Buka endpoint di browser, tunjukkan response JSON langsung.
5️⃣
Ubah Sensor
Dekatkan tangan ke MQ135 — lihat prediksi berubah di dashboard.
💻 Simulasi Tanpa Hardware (Postman / curl)
Terminal / CMD
# Kirim data simulasi ke server
curl -X POST http://localhost/goiot/api/sensor.php \
  -H "Content-Type: application/json" \
  -d '{"mq135": 145, "suhu": 32, "kelembaban": 78}'
🚀 Ide Pengembangan Lanjutan
IdeTeknologiKesulitan
Notifikasi WhatsApp saat udara burukFonnte / Twilio APIMudah
Simpan data ke cloudFirebase / AWS IoTMenengah
Model ML yang lebih akuratPython scikit-learnMenengah
Tambah sensor CO2 (MH-Z19)Arduino libraryMudah
Export data ke ExcelPHP PhpSpreadsheetMudah
Autentikasi login dashboardPHP Session / JWTMenengah
Prediksi dengan Random ForestPython + PHP bridgeLanjutan
📚 Referensi Belajar Lebih Lanjut
📖
ESP32 Docs
docs.espressif.com — dokumentasi resmi ESP32
📖
ArduinoJson
arduinojson.org — panduan lengkap JSON di Arduino
📖
Chart.js
chartjs.org — dokumentasi grafik interaktif
📖
Decision Tree
scikit-learn.org — Decision Tree untuk ML lanjutan