Pendahuluan & Tujuan Pembelajaran

Bagian ini memberikan gambaran umum tentang modul praktik IoT Penyiram Tanaman Otomatis. Anda dapat melihat sasaran pembelajaran serta metadata kelas untuk menyesuaikan penyampaian materi kepada siswa. Tujuannya adalah untuk memahami esensi proyek sebelum memulai perakitan fisik.

âąī¸ Informasi Praktik

  • Topik: Sistem Kontrol Otomatis
  • Tingkat: SMP / SMA / SMK
  • Estimasi Waktu: 2 - 3 Jam Pelajaran

đŸŽ¯ Kompetensi Siswa

  • Memahami konsep dasar Internet of Things (IoT).
  • Merangkai mikrokontroler (Wemos D1 Mini) dengan sensor dan aktuator.
  • Menghubungkan hardware ke Cloud (Blynk) dan API (WhatsApp).
  • Melakukan kalibrasi sensor analog sederhana.

Persiapan Alat & Bahan

Gunakan daftar periksa interaktif ini untuk memastikan setiap kelompok siswa telah memiliki komponen yang lengkap sebelum merakit. Klik pada setiap kartu untuk menandai item tersebut sebagai "Tersedia". Ini membantu pengorganisasian kelas yang lebih baik.

Progres Persiapan: 0/7 Selesai
🧠

Wemos D1 Mini

Mikrokontroler ESP8266 + Kabel Micro USB

🌱

Sensor Kelembaban

Soil Moisture Sensor (Analog)

💧

Pompa Air Mini

Water Pump 5V DC + Selang kecil

⚡

Modul Relay

1-Channel (5V) untuk kontrol arus pompa

đŸ“ē

LCD 16x2

Lengkap dengan modul I2C terpasang

🔌

Kabel Jumper

Male-to-Female dan Female-to-Female

đŸĨ¤

Bahan Simulasi

1 Gelas air tawar & 1 Gelas kosong/tanah kering

Tahap 1: Perakitan (Wiring)

Ikuti langkah perakitan interaktif ini. Guru membimbing siswa merangkai komponen dengan hati-hati. Mengisolasi setiap tahap perakitan meminimalkan risiko korsleting atau kesalahan pin. Klik pada masing-masing komponen untuk melihat detail koneksi pin ke Wemos D1 Mini.

âš ī¸ Peringatan Keselamatan: Pastikan Wemos BELUM terhubung ke komputer atau listrik saat merangkai.

Koneksi: Sensor Kelembaban

  • Pin Sensor VCC ➔ Wemos 3.3V / 5V
  • Pin Sensor GND ➔ Wemos GND
  • Pin Sensor A0 (Analog) ➔ Wemos A0

Koneksi: Modul Relay & Pompa

  • Relay VCC/DC+ ➔ Wemos 5V (VU/Vin)
  • Relay GND/DC- ➔ Wemos GND
  • Relay IN/Data ➔ Wemos D7
Sambungan Pompa: Potong satu kabel pompa (merah). Hubungkan ujung satu ke COM relay, ujung lainnya ke NO (Normally Open). Sisa kabel ke sumber listrik.

Koneksi: LCD 16x2 (I2C)

  • Pin LCD VCC ➔ Wemos 5V (VU/Vin)
  • Pin LCD GND ➔ Wemos GND
  • Pin LCD SDA ➔ Wemos D2
  • Pin LCD SCL ➔ Wemos D1

Tahap 2 & 3: Cloud & Kode

Di bagian ini, pelajari struktur platform yang digunakan (Arduino IDE, Blynk Cloud, dan Fonnte WhatsApp API). Di bawah ini Anda dapat menyalin program Arduino secara lengkap. Arahkan siswa untuk mengubah nilai kredensial saja pada baris teratas kode.

â˜ī¸ Pengaturan Blynk IoT

Virtual Pin Tipe Data Fungsi / Widget
V0 Integer (0-100) Kelembaban (%) - Gauge
V1 String Status Sistem - Value Display
V2 Integer (0-1) Mode Auto/Manual - Switch
V3 Integer (0-1) Tombol Pompa - Switch

âœī¸ Panduan Library & Board

Sebelum mengunggah kode, pastikan di Arduino IDE sudah terinstal:

  • Library Blynk (oleh Volodymyr Shymanskyy)
  • Library LiquidCrystal I2C (oleh Frank de Brabander)

Pastikan juga Board yang terpilih di menu Tools adalah:
LOLIN(WEMOS) D1 R2 & mini

📄 Smart_Farming.ino
/*
  Proyek      : IoT Pengukur Kelembaban Tanah & Penyiram Otomatis
  Board       : Wemos D1 Mini (ESP8266)
  Integrasi   : Blynk IoT & WhatsApp API Fonnte
*/

// --- BLYNK CREDENTIALS (HARUS DI PALING ATAS) ---
#define BLYNK_TEMPLATE_ID "TMPL6xTjYZOFa"   // Ganti dengan Template ID Blynk
#define BLYNK_TEMPLATE_NAME "Smart Farming"   // Ganti dengan Template Name Blynk
#define BLYNK_AUTH_TOKEN "fzPEGMjL7ZE2kWebrpYC-oqhTThRqdzT";   // Ganti dengan token Blynk

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <LiquidCrystal_I2C.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecure.h>

// --- KONFIGURASI WIFI ---
char ssid[] = "NAMA_WIFI_ANDA";       // Ganti dengan nama WiFi Anda
char pass[] = "PASSWORD_WIFI_ANDA";   // Ganti dengan password WiFi Anda

// --- KONFIGURASI FONNTE WA ---
String fonnteToken = "xxxxxxxxxx";   // Ganti dengan Token API WA
String targetWA = "08xxxxxxxxxxxxxx";   // Ganti dengan no WA Tujuan

// --- KONFIGURASI PIN & HARDWARE ---
#define SENSOR_PIN A0
#define RELAY_PIN D7   // Pin D7 terhubung ke Relay Pompa

// Jika relay Anda aktif LOW (nyala saat diberi logika LOW), ubah nilai di bawah ini:
// PUMP_ON = LOW, PUMP_OFF = HIGH
#define PUMP_ON LOW
#define PUMP_OFF HIGH

LiquidCrystal_I2C lcd(0x27, 16, 2); // Alamat I2C biasanya 0x27 atau 0x3F
BlynkTimer timer;

// --- VARIABEL GLOBAL ---
int moisturePercent = 0;
bool isAutoMode = true;   // Default mode Auto
bool isPumpOn = false;
bool waSent = false;      // Mencegah spam WA (Hanya dikirim sekali saat mulai kering)

// Batas kelembaban (Sesuai permintaan: Kering < 25%, Basah >= 80%)
const int DRY_THRESHOLD = 25; 
const int WET_THRESHOLD = 80; 

void setup() {
  Serial.begin(115200);
  
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, PUMP_OFF); // Pastikan pompa mati saat awal

  // Inisialisasi LCD
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Memulai Sistem..");
  
  // Inisialisasi Blynk & WiFi
  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
  
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("WiFi Terhubung!");
  delay(1000);

  // Set interval pembacaan sensor setiap 2 detik
  timer.setInterval(2000L, processSensor);
  
  // Set default state Blynk
  Blynk.virtualWrite(V2, 0); // Set ke Mode Auto
  Blynk.virtualWrite(V3, 0); // Matikan tombol manual
}

void loop() {
  Blynk.run();
  timer.run();
}

// --- FUNGSI PEMBACAAN SENSOR & LOGIKA AUTO ---
void processSensor() {
  int sensorValue = analogRead(SENSOR_PIN);
  
  // Berdasarkan pengujian, nilai analog basah maksimal sensor ada di kisaran 750.
  moisturePercent = map(sensorValue, 1023, 750, 0, 100); 
  
  // Batasi nilai persentase agar tidak tembus 0-100
  if (moisturePercent > 100) moisturePercent = 100;
  if (moisturePercent < 0) moisturePercent = 0;

  Serial.print("Kelembaban: ");
  Serial.print(moisturePercent);
  Serial.println("%");

  // Update ke Blynk dan LCD
  Blynk.virtualWrite(V0, moisturePercent);
  updateLCD();

  // Logika Mode Otomatis
  if (isAutoMode) {
    if (moisturePercent < DRY_THRESHOLD && !isPumpOn) {
      // Tanah Kering -> Nyalakan Pompa
      turnPump(true);
      Blynk.virtualWrite(V1, "Kering - Menyiram");
      
      // Kirim WA hanya sekali saat baru terdeteksi kering
      if (!waSent) {
        sendWA("Peringatan: Tanah kering (" + String(moisturePercent) + "%). Pompa air sedang menyiram tanaman.");
        waSent = true; 
      }
    } 
    else if (moisturePercent >= WET_THRESHOLD && isPumpOn) {
      // Tanah Basah Cukup -> Matikan Pompa
      turnPump(false);
      Blynk.virtualWrite(V1, "Tanah Basah - OK");
      
      // Reset flag WA agar bisa mengirim lagi jika nanti kering
      waSent = false;
      sendWA("Info: Kelembaban tanah sudah cukup (" + String(moisturePercent) + "%). Pompa dimatikan.");
    }
    else if (!isPumpOn) {
      Blynk.virtualWrite(V1, "Normal");
      waSent = false; // Reset jika status normal tapi belum basah maksimal
    }
  }
}

// --- FUNGSI KONTROL POMPA ---
void turnPump(bool state) {
  isPumpOn = state;
  if (state) {
    digitalWrite(RELAY_PIN, PUMP_ON);
    Blynk.virtualWrite(V3, 1); // Update tombol di Blynk
    Serial.println("Pompa MENYALA");
  } else {
    digitalWrite(RELAY_PIN, PUMP_OFF);
    Blynk.virtualWrite(V3, 0); // Update tombol di Blynk
    Serial.println("Pompa MATI");
  }
}

// --- FUNGSI UPDATE TAMPILAN LCD ---
void updateLCD() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Lembab: ");
  lcd.print(moisturePercent);
  lcd.print("%");

  lcd.setCursor(0, 1);
  if (isPumpOn) {
    lcd.print("Pompa:NYALA");
  } else {
    lcd.print("Pompa:MATI ");
  }
  
  if (isAutoMode) {
    lcd.print("(OTO)");
  } else {
    lcd.print("(MAN)");
  }
}

// --- BLYNK VIRTUAL WRITE (MENERIMA INPUT DARI APLIKASI) ---

// Mode Switch (V2)
BLYNK_WRITE(V2) {
  int mode = param.asInt();
  if (mode == 1) {
    isAutoMode = false; // Mode Manual
    Blynk.virtualWrite(V1, "Mode: MANUAL");
  } else {
    isAutoMode = true;  // Mode Auto
    waSent = false;     // Reset flag WA saat kembali ke auto
  }
  updateLCD();
}

// Manual Pump Control Switch (V3)
BLYNK_WRITE(V3) {
  int pumpControl = param.asInt();
  
  if (!isAutoMode) {
    if (pumpControl == 1) {
      turnPump(true);
      Blynk.virtualWrite(V1, "Manual: Menyiram");
    } else {
      turnPump(false);
      Blynk.virtualWrite(V1, "Manual: Siaga");
    }
    updateLCD();
  } else {
    // Jika masih mode Auto tapi user mencoba tekan tombol pompa,
    // kembalikan tombol ke state aslinya (ditolak)
    Blynk.virtualWrite(V3, isPumpOn ? 1 : 0);
  }
}

// --- FUNGSI KIRIM WHATSAPP VIA FONNTE ---
void sendWA(String message) {
  if (WiFi.status() == WL_CONNECTED) {
    WiFiClientSecure client;
    client.setInsecure(); // Abaikan SSL untuk ESP8266 agar tidak berat
    HTTPClient http;

    Serial.println("Mengirim WA...");
    
    // Ganti spasi dengan %20 untuk format URL (URL Encoding sederhana)
    message.replace(" ", "%20");
    
    http.begin(client, "https://api.fonnte.com/send");
    http.addHeader("Authorization", fonnteToken);
    http.addHeader("Content-Type", "application/x-www-form-urlencoded");

    String postData = "target=" + targetWA + "&message=" + message;
    
    int httpResponseCode = http.POST(postData);

    if (httpResponseCode > 0) {
      Serial.print("WA Terkirim. Kode: ");
      Serial.println(httpResponseCode);
    } else {
      Serial.print("Gagal kirim WA. Kesalahan: ");
      Serial.println(httpResponseCode);
    }
    http.end();
  } else {
    Serial.println("WiFi terputus, gagal kirim WA.");
  }
}

Tahap 4: Simulasi Logika Sistem

Visualisasikan bagaimana algoritma sistem bereaksi terhadap perubahan data kelembaban tanah. Gunakan tombol di bawah grafik untuk mensimulasikan kondisi "2 Gelas" di kelas. Grafik memetakan kelembaban secara real-time, menunjukkan batas pemicu (threshold) 25% (kering/pompa ON) dan 80% (basah/pompa OFF).

Display LCD 16x2

Lembab: 65%
Pompa:MATI (OTO)

Status Komponen

Relay / Pompa
OFF
Notifikasi WA
📱
Standby

â„šī¸ Konsep Kunci yang Diajarkan:

Logika pemrograman menggunakan Histeresis. Pompa menyala di titik kritis bawah (< 25%), namun tidak langsung mati di 26%. Pompa akan terus menyala hingga mencapai batas optimal kenyang air (>= 80%). Ini mencegah pompa terus-menerus menyala-mati (cycling) dengan cepat yang dapat merusak komponen fisik.

💡 Pemecahan Masalah (Troubleshooting)

Solusi cepat untuk kendala umum yang sering dihadapi siswa selama praktik di dalam kelas. Klik pada setiap gejala masalah untuk melihat solusi teknis dan penjelasan logisnya.

Solusi Kontras: Putar potensiometer kecil berwarna biru di belakang modul I2C LCD menggunakan obeng plus kecil secara perlahan hingga tulisan terlihat jelas.

Solusi Alamat I2C: Jika backlight nyala tapi tidak ada teks setelah kontras diputar, kemungkinan alamat I2C di kode program salah. Ubah `LiquidCrystal_I2C lcd(0x27, 16, 2);` menjadi `0x3F`.

Penyebab: Banyak modul relay di pasaran menggunakan sistem "Active Low" (menyala saat dikirim sinyal 0 / LOW).

Solusi Kode: Minta siswa membuka kode program dan memodifikasi definisi konstanta logika. Ubah baris `#define PUMP_ON LOW` menjadi `HIGH`, dan sebaliknya untuk `PUMP_OFF`.

Penyebab: Sensor fisik memerlukan kalibrasi. Resistansi air tiap daerah berbeda, batas analog tidak persis 0 atau 1023.

Solusi Kalibrasi: Minta siswa melihat nilai analog mentah di "Serial Monitor". Jika saat direndam mentok di angka 750, ubah rumus map di kode: `map(sensorValue, 1023, 750, 0, 100);`. Nilai 750 adalah batas basah maksimal yang terbaca secara fisik.