#include <LiquidCrystal_I2C.h>
#include <OneButton.h>
#include <RTClib.h>
#include <Servo.h>
int setAlarms[5][2];
// DEFINITIONS
#define sensorDetectPin 2
#define diodeSignalPin 3
#define buzzerSignalPin 4
#define encoderPinA 5
#define encoderPinB 6
#define lockCountPin 7
#define servoPinA 8
#define servoPinB 9
#define startPin 13
LiquidCrystal_I2C lcd(0x27, 16, 2);
OneButton btn = OneButton(lockCountPin);
RTC_DS1307 rtc;
Servo servoA;
Servo servoB;
int machineState = 0;
int alarmState = 0;
int dispensed = 0;
int timeState = 0;
int counter = 0;
int hourMax = 23;
int minuteMax = 59;
int nextAlarm[2] = {9, 30};
int curTime[2];
int lastEncoderPos;
int curEncoderPos;
int cursorPos;
int maxVal;
// ARDUINO CHIP
void setup() {
pinMode(sensorDetectPin, INPUT);
pinMode(diodeSignalPin, OUTPUT);
pinMode(buzzerSignalPin, OUTPUT);
pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);
pinMode(lockCountPin, INPUT);
pinMode(startPin, INPUT);
lcd.init();
btn.attachClick(changeTimeState);
rtc.begin();
servoA.attach(servoPinA);
servoB.attach(servoPinB);
servoA.write(0);
servoB.write(0);
initHourState();
lastEncoderPos = digitalRead(encoderPinA);
}
void loop() {
if (!digitalRead(startPin)) {
initMachineSetup();
checkEncoderMovement();
btn.tick();
} else {
initMachineFunctions();
showCurTime();
checkAlarmTime();
detectMotionEvent();
}
}
// SLIDESWITCH
void initMachineSetup() {
if (machineState != 0) {
machineState = 0;
setAlarmDisplay();
}
}
void initMachineFunctions() {
if (machineState != 1) {
machineState = 1;
nextAlarmDisplay();
}
}
// ROTARY ENCODER
void checkEncoderMovement() {
curEncoderPos = digitalRead(encoderPinA);
if (curEncoderPos != lastEncoderPos) {
if (digitalRead(encoderPinB) != curEncoderPos) {
incrementCount();
} else {
decrementCount();
}
lcd.setCursor(cursorPos, 1);
numberFormat(counter);
}
lastEncoderPos = curEncoderPos;
}
void changeTimeState() {
if (timeState > 0) {
timeState = 0;
initHourState();
} else {
timeState++;
initMinuteState();
}
}
void initHourState() {
maxVal = hourMax;
cursorPos = 0;
counter = 0;
setAlarmDisplay();
}
void initMinuteState() {
maxVal = minuteMax;
cursorPos = 3;
counter = 0;
}
// RTC MODULE
void setTimeFromRtc() {
DateTime now = rtc.now();
curTime[0] = now.hour();
curTime[1] = now.minute();
}
void showCurTime() {
if (!alarmState) {
setTimeFromRtc();
printCurTime();
}
}
void printCurTime() {
lcd.setCursor(0, 0);
lcd.print("Now ");
numberFormat(curTime[0]);
lcd.print(":");
numberFormat(curTime[1]);
}
void checkAlarmTime() {
if (nextAlarm[0] == curTime[0] && nextAlarm[1] == curTime[1]) {
if (dispensed != 1) {
dispensed++;
servoCommand();
}
} else {
if (dispensed != 0) {
dispensed = 0;
}
}
}
// LCD SCREEN
void setAlarmDisplay() {
lcd.setBacklight(1);
lcd.clear();
lcd.print("Set Alarm");
lcd.setCursor(0, 1);
lcd.print("00:00");
}
void incrementCount() {
if (counter < maxVal) {
counter++;
} else {
counter = 0;
}
}
void decrementCount() {
if (counter > 0) {
counter--;
} else {
counter = maxVal;
}
}
void numberFormat(int num) {
if (num < 10) {
lcd.print("0");
}
lcd.print(num);
}
void nextAlarmDisplay() {
lcd.setBacklight(0);
lcd.clear();
showCurTime();
findNextAlarm();
}
void findNextAlarm() {
int next;
printNextAlarm();
}
void printNextAlarm() {
lcd.setCursor(0, 1);
lcd.print("Next ");
numberFormat(nextAlarm[0]);
lcd.print(":");
numberFormat(nextAlarm[1]);
}
void alarmNowDisplay() {
lcd.setBacklight(1);
lcd.clear();
lcd.print("Take Medicine!");
}
// MOTION SENSOR
void detectMotionEvent() {
if (digitalRead(sensorDetectPin)) {
startAlarm();
} else {
stopAlarm();
}
}
void startAlarm() {
if (alarmState != 1) {
alarmState = 1;
signalAlarmStart();
}
ledBlink();
}
void stopAlarm() {
if (alarmState != 0) {
alarmState = 0;
signalAlarmStop();
}
}
void signalAlarmStart() {
digitalWrite(buzzerSignalPin, HIGH);
digitalWrite(diodeSignalPin, HIGH);
alarmNowDisplay();
}
void signalAlarmStop() {
digitalWrite(buzzerSignalPin, LOW);
digitalWrite(diodeSignalPin, LOW);
nextAlarmDisplay();
}
// SERVO MOTORS
void servoCommand() {
servoA.write(90);
delay(300);
servoA.write(0);
delay(300);
servoB.write(90);
delay(300);
servoB.write(0);
}
// LED & BUZZER
void ledBlink() {
digitalWrite(diodeSignalPin, HIGH);
delay(200);
digitalWrite(diodeSignalPin, LOW);
delay(200);
}