// ==========================
// SISTEM ANTRIAN TANPA LIBRARY & TANPA DELAY
// FAST RESPONSE + BUZZER DING-DONG
// ==========================
// --- Definisi pin LCD (mode 4-bit) ---
#define RS 12
#define EN 11
#define D4 10
#define D5 9
#define D6 8
#define D7 7
// --- Definisi pin tombol & buzzer ---
#define BUTTON_LOKET1 2
#define BUTTON_RESET 3
#define BUTTON_PAUSE 4
#define BUTTON_LOKET2 5
#define BUTTON_LOKET3 6
#define BUTTON_LOKET4 13
#define BUZZER 16
// --- Variabel global ---
int currentNumber = 0;
int activeLoket = 0;
bool buzzerEnabled = true;
bool isBuzzing = false;
unsigned long buzzerStartTime = 0;
int buzzerStep = 0;
// untuk debounce tombol (tanpa delay)
unsigned long lastPressLoket1 = 0;
unsigned long lastPressLoket2 = 0;
unsigned long lastPressLoket3 = 0;
unsigned long lastPressLoket4 = 0;
unsigned long lastPressReset = 0;
unsigned long lastPressPause = 0;
const unsigned long debounceDelay = 200;
// ================== BAGIAN LCD MANUAL ==================
void lcdPulseEnable() {
digitalWrite(EN, LOW);
digitalWrite(EN, HIGH);
digitalWrite(EN, LOW);
}
void lcdWrite4Bits(byte value) {
digitalWrite(D4, value & 1);
digitalWrite(D5, (value >> 1) & 1);
digitalWrite(D6, (value >> 2) & 1);
digitalWrite(D7, (value >> 3) & 1);
lcdPulseEnable();
}
void lcdCommand(byte cmd) {
digitalWrite(RS, LOW);
lcdWrite4Bits(cmd >> 4);
lcdWrite4Bits(cmd);
}
void lcdWrite(byte data) {
digitalWrite(RS, HIGH);
lcdWrite4Bits(data >> 4);
lcdWrite4Bits(data);
}
void lcdInit() {
pinMode(RS, OUTPUT);
pinMode(EN, OUTPUT);
pinMode(D4, OUTPUT);
pinMode(D5, OUTPUT);
pinMode(D6, OUTPUT);
pinMode(D7, OUTPUT);
delay(50); // hanya di inisialisasi awal LCD
lcdCommand(0x33);
lcdCommand(0x32);
lcdCommand(0x28);
lcdCommand(0x0C);
lcdCommand(0x06);
lcdCommand(0x01);
}
void lcdClear() {
lcdCommand(0x01);
}
void lcdSetCursor(int col, int row) {
int row_offsets[] = {0x00, 0x40, 0x14, 0x54};
lcdCommand(0x80 | (col + row_offsets[row]));
}
void lcdPrint(const char *s) {
while (*s) lcdWrite(*s++);
}
// ================== BUZZER NON-BLOCKING “DING-DONG” ==================
void playBuzzerStart() {
if (!buzzerEnabled || isBuzzing) return;
isBuzzing = true;
buzzerStep = 0;
buzzerStartTime = millis();
tone(BUZZER, 1000); // nada “ding”
}
void updateBuzzer() {
if (!isBuzzing) return;
unsigned long now = millis();
switch (buzzerStep) {
case 0:
if (now - buzzerStartTime >= 200) {
noTone(BUZZER);
buzzerStep = 1;
buzzerStartTime = now;
}
break;
case 1:
if (now - buzzerStartTime >= 60) {
tone(BUZZER, 1500); // nada “dong”
buzzerStep = 2;
buzzerStartTime = now;
}
break;
case 2:
if (now - buzzerStartTime >= 250) {
noTone(BUZZER);
isBuzzing = false;
}
break;
}
}
// ================== DISPLAY LCD ==================
void displayCall() {
lcdClear();
lcdSetCursor(4, 0);
lcdPrint("PANGGILAN KLINIK");
char buf[20];
sprintf(buf, "NOMOR ANTRIAN %02d", currentNumber);
lcdSetCursor(1, 1);
lcdPrint(buf);
lcdSetCursor(5, 2);
lcdPrint("MENUJU KE");
char loketBuf[10];
sprintf(loketBuf, "LOKET %d", activeLoket);
lcdSetCursor(7, 3);
lcdPrint(loketBuf);
}
void displayReady() {
lcdClear();
lcdSetCursor(3, 1);
lcdPrint("SISTEM ANTRIAN");
lcdSetCursor(4, 2);
lcdPrint("KLINIK READY");
}
void displayBuzzerStatus() {
lcdSetCursor(0, 0);
if (buzzerEnabled) lcdPrint("BUZZER: ON ");
else lcdPrint("BUZZER: OFF");
}
// ================== SISTEM ANTRIAN ==================
void handleNext(int loket) {
activeLoket = loket;
currentNumber++;
displayCall();
playBuzzerStart();
}
void resetSystem() {
currentNumber = 0;
activeLoket = 0;
displayReady();
}
// ================== SETUP ==================
void setup() {
pinMode(BUTTON_LOKET1, INPUT_PULLUP);
pinMode(BUTTON_RESET, INPUT_PULLUP);
pinMode(BUTTON_PAUSE, INPUT_PULLUP);
pinMode(BUTTON_LOKET2, INPUT_PULLUP);
pinMode(BUTTON_LOKET3, INPUT_PULLUP);
pinMode(BUTTON_LOKET4, INPUT_PULLUP);
pinMode(BUZZER, OUTPUT);
lcdInit();
displayReady();
}
// ================== LOOP UTAMA TANPA DELAY ==================
void loop() {
unsigned long now = millis();
updateBuzzer();
// ======= TOMBOL LOKET TANPA DELAY =======
if (digitalRead(BUTTON_LOKET1) == LOW && now - lastPressLoket1 > debounceDelay) {
lastPressLoket1 = now;
handleNext(1);
}
if (digitalRead(BUTTON_LOKET2) == LOW && now - lastPressLoket2 > debounceDelay) {
lastPressLoket2 = now;
handleNext(2);
}
if (digitalRead(BUTTON_LOKET3) == LOW && now - lastPressLoket3 > debounceDelay) {
lastPressLoket3 = now;
handleNext(3);
}
if (digitalRead(BUTTON_LOKET4) == LOW && now - lastPressLoket4 > debounceDelay) {
lastPressLoket4 = now;
handleNext(4);
}
// ======= RESET TANPA DELAY =======
if (digitalRead(BUTTON_RESET) == LOW && now - lastPressReset > debounceDelay) {
lastPressReset = now;
resetSystem();
}
// ======= PAUSE TANPA DELAY =======
if (digitalRead(BUTTON_PAUSE) == LOW && now - lastPressPause > debounceDelay) {
lastPressPause = now;
buzzerEnabled = !buzzerEnabled;
displayBuzzerStatus();
}
}