Olá pessoal! Estou começando agora no Arduino e meu primeiro projeto é acender uma lâmpada (30 LEDs) num aquário pequeno.  A questão é que preciso que a lâmpada acenda em dias e horários pré-definidos. Para isso estou usando um RTC. Consegui fazê-la acender todo dia das 17h às 22h, mas quando tento alternar com outros dias/horários, tipo, acender sábados e domingos das 8h-22h não funciona. E preciso também que o push button acenda ou apague a lâmpada fora desses horários predefinidos. Não consigo fazer a lógica toda sem conflitos. Até tentei por um sensor PIR, mas também conflitou.

Bom, resumindo: Consigo ter o RTC funcionando perfeitamente e acendendo o LED todo dia das 17h-22h, mas não consigo inserir nem o push button, nem o PIR ou nem mesmo acender a lampada em outros horários e dias. Eis o meu código:

//inclusão de biblioteca e objetos do módulo relógio
#include <DS3231.h>
DS3231 rtc(SDA, SCL);
Time t;

//determina pino botão
#define pinBotao 6

//determina pinoPIR
//#define pinPIR 7

//determina pinoRelè
#define pinRele 8

//determina estado relè
#define estadoRele

//parâmetros de horário que serão atualizados
int horaAtual, minutoAtual;

void setup()
{

//inicia o módulo relógio
rtc.begin();

//inicia o monitor serial
Serial.begin(115200);

//determina o pino do relé como saída
pinMode(pinRele, OUTPUT);

//determina pino do PIR como entrada
//pinMode(pinPIR, INPUT);

//determina pino botão como entrada usando resistor do arduino
pinMode(pinBotao, INPUT_PULLUP);

//desliga o relé para começar.
digitalWrite(pinRele, HIGH);

//as linhas abaixo devem ser descomentadas para configurar o relógio interno.
//Descomente, carregue o código para o arduino, comente novamente e suba o código mais uma vez.
//rtc.setDate(29,7,2019); // determina a data (dia, mes, ano)
//rtc.setDOW(MONDAY); // determina o dia da semana
//rtc.setTime(13,11,0); // determina o horário (hora, minuto, segundo)

}

void loop()
{

//determina o horário atual
t = rtc.getTime();
horaAtual = t.hour;
minutoAtual = t.min;

//lê estado da porta do PIR e guarda na variável
//bool valorPIR = digitalRead(pinPIR);

//verifica se iluminação precisa estar acesa por movimento
/*if (valorPIR)
{
digitalWrite(pinRele, LOW);
}
else
{
digitalWrite(pinRele, HIGH);
}
*/
//verifica se iluminação precisa estar acesa por horário
if ((horaAtual >=17) && (horaAtual <=21)){
digitalWrite(pinRele, LOW);
}
else{
digitalWrite(pinRele, HIGH);
}

//verifica se iluminação precisa estar acesa por botão
if(digitalRead(pinBotao) == LOW){
delay(300);
digitalWrite(pinRele, !digitalRead(pinRele));
}

//Imprime o horário
Serial.print("Horário atual: ");
Serial.println(rtc.getTimeStr());
//Serial.print("Sensor PIR: ");
//Serial.println(valorPIR);

//atualiza monitor serial
delay (1000);
}

Exibições: 1746

Responder esta

Respostas a este tópico

olá novamente Rodrigo.

      Primeiro irei publicar a implementação do seu Sistema, e em seguida irei descrever a forma de implementação, assim elucidando a Máquina de Estados que controla o mesmo.

     E claro, irei gradativamente publicando como implementar elementos mais "sofisticados" no Sistema.

      Assim, você poderá ver o resultado antes mesmo da parte de "aprendizado".

      Abrçs,

      Elcids

Beleza Elcids!

Abraços!

olá Rodrigo.

      Fiz o Diagrama de Estados (extremamente simples, com apenas dois estados)  para a implementação do Sistema de Controle da Lâmpada do Aquário. Neste sistema, há o Botão para controle manual da Lâmpada,  há o RTC para controle automático e com horários programáveis,  e há também o Sensor PIR  para  "acendimento presencial".

      Neste momento, tenho duas questões que preciso que vc elucide.  Vou postar primeiro uma delas, que eu considero mais fundamental, e num outro post perguntarei sobre a outra questão.

      Então segue a primeira questão:

      No início (na função setup) do seu código "original",  há um fragmento de código para setar a Data/Hora no RTC. Ali, é usada a técnica convencional que se vê em muitos sites por aí afora, que consiste em setar os valores de Data/Hora no código e fazer o Arduino executar este código, assim atualizando a Data/Hora no RTC.  Depois disto, então é comentado aquele fragmento de código, uma vez que o RTC já está com a Data/Hora correta,  e segue-se com a execução do código normalmente.

      Eu gostaria de sugerir outras duas alternativas:

      1)  usar o mesmo método de setar a Data/Hora  conforme seu código original, porém isto terá efeito apenas se vc  ligar o Arduino (ou resetá-lo)  mantendo o Botão pressionado.  Caso vc ligue (ou resete) o Arduino  sem o botão pressionado, a Data/Hora definida no código não será setada, e o RTC continuará com os dados atuais do mesmo.

      2)  incluir no Sistema, uma ou duas formas de ajustar a Data/Hora do RTC, sem precisar regravar código no Arduino.  Uma forma por exemplo, poderia ser através de enviar comandos pelo Terminal do Arduino (ou qualquer programa de Terminal, como por exemplo o popular "Termite"), com os valores de Data/Hora atuais.  Outra forma seria por exemplo, ter um Display LCD e dois Botões (inclusive um já existe no Sistema), com os quais se pode ajustar a Data/Hora quando se desejar, sem precisar conectar o Arduino ao Computador.  Este último método com LCD/Botões,  tem uma vantagem extra:  pode-se usá-los para programar os horários que se deseja ligar/desligar a Lâmpada (e isto pode ser salvo na EEPROM do Arduino, para o caso da energia cair).

      Gostaria de ouvir sua opinião a respeito.  Porém, sugiro que inicialmente usemos o método descrito em 1),  para que o Sistema inicialmente continue simples e não dificulte o entendimento de como ele é implementado.  Isto seria importante, pois o segundo método além de exigir diversas rotinas adicionais, tornará a Máquina de Estados  mais complexa o que não é o objetivo neste momento, já que este tópico tem também o objetivo de aprendizado.

      O segundo método, mais versátil,  poderia ser implementado em uma segunda etapa, ou seja, em uma segunda versão "aprimorada" do Sistema.

      Aguardo sua visão sobre isto.

      Abrçs,

      Elcids

Olá Elcids! Olha, acho que seria interessante nesse primeiro momento manter o RTC como está e, se for o caso, implementar o ajuste pelo botão pressionado durante o boot. Nesse caso ele despreza o ajuste do RTC no código mesmo sem estar comentado, é isso?

Bom, eu gostaria muito de aprender a incrementar o projeto com outras rotinas. Já até comprei módulos como o LCD 1602, Bluetooth e WI-FI (esse ESP acho que não vai rolar), mas com a greve dos correios iniciada hoje, não devo receber nada tão cedo. :(
O LCD seria pra mostrar hora, data e temperatura da água. Além, como você disse, facilitar o ajuste dos temporizadores e do relógio. Não sei se serei capaz de aprender a fazer tudo isso! Mas vamos começar devagar. Kkkkk
Abraços!

ok Rodrigo,

      Então faremos assim,  usando o Botão já existente, para setar a Data/Hora definida estaticamente no código, logo que o Arduino é ligado ou resetado (claro, quando o Botão é mantido pressionado durante a inicialização).  E depois, quando a coisa "andar",  acrescentamos as devidas "sofisticações".

      Quanto à questão do aprendizado, que vc tem dúvidas, não se preocupe agora. Tente aprender o que estiver ao seu alcance. Lembre-se que um aprendizado leva a outro, e aqui na área técnica esta regra é 100% aplicável.

      Abrçs,

      Elcids

Tá ótimo Elcids!
Abraços!

olá Rodrigo,

      Então segue a "segunda questão".

      Isto é uma curiosidade da minha parte, mas que também pode vir a influenciar na implementação. Segue:

      1)  qual a utilidade de se usar o Sensor de Presença (o PIR) para controlar a Lâmpada (LED) do Aquário?

      2)  após a Lâmpada ser ligada pelo PIR,  ela deverá apagar automaticamente após algum tempo?  Se sim, qual seria este tempo?

      Sobre o item 2),  é preciso lembrar que se uma pessoa permanece no ambiente físico do PIR  isto irá redisparar o Sensor (tenha ou não dado o tempo que a Lâmpada poderia apagar automaticamente).  Neste caso, um novo "trigger" do PIR  deveria reiniciar a contagem  para o apagamento automático?

      Sobre o Botão,  acionar o mesmo é um ato intencional, e depois que alguém apertou o mesmo pra acender a Lâmpada, espera-se que este alguém também aperte o Botão pra apagar a Lâmpada.  Mas se esta pessoa não apertar o Botão para apagar, o Sistema deveria também apagar automaticamente depois de um tempo especificado?

      Peço que analise bem os pontos que coloquei acima, e responda com clareza, pra evitarmos equívocos na implementação.

      Não se preocupe com a implementação, pois mesmo que ela tenha mais elementos (como por exemplo a temporização "automática" descrita acima),  eu irei implementar os controles de forma gradativa, para que seja simples e didático o aprendizado.

      Abrçs,

      Elcids

Olá Elcids! O PIR seria para no momento em que alguém levantasse a mão sobre o aquário (para alimentar os peixes, por exemplo), o mesmo acendesse e apagasse após uns minutos que posso programar no próprio PIR, através do trimpot. Mas se quiser implementar esse tempo de desligamento no código, também acho bom. No caso de um novo acionamento do sensor, pode sim reiniciar a contagem.
Em relação ao botão, gostaria que ele pudesse apagar após um intervalo de tempo também para prevenir que fique aceso direto. Além, é claro, que ele apague os LEDs num novo pressionamento.

Abraços!

ok Rodrigo, ficou claro.

      Então para o caso do PIR, me parece que o melhor mesmo é que sempre que ocorra uma detecção de movimento, se ligue a Lâmpada,  e após um tempo "X"  o Sistema automaticamente desligaria a mesma. Minha sugestão inicial é 1 minuto,  que acha?

      Claro, no código vc poderá facilmente alterar o tempo "X" conforme desejar.

      Em relação ao Botão, o comportamento seria o mesmo em relação ao tempo "X" (mas provavelmente um tempo "Y" diferente)  para o desligamento automático, caso o próprio Botão não seja usado para desligar.

      No entanto há um ponto mais interessante para checar:   caso a Lâmpada esteja dentro de um período de acendimento (conforme horário lido do RTC),  então tanto o PIR como o Botão não terão efeito, e da mesma forma não terá efeito o tempo "X" (ou o "Y") do apagamento automático (já que está dentro do período de acendimento por horário).  Caso minha interpretação esteja incorreta, me avise.

      Aproveito para dizer que o código já está 80% pronto.

      Abrçs,

      Elcids

Está tudo perfeito Elcids!
Dentro do horário de acendimento automático nem o botão, nem o PIR devem influenciar.
Legal que já está com 80% pronto! Você é rápido hein!?
Abraços!

olá Rodrigo.

      Estou iniciando a publicação da implementação do Controle da Lâmpada do Aquário, conforme as especificações apresentadas e discutidas neste tópico.

      Claro, conforme combinado, irei também descrever as bases da implementação, e a lógica da Máquina de Estados que controla o Sistema.

      Antes de tudo, preciso fazer um comentário sobre a Biblioteca DS3231  que vc escolheu para usar no Projeto.

      Fiz a implementação usando esta mesma Biblioteca DS3231.  Porém, como ocorre com algumas bibliotecas escritas sem seguir padrões mais rigorosos,  esta viola uma das  regras da implementação "ISO C++".  Não estou surpreso, pois já vi isto diversas outras vezes. Muitos provavelmente que usam esta Lib  DS3231 não devem perceber isso, porque não tem habilitada a exibição das mensagens de warnings  durante a compilação. Para aqueles que querem saber como configurar a exibição dessas mensagens, recomendo ver um documento que preparei recentemente para configuração de alguns itens significativos da IDE do Arduino, onde a parte de compilação está descrita na página 14 ("Configurações para o Processo de Compilação"), mas recomendo ver todo o documento pois poderá ser de grande ajuda.

 link para o documento:  config_IDE_Arduino.pdf

      Sobre estes warnings na compilação da LIB  DS3231, estou mostrando parte da listagem dos mesmos na figura a seguir (onde marquei parte do texto na cor rosa):

(clique na figura para "zoom")

      Ao todo, resultam mais de 35 warnings, todos pelo mesmo motivo (pois são strings com nomes e nomes abreviados dos dias da semana e meses na língua inglesa), que é a violação da regra "ISO C++ forbids converting a string constant to 'char*' ".  Claro é uma regra aparentemente "boba".  Mas ao mesmo tempo não é. Ocorre que sempre que se encontra a palavra "forbid" nestes warnings, isto pode realmente significar apenas um warning na compilação na Plataforma Arduino,  mas aguém acredita mesmo que o padrão ISO usaria "forbid" para um warning???  É claro que não.  Sempre que um warning é sinalizado, é preciso ver o que ele significa e então decidir o que fazer. Neste caso específico, estamos ignorando o warning, pois sabemos que na Plataforma Arduino, ele não causará problemas. Mas isto nem sempre é assim.  Normalmente quando encontro uma situação assim onde um código ao ser compilado gera warnings, eu sempre corrijo o código para que as mensagens não apareçam no Processo de Compilação.  Mas em se tratando de uma Biblioteca que não fui eu quem a escreveu, não faço isso, pois se fizesse eu estaria alterando a Biblioteca (mesmo que eu tenha a certeza que a correção não terá nenhum efeito colateral). Claro, o ideal aqui seria avisar o autor da Biblioteca sobre a questão, para que ele próprio fizesse a correção. Neste caso não o fiz, porque sei que não terá problemas no Arduino, e porque exitem diversas outras Bibliotecas para o RTC DS3231 (e que não geram estes warnings).

      Especificamente sobre este warning ocorrido,  ele indica que o padrão ISO C++  proíbe  a conversão de uma string constante para um Ponteiro de char.  Sobre isso, farei uma rápida explicação. Existem essencialmente dois motivos. O primeiro, é que a referência para uma String, é sempre um Ponteiro, e no caso de uma String constante isso significa que esse ponteiro poderá estar apontando para a Memória de Programa, que em muitas plataformas de Processadores tem um Espaço de Endereçamento separado do Espaço de Dados, e dependendo do Processador (o "Core") o simples uso de um Endereço da Memória de Programa para acessar a Memória de Dados, resultará em acesso de dados errôneos, uma vez que a String não está no Espaço de Dados (ela está no Espaço de Programa). Claro no Arduino, sabemos que isso não será um problema, pois o código "escondido" de inicialização do C/C++ (executado antes da função "setup" do Arduino) irá copiar a String da Memória de Programa para a RAM, e ela será acessada da RAM por toda a execução do código (claro, isso gera um efeito colateral que é o consumo de RAM).   O segundo motivo, mais evidente, é que uma vez que o Ponteiro da String constante  é copiado para um Ponteiro "char* ",  ele deixa de ser do tipo "constante", significando que o código poderá alterar a String durante a execução e assim corromper uma regra de tipo que foi justamente declarada para impedir que a String seja alterada. E neste segundo motivo não há como contra-argumentar,  já que estamos explicitamente usando uma regra da Linguagem de Programação C/C++,  e em seguida estamos violando esta mesma regra, o que é um Paradoxo, e é este o motivo do "forbid" (que no Arduino virou apenas "warning",  mas em outras Plataformas poderia ser gerado um erro que impediria a compilação de ser concluída com sucesso).

      Então, apenas esclarecido esta questão da Biblioteca DS3231,  iniciarei a publicação da implementação.

      Abrçs,

      Elcids

Olá Elcids! Poxa, que chato isso, hein?! Não imaginava que uma biblioteca poderia ser implementada violando regras e padrões da linguagem. Desculpa pelo inconveniente. É que essa foi a biblioteca que eu consegui fazer meu código funcionar, pois ela é do canal Manual do Mundo do YouTube. Como é voltada para iniciantes, acredito que o autor possa não ter conhecimento suficiente para evitar os avisos, será?

Bom, eu já me acostumei com ela. Mas de qualquer forma, fique à vontade para introduzir outra se assim desejar, só peço que não seja muito difícil de mexer, rs.

Abraços!

RSS

© 2024   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço