#include #include #include #include // --- THINGER.IO --- #define USERNAME "lindadwi" #define DEVICE_ID "Celengan_Pintar" #define DEVICE_CREDENTIAL "celengan8266" #define SSID "ozie 3" #define PASSWORD "followkami" ThingerESP8266 thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL); // --- TCS3200 --- #define S0 D5 #define S1 D6 #define S2 D7 #define S3 D8 #define sensorOut D3 // --- RELAY & SWITCH --- #define RELAY_PIN D0 #define SWITCH_PIN D4 // --- KEYPAD PCF8574 --- Adafruit_PCF8574 pcf; const byte ROWS = 4, COLS = 3; char keys[ROWS][COLS] = { {'1','2','3'}, {'4','5','6'}, {'7','8','9'}, {'*','0','#'} }; int rowPins[4] = {0, 1, 2, 3}; int colPins[3] = {4, 5, 6}; // --- LCD I2C --- LiquidCrystal_I2C lcd(0x27, 16, 2); // --- GLOBAL --- String nominal = "Tidak dikenali"; const int TOLERANSI = 20; String inputSandi = ""; bool relayAktif = false; bool pintuBaruDibuka = false; bool pintuTerbukaSebelumnya = false; int totalSaldo = 0; void setup() { Serial.begin(9600); // Thinger thing.add_wifi(SSID, PASSWORD); // Resource realtime saldo thing["total_saldo"] >> [](pson &out){ out = totalSaldo; }; // TCS3200 pinMode(S0, OUTPUT); pinMode(S1, OUTPUT); pinMode(S2, OUTPUT); pinMode(S3, OUTPUT); pinMode(sensorOut, INPUT); digitalWrite(S0, HIGH); digitalWrite(S1, LOW); // RELAY & SWITCH pinMode(RELAY_PIN, OUTPUT); digitalWrite(RELAY_PIN, HIGH); // Relay OFF pinMode(SWITCH_PIN, INPUT_PULLUP); // KEYPAD if (!pcf.begin(0x20)) { Serial.println("PCF8574 tidak terdeteksi!"); while (1); } for (int i = 0; i < 8; i++) pcf.pinMode(i, INPUT_PULLUP); // LCD lcd.begin(16, 2); lcd.backlight(); lcd.setCursor(0, 0); lcd.print("Masukkan uang"); } // === LOOP === void loop() { thing.handle(); bool pintuTertutup = digitalRead(SWITCH_PIN) == LOW; // Deteksi pintu dibuka untuk reset saldo if (!pintuTertutup && !pintuTerbukaSebelumnya) { if (totalSaldo > 0) { Serial.println("Pintu dibuka - reset saldo"); pson data; data["status"] = "diambil"; data["saldo"] = totalSaldo; thing.write_bucket("data_uang", data); totalSaldo = 0; } pintuTerbukaSebelumnya = true; } if (pintuTertutup && pintuTerbukaSebelumnya) { pintuTerbukaSebelumnya = false; } // Kontrol relay berdasarkan status if (relayAktif) { if (!pintuTertutup) { pintuBaruDibuka = true; } else if (pintuBaruDibuka && pintuTertutup) { relayAktif = false; digitalWrite(RELAY_PIN, HIGH); // Relay OFF pintuBaruDibuka = false; Serial.println("Pintu ditutup kembali - Relay OFF"); lcd.setCursor(0, 0); lcd.print("Pintu tertutup "); lcd.setCursor(0, 1); lcd.print("Akses selesai "); delay(2000); lcd.setCursor(0, 0); lcd.print("Masukkan uang "); lcd.setCursor(0, 1); lcd.print(" "); } } // === TOMBOL === char tombol = bacaTombol(); if (tombol != 0) { inputSandi += tombol; if (inputSandi.length() > 4) inputSandi.remove(0, 1); lcd.setCursor(0, 0); lcd.print("Masukkan sandi "); lcd.setCursor(0, 1); lcd.print(inputSandi + " "); if (tombol == '*') { if (nominal != "Tidak dikenali") { int nilai = konversiNominalKeInt(nominal); if (nilai > 0) { totalSaldo += nilai; lcd.setCursor(0, 0); lcd.print("Akses diterima "); lcd.setCursor(0, 1); lcd.print("Tambah: " + nominal + " "); Serial.println("Menambah: " + nominal); pson data; data["status"] = "tambah"; data["saldo"] = totalSaldo; data["nominal"] = nominal; thing.write_bucket("data_uang", data); delay(2000); lcd.setCursor(0, 0); lcd.print("Masukkan uang "); lcd.setCursor(0, 1); lcd.print(" "); } } else if (inputSandi == "123*") { if (pintuTertutup) { relayAktif = true; digitalWrite(RELAY_PIN, LOW); // Relay ON Serial.println("Akses diterima - Relay ON"); lcd.setCursor(0, 0); lcd.print("Akses diterima "); } else { Serial.println("Pintu tidak rapat"); lcd.setCursor(0, 0); lcd.print("Pintu terbuka "); } lcd.setCursor(0, 1); lcd.print(" "); delay(2000); lcd.setCursor(0, 0); lcd.print("Masukkan uang "); lcd.setCursor(0, 1); lcd.print(" "); } else { relayAktif = false; digitalWrite(RELAY_PIN, HIGH); // Relay OFF Serial.println("Akses ditolak"); lcd.setCursor(0, 0); lcd.print("Akses ditolak "); lcd.setCursor(0, 1); lcd.print(" "); delay(2000); lcd.setCursor(0, 0); lcd.print("Masukkan uang "); lcd.setCursor(0, 1); lcd.print(" "); } inputSandi = ""; } } // === DETEKSI WARNA === int red = bacaWarna(LOW, LOW); int green = bacaWarna(HIGH, HIGH); int blue = bacaWarna(LOW, HIGH); Serial.print("R: "); Serial.print(red); Serial.print(" G: "); Serial.print(green); Serial.print(" B: "); Serial.println(blue); nominal = detectUang(red, green, blue); Serial.println("Terdeteksi: " + nominal); lcd.setCursor(0, 1); if (nominal == "Tidak dikenali") { lcd.print("... "); } else { lcd.print("Nominal: " + nominal + " "); } delay(1000); } // === BACA WARNA === int bacaWarna(bool s2, bool s3) { digitalWrite(S2, s2); digitalWrite(S3, s3); return pulseIn(sensorOut, LOW); } // === KONVERSI NOMINAL === int konversiNominalKeInt(String nominal) { if (nominal == "1k") return 1000; if (nominal == "2k") return 2000; if (nominal == "5k") return 5000; if (nominal == "10k") return 10000; if (nominal == "20k") return 20000; if (nominal == "50k") return 50000; if (nominal == "100k") return 100000; return 0; } // === DETEKSI UANG === bool isInRange(int val, int ref) { return val >= (ref - TOLERANSI) && val <= (ref + TOLERANSI); } String detectUang(int r, int g, int b) { if (isInRange(r,195) && isInRange(g,200) && isInRange(b,196)) return "1k"; if (isInRange(r,132) && isInRange(g,165) && isInRange(b,132)) return "2k"; if (isInRange(r,215) && isInRange(g,260) && isInRange(b,215)) return "10k"; if (isInRange(r,155) && isInRange(g,157) && isInRange(b,155)) return "20k"; if (isInRange(r,137) && isInRange(g,170) && isInRange(b,137)) return "50k"; if (isInRange(r,148) && isInRange(g,167) && isInRange(b,148)) return "100k"; if (isInRange(r,175) && isInRange(g,171) && isInRange(b,175)) return "5k"; return "Tidak dikenali"; } // === BACA TOMBOL === char bacaTombol() { for (int r = 0; r < ROWS; r++) { pcf.pinMode(rowPins[r], OUTPUT); pcf.digitalWrite(rowPins[r], LOW); delayMicroseconds(50); for (int c = 0; c < COLS; c++) { if (!pcf.digitalRead(colPins[c])) { char key = keys[r][c]; while (!pcf.digitalRead(colPins[c])); pcf.pinMode(rowPins[r], INPUT_PULLUP); return key; } } pcf.pinMode(rowPins[r], INPUT_PULLUP); } return 0; }