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

ok Rodrigo,

      mas não será necessário substituir a Lib, como eu descrevi no texto acima.

      Apenas atente para a questão de que os "warnings" não devem ser ignorados, e sim analisados para ver sua significância. E claro, se possível veja o documento onde instruo como exibir mensagens significativas do Processo de Compilação, uma vez que por default, elas não são mostradas na IDE do Arduino.

      Daqui a pouco estarei fazendo a publicação inicial da implementação.

      Abrçs,

      Elcids

      ah sim:  percebi a questão dos warnings dessa Bibiloteca,  logo no início do tópico, mas como vi também que não haveria problema, então decidi que só falaria sobre isso quando fosse publicada a implementação.

      Abrçs,

      Elcids

.

Parte 1 - publicando a implementação:

      A Máquina de Estados que controla o Sistema, inicialmente tinha 2 estados.  Mas como foi acrescentada a característica de "auto-desligamento" da Lâmpada (LED) após um período de tempo quando o acionamento é feito pelo Botão ou pelo Sensor PIR,  então foi necessário acrescentar mais um estado, com o que a Máquina passou a ter 3 estados.

      Nesta  Parte 1,  estarei publicando a implementação do Sistema de Controle da Lâmpada do Aquário, usando Arduino UNO.  Mas a implementação poderá ser estendida a qualquer outra Placa disponível que utilize a Plataforma Arduino (Nano, ESP32, ESP8266, Due, etc).

      Nos posts seguintes a este, a implementação será descrita na seguinte ordem, onde cada item será um "post", iniciando pela Parte 2:

      2)  descrição dos elementos e estruturas de dados usados na implementação, e das implicações resultantes de algumas destas definições.

      3)  descrição dos Estados e Eventos necessários para o Sistema funcionar, e das implicações resultantes.

      4)  descrição da técnica básica de implementação de uma Máquina de Estados (na Plataforma Arduino e de forma genérica), usando como referência este exemplo do Controle do Aquário e/ou outros exemplos simples.

      5)  apresentação de possibilidades para a implementação, usando técnicas mais "avançadas" ou sofisticadas.

      Assim a Parte 1,  efetivamente se inicia a seguir:

      O Diagrama de Estados da Máquina de Estados que controla este Sistema, pode ser visto na figura a seguir: 

(clique na figura para "zoom")

      O Diagrama em si é simples e praticamente dispensaria explicações. Mas eu entendo que para quem for principiante poderá ter dificuldades em entender a dinâmica do funcionamento, e por isso mesmo (como dito anteriormente), em outro post irei descrever a técnica e a metodologia por trás da implementação dessa Máquina de Estados.

      A implementação foi feita também em Simulação no Proteus, o que dá grande flexibilidade para testar as diversas condições e possibilidades de configuração do código. O Hardware para a Simulação no Proteus, é mostrado na figura a seguir:

(clique na figura para "zoom")

      Observar que embora na simulação tenha sido utilizado um Sensor PIR de autoria do "TEP" ("The Engineering Projects"),  isto é quase um "enfeite", uma vez que na simulação o PIR poderia ser simplesmente substituído por um Botão (ou então um Monoestável e um Botão).

      Observar também, que após a inicialização, algumas informações são exibidas no Terminal do Arduino, a saber:

      -  o "total de comandos":  isto está descrito em mais detalhes logo adiante no texto.

      -  o "tempo de apagamento automático", que é o tempo que a Lâmpada apagará automaticamente após ter sido ligada pelo Botão ou pelo Sensor PIR. Observar que no código da simulação, eu deixei apenas 20 segundos, para ficar mais dinâmico o teste (ou seja, não ter que esperar muito pra ver se o apagamento automático está funcionando). Mas no código aqui publicado, este tempo está setado em 60 segundos, mas deve ser alterado conforme se deseja (ele está definido logo no início do código).

      -  a Data/Hora  atual lida do RTC DS3231 (incluindo o Dia da Semana, informado em Português).  Sobre este ponto, no código da simulação foi setado através do Botão apertado logo que o Arduino é iniciado,  um dia e horário que permitisse verificar rapidamente o funcionamento para os Dias e Horários de acendimento e apagamento programados no Sistema. E foi verificado o correto funcionamento (na simulação, programei para ligar às 17:01 e para desligar às 17:03 do domingo).

      Sobre o "total de comandos" vou esclarecer.

      O método utilizado para se "programar" os Dias e Horários que se quer ligar/desligar  a Lâmpada, é utilizando um "Vetor de Comandos", ou seja, uma "Lista de Comandos".  Estes Comandos podem estar em qualquer ordem no Vetor (a "Lista"), uma vez que está descrito no próprio Comando qual o Dia e Horário  que o comando deve ser executado. Vejamos um exemplo na figura a seguir, onde são mostrados 4 Comandos na "Lista":

(clique na figura para "zoom")

      Observe que o primeiro elemento de um Comando, é o Dia da Semana (segunda, sexta, domingo, etc), seguido pelo horário (Hora e Minuto), e por último se o Comando é para ligar ou desligar a Lâmpada. Assim, já adiantando parte de como a coisa funciona (pois isto será efetivamente descrito no próximo post):  o tal "Vetor de Comandos" é uma "Lista de Comandos", a qual será "varrida" pelo código para execução de cada um dos Comandos, assim ligando ou desligando a Lâmpada no Dia e Horário descrito em cada Comando (e claro, o Dia/Horário atual é fornecido pelo RTC DS3231 do Sistema).

      Notar que embora os Comandos possam estar na Lista em qualquer ordem,  é aconselhável por motivos óbvios de organização, que se procure colocar sequencialmente na Lista um Comando para ligar seguido de um Comando para desligar. Ou seja, assim fica fácil observar olhando a sequência na Lista (ou Vetor), como irá funcionar toda a programação feita para o Controle da Lâmpada.

      Pode-se ter quaisquer quantidades de Comandos na Lista. Cada Comando ocupa 4 bytes na Memória RAM do Arduino,  e uma vez que ainda resta de RAM bem mais de 1000 bytes, então isto permitiria se ter bem além de 250 comandos programados para execução. Ou seja, tranquilo em relação à uma eventual necessidade de programação de uma grande quantidade de comandos.

      No código que está anexado nesta publicação, eu deixei apenas 6 comandos, e por este motivo este é o valor mostrado no Terminal do Arduino.

      Acrescentar Comandos é simples.  A única coisa necessária é colocá-los na Lista, a qual está logo no início do código (lá a Lista é chamada de "Vetor_Comandos"). Mais nada precisa ser feito.

      Para ilustrar essa facilidade, é mostrada na figura a seguir, como a "Lista" com os 6 comandos está definida no código que estou disponibilizando neste post:

(clique na figura para "zoom")

      Observar que os nomes dos dias da semana podem ser escritos em Português, pois estes nomes também foram definidos no início do código (e são compatíveis com os nomes em inglês definidos na Biblioteca  DS3231).

      O código do Arduino, os Arquivos para Simulação, e o Diagrama de Estados (Visio e PDF), estão neste link:

      Lampada_Aquario_01.zip

      O Sistema foi testado, mas caso seja detectada alguma anomalia no funcionamento, basta sinalizar aqui, que irei considerar logo que possível.

      Não se deixe enganar achando que existe alguma complexidade. Não existe. Ocorre que o tratamento "anti-bouncing" para o Botão (e algo semelhante para o PIR), exigiu rotinas um pouco maiores. Mas isto é apenas devido ao "anti-bouncing", e nada mais. E também foram necessárias algumas rotinas a mais para o RTC, com funções bem simples.

      Sobre o funcionamento  e  porque o Sistema foi implementado dessa forma (usando os "Comandos"), será abordado nos próximos posts.

      Abrçs,

      Elcids

Beleza Elcids, já adorei mesmo sem ver funcionando! Kkkk. Eu tenho mesmo essa necessidade de individualizar os comandos por dias da semana. Amanhã vou estudar tudinho e testar meu aprendizado. Já te adianto que você é, sem dúvidas, um excelente professor, viu?! Consegue ensinar com facilidade. Mesmo eu sendo principiante em Arduino, você passa muita segurança em suas explicações. Em relação à complexidade do código, não parece simples pra quem nunca programou, mas como já disse, você consegue fazer ficar bem mais fácil de entender. Espero que eu consiga aproveitar todo seu conhecimento e aos poucos ir crescendo nesse aprendizado. Quero também ensinar meu filho (10 anos) a programar com Arduino. Estou aguardando um kit chegar (da China) para iniciar o ensino dele. Claro, preciso aprender um pouco antes. Esse Uno quero deixar dedicado ao Aquário. Talvez mais pra frente eu o substitua por um Nano.

Muito obrigado mais uma vez por tudo!

Abraços!

Olá Elcids! Hoje tá sendo um dia muito corrido, mas não poderia deixar de testar o código até mesmo como uma forma de expressar minha gratidão. Está realmente muito bonito! Ficou um tanto grande, hein! Parece complexo para min, mas olhando com mais calma, você detalha tudo tão bem que vai clareando bastante o entendimento.

O que vi rapidamente que precisa mudar é que a hora de início e final para acionamento automático (Vetor de Comandos) dos LEDs precisa estar dentro de um intervalo. Isso porque ao faltar energia ou por algum outro motivo eu precisar desenergizar o Arduino, ele precisa entender que estando no intervalo de tempo do acionamento automático (Vetor de Comandos) ele deve acender.

Ex. Se está programado para as segundas-feiras acender das 17h00 às 22h00 e às 17h00 ele acende como esperado, porém as 19h20 falta energia (moro no interior RJ e falta bastante, acredite!), então a energia só retorna às 19h55, logo ele precisa acender pelo acionamento automático porque ainda não são 22h00.

Observe o seguinte: eu fui mexer no código hoje às 9h20 e após carregar o mesmo no Arduino ele não acendeu os LEDs porque já havia passado da hora de acender no acionamento automático que está configurada para domingo 8h.  Então ele só acenderia amanhã, segunda, às 17h, no próximo acionamento automático pelo código original.

Essa parte era a única que funcionava em meu antigo e famigerado retalho de códigos. Desligando e religando ele dentro desses intervalos de acionamento automático ele realmente ligava e acendia automaticamente. Nesse ponto, o sensor PIR também não deve alterar o funcionamento dos LEDs quando o mesmo estiver dentro do intervalo de acionamento automático. O PIR não pode, por exemplo, introduzir a contagem Tempo_ON durante o intervalo de acionamento automático.

Ele só deve manter os LEDs apagados dentro do acionamento automático se eu forçar o apagamento pelo push button. Da mesma maneira ao pressionar o push button novamente os LEDs acendem e inicia a contagem Tempo_ON. Somente o pushu button tem controle de apagar os LEDs a qualquer tempo. Nesse caso, para que eu consiga deixar os LEDs acesos novamente até que se apaguem pelo acionamento automático (Vetor de Comandos), é só resetar (On/Off) o Arduino.

Então, após um reset e falta/retorno de energia, ele deverá sempre ligar satisfazendo o intervalo automático. Isso é bastante relevante pra mim pelos motivos relatados acima.

Mais uma vez obrigado e espero que não seja muito trabalhoso implementar essas alterações no código.

Abraços!

ok Rodrigo, vamos ver estes pontos:

      1)  sobre a questão do controle via PIR e Botão, minha sugestão é que vc descreva o comportamento do Sistema quando se está no intervalo programado de acendimento:

              a)  no intervalo de acendimento, o que o Sistema deve fazer quando o Botão for acionado.

              b)  no intervalo de acendimento, o que o Sistema deve fazer quando o PIR for acionado.

      Confira se é isto mesmo, pois anteriormente vc tinha descrito como mostrado  a seguir:

      2)  sobre a questão de cair a energia, isto pode ser resolvido por código, uma vez que o RTC tem a data/hora  atual, e baseado nisto pode-se descobrir como deveria estar o estado da Lâmpada nesta data/hora atual.

      Ainda sobre o item 2 (queda de energia) há diversas soluções. Porém aqui, como queremos que o Sistema continue simples devido ao caráter de aprendizado e a favor da didática, vamos evitar fazer mudanças muito drásticas neste ponto (pois ainda não apresentei a descrição do funcionamento e já estaríamos mudando este funcionamento, o que normalmente não é considerado uma boa ideia em um tópico deste tipo, porque poderia tornar a coisa um "labirinto" e desestimular aqueles que possam se interessar pela questão).

      Então, partindo deste ponto de manter o Sistema simples, minha sugestão para a questão da queda de energia, é pensar num Formato dos Comandos de forma que quando o Sistema é ligado (após a queda de energia), se possa restabelecer o controle correto. Por exemplo:  usar um Formato de Comando especificando a Hora inicial e a Hora final para ligar a Lâmpada. E fora deste intervalo, implica que a Lâmpada, estaria desligada (algo bem semelhante à sua ideia original, mas usando a Máquina de Estados para controle e restabelecendo o estado após uma queda de energia).  Preciso também analisar se após alterar o Formato do Comando, ainda é possível manter a mesma Máquina de Estados atual,  o que certamente seria o ideal.

      Vamos então tentar encontrar a melhor forma de conseguir o funcionamento que vc descreveu. Estamos aqui pra conseguir,  e acredito nisso.

      Abrçs,

      Elcids

Olá Elcids! Verdade! De início eu pensava que nem o Botão, nem o Sensor PIR devessem atuar quando os LEDs estivessem ligados dentro do intervalo de acendimento automático. Mas ao rodar seu código, gostei da ideia de poder interromper o acendimento automático com o botão. Isso pode me ser útil. Mas o PIR não deve atuar mesmo. Durante o intervalo de acendimento automático, o botão pode apagar os LEDs. Mas se isso for muito complicado, posso ficar sem.

O que realmente não dá é perder o intervalo de acendimento automático por desligamento do sistema. Imagine que eu quisesse, como estou fazendo agora, estudar outros códigos num momento em que o acendimento automático esteja atuando, por exemplo domingo às 20h40. Eu desligaria o Arduino do carregador DC 5V e o conectaria em meu notebook para desbravar a plaquinha. Ao terminar de brincar no IDE, ele não iria acender por conta do horário do acendimento automático não estar em intervalos. Até ficar tudo redondinho, farei muito isso. E enquanto não recebo outra placa, (malditos Correios!) preciso usá-lo para aprender. Isso realmente é muito chato porque poderia passar o dia inteiro apagado até que um novo horário de acendimento automático o fizesse acender. Ou seja, toda vez que eu quiser olhar ou alterar o código, perco o acendimento automático do momento.

Tem outra questão que percebi. Preciso que o horário seja ajustado com precisão de segundos (é, eu sei que tenho mania de precisão, kkk) No código antigo eu tinha o terminal atualizando a cada segundo o que fazia com que eu pudesse conferir com o relógio do Windows e, descontando o tempo de compilação, conseguia ajustar de maneira sincronizada com o relógio do Windows. Até coloquei no Serial.print o comando RTC_time.sec mas não ficou atualizando.

Um grande abraço!

olá Rodrigo.

      Revisei seu código original, para ver a funcionalidade que havia ali.

      Sobre a questão do "print" do horário lido do RTC no Terminal do Arduino, vc estava fazendo como mostrado na figura a seguir:

(clique na figura para "zoom")

      Essencialmente era a impressão de uma "String" retornada pelo método "getTimeStr". E depois da impressão, vc usava um delay de 1 segundo, para que a cada segundo tivesse uma atualização do horário.  Ok, isto funcionava no seu código original,  mas não é  a forma adequada de fazer isso, ou seja:  não se deve usar o "delay" para temporizar o Sistema.  O "delay" deve ser usado em condições específicas,  quando se sabe que ele não irá comprometer as demais temporizações do Sistema (que normalmente usam o "millis").  Se vc não tem certeza se o "delay"  irá comprometer a temporização do Sistema, então não use o mesmo.

      Atente para o seguinte:  na primeira liberação do código eu não coloquei esta impressão do horário, simplesmente porque vc não disse que ela era necessária.  E veja: mesmo que seu código estivesse fazendo a impressão do horário,  da forma que ele estava ali sem um propósito claro,  parecia ser apenas uma funcionalidade para debug/testes.

      Mas agora que sei que vc necessita dessa "impressão" do horário no Terminal do Arduino,  então acrescentei no Sistema uma função para imprimir o horário a cada segundo,  mas da forma adequada, ou seja: sem comprometer as demais temporizações do Sistema.

      Sobre a questão da queda da energia,  já alterei o formato do Comando (conforme propus no post anterior),  e os comandos agora contém a hora de ligar e a hora de desligar  a Lâmpada. Então não tem  mais o problema de perder o estado da Lâmpada após a energia voltar.

      Mas há um pequeno problema:  devido à questão do acionamento manual via Botão,  foi preciso diferenciar no Sistema entre um acionamento fora do período de acendimento programado e um acionamento dentro do período de acendimento programado.  Esta diferenciação se dá na Máquina de Estados,  e para isto tive que acrescentar mais um estado.

      A questão é que eu não considero adequado usar para aprendizado sobre Máquina de Estados, qualquer Máquina que tenha mais de 3 estados. O ideal para não comprometer o aprendizado, são 2 estados, e até 3 ainda vai. Mas 4 estados já passou da conta.

      Então vamos usar este tópico do Aquário apenas para a implementação do Sistema, pois tendo a Máquina de Estados  4 estados, se usarmos o tópico para aprendizado não dará o resultado esperado.  Eu sei o que estou dizendo, e não quero que isto afugente as pessoas interessadas em aprender (ou pior, desistam achando que a coisa é complicada, quando não é). Então não vamos arriscar pois é certo que irá causar dificuldades.

      Como solução, então vamos fazer a implementação do Sistema do Aquário,  e posteriormente usarei outro exemplo mais simples com uma Máquina de Estados com apenas 2 estados  para que o aprendizado seja eficiente e se mantenha acessível a todos.

      Aproveito também para informar que encontrei pequenas falhas que cometi na primeira implementação, e que talvez não sejam percebidas. Mas já tratei de corrigir estes pontos.

      Ah, tem uma coisa que acho que vc irá apreciar muito:  nesta "nova" implementação,  vc pode alterar a Data/Hora a partir de comandos enviados ao UNO através do Terminal do Arduino.  Ou seja, para ajustar a Data/Hora vc não precisa mais alterar e regravar o código no Arduino.  E fique tranquilo, pois o comando é muito simples e fácil de usar (vou mostrar quando postar a implementação).

      Abrçs,

      Elcids

Olá Elcids! Entendi tudo perfeitamente e acredito que vai ficar bom. Você está correto. Deixemos essa Máquina de Estados com 4 estados só para implementar meu Aquário e outra para aprendizado. Até porque quando chegarem meus outros componentes, como LCD, Bluetooth, etc ela irá fica bem mais complexa. Espero conseguir aprender para implementar tudo.

Abçs!

.

Parte 1A - alterações conforme solicitado:

      Olá Rodrigo.

      Conforme vc solicitou, alterei o Sistema para que não perdesse o status de controle da Lâmpada (ou LEDs)  após ter ocorrido queda de energia,  e para que o Botão  possa desligar a Lâmpada quando se estiver dentro de um horário para acendimento programado (através do Vetor de Comandos).

      Importante:  sobre este apagamento via Botão dentro de um horário programado para acender a Lâmpada,  observe que poderia ocorrer da pessoa que acionou o Botão esquecer que estava dentro do período de acendimento automático, e com este esquecimento deixar a Lâmpada apagada.  Então para avisar que o Sistema está nesta condição (Lâmpada apagada via Botão dentro do horário para estar ligada), acrescentei um LED comum, que irá piscar duas vezes por segundo, avisando sobre a condição (a taxa de pisca do LED é facilmente alterada no código, como mostrado logo adiante no texto).

      Aproveitando isso,  resolvi também indicar os demais estados do Sistema, usando diferentes taxas de pisca do mesmo LED.  Devido ao LED sempre piscar, mas a taxas diferentes,  o nome que normalmente damos a ele é "LED Alive"  (ou simplesmente "Alive", indicando que o Sistema está "vivo" e funcionando).  Veja na figura a seguir como estão definidas as diferentes taxas de pisca para o "LED Alive":

(clique na figura para "zoom")

      Observe que no código, são definidos os intervalos de pisca do LED,  marcados em verde na figura anterior.  Por exemplo para o estado "Desligado" onde o valor é 20, significa que o "LED Alive"  irá piscar uma vez a cada 20 segundos.  Cada piscada é bem rápida e demora apenas 1/5 de segundo (ou 0.2 segundos), independente do intervalo entre piscadas.

      Quando a Lâmpada for ligada via Sensor PIR ou via Botão,  mas fora do horário de acendimento programado, o "Alive" piscará a cada 5 segundos (indicando que o Sistema está no estado "Tempo_ON".  Já quando a Lâmpada for ligada automaticamente devido ao horário programado, o "Alive" irá piscar a cada 2 segundos, e se neste intervalo o Botão for acionado para desligar a Lâmpada, o "Alive" piscará 2 vezes por segundo (ou a cada 0.5 segundo, como definido no código).

      Estes intervalos do "Alive", escolhi procurando usar o bom senso, de forma que identifique claramente cada estado sem confundir um com o outro,  e que também chame a atenção que seja necessária quando a Lâmpada for apagada dentro do intervalo de acendimento programado.

      Como vc pode ver, é muito simples alterar o intervalo, uma vez que ele é especificado em segundos.  Então basta ajustar conforme desejado.

      Mas caso não deseje usar o "Alive", então basta desabilitá-lo no código.  Na figura a seguir, o "Alive" está habilitado, conforme marquei em amarelo na figura:

(clique na figura para "zoom")

      Observe  que  para  desabilitar  o  "LED Alive",  basta  mudar  para  "0"  no  "#define habilita_Alive".  Se o "Alive" for desabilitado neste ponto do código, nenhuma outra ação precisa se feita (nem é preciso excluir as chamadas às funções do "Alive"), e nem mesmo precisa se preocupar em comentar a linha onde o pino do "LED Alive" é definido (pois o código irá ignorar estas definições).

      Mas caso use o "Alive",  então veja na figura anterior, que vc deve definir em qual pino o "LED Alive"  está conectado (além do Nível Lógico que liga o LED). No código que estou publicando, usei o pino 5 do Arduino,  mas use e especifique conforme desejado.

      Sobre o funcionamento do Sistema, para atender às novas características solicitadas, conforme informei em post anterior,  tive que acrescentar um novo estado  na  Máquina de Estados  que controla o Sistema. A este estado chamei de "Botão OFF",  pois ele desliga a Lâmpada quando se estiver dentro do período de acendimento automático.

      O novo Diagrama de Estados pode ser visto na figura a seguir:

(clique na figura para "zoom")

      O Diagrama ainda é simples,  mas devido a quantidade de elementos de controle (PIR, Botão, e Temporizações automáticas, etc),  fica realmente claro que este Sistema não é nada adequado para o aprendizado,  e poderia afugentar ou desestimular as pessoas interessadas em aprender sobre a implementação de Máquinas de Estados.  Assim a decisão tomada no post anterior faz sentido,  quando vemos todo o Sistema funcionando, pois ele tem uma complexidade um pouco além daquela exigida para ser usado como exemplo para um aprendizado.

      Também testei o Sistema em simulação no Proteus.  O circuito usado é praticamente idêntico ao anterior, porém como dito, foi acrescentado o "LED Alive", que indica o "Status" que o Sistema se encontra, conforme mostrado na figura a seguir:

(clique na figura para "zoom")

      Observe na figura anterior, que no Terminal do Arduino, além das informações que já eram exibidas na primeira versão do código,  também é informado que o "LED Alive" existe no Sistema.

      Veja também que é exibido no Terminal,  a hora atual, conforme vc solicitou.  A exibição é feita a cada segundo (mas sem usar o "delay", lembre-se disso, que já enfatizei no post anterior !!! ).

      Sobre a questão da queda da energia, isso foi resolvido com a alteração do Formato do Comando, que agora especifica a Hora que o LED deve ser ligado e a Hora que ele deve ser desligado.  Pode-se ver no exemplo que está no código,  onde deixei 3 Comandos na Lista de Comandos (ou "Vetor de Comandos"), mostrado na figura a seguir:

(clique na figura para "zoom")

      Observe na figura anterior, que marquei em amarelo e verde  a definição do horário no primeiro Comando na Lista,  mostrando como é simples acrescentar um Comando.  Como antes,  vc pode acrescentar qualquer quantidade de Comandos que desejar,  e novamente a ordem na Lista não interfere, uma vez que o próprio comando já tem o horário dizendo quando ele tem efeito.

      Neste novo Formato, aumentou em 1 byte o tamanho de um Comando em relação à primeira versão.  Assim cada Comando ocupa agora o espaço de 5 bytes (ainda totalmente viável para a aplicação desejada).

      Sobre o Sistema acredito que não há mais o que dizer, pois praticamente tudo já foi dito neste ou nos posts anteriores.

      Mas há uma característica (ou "feature" se preferir), que conforme eu disse no post anterior, acredito que vc irá apreciar.  É sobre o ajuste da Data/Hora,  que agora vc pode fazer diretamente pelo Terminal do Arduino (ou qualquer outro Programa de Terminal que desejar, como por exemplo o "Termite").

      O ajuste da Data/Hora pelo Terminal, pode ser feita a qualquer momento, independente de qual estado o Sistema esteja atualmente.  Para isto, basta enviar um "Comando de Ajuste"  através do Terminal. O comando é muito simples, e pode ser visto na figura a seguir:

(clique na figura para "zoom")

      A figura é auto-explicativa (não esqueça de clicar no Botão "Enviar" do Terminal,  o qual marquei na figura).

      Sempre que vc ajustar a Data/Hora  através do Comando,  será exibido imediatamente no próprio Terminal,  a nova Data/Hora lida do RTC,  de forma que assim vc pode conferir se o ajuste foi feito conforme especificado pelo comando.

      Esta segunda versão  da implementação do Sistema para Controle da Lâmpada do Aquário, está no link a seguir:

      Lampada_Aquario_02.zip

      Lembre-se:  pode não parecer, mas a implementação ainda se mantém simples.  Assim, se vc analisar o código com atenção (e sem pressa), irá aprender muito. E veja que no próprio código há comentários e explicações sobre cada parte dele (preste atenção a estas informações inseridas no código).  E não pare de estudar a Linguagem C,  pois isto é muito importante neste caminho de aprendizado.

      Apesar Rodrigo, de ainda não ter seu retorno sobre esta segunda implementação, considero este Sistema concluído, principalmente porque todas as solicitações foram atendidas.

      Entenda que a coisa toda aqui no site é espontaneamente colaborativa,  e que também estou envolvido em outros tópicos aqui no LDG  que necessitam da minha atenção.

      Veja também que quaisquer alterações que vc faça no código, são inteiramente de sua responsabilidade.

      Sobre o aprendizado de como funcionam e como implementar Máquinas de Estados,  fique atento ao site, pois estarei iniciando isto em breve (logo depois que eu conseguir atender alguns tópicos que estão pendentes aqui no LDG).

      Espero que fique satisfeito com as implementações, e que tenham ido além da sua expectativa, pois foi esta a intenção.

      Abrçs,

      Elcids

Olá Elcids!
Que ótimo que você conseguiu!
Ainda hoje quando estiver em casa estarei testando o código com as alterações recentes. Ao longo da semana já consigo dar um retorno sobre o seu funcionamento completo no meu sistema.
Obrigado mais uma vez pelo empenho e dedicação!
Tenha uma ótima sexta-feira!

Abçs!

Olá Elcids, tudo bem? Fiquei um tanto enrolado porque estou fazendo obra em casa. :/

Mas consegui testá-lo. Olha, o seu código é realmente incrível! O "LED Alive" além de extremamente funcional, dá um charme e elegância ao sistema! Agora, ao se interromper a energia do arduino ele volta acendendo perfeitamente, se ainda estiver no horário de acendimento automático. Maravilhoso!

Apenas uma coisa me inculcou: os horários de acendimento automático dos LEDs de iluminação não estão funcionando no horário de 4h30 às 7h30 nas segundas e quintas-feiras. O código permanece inalterado na versão 2. já revisei tudo e não entendo porque somente nessa faixa de horário ele não quer acender. A minha linha de comandos está assim:

LED_prog_type Vetor_Comandos [] = // Vetor de Comandos:
{
segunda, 4, 30, 7, 0, // liga o LED as segundas, entre 4:30 e 7:00 horas.
segunda, 17, 0, 22, 0, // liga o LED as segundas, entre 17:00 e 22:00 horas.

terca, 17, 0, 22, 0, // liga o LED as terças, entre 17:00 e 22:00 horas.

quarta, 17, 0, 22, 0, // liga o LED as quartas, entre 17:00 e 22:00 horas.

quinta, 4, 30, 7, 0, // liga o LED as quintas, entre 4:30 e 7:00 horas.
quinta, 17, 0, 22, 0, // liga o LED as quintas, entre 17:00 e 22:00 horas.

sexta, 17, 0, 22, 0, // liga o LED as sextas, entre 17:00 e 22:00 horas.

sabado, 8, 0, 22, 0, // liga o LED aos sabados, entre 8:00 e 22:00 horas.

domingo, 8, 0, 22, 0, // liga o LED aos domingos, entre 8:00 e 22:00 horas.
};

Tem alguma coisa erra aí?

Bom, os Correios resolveram trabalhar e meu kit arduino chegou, finalmente! Nele eu tenho um interruptor magnético MC-38 para porta/janela, um termômetro à prova d'água e um display LCD 1602, dentro outras coisas. Gostaria de uma ajuda apenas para o sensor magnético mc38, já que os outros sensores/atuadores são para eu (sozinho) quebrar a cabeça mais pra frente.

Eu tenho uma porta de vidro, de correr, que fica atrás do aquario e fecha a minha sala quando estamos com ar condicionado ligado. Este ano, há cerca de 3 meses aconteceu um acidente comigo e essa porta. Eu levantei bem cedo e, ainda sonolento, dei de cara na porta, que é toda transparente, e a derrubei em cima do aquário e rack da sala. Voou peixe e água pra tudo quanto é lado! Cortei meus pés, quebrou meu receiver, mas a porta (vidro temperado) não quebrou! Uma verdadeira cena de terror! Diante disso, decidi adesivar algumas faixas vermelhas na porta e coloquei uma iluminação em fita led (+/- 2m) em um dos lados da parede em que ela fecha.

Já consegui um código que ao fechar a porta, acende a fita LED instalada próximo à ela. Ao fechar, a fita LED se apaga. A questão é que quando eu acrescento esse código ao seu, ele de cara acusa erro nas partes do LED Alive. Então comentei tudo do Alive, então, compilou. Mas, além de perder o Alive (não queria!), tá dando um pequeno conflito que toda vez ao ligar o arduino numa faixa de horário do acendimento automático, os LED do aquário não acendem se a fita LED estiver ligada. Então eu movimento a porta para apagar a fita LED, os LEDs do aquário acendem, e então, eu movimento a porta novamente para acender a fita LED. Daí pra frente fica funcionado normalmente. Posso apagar ou acender a fita LED que não interrompe os LEDs do aquário.

As modificações de hardware foram um relè duplo no lugar dos simples e o interrptor magnético. O código que tenho é de um pushbutton comum, mas adaptei e funcionou no sensor magnético:

// digital pin 2 has a interuptor magnético attached to it. Give it a name:
const int pino_magnetico = 10;
const int pino_RELE2 = 9;
int estadoMagnetico = 0;

// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);


// definindo pino interruptor magnético como entrada:
pinMode(pino_magnetico, INPUT_PULLUP);
pinMode(pino_RELE2, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {


estadoMagnetico = digitalRead(pino_magnetico);

// check if the pushbutton is pressed. If it is, the buttonState is HIGH:
if (estadoMagnetico == HIGH) {
// turn LED on:
digitalWrite(pino_RELE2, LOW);
} else {
// turn LED off:
digitalWrite(pino_RELE2, HIGH);
}


// read the input pin:
int estadoMagnetico = digitalRead(pino_magnetico);


// print out the state of the button:
Serial.println(estadoMagnetico);
delay(1); // delay in between reads for stability
}

Sei que o solicitado já foi atendido e você está correto em dizer que o sistema já foi concluído. Mas, se não for pedir muito, preciso pelo menos dessa parte da fita LED no sensor magnético porque, como disse, tenho medo que se repita esse acidente com mais alguém.

Tenha uma ótima semana e mais uma vez: obrigado por tudo!!!!

RSS

© 2024   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço