/*
* Telephone activation clock
* This is a clock to activate a telephone for a programmed time.
* I use the DS3231 real time clock, this is more accurate than the DS1302 version from Velleman (VMA 301).
* The 16/2 LCD screen is the one that came with the Genuino Starter kit.
* For the relais I used the Velleman VMA406. For safety reasons i use the normally closed contacts to have
* an active telephone een when power supply to the unit fails.
*
* Erik Luyten
* March 11th, 2019
*/
#include <DS3231.h> //for clock
#include <LiquidCrystal.h> //for LCD display
#include <EEPROM.h> //for EEPROM on UNO to store phone activation time settings during power failure
DS3231 rtc(SDA, SCL);
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int RelayPin = 7; //activation relay for telephone (normally closed is used so phone is active if unit is without power)
const int LedTel = 6; //signal LED for phonerelay
//************Buttons for setclock*****************//
int P1=8; // Button SELECT to cycle through possible MENU settings (0 = display actual date/time TO 10 = store changed values)
int P2=9; // Button +
int P3=10; // Button -
//************Variables for setclock **************//
int hourupg; //upgrade setting for hours
int minupg; //upgrade setting for minutes
int yearupg; //upgrade setting for year (will be set to actual year in SETUP so we don't have to start from zero)
int monthupg; //upgrade setting for month(number)
int dayupg; //upgrade setting for day(number)
int menu = 0; //cycles from 0 to 10
int starthourupg = 00; //starting hour for telephone
int startminupg = 00; //starting minutes for telephone
int stophourupg = 00; //stop hour for telephone
int stopminupg = 00; //stop minutes for telephone
unsigned long BreakSetClock; //breakout from menu settings after 10 seconds (each buttonpress resets BreakSetClock time)
//************Time to set phone on and off **********//
Time PhoneOn; // Time to activate telephone
Time PhoneOff; // Time to deactivate telephone
Time ClockTijd; // Actual DayTime from Real Time Clock
int DST; //Daylight Saving Time (read from EEPROM address 0: 0 = winter, 1 = Summer ) (not implemented yet)
unsigned long StartPhoneSec; // time to activate telephone in seconds from midnight
unsigned long StopPhoneSec; // time to deactivate telephone in seconds from midnight
unsigned long DagSeconden; // actual seconds since midnight
Time t; //the actual time/date info
void setup() {
Serial.begin(9600);
pinMode(RelayPin, OUTPUT);
pinMode(LedTel, OUTPUT);
pinMode(P1,INPUT);
pinMode(P2,INPUT);
pinMode(P3,INPUT);
rtc.begin();
lcd.begin(16,2);
// *********** Time and Date (no day of week) can now be set with setup buttons (P1= Menu, P2= +, P3= -)
//rtc.setDOW(SATURDAY); // Set Day-of-Week to SUNDAY
//rtc.setTime(11,19,30); // Set the time to 12:00:00 (24hr format)
//rtc.setDate(23, 2, 2019); // Day, Month, Year
//*******
//Default activation time for telephone (can be changed with setup buttons)
/* //not needed anymore since activation can be set with buttons
PhoneOn.hour = 18;
PhoneOn.min = 00;
PhoneOn.sec = 00;
//State deactivation time for telephone
PhoneOff.hour = 20;
PhoneOff.min = 00;
PhoneOff.sec = 00;
//store default activation and de-activation time to EEPROM in UNO
EEPROM.write(1,PhoneOn.hour);
EEPROM.write(2,PhoneOn.min);
EEPROM.write(3,PhoneOff.hour);
EEPROM.write(4,PhoneOff.min);
*/
//Read activation and deactivation time from EEPROM at powerup
PhoneOn.hour = EEPROM.read(1);
PhoneOn.min = EEPROM.read(2);
PhoneOff.hour = EEPROM.read(3);
PhoneOff.min = EEPROM.read(4);
StartPhoneSec = seconden(PhoneOn); //recalculate Phone starttime to number of seconds since midnight
StopPhoneSec = seconden(PhoneOff); //recalculate Phone stoptime to number of seconds since midnight
// ??? no idea why we have to add 5 years but it works like this ????
yearupg = t.year + 5; //yearupg is set to actual year to allow easy setup (we do not have to start from the beginning of (unix) time)
}
void loop() {
// check if you press the SET button and increase the menu index
if(digitalRead(P1))
{
menu=menu+1;
BreakSetClock = DagSeconden; //store keypress time to allow breakout after 10 seconds
}
if (DagSeconden > (BreakSetClock + 10)) //display time and date after 10 seconds without keypress
{
menu = 0;
}
// in which subroutine should we go?
/*
* Since clock time settings should be as accurate as possible we will perform them last in the cycle (just before storing the values).
* You cannot set seconds. This is always 0. Set minutes 1 higher and press select when the reference clock is at 59 seconds.
* This has to be done in the 10 seconds timeout frame so you might have to press the + and - a few times to cancel the breakout routine.
*/
switch (menu) {
case 0:
DisplayDateTime(); // void DisplayDateTime
break;
case 1:
DisplaySetStartHour(); // void DisplaySetStartHour (for telephone activation)
break;
case 2:
DisplaySetStartMin(); // void DisplaySetStartMin (for telephone activation)
break;
case 3:
DisplaySetStopHour(); // void DisplaySetStopHour (for telephone De-activation)
break;
case 4:
DisplaySetStopMin(); // void DisplaySetStopMin (for telephone De-activation)
break;
case 5:
DisplaySetYear(); // void DisplaySetYear
break;
case 6:
DisplaySetMonth(); // void DisplaySetMonth
break;
case 7:
DisplaySetDay(); // void DisplaySetDay
break;
case 8:
DisplaySetHour(); // void DisplaySetHour
break;
case 9:
DisplaySetMinute(); // void DisplaySetMinute
break;
case 10:
StoreSettings(); // void StoreSettings (only for the settings that changed: Time - Date - PhoneOn - PhoneOff)
menu=0;
break;
}
t = rtc.getTime(); // Read current time and date.
DagSeconden = seconden(t); //calculate seconds since midnight
// print control info to Serial Monitor (commented out for better LCD clock response)
/* Serial.print("Uur: ");
Serial.print(t.hour);
Serial.print(" Min: ");
Serial.print(t.min);
Serial.print(" Sec: ");
Serial.print(t.sec);
Serial.print(" Menupressed: ");
Serial.println(menu);
Serial.print("Seconden sinds middernacht: ");
Serial.print(DagSeconden);
Serial.print(" Start telephone: ");
Serial.print(StartPhoneSec);
Serial.print(" Stop telephone: ");
Serial.println(StopPhoneSec);
Serial.print("Starttijd: ");
Serial.print(PhoneOn.hour);
Serial.print(":");
if (PhoneOn.min < 10)
{
Serial.print("0");
}
Serial.print(PhoneOn.min);
Serial.print(" Stoptijd: ");
Serial.print(PhoneOff.hour);
Serial.print(":");
if (PhoneOff.min < 10)
{
Serial.print("0");
}
Serial.println(PhoneOff.min);
*/
if (StartPhoneSec < StopPhoneSec) //no activation possible at midnight - stoptime is larger than starttime
{
if ((DagSeconden > StartPhoneSec) && (DagSeconden < StopPhoneSec)) //ClockTime is between start and stop times - activate phone
{
digitalWrite(RelayPin, LOW);
digitalWrite(LedTel, HIGH);
}
else // Clocktime is outside start and stoptimes - deactivate phone
{
digitalWrite(RelayPin, HIGH);
digitalWrite(LedTel, LOW);
}
}
else if (StartPhoneSec > StopPhoneSec) //we are running over midnight to the next day - phone active at midnight
{
if (DagSeconden > StartPhoneSec) //activate phone
{
digitalWrite(RelayPin, LOW);
digitalWrite(LedTel, HIGH);
}
else if (DagSeconden > StopPhoneSec) //deactivate phone
{
digitalWrite(RelayPin, HIGH);
digitalWrite(LedTel, LOW);
}
}
delay(500); //wait 0.5 seconds (keypress reaction time is 0.5 second)
}
unsigned long seconden(Time dezetijd){ //calculate seconds sinds midnight for: ClockTime, PhoneStart and PhoneStop
unsigned long result;
unsigned long mijnuur = dezetijd.hour;
unsigned long uurseconden = 3600;
result = (dezetijd.sec + dezetijd.min * 60 + mijnuur * uurseconden);
return result;
}
void DisplayDateTime () //show Time, Date, PhoneStartTime and PhoneStopTime on LCD screen
{
lcd.clear();
lcd.setCursor(1,0);
lcd.print(rtc.getTimeStr());
lcd.print(" ");
lcd.print(PhoneOn.hour);
lcd.print(":");
if (PhoneOn.min < 10)
{
lcd.print("0");
}
lcd.print(PhoneOn.min);
lcd.setCursor(0,1);
lcd.print(rtc.getDateStr());
lcd.print(" ");
lcd.print(PhoneOff.hour);
lcd.print(":");
if (PhoneOff.min < 10)
{
lcd.print("0");
}
lcd.print(PhoneOff.min);
}
void DisplaySetHour() //set clock hours
{
// time setting
lcd.clear();
if(digitalRead(P2)==HIGH)
{
BreakSetClock = DagSeconden; //store menupress time to allow breakout after 10 seconds
if(hourupg==23)
{
hourupg=0;
}
else
{
hourupg=hourupg+1;
}
}
if(digitalRead(P3)==HIGH)
{
BreakSetClock = DagSeconden; //store menupress time to allow breakout after 10 seconds
if(hourupg==0)
{
hourupg=23;
}
else
{
hourupg=hourupg-1;
}
}
lcd.setCursor(0,0);
lcd.print("Set hour:");
lcd.setCursor(0,1);
lcd.print(hourupg,DEC);
delay(200);
}
void DisplaySetMinute() //set clock minutes
{
// Setting the minutes
lcd.clear();
if(digitalRead(P2)==HIGH)
{
BreakSetClock = DagSeconden; //store menupress time to allow breakout after 10 seconds
if (minupg==59)
{
minupg=0;
}
else
{
minupg=minupg+1;
}
}
if(digitalRead(P3)==HIGH)
{
BreakSetClock = DagSeconden; //store menupress time to allow breakout after 10 seconds
if (minupg==0)
{
minupg=59;
}
else
{
minupg=minupg-1;
}
}
lcd.setCursor(0,0);
lcd.print("Set Minutes:");
lcd.setCursor(0,1);
lcd.print(minupg,DEC);
delay(200);
}
void DisplaySetYear() //set clock year (allready filled with year in clockmemory)
{
// setting the year
lcd.clear();
if(digitalRead(P2)==HIGH)
{
BreakSetClock = DagSeconden; //store menupress time to allow breakout after 10 seconds
yearupg=yearupg+1;
}
if(digitalRead(P3)==HIGH)
{
BreakSetClock = DagSeconden; //store menupress time to allow breakout after 10 seconds
yearupg=yearupg-1;
}
lcd.setCursor(0,0);
lcd.print("Set Year:");
lcd.setCursor(0,1);
lcd.print(yearupg,DEC);
delay(200);
}
void DisplaySetMonth() //set clock month
{
// Setting the month
lcd.clear();
if(digitalRead(P2)==HIGH)
{
BreakSetClock = DagSeconden; //store menupress time to allow breakout after 10 seconds
if (monthupg==12)
{
monthupg=1;
}
else
{
monthupg=monthupg+1;
}
}
if(digitalRead(P3)==HIGH)
{
BreakSetClock = DagSeconden; //store menupress time to allow breakout after 10 seconds
if (monthupg==1)
{
monthupg=12;
}
else
{
monthupg=monthupg-1;
}
}
lcd.setCursor(0,0);
lcd.print("Set Month:");
lcd.setCursor(0,1);
lcd.print(monthupg,DEC);
delay(200);
}
void DisplaySetDay() //set clock day
{
// Setting the day
lcd.clear();
if(digitalRead(P2)==HIGH)
{
BreakSetClock = DagSeconden; //store menupress time to allow breakout after 10 seconds
if (dayupg==31)
{
dayupg=1;
}
else
{
dayupg=dayupg+1;
}
}
if(digitalRead(P3)==HIGH)
{
BreakSetClock = DagSeconden; //store menupress time to allow breakout after 10 seconds
if (dayupg==1)
{
dayupg=31;
}
else
{
dayupg=dayupg-1;
}
}
lcd.setCursor(0,0);
lcd.print("Set Day:");
lcd.setCursor(0,1);
lcd.print(dayupg,DEC);
delay(200);
}
void DisplaySetStartHour() //set phone starthour
{
// time setting
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Set starthour:");
lcd.setCursor(0,1);
lcd.print(starthourupg,DEC);
if(digitalRead(P2)==HIGH)
{
BreakSetClock = DagSeconden; //store menupress time to allow breakout after 10 seconds
if(starthourupg==23)
{
starthourupg=0;
}
else
{
starthourupg=starthourupg+1;
}
}
if(digitalRead(P3)==HIGH)
{
BreakSetClock = DagSeconden; //store menupress time to allow breakout after 10 seconds
if(starthourupg==0)
{
starthourupg=23;
}
else
{
starthourupg=starthourupg-1;
}
}
delay(200);
}
void DisplaySetStartMin() //set phonestartminutes
{
// time setting
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Set startminutes:");
lcd.setCursor(0,1);
lcd.print(startminupg,DEC);
if(digitalRead(P2)==HIGH)
{
BreakSetClock = DagSeconden; //store menupress time to allow breakout after 10 seconds
if(startminupg==59)
{
startminupg=0;
}
else
{
startminupg=startminupg+1;
}
}
if(digitalRead(P3)==HIGH)
{
BreakSetClock = DagSeconden; //store menupress time to allow breakout after 10 seconds
if(startminupg==0)
{
startminupg=59;
}
else
{
startminupg=startminupg-1;
}
}
delay(200);
}
void DisplaySetStopHour() //set phonestophour
{
// time setting
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Set stophour:");
lcd.setCursor(0,1);
lcd.print(stophourupg,DEC);
if(digitalRead(P2)==HIGH)
{
BreakSetClock = DagSeconden; //store menupress time to allow breakout after 10 seconds
if(stophourupg==23)
{
stophourupg=0;
}
else
{
stophourupg=stophourupg+1;
}
}
if(digitalRead(P3)==HIGH)
{
BreakSetClock = DagSeconden; //store menupress time to allow breakout after 10 seconds
if(stophourupg==0)
{
stophourupg=23;
}
else
{
stophourupg=stophourupg-1;
}
}
delay(200);
}
void DisplaySetStopMin() //set phonestopminutes
{
// time setting
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Set stopminutes:");
lcd.setCursor(0,1);
lcd.print(stopminupg,DEC);
if(digitalRead(P2)==HIGH)
{
BreakSetClock = DagSeconden; //store menupress time to allow breakout after 10 seconds
if(stopminupg==59)
{
stopminupg=0;
}
else
{
stopminupg=stopminupg+1;
}
}
if(digitalRead(P3)==HIGH)
{
BreakSetClock = DagSeconden; //store menupress time to allow breakout after 10 seconds
if(stopminupg==0)
{
stopminupg=59;
}
else
{
stopminupg=stopminupg-1;
}
}
delay(200);
}
void StoreSettings() //store the results depending on values in variables
{
// Saving Time, Date, StopTime and StartTime only if they are changed
// Disabled message to LCD to allow more accurate time setting
lcd.clear();
lcd.setCursor(0,0);
if ((hourupg == 0) && (minupg == 0)) //do not set time if both hours and minutes are zero (cannot set clock to midnight time)
{
lcd.print("TIME not saved !");
delay(2000);
}
else
{
lcd.print("Saving TIME");
rtc.setTime(hourupg,minupg,00); // Set the time (24hr format)
hourupg = 0;
minupg = 0;
delay(2000);
}
lcd.clear();
lcd.setCursor(0,0);
if ((dayupg == 0) || (monthupg == 0) || (yearupg == 0)) //do not set date if any of these values is zero
{
lcd.print("DATE not saved !");
delay(2000);
}
else
{
lcd.print("Saving DATE");
rtc.setDate(dayupg, monthupg, yearupg); // Day, Month, Year
dayupg = 0;
monthupg = 0;
delay(2000);
}
//First Check if start and stoptime are not the same (should be at least one minute difference)
lcd.clear();
lcd.setCursor(0,0);
if ((starthourupg == stophourupg) && (startminupg == stopminupg) && ((starthourupg + startminupg + stophourupg + stopminupg) != 0))
{
lcd.print("START & STOPTIME");
lcd.setCursor(0,1);
lcd.print("Cant be the same");
delay(2000);
}
else
{
//check to see if starttime should be saved
if ((starthourupg == 0) && (startminupg == 0)) //don't set starttime if both hours and minutes are zero(cannot set starttime to midnight)
{
lcd.print("STARTTIME ");
lcd.setCursor(0,1);
lcd.print("not saved !");
delay(2000);
}
else
{
lcd.print("Saving STARTTIME");
PhoneOn.hour = starthourupg;
PhoneOn.min = startminupg;
PhoneOn.sec = 00;
StartPhoneSec = seconden(PhoneOn); //recalculate Phone starttime to number of seconds since midnight
EEPROM.write(1,PhoneOn.hour); //write activation time to EEPROM on UNO
EEPROM.write(2,PhoneOn.min); //write activation time to EEPROM on UNO
lcd.setCursor(0,1);
lcd.print(PhoneOn.hour);
lcd.print(":");
if (PhoneOn.min < 10)
{
lcd.print("0");
}
lcd.print(PhoneOn.min);
starthourupg = 0;
startminupg = 0;
delay(2000);
}
lcd.clear();
lcd.setCursor(0,0);
//check to aee if stoptime should be changed
if ((stophourupg == 0) && (stopminupg == 0)) //don't set stoptime if both hours and minutes are zero(cannot set stoptime to midnight)
{
lcd.print("STOPTIME ");
lcd.setCursor(0,1);
lcd.print("not saved !");
delay(2000);
}
else
{
lcd.print("Saving STOPTIME");
PhoneOff.hour = stophourupg;
PhoneOff.min = stopminupg;
PhoneOff.sec = 00;
StopPhoneSec = seconden(PhoneOff); //recalculate Phone stoptime to number of seconds since midnight
EEPROM.write(3,PhoneOff.hour); //write de-activation time to EEPROM on UNO
EEPROM.write(4,PhoneOff.min); //write de-activation time to EEPROM on UNO
lcd.setCursor(0,1);
lcd.print(PhoneOff.hour);
lcd.print(":");
if (PhoneOff.min < 10)
{
lcd.print("0");
}
lcd.print(PhoneOff.min);
stophourupg = 0;
stopminupg = 0;
delay(2000);
}
}
//delay(200);
}
Comments