#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <Servo.h>
// ===== RTC & LCD =====
RTC_DS1307 rtc;
LiquidCrystal_I2C lcd(0x27, 16, 2);
// ===== SERVO =====
Servo servos[7];
int servoPins[7] = {22,23,24,25,26,27,28};
// ===== BUZZER =====
#define BUZZER 9
// ===== KEYPAD =====
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {30,31,32,33};
byte colPins[COLS] = {34,35,36,37};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// ===== SERVO TIME =====
int servoHour[7] = {-1,-1,-1,-1,-1,-1,-1};
int servoMin[7] = {-1,-1,-1,-1,-1,-1,-1};
bool servoDone[7] = {false,false,false,false,false,false,false};
// ===== SET MODE =====
bool setMode = false;
int selectServo = -1;
String inputTime = "";
// ===== SHOW STATUS =====
void showServoStatus() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("S:");
for (int i=0;i<4;i++){
lcd.print(i+1);
lcd.print(servoHour[i] != -1 ? '*' : '-');
lcd.print(' ');
}
lcd.setCursor(0,1);
for (int i=4;i<7;i++){
lcd.print(i+1);
lcd.print(servoHour[i] != -1 ? '*' : '-');
lcd.print(' ');
}
}
// ===== SETUP =====
void setup() {
Wire.begin();
rtc.begin();
lcd.init();
lcd.backlight();
pinMode(BUZZER, OUTPUT);
for (int i=0;i<7;i++){
servos[i].attach(servoPins[i]);
servos[i].write(0);
}
lcd.print("Medicine Box");
delay(1500);
lcd.clear();
}
// ===== LOOP =====
void loop() {
DateTime now = rtc.now();
char key = keypad.getKey();
// ===== NORMAL MODE =====
if (!setMode) {
lcd.setCursor(0,0);
lcd.print("Time ");
if(now.hour()<10) lcd.print("0");
lcd.print(now.hour());
lcd.print(":");
if(now.minute()<10) lcd.print("0");
lcd.print(now.minute());
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print("A:Set B:View ");
// เข้าโหมดตั้งค่า
if (key == 'A') {
setMode = true;
selectServo = -1;
inputTime = "";
lcd.clear();
}
// กด B ดูสถานะ
if (key == 'B') {
showServoStatus();
delay(2000);
lcd.clear();
}
}
// ===== SET MODE =====
else {
if (selectServo == -1) {
lcd.setCursor(0,0);
lcd.print("Select Servo");
lcd.setCursor(0,1);
lcd.print("1-7 (*=Clr)");
if (key >= '1' && key <= '7') {
selectServo = key - '1';
inputTime = "";
lcd.clear();
}
}
else {
lcd.setCursor(0,0);
lcd.print("S");
lcd.print(selectServo+1);
lcd.print(" Time");
lcd.setCursor(0,1);
lcd.print(inputTime);
lcd.print(" ");
if (key >= '0' && key <= '9' && inputTime.length() < 4)
inputTime += key;
// CLEAR TIME
if (key == '*') {
servoHour[selectServo] = -1;
servoMin[selectServo] = -1;
servoDone[selectServo] = false;
setMode = false;
selectServo = -1;
inputTime = "";
showServoStatus();
delay(1500);
lcd.clear();
}
// SAVE TIME
if (key == '#' && inputTime.length() == 4) {
servoHour[selectServo] =
(inputTime[0]-'0')*10 + (inputTime[1]-'0');
servoMin[selectServo] =
(inputTime[2]-'0')*10 + (inputTime[3]-'0');
servoDone[selectServo] = false;
setMode = false;
selectServo = -1;
inputTime = "";
showServoStatus();
delay(1500);
lcd.clear();
}
}
}
// ===== CHECK TIME =====
for (int i=0;i<7;i++){
if (servoHour[i] == -1) continue;
if (now.hour()==servoHour[i] &&
now.minute()==servoMin[i] &&
!servoDone[i]) {
servoDone[i] = true;
tone(BUZZER,1000,1000);
servos[i].write(90);
delay(2000);
servos[i].write(0);
}
if (now.minute()!=servoMin[i])
servoDone[i] = false;
}
}