You are on page 1of 9

#include <LiquidCrystal.

h>
#include <EEPROM.h>
#include <Wire.h>
#include <MenuBackend.h>

// This is the RealTimeModule address.


#define DS1307 0x68

//Initialize LCD.
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// Initialize values for timekeeping.


byte second = 0;
byte minute = 0;
byte hour = 0;
byte weekday = 0;
byte monthday = 0;
byte month = 0;
byte year = 0;

//Initialize values for alarms.


byte minsB1 = 0, hourB1 = 0, lastB1mins = 0, lastB1hour = 0;
byte minsB2 = 0, hourB2 = 0, lastB2mins = 0, lastB2hour = 0;
byte minsB3 = 0, hourB3 = 0, lastB3mins = 0, lastB3hour = 0;
bool b1 = true, b2 = true, b3 = true;

//Define photoresistor values.


int bottle1 = 0;
int bottle2 = 0;
int bottle3 = 0;
int lastBottle = 0;
int bottleReset = 0;
int curr = 0;

// Define keypad values.


#define btnRIGHT 0
#define btnUP 1
#define btnDOWN 2
#define btnLEFT 3
#define btnSELECT 4
#define btnNONE 5
int lcd_key = 0;
int adc_key_in = 0;

//Define memory locations for the EEPROM.


#define ONE_PERIOD 0
#define ONE_PILLS 1
#define TWO_PERIOD 2
#define TWO_PILLS 3
#define THREE_PERIOD 4
#define THREE_PILLS 5

// Read keypad buttons.


int read_LCD_buttons(){
adc_key_in = analogRead(0);
//Debounce time.
delay(100);
//Correction for value drifting.
int k = (analogRead(0) - adc_key_in);
if(5 < abs(k)) { return btnNONE;}
if (adc_key_in > 1000) return btnNONE;
if (adc_key_in < 50) return btnRIGHT;
if (adc_key_in < 250) return btnUP;
if (adc_key_in < 450) return btnDOWN;
if (adc_key_in < 650) return btnLEFT;
if (adc_key_in < 850) return btnSELECT;
return btnNONE;
}

//Menu variables.
MenuBackend menu = MenuBackend(menuUsed,menuChanged);
//initialize menuitems
MenuItem setupMode = MenuItem("setupMode");
MenuItem setupHours = MenuItem("setupHours");
MenuItem setupMinutes = MenuItem("setupMinutes");
MenuItem setupBottles = MenuItem("setupBottles");
MenuItem B1interval = MenuItem("B1interval");
MenuItem B1pills = MenuItem("B1pills");
MenuItem B2interval = MenuItem("B2interval");
MenuItem B2pills = MenuItem("B2pills");
MenuItem B3interval = MenuItem("B3interval");
MenuItem B3pills = MenuItem("B3pills");

void setup(){
//Wire handles communication with RTM.
Wire.begin();
//Serial is used for debugging purposes.
Serial.begin(9600);
//LCD is main output.
lcd.begin(16, 2);
//Set pins for LEDs.
pinMode(11,OUTPUT);
pinMode(12,OUTPUT);
pinMode(13,OUTPUT);
//Control backlight.
pinMode(10, OUTPUT);
analogWrite(10, 100);
//Setup menu.
menu.getRoot().add(setupMode);
setupMode.add(setupBottles).addRight(setupHours).addRight(setupMinutes);

setupBottles.add(B1interval).addRight(B1pills).addRight(B2interval).addRight(B2pill
s).addRight(B3interval).addRight(B3pills);
menu.toRoot();

//Test EEPROM memory.


EEPROM.write(ONE_PERIOD, (char)1);
EEPROM.write(ONE_PILLS, (char)1);
EEPROM.write(TWO_PERIOD, (char)1);
EEPROM.write(TWO_PILLS, (char)2);
EEPROM.write(THREE_PERIOD, (char)1);
EEPROM.write(THREE_PILLS, (char)3);
}

void loop(){
//Check alarms for each bottle.
checkAlarms();
//Manage GUI.
if(menu.getCurrent().getName()==menu.getRoot()){
readTime();
mainMenuAction();
}else if(menu.getCurrent().getName() == "setupHours" ||
menu.getCurrent().getName() == "setupMinutes"){
printTime();
}else if(menu.getCurrent().getName() == "B1interval"){
printNumber(EEPROM.read(ONE_PERIOD));
}else if(menu.getCurrent().getName() == "B1pills"){
printNumber(EEPROM.read(ONE_PILLS));
}else if(menu.getCurrent().getName() == "B2interval"){
printNumber(EEPROM.read(TWO_PERIOD));
}else if(menu.getCurrent().getName() == "B2pills"){
printNumber(EEPROM.read(TWO_PILLS));
}else if(menu.getCurrent().getName() == "B3interval"){
printNumber(EEPROM.read(THREE_PERIOD));
}else if(menu.getCurrent().getName() == "B3pills"){
printNumber(EEPROM.read(THREE_PILLS));
}else{
lcd.setCursor(0,0);
lcd.print(" ");
}

//Respond to user input (through pushbuttons)


lcd_key = read_LCD_buttons();
navigateMenus();
}

void navigateMenus(){
MenuItem currentMenu=menu.getCurrent();

switch (lcd_key)
{
case btnRIGHT:
{
menu.moveRight();
break;
}
case btnLEFT:
{
menu.moveLeft();
break;
}
case btnUP:
{
if(currentMenu.getName() == "setupHours"){
hour++;
if(hour>23){hour=0;}
setTime();
}else if(currentMenu.getName() == "setupMinutes"){
minute++;
if(minute>59){minute=0;}
setTime();
}else if(currentMenu.getName() == "B1pills"){
char newVal = EEPROM.read(ONE_PILLS);
newVal = newVal + 1;
if(newVal > 10){ newVal = 0;}
EEPROM.write(ONE_PILLS, (char)newVal);
}else if(currentMenu.getName() == "B1interval"){
char newVal = EEPROM.read(ONE_PERIOD);
newVal = newVal + 1;
if(newVal > 24){ newVal = 0;}
EEPROM.write(ONE_PERIOD, (char)newVal);
}else if(currentMenu.getName() == "B2pills"){
char newVal = EEPROM.read(TWO_PILLS);
newVal = newVal + 1;
if(newVal > 10){ newVal = 0;}
EEPROM.write(TWO_PILLS, (char)newVal);
}else if(currentMenu.getName() == "B2interval"){
char newVal = EEPROM.read(TWO_PERIOD);
newVal = newVal + 1;
if(newVal > 24){ newVal = 0;}
EEPROM.write(TWO_PERIOD, (char)newVal);
}else if(currentMenu.getName() == "B3pills"){
char newVal = EEPROM.read(THREE_PILLS);
newVal = newVal + 1;
if(newVal > 10){ newVal = 0;}
EEPROM.write(THREE_PILLS, (char)newVal);
}else if(currentMenu.getName() == "B3interval"){
char newVal = EEPROM.read(THREE_PERIOD);
newVal = newVal + 1;
if(newVal > 24){ newVal = 0;}
EEPROM.write(THREE_PERIOD, (char)newVal);
}else if(currentMenu.getName() == menu.getRoot()){
if(bottleReset == 1){
hourB1 = lastB1hour;
minsB1 = lastB1mins;
Serial.print("Last: ");
Serial.print(lastB1hour);
Serial.print(":");
Serial.println(lastB1mins);
Serial.print("Now: ");
Serial.print(hourB1);
Serial.print(":");
Serial.println(minsB1);
}
}
break;
}
case btnDOWN:
{
if(currentMenu.getName() == "setupHours"){
hour--;
if(hour<0){hour=23;}
setTime();
}else if(currentMenu.getName() == "setupMinutes"){
minute--;
if(minute<0){minute=59;}
setTime();
}else if(currentMenu.getName() == "B1pills"){
char newVal = EEPROM.read(ONE_PILLS);
newVal = newVal - 1;
if(newVal < 0){ newVal = 10;}
EEPROM.write(ONE_PILLS, (char)newVal);
}else if(currentMenu.getName() == "B1interval"){
char newVal = EEPROM.read(ONE_PERIOD);
newVal = newVal - 1;
if(newVal < 0){ newVal = 24;}
EEPROM.write(ONE_PERIOD, (char)newVal);
}else if(currentMenu.getName() == "B2pills"){
char newVal = EEPROM.read(TWO_PILLS);
newVal = newVal - 1;
if(newVal < 0){ newVal = 10;}
EEPROM.write(TWO_PILLS, (char)newVal);
}else if(currentMenu.getName() == "B2interval"){
char newVal = EEPROM.read(TWO_PERIOD);
newVal = newVal - 1;
if(newVal < 0){ newVal = 24;}
EEPROM.write(TWO_PERIOD, (char)newVal);
}else if(currentMenu.getName() == "B3pills"){
char newVal = EEPROM.read(THREE_PILLS);
newVal = newVal - 1;
if(newVal < 0){ newVal = 10;}
EEPROM.write(THREE_PILLS, (char)newVal);
}else if(currentMenu.getName() == "B3interval"){
char newVal = EEPROM.read(THREE_PERIOD);
newVal = newVal - 1;
if(newVal < 0){ newVal = 24;}
EEPROM.write(THREE_PERIOD, (char)newVal);
}
break;
}
case btnSELECT:
{
if(currentMenu.moveDown()){
menu.moveDown();
}else{
menu.use();
}
break;
}
case btnNONE:
{
break;
}
}
}

//Functions handling alarms.


void setAlarm(int bottle, char interval){
if(bottle == 1){
lastB1hour = hourB1;
lastB1mins = minsB1;
hourB1 = minute + interval;
if(hourB1>59){hourB1=hourB1-60;}
minsB1 = second;
//Debugging.
Serial.print("Now: ");
Serial.print(hourB1);
Serial.print(":");
Serial.println(minsB1);
}else if(bottle == 2){
lastB2hour = hourB2;
lastB2mins = minsB2;
hourB2 = minute + interval;
if(hourB2>59){hourB2=hourB2-60;}
minsB2 = second;
Serial.print("Now: ");
Serial.print(hourB2);
Serial.print(":");
Serial.println(minsB2);
}else if(bottle == 3){
lastB3hour = hourB3;
lastB3mins = minsB3;
hourB3 = minute + interval;
if(hourB3>59){hourB3=hourB3-60;}
minsB3 = second;
Serial.print("Now: ");
Serial.print(hourB3);
Serial.print(":");
Serial.println(minsB3);
}
}

void checkAlarms(){
if(!b1){
if(minute == hourB1 && second >= minsB1){
b1 = true;
}
}
if(!b2){
if(minute == hourB2 && second >= minsB2){
b2 = true;
}
}
if(!b3){
if(minute == hourB3 && second >= minsB3){
b3 = true;
}
}

digitalWrite(11, b1);
digitalWrite(12, b2);
digitalWrite(13, b3);
}

//Helper functions for clock.


byte decToBcd(byte val) {return ((val/10*16) + (val%10));}
byte bcdToDec(byte val) {return ((val/16*10) + (val%16));}

// Set the time in the RTM.


void setTime() {
// The following codes transmits the data to the RTC
Wire.beginTransmission(DS1307);
Wire.write(byte(0));
Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(weekday));
Wire.write(decToBcd(monthday));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.write(byte(0));
Wire.endTransmission();
// Ends transmission of data
}

//Read time from RTM.


void readTime() {
Wire.beginTransmission(DS1307);
Wire.write(byte(0));
Wire.endTransmission();
Wire.requestFrom(DS1307, 7);
second = bcdToDec(Wire.read());
minute = bcdToDec(Wire.read());
hour = bcdToDec(Wire.read());
weekday = bcdToDec(Wire.read());
monthday = bcdToDec(Wire.read());
month = bcdToDec(Wire.read());
year = bcdToDec(Wire.read());
}

//Print time.
void printTime(){
lcd.setCursor(0,0);
lcd.print(" ");
if (hour < 10){lcd.print("0");}
lcd.print(hour, DEC);
lcd.print(":");
if (minute < 10){lcd.print("0");}
lcd.print(minute, DEC);
lcd.print(":");
if (second < 10){lcd.print("0");}
lcd.print(second, DEC);
lcd.print(" ");
}

//Print a number.
void printNumber(int number){
lcd.setCursor(0,0);
lcd.print(" ");
if(number/10 == 0){
lcd.print("0");
}else{
lcd.print(" ");
}
lcd.print(number);
lcd.print(" ");
}

//Menu callback functions.


//Navigation controls.
void menuChanged(MenuChangeEvent changed){
MenuItem newMenuItem=changed.to; //get the destination menu
lcd.setCursor(0,1); //set the start position for lcd printing to the second row
}
if(newMenuItem.getName()==menu.getRoot()){
lcd.print(" ");
}else if (newMenuItem.getName()=="setupMode"){
lcd.print("ENTER SETUP MODE");
}else if (newMenuItem.getName()=="setupHours"){
lcd.print("Set hour. ");
}else if (newMenuItem.getName()=="setupMinutes"){
lcd.print("Set minute. ");
}else if (newMenuItem.getName()=="setupBottles"){
lcd.print("Setup bottles. ");
}else if (newMenuItem.getName()=="B1interval"){
lcd.print("B1 interval. ");
}else if (newMenuItem.getName()=="B1pills"){
lcd.print("B1 pill number. ");
}else if (newMenuItem.getName()=="B2interval"){
lcd.print("B2 interval. ");
}else if (newMenuItem.getName()=="B2pills"){
lcd.print("B2 pill number. ");
}else if (newMenuItem.getName()=="B3interval"){
lcd.print("B3 interval. ");
}else if (newMenuItem.getName()=="B3pills"){
lcd.print("B3 pill number. ");
}
}

//Usage controls.
void menuUsed(MenuUseEvent used){
menu.toRoot(); //back to Main
}

//Root menu action.


void mainMenuAction(){
//Read values of photoresistors.
bottle1 = analogRead(1);
bottle2 = analogRead(2);
bottle3 = analogRead(3);

//Find out which bottle(s) are out of the box, print instructions.
if(bottle1 < 800){
b1 = false;
char nextIn = EEPROM.read(ONE_PERIOD);
curr = 1;
printInstructions(EEPROM.read(ONE_PILLS), nextIn);
setAlarm(1,nextIn);
} else if(bottle2 < 800){
b2 = false;
curr = 2;
char nextIn = EEPROM.read(TWO_PERIOD);
printInstructions(EEPROM.read(TWO_PILLS), nextIn);
setAlarm(2,nextIn);
}else if(bottle3 < 800){
curr = 3;
b3 = false;
char nextIn = EEPROM.read(THREE_PERIOD);
printInstructions(EEPROM.read(THREE_PILLS), nextIn);
setAlarm(3,nextIn);
}else{
if(lastBottle != 0){
lcd.clear();
lastBottle = 0;
}
printTime();
}
}
//Print instructions for each bottle.
void printInstructions(int pills, int period){
//Don't clear if bottle hasn't changed.
if(lastBottle != curr){
lcd.clear();
}
lastBottle = curr;
bottleReset = curr;
lcd.setCursor(0,0);
lcd.print("Take ");
lcd.print(pills);
lcd.print(" pill(s)");
lcd.setCursor(0,1);
lcd.print("every ");
lcd.print(period);
lcd.print(" hours.");
return;
}

You might also like