可用于激活设备的可编程定时器 part2
文件列表(压缩包大小 337.35K)
免费
概述
Arduino UNO
Arduino 5V继电器模块
DS1307 RTC模块
LCD1602显示屏
杜邦线
面包板
10kohm旋转电位器
LED5mm
Arduino IDE
在本文的第一部分,我们介绍如何创建实现该项目的所有过程。你可以访问链接的第一部分
现在,通过第二部分,我们将介绍创建函数的所有过程,以对时钟和日期进行编程,并对设备激活的小时进行编程。
因此,通过这些功能,我们将学习实时时钟(RTC)DS1307的几种应用和使用原理。
根据第一部分的解释,该项目的目的是在用户编程的时间内激活和停用设备。
因此,基于该问题,需要使用CHIP实时时钟。CHIP用于计数7个变量:秒,分钟,小时,星期几,月份的日期,月份和年份。因此,为此,需要实现一个小时系统供用户调整小时,日期,激活和停用时间。
为此,将根据第I部分中的图表实现一些功能来解决此问题。因此,我们将开发这些功能来配置实时时钟的实际时间和日期以及激活设备的小时数连接在继电器上。
此后将展示下图中的原理图电路和为该项目的第二部分开发的代码。
第一部分项目的电子示意图。
首先,我们将通过变量创建和设备初始化来介绍配置过程。
因此,在输入void setup()之前,包括所有库,变量和函数原型。因此,请参见已实现的三个功能:ReadKeypad,AdjustHour和ActivationHour。
此后,下面指定每个功能:
#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);
}
在原型声明之后,立即初始化了设备RTC DS1307和LCD 16x2以及Arduino的所有引脚。
现在,我们将通过函数void loop()学习如何对该系统进行逻辑编程。
首先,当系统处于循环功能的开始时,执行初始化过程的验证。此验证由第一个条件表示,如下所示。
if(EEPROM.read(MEMORY) != 73)
这样,系统会验证这是用户首次进入系统。如果EEPROM(位置100)的读取编号不同于73,则需要配置系统的时间和日期。
因此,配置时间和日期后,系统会将73值写入EEPROM。
EEPROM.write(MEMORIA, 73);
该数字用于向用户表示已经配置了时间和日期。
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;
}
}
此后,获取日期和时间的所有7个参数并将其存储在DataTime向量中。
采集后,秒的值存储在变量SegAtual中。此变量用于存储秒的值。这些命令如下所示。
DS1307.getDate(DataTime);
SegAtual = DataTime[6];
现在,将执行条件来知道用户是否按下了按键“ A”来调整时钟时间和设备激活的小时数。
按键“ A”由10表示,这是按下“ A”时函数的返回值,如下所示。
if(LerTeclado() == 10)
{
AjustarHora();
lcd.clear();
ActivationHour();
lcd.clear();
}
最后,小时和数据将显示在显示屏LCD上。为了表示小时和日期,在以下条件下进行了实施。
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;
}
因此,在这种情况下,日期和小时将每秒显示在LCD上,如下图所示。
LCD中显示的小时和日期。
现在,将说明调整时间和调整小时的功能,以激活继电器上连接的设备。
首先,这两个功能非常相似,但你将看到每个功能的工作原理,我们将分析AdjustTime()函数。
现在,通过我们的函数,我们将看到该函数的某些部分在整个函数中自己重复,并且你将看到该函数分为两部分:
首先,我们创建函数中使用的所有变量。
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
}
此后,DS1307的功能是获取数据并将其存储在DadosTempo中,然后将值分割并打印在字符串“ tempo”和“ data”中。这两个字符串用于在LCD后面打印其信息。
DS1307.getDate(DadosTempo);
sprintf(tempo, "%02d:%02dh", DadosTempo[4], DadosTempo[5]);
sprintf(data, "%02d/%02d/%02d", DadosTempo[2], DadosTempo[1], DadosTempo[0]);
向量“ DadosTempo”的数据被分离并存储在向量时间中。向量“时间”将用于接收副本并操纵“ DadosTempo”向量的数据。
之后,times [4]和times [5]将被分隔为数十位和几位的数字,以便在时间设置中进行操作。
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
此后,系统将显示消息“ Adjust Hour:”,并根据下面显示的代码在第二行显示“ tempo”字符串的内容。
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;
下图中显示了LCD显示屏中显示的消息。
调整小时信息。
一旦在LCD上打印了该消息,系统就会开始读取过程,以验证用户按下了什么键。此过程由以下代码表示。
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);
首先,系统读取键盘并将值存储在变量号中,此后,请验证以下所示的条件。
if( (number >= 0 && number <= 9) && (controle == 0) && (cont < 4) )
根据情况,它验证了三个要点:
这样,当条件为真时,将数字存储在数字向量中并打印在LCD上。此后,“ PosCursor”变量将递增以指向单位放置位置。
如果cont变量等于2或cont等于4,则由于信号“:”,光标位置再次增加。这样,光标将指向分钟的小数位。
现在,如果上述条件不成立,将验证以下条件。如果用户按下了任何人的按键,函数“ LerTeclado()”将返回数字16,表示没有按键被按下。
if(number == 16 && controle == 1)
{
controle = 0;
}
因此,如果此条件为真,则系统将在变量“ controle”中将属性归零。在接收用户按下的0到9之间的数字的情况下,此变量用于控制访问。
最后,我们要检查最后一个条件。如果按下“ C”键,则返回值为13。
因此,通过此键,系统将清除小时值,以允许用户再次输入新值。如下图所示。
LCD的清除屏幕。
当用户输入错误的值并需要输入新值时,这非常有用,如下图所示。
插入错误的小时数。
现在,查看“ do while”循环的条件。系统在do-while中运行,直到用户按下“ D”键(“完成”)为止,该键由值13表示。
此键用于通知系统用户已插入值。
}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(byte i = 0; i < 4; i++)
{
times[i] = 0;
}
}
}while(Validate == 1);
最后,我们有最后一个条件。最后一个条件用于验证用户输入的小时和分钟。
如果用户输入的值错误,则布尔变量Validate将收到1。该值将向系统发出信号,表明某些值是错误的,并显示“ Invalid Hour”消息,如下图所示。
无效小时消息。
因此,系统将需要接收新的正确值。但是,如果值正确,则系统不会在这种情况下进入并通过功能的第二部分:接收日期数据。
以相同的形式,在配置时钟数据时,我们将设置日期。这个过程是相似的。它具有接收数字的过程,数字错误的情况下的擦除功能以及用户输入的数字的验证过程。
最后,在配置完所有参数之后,有一个发送实时时钟芯片的参数的功能,如下所示。
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
通过此功能,可以为RTC配置小时和日期参数。此后,系统返回空循环功能。
返回空循环功能后,将立即清除LCD屏幕并调用ActiveHour功能。
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);
}
功能HourActivate与设置RTC时钟的功能相似。唯一的区别是小时和分钟的值存储在EEPROM存储器中,如下所示。
EEPROM.write(1, times[4]);
EEPROM.write(2, times[5]);
这些值存储在EEPROM存储器中,以便在初始化系统开始时读取。因此,通过这些值,可以与时钟进行比较并在编程的小时内启动设备。
在完全执行功能HourActivation之后,系统将返回空循环功能并显示日期和小时,如本文开头所示。
现在,将在下一篇文章-第三部分中解释新功能。
通过到目前为止已实现的功能,在第三部分中,我们将实现新功能,以提高工作质量。此后将介绍新功能:
所有需要的文件在下载区均可找到。
via:https://www.hackster.io/166068/programmable-timer-for-activation-of-devices-part-ii-802a95
如果遇到文件不能下载或其他产品问题,请添加管理员微信:ligongku001,并备注:产品反馈
评论(0)