/**
Arduino Pump Control 2025
Copyright (C) 2025
Released under the MIT License.
*/
#include <LiquidCrystal.h>
#include <Keypad.h>
#include <Servo.h>
#include "SafeState.h"
#include "icons.h"
#define Pump_Relay 13 // Relay Pompa
#define LED_Pin 1 // LED Counter
/* Locking mechanism definitions */
#define PushButton_Pin 0 // Pin Input Start / Stop Pompa
#define SERVO_PIN 6
#define SERVO_LOCK_POS 20
#define SERVO_UNLOCK_POS 90
#define Stop_Pin A5
Servo lockServo; // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
/* Display */
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
/* Keypad Setup */
const byte KEYPAD_ROWS = 4;
const byte KEYPAD_COLS = 4;
// Keypad Wiring
byte rowPins[KEYPAD_ROWS] = {5, 4, 3, 2};
byte colPins[KEYPAD_COLS] = {A3, A2, A1, A0};
// Keypad definition
char keys[KEYPAD_ROWS][KEYPAD_COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, KEYPAD_ROWS, KEYPAD_COLS);
/* SafeState stores the secret code in EEPROM */
SafeState safeState;
void lock() {
lockServo.write(SERVO_LOCK_POS);
safeState.lock();
}
void unlock() {
lockServo.write(SERVO_UNLOCK_POS);
}
void showStartupMessage() {
lcd.setCursor(1, 0);
lcd.print("Selamat Datang");
delay(1000);
lcd.clear();
lcd.setCursor(0, 0);
String message = "Pengendali Pompa";
for (byte i = 0; i < message.length(); i++) {
lcd.print(message[i]);
delay(50);
}
delay(1000);
lcd.setCursor(2, 1);
String message2 = "Oleh Cherry";
for (byte i = 0; i < message2.length(); i++) {
lcd.print(message2[i]);
delay(50);
}
delay(1000);
}
String inputSecretCode() {
lcd.setCursor(2, 1);
lcd.print("[____] detik");
lcd.setCursor(3, 1);
String result = "";
while (result.length() < 4) {
char key = keypad.getKey();
if (key >= '0' && key <= '9') {
lcd.print(key);
result += key;
}
}
return result;
}
void showWaitScreen(int delayMillis) {
lcd.setCursor(2, 1);
lcd.print("[..........]");
lcd.setCursor(3, 1);
for (byte i = 0; i < 10; i++) {
delay(delayMillis);
lcd.print("=");
}
}
bool setNewCode() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Enter new time:");
String newCode = inputSecretCode();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Confirm new time");
String confirmCode = inputSecretCode();
if (newCode.equals(confirmCode)) {
safeState.setCode(newCode);
return true;
} else {
lcd.clear();
lcd.setCursor(1, 0);
lcd.print("Code mismatch");
lcd.setCursor(0, 1);
lcd.print("Safe not locked!");
delay(2000);
return false;
}
}
void showUnlockMessage() {
lcd.clear();
lcd.setCursor(0, 0);
//lcd.write(ICON_UNLOCKED_CHAR);
lcd.setCursor(4, 0);
lcd.print("Terbuka!");
lcd.setCursor(15, 0);
//lcd.write(ICON_UNLOCKED_CHAR);
delay(1000);
}
void safeUnlockedLogic() {
lcd.clear();
lcd.setCursor(0, 0);
//lcd.write(ICON_UNLOCKED_CHAR);
lcd.setCursor(0, 0);
lcd.print("# = mengunci");
lcd.setCursor(15, 0);
//lcd.write(ICON_UNLOCKED_CHAR);
bool newCodeNeeded = true;
if (safeState.hasCode()) {
lcd.setCursor(0, 1);
lcd.print(" A = kode baru");
newCodeNeeded = false;
}
auto key = keypad.getKey();
while (key != 'A' && key != '#') {
key = keypad.getKey();
}
bool readyToLock = true;
if (key == 'A' || newCodeNeeded) {
readyToLock = setNewCode();
}
if (readyToLock) {
lcd.clear();
lcd.setCursor(5, 0);
//lcd.write(ICON_UNLOCKED_CHAR);
//lcd.print(" ");
lcd.write(ICON_RIGHT_ARROW);
//lcd.print(" ");
//lcd.write(ICON_LOCKED_CHAR);
safeState.lock();
lock(); // Servo bergerak mengunci
digitalWrite(Pump_Relay, HIGH); // Pompa ON
showWaitScreen(100);
}
}
void safeLockedLogic() {
lcd.clear();
lcd.setCursor(0, 0);
//lcd.write(ICON_LOCKED_CHAR);
lcd.print("Kode membuka..");
//lcd.write(ICON_LOCKED_CHAR);
String userCode = inputSecretCode();
bool unlockedSuccessfully = safeState.unlock(userCode);
showWaitScreen(200);
if (unlockedSuccessfully) {
showUnlockMessage();
unlock(); // Servo bergerak membuka
digitalWrite(Pump_Relay, LOW); // Pompa OFF
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Access Denied!");
showWaitScreen(1000);
}
}
// ---------------------------------------------------------------
int ICounter;
//int i;
bool CounterStatus;
String SGCounter;
void setup() {
pinMode(PushButton_Pin, INPUT_PULLUP); // initialize the pushbutton pin as an input
pinMode(Pump_Relay, OUTPUT);
pinMode(Stop_Pin, INPUT_PULLUP);
CounterStatus=false;
lcd.begin(16, 2);
init_icons(lcd);
showStartupMessage();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("A Timer B Stop");
//delay (200);
lcd.setCursor(0, 1);
lcd.print("C ON D OFF");
delay (2000);
//===================================================================
// lockServo.attach(SERVO_PIN);
/* Make sure the physical lock is sync with the EEPROM state */
// Serial.begin(115200);
// if (safeState.locked()) {
// lock();
// } else {
// unlock();
// }
//=====================================================================
}
void loop() {
//i = 0;
// lcd.clear();
char key1 = keypad.getKey(); // Membaca tombol keypad yang ditekan
if (key1=='A') {
lcd.clear();
lcd.setCursor(2, 0);
lcd.print("Input Timer");
lcd.setCursor(2, 1);
lcd.print("[____] detik");
lcd.setCursor(3, 1);
String SCounter = "";
while (SCounter.length() < 4) {
char key = keypad.getKey();
if (key >= '0' && key <= '9') {
lcd.print(key);
SCounter += key; // SCounter = SCounter + key
}
SGCounter = SCounter;
}
return SCounter;
}
if (key1=='B') {}
if (key1=='C') {digitalWrite(Pump_Relay, HIGH); ICounter=1;}
if (key1=='D') {digitalWrite(Pump_Relay, LOW);}
//if (key1=='#') {
// lcd.setCursor(0, 1);
// lcd.print(result);
// }
int ButtonStatus = digitalRead(PushButton_Pin); // Baca status tombol Run
int StopStatus = digitalRead(Stop_Pin); // Baca status tombol Stop
if (ButtonStatus == LOW && StopStatus == HIGH) { // Jika Tombol RUN ditekan (aktif LOW)
// if (ButtonStatus == LOW) {digitalWrite(Pump_Relay, HIGH);}
digitalWrite(Pump_Relay, HIGH); // Pompa Hidup
//String myString = "12345";
//int myInt = myString.toInt();
//counter = 10; // set up the counter for testing
String mS = SGCounter;
int counter = mS.toInt(); // Ubah variabel string ke Int
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Count:");
lcd.setCursor(7, 0);
lcd.print(counter);
lcd.setCursor(12, 0);
lcd.print(SGCounter);
lcd.setCursor(0, 1);
lcd.print("Tekan B --> STOP");
while (counter > 0) {
int StopStatus = digitalRead(Stop_Pin); // Baca status tombol Stop
if (StopStatus == LOW) {counter = 1; digitalWrite(Pump_Relay, LOW); break;}
char key2 = keypad.getKey(); // Membaca tombol keypad yang ditekan untuk STOP
digitalWrite(LED_Pin, HIGH); // LED ON
delay (500); // Wait 500ms
digitalWrite(LED_Pin, LOW); // LED OFF
//delay (500); // Wait 500ms
if (key2 == 'B') {counter = 1;}
counter = counter - 1; // decrease counter
//---------------------
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Count:");
lcd.setCursor(7, 0);
lcd.print(counter);
lcd.setCursor(12, 0);
lcd.print(SGCounter);
lcd.setCursor(0, 1);
lcd.print("Tekan B --> STOP");
//---------------------
delay(500);
}
ICounter=0; // Memastikan pompa mati, jika tidak ada count value
}
else // Jika tombol Run tidak ditekan
{
if (ICounter == 0) {digitalWrite(Pump_Relay, LOW);} // Pompa mati
//digitalWrite(Pump_Relay,LOW);
// lcd.clear();
// lcd.setCursor(1, 0);
//lcd.print("Pompa Mati.");
// delay (200);
}
if (StopStatus == LOW) {digitalWrite(Pump_Relay,LOW);} // Mematikan Pompa
// ===========================================================================
// if (safeState.locked()) {
// safeLockedLogic();
// } else {
// safeUnlockedLogic();
// }
}
Pump
Counter
RUN
STOP
12V
Pump Motor
Emergency Stop