In the first part of this article, we presenting how to create all the process to implement this project. You can access the first part in the link (Access the first part of the Article)
Now, through this second part, we'll present all processes to create the functions to program the clock and date and program the hour of device activation.
Therefore, through these functions, we'll learn several principles of application and uses of Real-Time Clock (RTC) DS1307.
Proposed Functions for the ProjectAccording to explain in part I, the project has an aim to activate and deactivate the device in a programmed hour by the user.
Therefore, based on the problem, is need to use the CHIP Real-Time Clock. The CHIP is used to count 7 variables: second, minute, hour, day of wee, date of the month, month and year. So, for this, is need to implement a system of the hour for user adjust the hour, the date, the activation, and deactivation hour.
For this, several functions will be implemented to solve this problem according to the diagram shown in the Part I. So, we'll develop the functions to configure the actual time and the date of the Real-Time Clock and hour to activate the device connected in the relay.
Hereafter will be presented the schematic circuit in Figure 2 and code developed for the second part of the project.
Firstly, we'll present the configuration process through the variable creation and device initialization.
Thus, before entering in void setup(), was include all libraries, variables and function prototypes. Therefore, see that were implemented three functions: ReadKeypad, AdjustHour, and ActivationHour.
Hereafter each function is specified below:
- ReadKeyPad(): Perform the reading of keypad buttons and through this keypad, are used the numbers and its letters. The "A" letter is used to Adjust the hours, "C" will be used to clear the hour information and "D" will be used as a key to finish the configuration of parameters.
- AdjustTime(): Responsible to adjust the internal date and hour of the DS1307;
- ActivationHour(): Used to adjust the hour to activate the device connected in the relay.
#include <DS1307.h>
#include <Wire.h>
#include <EEPROM.h>
#include <LiquidCrystal.h>
#define MEMORY 100
const int rs = 2, en = 3, d4 = 4, d5 = 5, d6 = 6, d7 = 7;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
char tempo[9] = "";
char data[9] = "";
int DataTime[7];
byte SegAnt = 0, SegAtual = 0;
byte ReadKeyPad(void);
void AdjustTime(void);
void ActivationHour(void);
void setup()
{
Serial.begin(9600);
DS1307.begin();
//Config pins to control columns of the matrix keyboard
for(int key = 8; key < 12; key++)
{
pinMode(key, OUTPUT);
}
//Config pins to read lines of the matrix keyboard
for(int key = 12; key < 16; key++)
{
pinMode(key, INPUT);
}
for(int key = 8; key < 12; key++)
{
digitalWrite(key, LOW);
}
lcd.begin(16,2);
}
Right after prototype declarations, were initialized the devices RTC DS1307 and LCD 16x2 and all pins of Arduino are configured.
Now, we'll learn how works the logical programming for this system through the function void loop().
Main Logic of the ProjectAt first, when the system is at the beginning of the loop function is performed the verification of the initialization process. This verification is represented by the first condiction as is presented below.
if(EEPROM.read(MEMORY) != 73)
In this way, the system verifies it is the first time that the user enters in the system. Case the read number of the EEPROM (position 100) was different from 73, is need to configure the time and date of the system.
So, after config the time and date, the system writes the 73 value in the EEPROM.
EEPROM.write(MEMORIA, 73);
This number was used to signal for the user, that the time and date already be configured.
void loop()
{
if(EEPROM.read(MEMORIA) != 73)
{
AjustarHora();
EEPROM.write(MEMORIA, 73);
lcd.clear();
ActivationHour();
}
DS1307.getDate(DataTime);
SegAtual = DataTime[6];
if(LerTeclado() == 10)
{
AjustarHora();
lcd.clear();
ActivationHour();
lcd.clear();
}
if(abs(SegAtual - SegAnt) >= 1)
{
sprintf(tempo, "%02d:%02d:%02d", DataTime[4], DataTime[5], DataTime[6]);
sprintf(data, "%02d/%02d/%02d", DataTime[2], DataTime[1], DataTime[0]);
lcd.setCursor(4,1);
lcd.print(tempo);
lcd.setCursor(4,0);
lcd.print(data);
SegAnt = SegAtual;
}
}
Afterhere, all 7 parameters of date and time are acquisited and stored in the DataTime vector.
After the acquisition, the value of seconds is stored in the variable SegAtual. This variable is used to store the value of thesecond. The commands are presented below.
DS1307.getDate(DataTime);
SegAtual = DataTime[6];
Now, will be executed the condition to know if the user pressed the key "A" to adjust the clock time and the hour of activation of the device.
The key "A" is represented by 10, which is a returned value of the function when "A" is pressed, as is shown hereafter.
if(LerTeclado() == 10)
{
AjustarHora();
lcd.clear();
ActivationHour();
lcd.clear();
}
Lastly, the hour and the data are presented in the Display LCD. So that the hour and the date are presented, was implemented the following condition below.
if(abs(SegAtual - SegAnt) >= 1)
{
sprintf(tempo, "%02d:%02d:%02d", DataTime[4], DataTime[5], DataTime[6]);
sprintf(data, "%02d/%02d/%02d", DataTime[2], DataTime[1], DataTime[0]);
lcd.setCursor(4,1);
lcd.print(tempo);
lcd.setCursor(4,0);
lcd.print(data);
SegAnt = SegAtual;
}
So, through this condition, the date and hour will appear in LCD each one second, as is show in Figure 3.
Now, will explain the functions to adjust the time and adjust the hour to activate the device connected on the relay.
Functions to Adjust the Clock and Activation Hour of the DeviceFirstly, the functions are very similar and now, you'll see the working of each one. In this way, we'll analyze the AdjustTime() function.
AdjustTime FunctionNow, with our function, we'll see that some parts this function is repeated himself throughout the function and you'll see that the function is divided into two parts:
- Insert hour and minute of the clock,
- Insert data of month, month and year;
Firstly, we create all thevariables used in the function.
void AdjustTime()
{
int times[6];
int DadosTempo[7];
bool controle = 0;
bool EstadoSobe = 0, EstadoDesce = 0;
byte cont = 0;
byte number = 0;
int digitos[6];
byte PosCursor = 0;
byte t = 0;
bool Validate = 0;
char tempo[7] = "";
char data[15] = "";
DS1307.getDate(DadosTempo);
sprintf(tempo, "%02d:%02dh", DadosTempo[4], DadosTempo[5]);
sprintf(data, "%02d/%02d/%02d", DadosTempo[2], DadosTempo[1], DadosTempo[0]);
times[4] = DadosTempo[4];
times[5] = DadosTempo[5];
times[3] = DadosTempo[3];
times[2] = DadosTempo[2];
times[1] = DadosTempo[1];
times[0] = DadosTempo[0];
times[6] = DadosTempo[6];
digitos[0] = times[4]/10; //Armazena a Dezena das Horas
digitos[1] = times[4]%10; //Armazena a Unidade das Horas
digitos[2] = times[5]/10; //Armazena a Dezena dos Minutos
digitos[3] = times[5]%10; //Armazena a Unidade dos Minutos
do
{
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(2,0);
lcd.print("Adjust hour:");
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(5,1);
lcd.print(tempo);
PosCursor = 5;
do
{
number = ReadKeyPad();
delay(100);
if( (number >= 0 && number <= 9) && (controle == 0) && (cont < 4) )
{
digitos[cont] = number;
cont++;
controle = 1;
lcd.setCursor(PosCursor,1);
lcd.print(number);
PosCursor++;
if(cont == 2 || cont == 4)
{
PosCursor = PosCursor + 1;
}
}
if(number == 16 && controle == 1)
{
controle = 0;
}
if(number == 12)
{
for(cont = 0; cont < 4; cont++)
{
digitos[cont] = 0;
}
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(5,1);
lcd.print("00:00h");
PosCursor = 5;
cont = 0;
for(int i = 4; i < 6; i++)
{
times[i] = 0;
}
}
}while(number != 13);
times[4] = (digitos[0]*10) + digitos[1];
times[5] = (digitos[2]*10) + digitos[3];
if((times[4] < 0 || times[4] > 23) || (times[5] < 0 || times[5] > 59))
{
lcd.clear();
lcd.setCursor(4,0);
lcd.print("Invalid");
lcd.setCursor(6,1);
lcd.print("Hour");
delay(2000);
Validate = 1;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(1,0);
lcd.print("Adjust Hours:");
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(5,1);
lcd.print("00:00h");
sprintf(tempo, "%02d:%02dh", 0, 0);
PosCursor = 5;
cont = 0;
for(int i = 0; i < 4; i++)
{
times[i] = 0;
}
}
}while(Validate == 1);
do
{
number = ReadKeyPad();
delay(200);
}while(number != 16);
/*--------------------------------Date Configuration--------------------------------*/
PosCursor = 4;
do
{
//Transformacao dos digitos da data para dezenas e unidades
digitos[0] = times[2]/10; //Armazena a Dezena da Data
digitos[1] = times[2]%10; //Armazena a Unidade da Data
digitos[2] = times[1]/10; //Armazena a Dezena do Mes
digitos[3] = times[1]%10; //Armazena a Unidade do Mes
digitos[4] = times[0]/10; //Armazena a Dezena do Ano
digitos[5] = times[0]%10; //Armazena a Unidade do Ano
sprintf(data, "%02d/%02d/%02d", times[2], times[1], times[0]);
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(2,0);
lcd.print("Adjust Date:");
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(4,1);
lcd.print(data);
PosCursor = 4;
cont = 0;
do
{
number = ReadKeyPad();
delay(100);
if( (number >= 0 && number <= 9) && (controle == 0) && (cont < 6) )
{
digitos[cont] = number;
cont++;
controle = 1;
lcd.setCursor(PosCursor,1);
lcd.print(number);
PosCursor++;
if(cont == 2 || cont == 4)
{
PosCursor = PosCursor + 1;
}
}
if(number == 16 && controle == 1)
{
controle = 0;
}
if(number == 12)
{
for(cont = 0; cont < 6; cont++)
{
digitos[cont] = 0;
}
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(4,1);
lcd.print("00/00/00");
PosCursor = 4;
cont = 0;
}
}while(number != 13);
times[2] = (digitos[0]*10) + digitos[1]; //Transformando os numeros lidos para data do mes em dois dígitos
times[1] = (digitos[2]*10) + digitos[3]; //Transformando os numeros lidos para mes em dois dígitos
times[0] = (digitos[4]*10) + digitos[5]; //Transformando os numeros lidos para ano em dois dígitos
if((times[2] <= 0 || times[2] > 31) || (times[1] <= 0 || times[1] > 12) || times[0] <= 0)
{
lcd.clear();
lcd.setCursor(4,0);
lcd.print("Invalid");
lcd.setCursor(6,1);
lcd.print("Date");
delay(2000);
Validate = 1;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(2,0);
lcd.print("Adjuste Date:");
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(3,1);
lcd.print("00/00/00");
PosCursor = 5;
cont = 0;
for(byte i = 0; i < 3; i++)
{
times[i] = 0;
}
}
}while(Validate == 1);
do
{
number = ReadKeyPad();
delay(200);
}while(number != 16);
lcd.clear();
DS1307.setDate(times[0],times[1],times[2],times[3],times[4],times[5],00);//year,month,date of month, day of week,hour,minutes,second
}
Hereafter, the function of DS1307 acquisition of the data and store in the DadosTempo and after, split the values and print in the strings "tempo" and "data". These two strings are used to print its information in the LCD, posteriorly.
DS1307.getDate(DadosTempo);
sprintf(tempo, "%02d:%02dh", DadosTempo[4], DadosTempo[5]);
sprintf(data, "%02d/%02d/%02d", DadosTempo[2], DadosTempo[1], DadosTempo[0]);
The data of the vector "DadosTempo" are separated and stored in the vector times. The vector "times" will be used to receive the copy and to manipulate the data of the "DadosTempo" vector.
Right after, the times[4] and times[5] will be separated into digits of tens and units, to be manipulated in the time setting.
times[4] = DadosTempo[4];
times[5] = DadosTempo[5];
times[3] = DadosTempo[3];
times[2] = DadosTempo[2];
times[1] = DadosTempo[1];
times[0] = DadosTempo[0];
times[6] = DadosTempo[6];
digitos[0] = times[4]/10; //Store ten of hours
digitos[1] = times[4]%10; //Store unit of hours
digitos[2] = times[5]/10; //Store ten of minutes
digitos[3] = times[5]%10; //Store unit of minutes
After this, the system presents the message "Adjust Hour:" and show the content of the "tempo" string on the second line, according to the code presented below.
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(2,0);
lcd.print("Adjust hour:");
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(5,1);
lcd.print(tempo);
PosCursor = 5;
In Figure 4 is shown the message presented in the LCD Display.
Once time that the message is printed in the LCD, the system starts the process of reading to verify what was the pressed key by the user. This process is represented by the code below.
do
{
number = ReadKeyPad();
delay(100);
if( (number >= 0 && number <= 9) && (controle == 0) && (cont < 4) )
{
digitos[cont] = number;
cont++;
controle = 1;
lcd.setCursor(PosCursor,1);
lcd.print(number);
PosCursor++;
if(cont == 2 || cont == 4)
{
PosCursor = PosCursor + 1;
}
}
if(number == 16 && controle == 1)
{
controle = 0;
}
if(number == 12)
{
for(cont = 0; cont < 4; cont++)
{
digitos[cont] = 0;
}
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(5,1);
lcd.print("00:00h");
PosCursor = 5;
cont = 0;
for(int i = 4; i < 6; i++)
{
times[i] = 0;
}
}
}while(number != 13);
Firstly, the system read the keypad and store the value in the variable number and hereafter, verify the condition shown below.
if( (number >= 0 && number <= 9) && (controle == 0) && (cont < 4) )
According to condition, it verifies three important points:
- Verify if a number is pressed key is between 0 and 9;
- Verify if variable "controle" is equal at 0. This variable is used to allow that the condition is true only one time and read the number only one time.
- Verify if variable "cont" is less than 4. This variable is used to allow the user can enter with only 4 digits: two digits for the hour and two digits for minutes.
In this way, when the condition is true, the digit is stored in digit vector and printed in the LCD. After this, the variable of "PosCursor" is incremented to point for units place.
Case the cont variable is equal at 2 or cont equal at 4, the cursor position is incremented again, because of the signal of ":". In this way, the cursor will point for the decimal place of minutes.
Now, case the condition above doesn't be true, the following condition will be verified. Case anyone key is pressed by the user, the function "LerTeclado()" returns the number 16 to represents that none key was pressed.
if(number == 16 && controle == 1)
{
controle = 0;
}
So, if this condition is true, the system will attribute zero at variable "controle". This variable is used to control access in the condition to receive the numbers between 0 and 9 pressed by the user.
Lastly, we have the last condition to be checked. Case the "C" key is pressed, the returned value is 13.
So, through this key, the system will clear the values of the hour to allow the user to enter with new values again. This can see in Figure 5.
This is useful when the user inserts a wrong value and need to enter with new values, as is shown in Figure 6.
Now, see the condition of the "do while" loop. The system running in the do-while until the user presses the "D" key (Done), which is represented by the value 13.
This key is used to inform at the system, that values were inserted by the user.
}while(number != 13);
Hereafter, the digits entered by the user will be mounted in an hour and tens, as is shown in the following code.
times[4] = (digitos[0]*10) + digitos[1];
times[5] = (digitos[2]*10) + digitos[3];
if((times[4] < 0 || times[4] > 23) || (times[5] < 0 || times[5] > 59))
{
lcd.clear();
lcd.setCursor(4,0);
lcd.print("Invalid");
lcd.setCursor(6,1);
lcd.print("Hour");
delay(2000);
Validate = 1;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(1,0);
lcd.print("Adjust Hours:");
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(5,1);
lcd.print("00:00h");
sprintf(tempo, "%02d:%02dh", 0, 0);
PosCursor = 5;
cont = 0;
for(byte i = 0; i < 4; i++)
{
times[i] = 0;
}
}
}while(Validate == 1);
Finally, we have the last condition. This last condition is used to validate the hour and minute entered by the user.
Case the values entered by the user are wrong, the boolean variable Validate will receive 1. The value will signal for the system, that some of the values are wrong and present the "Invalid Hour" message as is shown in Figure 7.
Therefore, the system will need to receive new correct values. But, if the values are correct the system doesn't enter in this condition and pass for the second part of the function: Receive the data of Date.
Process of Setting the DateIn the same form, as we configure the clock data, we'll set the date. The process is similar. It has the process to receive the numbers, the erase function in case of wrong digited numbers and validation process of the numbers entered by the user.
Lastly, after the configure all parameters, there is a function for sending the parameters for the Real-Time Clock CHIP, as is shown below.
DS1307.setDate(times[0],times[1],times[2],times[3],times[4],times[5],00);//year,month,date of month, day of week,hour,minutes,second
Through this function, the RTC is configured with parameters of the hour and date. Hereafter, the system return for void loop function.
Right after your return for void loop function, the LCD screen will be erased and the function ActiveHour will be called.
void ActivationHour(void)
{
int times[6];
int DadosTempo[7];
bool controle = 0;
bool EstadoSobe = 0, EstadoDesce = 0;
byte cont = 0;
byte number = 0;
int digitos[6];
byte PosCursor = 0;
bool Validate = 0;
lcd.clear();
for(byte i = 0; i < 6; i++)
{
digitos[i] = 0;
}
do
{
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(0,0);
lcd.print("Activation Hour:");
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(5,1);
lcd.print("00:00h");
PosCursor = 5;
do
{
number = ReadKeyPad();
delay(100);
if( (number >= 0 && number <= 9) && (controle == 0) && (cont < 4) )
{
digitos[cont] = number;
cont++;
controle = 1;
lcd.setCursor(PosCursor,1);
lcd.print(number);
PosCursor++;
if(cont == 2 || cont == 4)
{
PosCursor = PosCursor + 1;
}
}
if(number == 16 && controle == 1)
{
controle = 0;
}
if(number == 12)
{
for(cont = 0; cont < 4; cont++)
{
digitos[cont] = 0;
}
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(5,1);
lcd.print("00:00h");
PosCursor = 5;
cont = 0;
for(int i = 4; i < 6; i++)
{
times[i] = 0;
}
}
}while(number != 13);
times[4] = (digitos[0]*10) + digitos[1];
times[5] = (digitos[2]*10) + digitos[3];
if((times[4] < 0 || times[4] > 23) || (times[5] < 0 || times[5] > 59))
{
lcd.clear();
lcd.setCursor(3,0);
lcd.print("Invalid");
lcd.setCursor(4,1);
lcd.print("Hour");
delay(2000);
Validate = 1;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(1,0);
lcd.print("Activation Hour:");
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(5,1);
lcd.print("00:00h");
sprintf(tempo, "%02d:%02dh", 0, 0);
PosCursor = 5;
cont = 0;
for(cont = 0; cont < 4; cont++)
{
digitos[cont] = 0;
}
}
}while(Validate == 1);
EEPROM.write(1, times[4]);
EEPROM.write(2, times[5]);
do
{
number = ReadKeyPad();
delay(200);
}while(number != 16);
}
The function HourActivate is similar at the function to set the clock for RTC. The single difference is that the values of the hour and minute are stored in the EEPROM memory, as is shown below.
EEPROM.write(1, times[4]);
EEPROM.write(2, times[5]);
These values are stored in the EEPROM memory to be read at the beginning of the initialization system. Therefore, through these values, will be possible to compare with the clock and actuate the devices in the programmed hour.
After the full execution of the function HourActivation, the system return for void loop function and show the date and hours as is shown at the beginning of the article.
Now, will explain the new features in the next article - Part III.
Next Features to be ImplementedThrough the implemented functions until now, in the third part, we'll implement new features to better the quality of our work. Hereafter will present the new features:
- Implement DeactivationHour() function;
- Implement a logical system to compare the clock to activate and deactivate the device connected in the relay;
- Implement signalization to indicate the key pressed.
Thanks to the PCBWay for support the our YouTube Channel and produce and assembly PCBs with better quality.
The Silícios Lab thanks UTSOURCE to offer the electronic components.
Comments