KODE ESP
This commit is contained in:
parent
e78ab91794
commit
07f12ca050
|
|
@ -0,0 +1,589 @@
|
|||
#include <WiFi.h>
|
||||
#include <WiFiManager.h>
|
||||
#include <Firebase_ESP_Client.h>
|
||||
#include <ESP32Servo.h>
|
||||
#include <Wire.h>
|
||||
#include <LiquidCrystal_I2C.h>
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
|
||||
|
||||
// ================= FIREBASE =================
|
||||
#define API_KEY "AIzaSyDOt0tippHwz6JaPG9Zo147ATJ9USV5bKs"
|
||||
#define DATABASE_URL "https://tabungankuy-30a9d-default-rtdb.firebaseio.com/"
|
||||
#define LEGACY_TOKEN "FTqzKI4HW32paLnR9pQXB72YoUHN1NXEjZMfjO4f"
|
||||
|
||||
// ================= TCS3200 =================
|
||||
#define S0 14
|
||||
#define S1 27
|
||||
#define S2 26
|
||||
#define S3 25
|
||||
#define SENSOR_OUT 33
|
||||
|
||||
// ================= HARDWARE =================
|
||||
#define SERVO_MASUK_PIN 4
|
||||
#define SERVO_TURUN_PIN 5
|
||||
#define SERVO_BUKA_PIN 15
|
||||
|
||||
// ================= OBJECT =================
|
||||
LiquidCrystal_I2C lcd(0x27, 16, 2);
|
||||
|
||||
FirebaseData fbdo;
|
||||
FirebaseAuth auth;
|
||||
FirebaseConfig config;
|
||||
|
||||
Servo servoMasuk;
|
||||
Servo servoTurun;
|
||||
Servo servoBuka;
|
||||
|
||||
// ================= STATE =================
|
||||
int lastDetectedVal = 0;
|
||||
|
||||
bool lastKonfirmasi = false;
|
||||
bool lastBukaTabungan = false;
|
||||
bool lastServoMasuk = false;
|
||||
|
||||
bool servoAttached = false;
|
||||
|
||||
// =====================================================
|
||||
// LCD
|
||||
// =====================================================
|
||||
|
||||
void lcdDefault() {
|
||||
|
||||
lcd.clear();
|
||||
|
||||
lcd.setCursor(0, 0);
|
||||
lcd.print(" TABUNGANKU ");
|
||||
|
||||
lcd.setCursor(0, 1);
|
||||
lcd.print(" SIAP DIGUNAKAN ");
|
||||
}
|
||||
|
||||
void lcdUangTerdeteksi(int nilai) {
|
||||
|
||||
lcd.clear();
|
||||
|
||||
lcd.setCursor(0, 0);
|
||||
lcd.print("UANG TERDETEKSI");
|
||||
|
||||
lcd.setCursor(0, 1);
|
||||
|
||||
String text = "Rp " + String(nilai);
|
||||
|
||||
while (text.length() < 16)
|
||||
text += " ";
|
||||
|
||||
lcd.print(text);
|
||||
}
|
||||
|
||||
void lcdUangMasuk(int nilai) {
|
||||
|
||||
lcd.clear();
|
||||
|
||||
lcd.setCursor(0, 0);
|
||||
lcd.print(" UANG MASUK ");
|
||||
|
||||
lcd.setCursor(0, 1);
|
||||
|
||||
String text = "Rp " + String(nilai);
|
||||
|
||||
while (text.length() < 16)
|
||||
text += " ";
|
||||
|
||||
lcd.print(text);
|
||||
}
|
||||
|
||||
void lcdTabunganTerbuka() {
|
||||
|
||||
lcd.clear();
|
||||
|
||||
lcd.setCursor(0, 0);
|
||||
lcd.print(" TABUNGAN ");
|
||||
|
||||
lcd.setCursor(0, 1);
|
||||
lcd.print(" TERBUKA ");
|
||||
}
|
||||
|
||||
void updateLCD() {
|
||||
|
||||
if (lastBukaTabungan) {
|
||||
|
||||
lcdTabunganTerbuka();
|
||||
|
||||
} else if (lastKonfirmasi && lastDetectedVal > 0) {
|
||||
|
||||
lcdUangMasuk(lastDetectedVal);
|
||||
|
||||
} else if (lastDetectedVal > 0) {
|
||||
|
||||
lcdUangTerdeteksi(lastDetectedVal);
|
||||
|
||||
} else {
|
||||
|
||||
lcdDefault();
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// WIFI
|
||||
// =====================================================
|
||||
|
||||
void connectWiFi() {
|
||||
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.setSleep(false);
|
||||
|
||||
WiFiManager wm;
|
||||
|
||||
wm.setTimeout(180); // 3 menit untuk setup WiFi
|
||||
|
||||
bool res = wm.autoConnect("TABUNGANKU_SETUP");
|
||||
|
||||
if (!res) {
|
||||
Serial.println("Gagal konek WiFi");
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
Serial.println("WiFi Connected!");
|
||||
Serial.print("IP : ");
|
||||
Serial.println(WiFi.localIP());
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// FIREBASE
|
||||
// =====================================================
|
||||
|
||||
void setupFirebase() {
|
||||
|
||||
config.api_key = API_KEY;
|
||||
config.database_url = DATABASE_URL;
|
||||
|
||||
config.signer.tokens.legacy_token = LEGACY_TOKEN;
|
||||
|
||||
Firebase.begin(&config, &auth);
|
||||
|
||||
Firebase.reconnectWiFi(true);
|
||||
|
||||
Serial.println("Firebase Connected");
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// TCS3200
|
||||
// =====================================================
|
||||
|
||||
void setupTCS3200() {
|
||||
|
||||
pinMode(S0, OUTPUT);
|
||||
pinMode(S1, OUTPUT);
|
||||
|
||||
pinMode(S2, OUTPUT);
|
||||
pinMode(S3, OUTPUT);
|
||||
|
||||
pinMode(SENSOR_OUT, INPUT);
|
||||
|
||||
digitalWrite(S0, HIGH);
|
||||
digitalWrite(S1, LOW);
|
||||
|
||||
Serial.println("Sensor TCS3200 Ready");
|
||||
}
|
||||
|
||||
int avgFreq(int s2Val, int s3Val) {
|
||||
|
||||
long total = 0;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
|
||||
digitalWrite(S2, s2Val);
|
||||
digitalWrite(S3, s3Val);
|
||||
|
||||
delayMicroseconds(300);
|
||||
|
||||
total += pulseIn(SENSOR_OUT, LOW);
|
||||
}
|
||||
|
||||
return total / 3;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// DETEKSI UANG
|
||||
// =====================================================
|
||||
|
||||
void cekUangKertas() {
|
||||
|
||||
static unsigned long lastCheck = 0;
|
||||
static unsigned long lastDetectedTime = 0;
|
||||
|
||||
static int lastDetectedValue = 0;
|
||||
|
||||
if (millis() - lastCheck < 300)
|
||||
return;
|
||||
|
||||
lastCheck = millis();
|
||||
|
||||
if (lastKonfirmasi)
|
||||
return;
|
||||
|
||||
int r = avgFreq(LOW, LOW);
|
||||
int g = avgFreq(HIGH, HIGH);
|
||||
int b = avgFreq(LOW, HIGH);
|
||||
|
||||
Serial.print("R: ");
|
||||
Serial.print(r);
|
||||
|
||||
Serial.print(" | G: ");
|
||||
Serial.print(g);
|
||||
|
||||
Serial.print(" | B: ");
|
||||
Serial.println(b);
|
||||
|
||||
int val = 0;
|
||||
|
||||
if (r>=110&&r<=120 && g>=140&&g<=150 && b>=124&&b<=134) val = 100000;
|
||||
else if (r>=175&&r<=185 && g>=160&&g<=170 && b>=150&&b<=160) val = 50000;
|
||||
else if (r>=138&&r<=148 && g>=125&&g<=135 && b>=105&&b<=115) val = 20000;
|
||||
else if (r>=145&&r<=155 && g>=180&&g<=190 && b>=150&&b<=160) val = 10000;
|
||||
else if (r>=115&&r<=125 && g>=169&&g<=179 && b>=140&&b<=150) val = 5000;
|
||||
else if (r>=145&&r<=155 && g>=145&&g<=155 && b>=120&&b<=130) val = 2000;
|
||||
else if (r>=129&&r<=139 && g>=125&&g<=135 && b>=120&&b<=130) val = 1000;
|
||||
|
||||
if (val > 0 &&
|
||||
(millis() - lastDetectedTime > 1500 ||
|
||||
val != lastDetectedValue)) {
|
||||
|
||||
Serial.println("====================");
|
||||
Serial.print("Uang : Rp ");
|
||||
Serial.println(val);
|
||||
Serial.println("====================");
|
||||
|
||||
Firebase.RTDB.setInt(
|
||||
&fbdo,
|
||||
"/tabungan/detected_value",
|
||||
val
|
||||
);
|
||||
|
||||
lastDetectedTime = millis();
|
||||
lastDetectedValue = val;
|
||||
|
||||
lastDetectedVal = val;
|
||||
|
||||
updateLCD();
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// SERVO HELPER
|
||||
// =====================================================
|
||||
|
||||
void attachServo() {
|
||||
|
||||
if (!servoAttached) {
|
||||
|
||||
servoMasuk.attach(SERVO_MASUK_PIN);
|
||||
servoTurun.attach(SERVO_TURUN_PIN);
|
||||
servoBuka.attach(SERVO_BUKA_PIN);
|
||||
|
||||
|
||||
servoAttached = true;
|
||||
|
||||
delay(300);
|
||||
|
||||
servoMasuk.write(0);
|
||||
servoTurun.write(0);
|
||||
servoBuka.write(0);
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// FIREBASE LISTENER
|
||||
// =====================================================
|
||||
|
||||
void cekKonfirmasiFlutter() {
|
||||
|
||||
if (!Firebase.RTDB.getBool(
|
||||
&fbdo,
|
||||
"/tabungan/konfirmasi_masuk"))
|
||||
return;
|
||||
|
||||
bool konfirmasi = fbdo.boolData();
|
||||
|
||||
if (konfirmasi == lastKonfirmasi)
|
||||
return;
|
||||
|
||||
lastKonfirmasi = konfirmasi;
|
||||
|
||||
Serial.print("Konfirmasi: ");
|
||||
Serial.println(konfirmasi);
|
||||
|
||||
attachServo();
|
||||
|
||||
if (konfirmasi) {
|
||||
|
||||
servoTurun.write(90);
|
||||
|
||||
Serial.println("Servo Turun Aktif");
|
||||
|
||||
} else {
|
||||
|
||||
servoTurun.write(0);
|
||||
|
||||
Serial.println("Servo Turun Mati");
|
||||
|
||||
// reset nominal ketika tombol batalkan ditekan
|
||||
lastDetectedVal = 0;
|
||||
|
||||
Firebase.RTDB.setInt(
|
||||
&fbdo,
|
||||
"/tabungan/detected_value",
|
||||
0
|
||||
);
|
||||
|
||||
Serial.println("Detected Reset");
|
||||
|
||||
// kembali ke tampilan awal
|
||||
lcdDefault();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
updateLCD();
|
||||
}
|
||||
|
||||
void cekServoMasuk() {
|
||||
|
||||
if (!Firebase.RTDB.getBool(
|
||||
&fbdo,
|
||||
"/tabungan/masukkan_uang"))
|
||||
return;
|
||||
|
||||
bool buka = fbdo.boolData();
|
||||
|
||||
if (buka == lastServoMasuk)
|
||||
return;
|
||||
|
||||
lastServoMasuk = buka;
|
||||
|
||||
attachServo();
|
||||
|
||||
servoMasuk.write(buka ? 150 : 0);
|
||||
|
||||
Serial.print("Servo Masuk: ");
|
||||
|
||||
Serial.println(
|
||||
buka ? "BUKA" : "TUTUP"
|
||||
);
|
||||
}
|
||||
|
||||
void cekServoBukaTabungan() {
|
||||
|
||||
static bool sedangBuka = false;
|
||||
static unsigned long waktuBuka = 0;
|
||||
static int lastSisa = -1;
|
||||
|
||||
if (!Firebase.RTDB.getBool(
|
||||
&fbdo,
|
||||
"/tabungan/buka_tabungan"))
|
||||
return;
|
||||
|
||||
bool buka = fbdo.boolData();
|
||||
|
||||
// buka servo sekali saat menerima TRUE
|
||||
if (buka && !sedangBuka) {
|
||||
|
||||
attachServo();
|
||||
|
||||
servoBuka.write(150);
|
||||
|
||||
waktuBuka = millis();
|
||||
sedangBuka = true;
|
||||
|
||||
lastBukaTabungan = true;
|
||||
|
||||
Serial.println("Servo Tabungan: TERBUKA");
|
||||
}
|
||||
|
||||
// countdown 25 detik
|
||||
if (sedangBuka) {
|
||||
|
||||
int sisa = 25 - ((millis() - waktuBuka) / 1000);
|
||||
|
||||
if (sisa < 0) sisa = 0;
|
||||
|
||||
if (sisa != lastSisa) {
|
||||
|
||||
lastSisa = sisa;
|
||||
|
||||
lcd.clear();
|
||||
|
||||
lcd.setCursor(0, 0);
|
||||
lcd.print("Pintu Terbuka");
|
||||
|
||||
lcd.setCursor(0, 1);
|
||||
lcd.print("Sisa:");
|
||||
lcd.print(sisa);
|
||||
lcd.print(" dtk");
|
||||
}
|
||||
|
||||
// tutup otomatis setelah 25 detik
|
||||
if (millis() - waktuBuka >= 25000) {
|
||||
|
||||
servoBuka.write(0);
|
||||
|
||||
sedangBuka = false;
|
||||
lastBukaTabungan = false;
|
||||
|
||||
Firebase.RTDB.setBool(
|
||||
&fbdo,
|
||||
"/tabungan/buka_tabungan",
|
||||
false
|
||||
);
|
||||
|
||||
lcdDefault();
|
||||
|
||||
Serial.println("Servo Tabungan: TERTUTUP");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void cekDetectedValueFirebase() {
|
||||
|
||||
static unsigned long lastSync = 0;
|
||||
|
||||
if (millis() - lastSync < 1000)
|
||||
return;
|
||||
|
||||
lastSync = millis();
|
||||
|
||||
if (!Firebase.RTDB.getInt(
|
||||
&fbdo,
|
||||
"/tabungan/detected_value"))
|
||||
return;
|
||||
|
||||
int val = fbdo.intData();
|
||||
|
||||
// jika nilai direset dari Flutter
|
||||
if (val == 0) {
|
||||
|
||||
lastDetectedVal = 0;
|
||||
|
||||
lcdDefault();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (lastKonfirmasi)
|
||||
return;
|
||||
|
||||
if (val == lastDetectedVal)
|
||||
return;
|
||||
|
||||
lastDetectedVal = val;
|
||||
|
||||
Serial.print("Sync Firebase: ");
|
||||
Serial.println(val);
|
||||
|
||||
updateLCD();
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// SETUP
|
||||
// =====================================================
|
||||
|
||||
void setup() {
|
||||
|
||||
// disable brownout sementara
|
||||
WRITE_PERI_REG(
|
||||
RTC_CNTL_BROWN_OUT_REG,
|
||||
0
|
||||
);
|
||||
|
||||
Serial.begin(115200);
|
||||
|
||||
Serial.println();
|
||||
Serial.println("System Booting...");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
lcd.init();
|
||||
lcd.backlight();
|
||||
|
||||
lcd.clear();
|
||||
|
||||
lcd.setCursor(0, 0);
|
||||
lcd.print(" TABUNGANKU ");
|
||||
|
||||
lcd.setCursor(0, 1);
|
||||
lcd.print(" BOOTING... ");
|
||||
|
||||
setupTCS3200();
|
||||
|
||||
|
||||
// JANGAN attach servo di awal
|
||||
// supaya tidak brownout
|
||||
|
||||
connectWiFi();
|
||||
|
||||
setupFirebase();
|
||||
|
||||
// reset firebase
|
||||
Firebase.RTDB.setInt(
|
||||
&fbdo,
|
||||
"/tabungan/detected_value",
|
||||
0
|
||||
);
|
||||
|
||||
Firebase.RTDB.setBool(
|
||||
&fbdo,
|
||||
"/tabungan/konfirmasi_masuk",
|
||||
false
|
||||
);
|
||||
|
||||
Firebase.RTDB.setBool(
|
||||
&fbdo,
|
||||
"/tabungan/masukkan_uang",
|
||||
false
|
||||
);
|
||||
|
||||
Firebase.RTDB.setBool(
|
||||
&fbdo,
|
||||
"/tabungan/buka_tabungan",
|
||||
false
|
||||
);
|
||||
|
||||
Serial.println("Firebase Reset");
|
||||
|
||||
lcdDefault();
|
||||
|
||||
Serial.println("System Ready");
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// LOOP
|
||||
// =====================================================
|
||||
|
||||
void loop() {
|
||||
|
||||
static unsigned long lastWiFiCheck = 0;
|
||||
|
||||
if (millis() - lastWiFiCheck > 10000) {
|
||||
lastWiFiCheck = millis();
|
||||
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
connectWiFi();
|
||||
}
|
||||
}
|
||||
|
||||
cekUangKertas();
|
||||
|
||||
cekKonfirmasiFlutter();
|
||||
|
||||
cekServoMasuk();
|
||||
|
||||
cekServoBukaTabungan();
|
||||
|
||||
cekDetectedValueFirebase();
|
||||
|
||||
delay(200);
|
||||
}
|
||||
Loading…
Reference in New Issue