Tirai kecil yang terbuka sendiri saat pagi terang dan menutup saat malam. Stepper 28BYJ-48 menggulung tali tirai, dan LDR menilai terang-gelap. Dari Klenik tirai bisa dibuka-tutup manual, dan mode otomatis bisa dinyalakan kembali kapan saja.
Penggerak stepper sama dengan proyek 095. Tirai dianggap tertutup saat ESP32 menyala (posisi 0) dan terbuka penuh setelah 5 putaran motor. Ukur jumlah putaran yang pas untuk tirai atau gulungan tali milikmu, lalu ubah LANGKAH_BUKA.
LDR dibaca setiap 5 detik. Ada dua batas: tirai dibuka kalau angka di bawah 1500 (terang) dan ditutup kalau di atas 3000 (gelap). Di antara keduanya, misalnya saat mendung atau senja, tirai tidak bergerak, jadi tidak buka-tutup bolak-balik.
Perintah manual dari dashboard otomatis mematikan mode otomatis. Kalau tidak, tirai yang kamu tutup siang hari akan langsung dibuka lagi oleh LDR.
Komponen
| Komponen | Qty | Harga |
|---|---|---|
| ESP32 DOIT DevKit V1 30 pin | 1 | Rp75.000 |
| Motor Stepper 28BYJ-48 DC 5V 4-Phase 5-Wire Ardu | 1 | Rp15.500 |
| Driver Stepper ULN2003 5V 28BYJ-48 Module Board | 1 | Rp10.000 |
| Modul sensor cahaya LDR | 1 | Rp7.200 |
| Kabel jumper female-female 10 cm (isi 10)isi 10, terpakai 9 | 1 | Rp3.500 |
| Kabel micro USB data 30 cmopsional, kalau belum punya kabel micro USB data | 1 | Rp11.700 |
| Total (tanpa opsional) | Rp111.200 |
Langkah 1: Rangkai komponen
Sambungkan kabel sesuai gambar di atas. Kalau gambar dan tabel terlihat berbeda, ikuti tabel.
| Dari | Ke | Kabel | |
|---|---|---|---|
| ULN2003 + stepper 28BYJ-48 IN1 | → | D19 GPIO19 | biru |
| ULN2003 + stepper 28BYJ-48 IN2 | → | D18 GPIO18 | hijau |
| ULN2003 + stepper 28BYJ-48 IN3 | → | D5 GPIO5 | kuning |
| ULN2003 + stepper 28BYJ-48 IN4 | → | D4 GPIO4 | oranye |
| ULN2003 + stepper 28BYJ-48 − | → | GND | hitam |
| ULN2003 + stepper 28BYJ-48 + | → | VIN | merah |
| Modul LDR KY-018 S | → | D34 GPIO34 | ungu |
| Modul LDR KY-018 + | → | 3V3 | merah |
| Modul LDR KY-018 − | → | GND | hitam |
Langkah 2: Siapkan dashboard Klenik
Cara cepat: unduh p096.json, ganti budi1234 dengan KODE-mu, lalu import di Klenik (menu titik tiga → Export / Import → Import → Ganti total). Langkah lengkapnya ada di Panduan Klenik.
| Widget | Topic | Setting |
|---|---|---|
| Switch Mode Otomatis | ichibot/KODE/p096/otomatis | payload ON / OFF |
| Switch Tirai Manual | ichibot/KODE/p096/tirai | payload ON / OFF |
| Indikator Boolean Tirai | ichibot/KODE/p096/terbuka | ON = 1 “TERBUKA”, OFF = 0 |
| Gauge Bacaan LDR | ichibot/KODE/p096/cahaya | 0–4095 |
| Text Log Riwayat Tirai | ichibot/KODE/p096/log | menampilkan teks masuk |
Langkah 3: Upload kode
Library: PubSubClient (Nick O'Leary). Board di Arduino IDE: ESP32 Dev Module.
Isi dulu nama WiFi dan password di bagian ISI DULU, lalu ganti budi1234 di baris topic dengan KODE-mu, lalu upload dan buka Serial Monitor (115200).
// Proyek 096 - Tirai Otomatis Stepper
// Board: ESP32 DOIT DevKit V1 | Dashboard: klenik.ichibot.id
#include <WiFi.h>
#include <PubSubClient.h>
// ===== ISI DULU =====
const char* WIFI_NAMA = "nama-wifi-kamu";
const char* WIFI_PASS = "password-wifi-kamu";
// topic MQTT: ganti budi1234 dengan KODE-mu (sama dengan di dashboard Klenik)
const char* TOPIK_LOG = "ichibot/budi1234/p096/log";
const char* TOPIK_OTOMATIS = "ichibot/budi1234/p096/otomatis";
const char* TOPIK_TIRAI = "ichibot/budi1234/p096/tirai";
const char* TOPIK_TERBUKA = "ichibot/budi1234/p096/terbuka";
const char* TOPIK_CAHAYA = "ichibot/budi1234/p096/cahaya";
const char* BROKER = "mqtt.ichibot.id";
WiFiClient wifi;
PubSubClient mqtt(wifi);
const int PIN[4] = {19, 18, 5, 4};
const int PIN_LDR = 34;
const long LANGKAH_BUKA = 4096L * 5; // tirai terbuka penuh = 5 putaran motor
const int LDR_TERANG = 1500, LDR_GELAP = 3000; // histeresis
const uint8_t URUTAN[8] = {0b1000, 0b1100, 0b0100, 0b0110, 0b0010, 0b0011, 0b0001, 0b1001};
long posisi = 0, tujuan = 0; // 0 = tertutup (posisi saat dinyalakan)
int fase = 0;
bool otomatis = true;
unsigned long langkahTerakhir = 0, cekTerakhir = 0;
void satuLangkah(int arah) {
fase = (fase + arah + 8) % 8;
for (int i = 0; i < 4; i++) digitalWrite(PIN[i], (URUTAN[fase] >> (3 - i)) & 1);
posisi += arah;
}
void aturTirai(bool buka, const char* sebab) {
long baru = buka ? LANGKAH_BUKA : 0;
if (baru == tujuan) return;
tujuan = baru;
mqtt.publish(TOPIK_LOG, (String(buka ? "Tirai dibuka" : "Tirai ditutup") + " (" + sebab + ")").c_str());
}
void pesanMasuk(char* t, byte* isi, unsigned int panjang) {
String topik = t;
String p;
for (unsigned int i = 0; i < panjang; i++) p += (char)isi[i];
if (topik == TOPIK_OTOMATIS) otomatis = (p == "ON");
else if (topik == TOPIK_TIRAI) {
otomatis = false; // perintah manual mematikan mode otomatis
mqtt.publish(TOPIK_OTOMATIS, "OFF", true);
aturTirai(p == "ON", "manual");
}
}
void langganan() {
mqtt.subscribe(TOPIK_OTOMATIS);
mqtt.subscribe(TOPIK_TIRAI);
}
sambungWiFi() dan sambungMQTT(): sama di semua proyek (klik untuk lihat)
void sambungWiFi() {
WiFi.begin(WIFI_NAMA, WIFI_PASS);
Serial.print("WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" OK, IP " + WiFi.localIP().toString());
}
void sambungMQTT() {
while (!mqtt.connected()) {
if (mqtt.connect(WiFi.macAddress().c_str())) {
Serial.println("Terhubung ke Klenik");
langganan();
} else {
Serial.println("Broker gagal, coba lagi 3 detik");
delay(3000);
}
}
}
void setup() {
Serial.begin(115200);
for (int i = 0; i < 4; i++) pinMode(PIN[i], OUTPUT);
sambungWiFi();
mqtt.setServer(BROKER, 1883);
mqtt.setCallback(pesanMasuk);
}
void loop() {
if (!mqtt.connected()) sambungMQTT();
mqtt.loop();
if (posisi != tujuan) {
if (micros() - langkahTerakhir >= 1200) {
langkahTerakhir = micros();
satuLangkah(tujuan > posisi ? 1 : -1);
if (posisi == tujuan) {
for (int i = 0; i < 4; i++) digitalWrite(PIN[i], LOW);
mqtt.publish(TOPIK_TERBUKA, posisi ? "1" : "0", true);
}
}
return; // selama bergerak, fokus ke motor
}
if (millis() - cekTerakhir >= 5000) {
cekTerakhir = millis();
int ldr = analogRead(PIN_LDR); // KY-018: makin terang makin kecil
mqtt.publish(TOPIK_CAHAYA, String(ldr).c_str());
if (otomatis) {
if (ldr < LDR_TERANG) aturTirai(true, "pagi");
else if (ldr > LDR_GELAP) aturTirai(false, "malam");
}
}
}Langkah 4: Pahami kodenya
- Jarak buka dalam langkah. Huruf
Lmemastikan perkaliannya memakai angka besar (long). - Dua batas cahaya (histeresis). Lihat gauge LDR saat pagi dan malam di ruanganmu, lalu sesuaikan.
- Saat tirai bergerak, pembacaan LDR dilewati. Gerakan motor tetap rata tanpa jeda dari
analogRead()danpublish(). - Manual menang atas otomatis. Switch Mode Otomatis di dashboard ikut bergeser ke OFF.