Ir para o conteúdo
klaudio_f

[Resolvido] Arduino como "Interruptor Horário" com Tiny_RTC_I2C"

Mensagens Recomendadas

klaudio_f

Olá

Estou a iniciar uns projectos com o Arduino e um deles é um interruptor horário mas preciso de ajuda.

Devo salientar que sou mesmo iniciante nesta área, programação estou mesmo a começar na parte electrónica desenrasco-me "facilmente".

Já tenho um Tiny RTC já a funcionar (ainda deu alguma luta), com o seguinte código (atenção que o código não é da minha autoria, apenas fiz algumas alterações):

#include <Wire.h> // I2C-biblioteca
#include "RTClib.h" // RTC-biblioteca
RTC_DS1307 RTC;	 // RTC Modulo

void setup(void) { // configuraçoes gerais
Wire.begin();// Inicializar I2C
RTC.begin();// Inicializar RTC
Serial.begin(9600); // Comece saída Serial
Serial.println("Data e hora Com RTC_DS1307");// Apresentação
// Verifiqua se RTC esta funcionar
if (! RTC.isrunning()) {
RTC.adjust(DateTime(__DATE__ , __TIME__));// Definir data e hora atual, se o relógio não está funcionando.
Serial.println("Relogio em tempo real iniciado e configurado com a hora do PC.");
}
else Serial.println("Relogio em tempo real ja esta em execucao.");
}
void loop(){ // execução continua
DateTime now=RTC.now(); // Obter o horário do modulo
show_time_and_date(now); // Mostra a data e hora
delay(1000); // Aguarde 30 segundos até que a próxima edição
}
// Para Determinar o dia da semana
String get_day_of_week(uint8_t dow){
String dows=" ";
switch(dow){
case 0:dows="Domingo";
break;
case 1:dows="Segunda";
break;
case 2:dows=" Terca ";
break;
case 3:dows="Quarta ";
break;
case 4:dows="Quinta ";
break;
case 5:dows=" Sexta ";
break;
case 6:dows="Sabado ";
break;
}
return dows;
}
// Mostra a data e hora
void show_time_and_date(DateTime datetime){
// Dia de semana , Dia.Mês.Ano
Serial.print(get_day_of_week(datetime.dayOfWeek()));
Serial.print(", ");
if(datetime.day()<10)Serial.print(0);// se dia inferior a 10 coloca "0" antes do dia
Serial.print(datetime.day(),DEC);
Serial.print(".");
if(datetime.month()<10)Serial.print(0);
Serial.print(datetime.month(),DEC);
Serial.print(".");
Serial.print(datetime.year(),DEC);
Serial.print(" / ");
// Horas : minuto: segundo
if(datetime.hour()<10)Serial.print(0);
Serial.print(datetime.hour(),DEC);
Serial.print(":");
if(datetime.minute()<10)Serial.print(0);
Serial.print(datetime.minute(),DEC);
Serial.print(":");
if(datetime.second()<10)Serial.print(0);
Serial.println(datetime.second(),DEC);
}

Como posso dizer ao arduino para no dia "D" na hora "H" no minutos "M" para colocar a saída X no estado 1 e vice versa?

solução que tenho em mente para Domino, as 12:10

adicionei esta linha no setup:

pinMode(13, OUTPUT);

adicionei no final do código:

if (datetime.dayOfWeek() = 1 && datetime.hour() >=12 && datetime.minute() >=10) digitalWrite(13, HIGH);
else (digitalWrite(13, LOW));

mas obtenho o seguinte erro:

Tiny_RTC_I2C_-_para_ih.ino: In function 'void show_time_and_date(DateTime)':

Tiny_RTC_I2C_-_para_ih.ino:81: error: lvalue required as left operand of assignment

Editado por apocsantos
geshi

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Nuno Santos

Boas klaudio,

O teu if parece bem, esse erro é porque o igual tem de ser double igual == so um igual nao e5 uma comparacao, mas sim uma atribuição

É relativamente simples, basta colocares um if com 3 condicoes ou 3 if encadeados.

Por exemplo

if (D == 10) {

if (H == 20) {

if (M == 0) {

Serial.println (" condicao atingida ")

}

}

}

Editado por Nuno Santos

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
klaudio_f

Boas klaudio,

É relativamente simples, basta colocares um if com 3 condicoes ou 3 if encadeados.

Por exemplo

if (H == 10) {

if (M == 0) {

if (S == 0) {

Serial.println (" condicao atingida ")

}

}

}

peço desculpa mas esqueci-me de colocar o código com que estava a tentar fazer isto.

entretanto editei o primeiro post, se poderes dá uma vista de olhos.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Nuno Santos

A versão corrigida devera ser

if ((datetime.dayOfWeek() == 1) && (datetime.hour() == 12) && (datetime.minute() == 10)) digitalWrite(13, HIGH);

else (digitalWrite(13, LOW));

Editado por Nuno Santos

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
klaudio_f

Já não dá erro o código.

mas só é activada a saída quando naquele momento ou seja no dia 1 as 12:10, mas pretendo que ela fique ligada até 13:00.

if ((datetime.dayOfWeek() == 1) && (datetime.hour() >= 12) && (datetime.minute() >= 10) && (datetime.hour() <= 13) && (datetime.minute() <= 00)) digitalWrite(13, HIGH);
else (digitalWrite(13, LOW));

assim de repente isto não funciona, as condições vão entrar em conflito

Editado por klaudio_f

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
bubulindo
if ((datetime.dayOfWeek() == 1) && (datetime.hour() == 12) && (datetime.minute() == 10)) digitalWrite(13, HIGH);
if ((datetime.dayOfWeek() == 1) && (datetime.hour() == 13) && (datetime.minute() == 0)) (digitalWrite(13, LOW));


include <ai se te avio>

Mãe () {

}

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Nuno Santos

O Post do bubulindo deve resolver o teu problema.

Queria-te deixar aqui duas notas :

- Esses 2 IFs vao correr inumeras vezes durante o periodo de 1 min.

- O outro else que tinhas para colocar o pin como low, vai correr durante o periodo todo.

Isso é capaz de ocupar o microcontrolador o tempo todo e podera aquecer um pouco, e vai acabar por gastar mais energia por estar a fazer sempre uma tarefa.

Deverias colocar uns estados a dizer que o pin esta high para nao colocares high nas subsequentes vezes que entrar no loop. e o mesmo para o pin low.

No entanto isso é so uma optimização.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
bubulindo

Queria-te deixar aqui duas notas :

- Esses 2 IFs vao correr inumeras vezes durante o periodo de 1 min.

- O outro else que tinhas para colocar o pin como low, vai correr durante o periodo todo.

Isso é capaz de ocupar o microcontrolador o tempo todo e podera aquecer um pouco, e vai acabar por gastar mais energia por estar a fazer sempre uma tarefa.

Deverias colocar uns estados a dizer que o pin esta high para nao colocares high nas subsequentes vezes que entrar no loop. e o mesmo para o pin low.

No entanto isso é so uma optimização.

Desculpa dizer isto, mas o que disseste nao faz sentido.

A funcao loop esta sempre a correr. Se nao for este if, sera o if que determina se o pino esta low ou high. O processador vai estar a consumir a mesma energia, a correr com a mesma tensao e com a mesma frequencia.

Mais, esse if nao vai correr inumeras vezes num minuto. Vai correr aproximadamente 60 vezes devido ao delay de 1000 milisegundos.

Mais ainda, esse delay de 1000 milisegundos vai comer tanta energia como se o processador estivesse a correr o mesmo tempo a avaliar o mesmo if.

O Arduino e um microprocessador... e aquele programa nao corre sobre um sistema operativo. Como tal, o conceito de "ocupar o microcontrolador o tempo todo" nao existe... o que estara a ocupar o microcontrolador vai mesmo ser o delay (implementado com busy-wait).

Que esse estado ou a leitura do porto, minimizaria o tempo gasto inutilmente a avaliar o tempo e a re-escrever o estado do pino, nao ha como negar, mas a tua explicacao nao faz sentido algum nesta plataforma.

Nota tambem que se vais falar em optimizacoes, provavelmente devias comecar pela remocao das funcoes delay() e digitalWrite... ;)


include <ai se te avio>

Mãe () {

}

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Nuno Santos

Desculpa dizer isto, mas o que disseste nao faz sentido.

A funcao loop esta sempre a correr. Se nao for este if, sera o if que determina se o pino esta low ou high. O processador vai estar a consumir a mesma energia, a correr com a mesma tensao e com a mesma frequencia.

Mais, esse if nao vai correr inumeras vezes num minuto. Vai correr aproximadamente 60 vezes devido ao delay de 1000 milisegundos.

Mais ainda, esse delay de 1000 milisegundos vai comer tanta energia como se o processador estivesse a correr o mesmo tempo a avaliar o mesmo if.

O Arduino e um microprocessador... e aquele programa nao corre sobre um sistema operativo. Como tal, o conceito de "ocupar o microcontrolador o tempo todo" nao existe... o que estara a ocupar o microcontrolador vai mesmo ser o delay (implementado com busy-wait).

Que esse estado ou a leitura do porto, minimizaria o tempo gasto inutilmente a avaliar o tempo e a re-escrever o estado do pino, nao ha como negar, mas a tua explicacao nao faz sentido algum nesta plataforma.

Nota tambem que se vais falar em optimizacoes, provavelmente devias comecar pela remocao das funcoes delay() e digitalWrite... ;)

Boas,

Não me estava a referir aos IF's, obviamente que os IFs vao ser sempre analisados.

Estava-me a referir aos 60 digitalWrite(HIGH) e digitalWrite(LOW) dos IFs, mais os "infinitos" que vao ficar a correr para o else.

A função digitalwrite consome mais "cpu" time so pelo simples facto de ser chamada vezes sem conta.

O que estava a sugerir é colocar umas boolean para validar se ja estava HIGH ou LOW, assim cortando nos "n" digitalWrite...

Editado por Nuno Santos

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
bubulindo

Nao... a digitalWrite consome mais CPU time por causa de toda a "palha" que tem dentro.

Algo que pode ser feito com uma macro leva umas quantas linhas de codigo "desnecessarias" para quem sabe o que esta a fazer.

De resto, e inutil estar a optimizar codigo sem que possas medir a optimizacao ou onde a optimizacao nao traz beneficio algum. O codigo dele nao liga puto aos segundos... logo e aceitavel uma granularidade de segundos. optimizar uns quantos microsegundos nao faz diferenca... no entanto, o unsigned char para guardar o estado duma porta pode fazer diferenca na memoria do microcontrolador.

Obviamente que os ifs sao analisados, mas... fazer uma comparacao (pino:high?low) e bastante mais rapida que fazer 4 comparacoes numericas...

Mas pronto... o problema esta resolvido... qual sera o proximo problema? Alterar a hora de inicio/fim? Adicionar mais saidas controladas com horario?


include <ai se te avio>

Mãe () {

}

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
klaudio_f

Boa noite

Já testei o código do bubulindo e funciona perfeitamente. desde já obrigado.

mas depois de ler o que escreveram sobre a optimização, lembrei-me de reduzir as condições, tipo se for dia X executa o seguinte, então alterei o codigo e ficou assim:

if ((datetime.dayOfWeek() == 2)) {
 if ((datetime.hour() == 20) && (datetime.minute() == 35)) {
digitalWrite(13, HIGH);
Serial.print("alarme on");
}
}
if ((datetime.dayOfWeek() == 2)) {
 if ((datetime.hour() == 20) && (datetime.minute() == 36)) {
 digitalWrite(13, LOW);
 Serial.print("alarme oFF");
}
}

ainda não testei, mas a compilação não dá erro.

acham que isto optimiza alguma coisa?

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Nuno Santos

Boas,

Fica igual ao que o bubulindo deu como solução.

Se testares, vais ver que tens mais ou menos 60 linhas a dizer, alarme on e outras tantas a dizer alarm off.

com o codigo abaixo, so ficas com 1 on e 1 off

if ((datetime.dayOfWeek() == 2) && (datetime.hour() == 20) && (datetime.minute() == 35)) {
if (stat == false) {
 digitalWrite(13, HIGH);
 Serial.print("alarme on");
 stat = true;
}
}
if ((datetime.dayOfWeek() == 2) && (datetime.hour() == 20) && (datetime.minute() == 36)) {
if (stat == true) {
 digitalWrite(13, LOW);
 Serial.print("alarme oFF");
 stat = false;
}
}

se adicionares uma variavel de status, ja só entra uma vez no if do digitalWrite por exemplo.

Se quiseres usar este exemplo, tens de declarar uma variavel global inicializada a false;

(no top do codigo colocas

boolean stat = false;

)

Da para fazer melhor ainda.

Editado por Nuno Santos

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
klaudio_f

agora entendi.

vou sugerir uma coisa que pode ser um completo disparate, mas como estou aqui para aprender aqui vai:

Se a verificação do da variável stat fosse efectuada antes da verificação das condições do dia, hora e minuto,

if (stat == false) {
if ((datetime.dayOfWeek() == 2) && (datetime.hour() == 20) && (datetime.minute() == 35)) {
	 digitalWrite(13, HIGH);
	 Serial.print("alarme on");
	 stat = true;
}
}
if (stat == true) {
if ((datetime.dayOfWeek() == 2) && (datetime.hour() == 20) && (datetime.minute() == 36)) {
	 digitalWrite(13, LOW);
	 Serial.print("alarme oFF");
	 stat = false;
}
}

Sempre ficam ali umas linhas de código que só são executadas quando são mesmo necessárias.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Nuno Santos

O stat é falso a maior parte do tempo. Mas tambem funciona.

Da outra forma tens dois ifs, e desta tens 3.

Os dois ifs do stat + o if do false.

Da outra forma so tens dois ifs da comparacao da data, hora, min.

Na outra tens 6 comparacoes nesta tens 5. ;) (para a maior parte do tempo)

Editado por Nuno Santos

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
klaudio_f

Testado e a funcionar :thumbsup:

#include <Wire.h> // I2C-biblioteca
#include "RTClib.h" // RTC-biblioteca
RTC_DS1307 RTC;	 // RTC Modulo
void setup(void) { // configuraçoes gerais
Wire.begin();// Inicializar I2C
RTC.begin();// Inicializar RTC
Serial.begin(9600); // Comece saída Serial
Serial.println("Data e hora Com RTC_DS1307");// Apresentação
// Verifiqua se RTC esta funcionar
if (! RTC.isrunning()) {
RTC.adjust(DateTime(__DATE__ , __TIME__));// Definir data e hora atual, se o relógio não está funcionando.
Serial.println("Relogio em tempo real iniciado e configurado com a hora do PC.");
}
else Serial.println("Relogio em tempo real ja esta em execucao.");
pinMode(13, OUTPUT);
}
void loop(){ // execução continua
DateTime now=RTC.now(); // Obter o horário do modulo RTC
show_time_and_date(now); // Mostra a data e hora
delay(3000); // Aguarde 3 segundos até que a próxima edição
}
// Para Determinar o dia da semana
String get_day_of_week(uint8_t dow){
String dows=" ";
switch(dow){
case 0:
dows="Domingo";
break;
case 1:
dows="Segunda";
break;
case 2:
dows=" Terca ";
break;
case 3:
dows="Quarta ";
break;
case 4:
dows="Quinta ";
break;
case 5:
dows=" Sexta ";
break;
case 6:
dows="Sabado ";
break;
}
return dows;
}
// Mostra a data e hora
void show_time_and_date(DateTime datetime){
// Dia de semana , Dia.Mês.Ano
Serial.print(get_day_of_week(datetime.dayOfWeek()));
Serial.print(", ");
if(datetime.day()<10)Serial.print(0);// se dia inferior a 10 coloca "0" antes do dia
Serial.print(datetime.day(),DEC);
Serial.print(".");
if(datetime.month()<10)Serial.print(0);
Serial.print(datetime.month(),DEC);
Serial.print(".");
Serial.print(datetime.year(),DEC);
Serial.print(" / ");
// Horas : minuto: segundo
if(datetime.hour()<10)Serial.print(0);
Serial.print(datetime.hour(),DEC);
Serial.print(":");
if(datetime.minute()<10)Serial.print(0);
Serial.print(datetime.minute(),DEC);
Serial.print(":");
if(datetime.second()<10)Serial.print(0);
Serial.println(datetime.second(),DEC);


boolean stat = false;
if ((datetime.dayOfWeek() == 2) && (datetime.hour() == 20) && (datetime.minute() == 35)) {
if (stat == false) {
	 digitalWrite(13, HIGH);
	 Serial.print("alarme on");
	 stat = true;
}
}
if ((datetime.dayOfWeek() == 2) && (datetime.hour() == 20) && (datetime.minute() == 36)) {
if (stat == true) {
	 digitalWrite(13, LOW);
	 Serial.print("alarme oFF");
	 stat = false;
}
}
}

Obrigado pela ajuda Nuno Santos e Bubulindo :thumbsup:

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
bubulindo

Isso pode ficar melhor.

Escusas de ter a funcao get_day_of_week. Se definires um array de strings (ou matriz) com os dias da semana no indice correcto, escusas de ter o switch e a String.

Algo como:

char days [][] = {'D', 'o', 'm', 'i', 'n','g','o' /*define o resto*/};

Serial.print(days[datetime.DayOfWeek()]);

Editado por bubulindo

include <ai se te avio>

Mãe () {

}

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
klaudio_f

Bubulindo, como mencionei no inicio do tópico estou em fase de aprendizagem em relação a programação "C", logo fiquei um pouco a nora com o teu post anterior.

será que podes explicar com mais detalhe.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.