eluyten
Published © GPL3+

Telephone Activation Clock

Clock to activate and de-activate a regular telephone wall connection to allow telephone calls only during selected hours.

IntermediateShowcase (no instructions)1,956
Telephone Activation Clock

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
Standard LCD - 16x2 White on Blue
Adafruit Standard LCD - 16x2 White on Blue
I suppose this is a good replacement from the one in the Genuino Starter kit
×1
RTC DS3231 ZS-042
This is the URL for 3 pieces but you only need one for this project
×1
Relais VMA406 (Velleman)
×1
Resistor 10k ohm
Resistor 10k ohm
×3
Resistor 1k ohm
Resistor 1k ohm
×1
Resistor 220 ohm
Resistor 220 ohm
×1
5 mm LED: Yellow
5 mm LED: Yellow
×1
Rotary potentiometer (generic)
Rotary potentiometer (generic)
I used one that came with the Starter Kit
×1
Pushbutton momentary ON
I bought them in the local electronics shop
×3

Software apps and online services

Arduino IDE
Arduino IDE
Box Designer
To design the box
Inkscape
To edit the box and the schematic

Hand tools and fabrication machines

Laser cutter (generic)
Laser cutter (generic)
needed for the box (I used Box Designer and a cutter in FabLab)
Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Custom parts and enclosures

PhoneClock enclosure

MDF 4mm lasercut box with additional MDF pieces for component parts

Schematics

schematicTelephone activation clock

wiring diagram

Code

TELEPHONECLOCK.ino

Arduino
Sketch for the Arduino Uno (a few Dutch words used as variables, sorry)
/*
 * 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);
}

Credits

eluyten

eluyten

0 projects • 0 followers

Comments