Amigos,

estou trabalhando em um projeto no qual uso um LCD 16 x 2, um arduino uno, um RTC 1307, e alguns relés para controlar um sistema de irrigação.

Já publiquei a parte física da montagem no vídeo abaixo.

Agora meu problema é um menu que seja eficiente e eu consiga agregar as funções que quero.

Montei o código abaixo que funciona mas encontrei o seguinte problema. O horário mostrado na primeira ela fica congelado no momento que dispara o timer até o fim da programação.

Não sei se tenho que mudar o código de lugar.

Gostaria de criticas e aprimoramentos para colocar para funcionar. Quem quiser discutir estou aberto. O codigo foi feito aproveitando ideias da internet e por isso pode ter alguma inconsistencia. Mas agente aprende sempre.

Este sistema já está em teste de desempenho e espero que tenha ele pronto até o fim da semana.

Desde já agradeço a ajuda.

Quem quiser ver a parte física montada olha o video a seguir:

https://www.youtube.com/watch?v=iWk_hh_ZA60

int t1[7]= { //Timer do motor de 3cv
0,0,0,0,0,0,0};

int dd=1000; // used for delay in show timer data


#include <LiquidCrystal.h>
#include <Wire.h>
#include <EEPROM.h>
#include "RTClib.h"

RTC_DS1307 RTC;


// Definição dos pinos dos botões

#define bMenu A2 // Os pinos analógicos podem ser
#define bChange A3 // usados como digitais, bastando
#define bUp A0 // referenciá-los por A0, A1..
#define bDown A1
#define benter 8

#define bMenu0 90 // Valor de referência que a
#define bChange0 91 // função CheckButton() passa
#define bUp0 92 // indicando que um botão foi
#define bDown0 93 // solto
#define benter0 94

boolean aMenu, aChange, aUp, aDown, aenter; // Grava o ultimo valor lidos nos botões.
// Utilizado pela função Checkbutton p/ identificar quando há uma alteração no estado do pino dos botões

int horini=EEPROM.read(0); // variavel a ser alterada pelo menu
int minini=EEPROM.read(1);
int horfim=EEPROM.read(2);
int minfim=EEPROM.read(3);

char state=1; // variável que guarda posição atual do menu
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // Declaração do objeto tipo lcd

String ArrumaZero(int i)
{
String ret;
if (i < 10) ret += "0";
ret += i;
return ret;
}

//============================================== SETUP
void setup()
{
Wire.begin();
lcd.begin(16, 2); // Iniciando a biblioteca do LCD
RTC.begin();

pinMode(bMenu, INPUT); // Botões
pinMode(bChange,INPUT);
pinMode(bUp, INPUT);
pinMode(bDown, INPUT);
pinMode(benter, INPUT);
pinMode(6, OUTPUT); // USADO PARA VALVULA 2
pinMode(7, OUTPUT); // USADO PARA VALVULA 1
pinMode(9, OUTPUT); // USADO PARA CONTROLAR A BOMBA


digitalWrite(bMenu, HIGH); // Aciona o pull-up interno
digitalWrite(bChange,HIGH); // dos botões
digitalWrite(bUp, HIGH);
digitalWrite(bDown, HIGH);
digitalWrite(benter, HIGH);


if (!RTC.isrunning())
{
RTC.adjust(DateTime(__DATE__, __TIME__));
}

t1[0]= EEPROM.read(0);
t1[1]= EEPROM.read(1);
t1[2]= EEPROM.read(2);
t1[3]= EEPROM.read(3);
t1[4]= 8;
t1[5]= 1;
}
//==============================================
//============================================== LOOP

void loop()
{
switch (state) { // Define checa qual tela atual
case 1: // executado quando na TELA 1
switch (CheckButton()) {
case bUp:
lcd.clear(); Set_state(7); // antes de mudar de tela, é necessário limpar o
break; // display com a função lcd.clear()
case bDown:
lcd.clear(); Set_state(2);
break;
default: // Caso nenhum botão tenha sido apertado, ela executa a set_state
Set_state(1); // mesmo assim para atualizar o display.
}
break;

case 2: // executado quando na TELA 2
switch (CheckButton()) {
case bMenu:
lcd.clear(); horini--;
break;
case bChange:
lcd.clear(); horini++;
break;
case bUp:
lcd.clear(); Set_state(1);
break;
case bDown:
lcd.clear(); Set_state(3);
break;
case benter:
EEPROM.write(0, horini);
default:
Set_state(2);
}
break;

case 3: // executado quando na TELA 3
switch (CheckButton()) {
case bMenu:
lcd.clear(); minini--;
break;
case bChange:
lcd.clear(); minini++;
break;
case bUp:
lcd.clear(); Set_state(2);
break;
case bDown:
lcd.clear(); Set_state(4);
break;
case benter:
EEPROM.write(1, minini);
default:
Set_state(3);
}
break;

case 4: // executado quando na TELA 4
switch (CheckButton()) {
case bMenu:
lcd.clear(); horfim--;
break;
case bChange:
lcd.clear(); horfim++;
break;
case bUp:
lcd.clear(); Set_state(3);
break;
case bDown:
lcd.clear(); Set_state(5);
break;
case benter:
EEPROM.write(2, horfim);
default:
Set_state(4);
}
break;

case 5: // executado quando na TELA 5
switch (CheckButton()) {
case bMenu:
lcd.clear(); minfim--;
break;
case bChange:
lcd.clear(); minfim++;
break;
case bUp:
lcd.clear(); Set_state(4);
break;
case bDown:
lcd.clear(); Set_state(6);
break;
case benter:
EEPROM.write(3, minfim);
default:
Set_state(5);
}
break;

case 6: // executado quando na TELA 6
switch (CheckButton()) {
case bUp:
lcd.clear(); Set_state(5);
break;
case bDown:
lcd.clear(); Set_state(7);
break;
default:
Set_state(6);
}
break;

case 7: // executado quando na TELA 7
switch (CheckButton()) {
case bUp:
lcd.clear(); Set_state(6);
break;
case bDown:
lcd.clear(); Set_state(1);
break;
default:
Set_state(7);
}
break;

default: ;
}

checktimer1();
delay(200); // to stop screen flicker
}

//============================================== FIM da função LOOP


void checktimer1()
// checa o horário para saber se irá ligar o motor
{
DateTime agora = RTC.now();

int hora = agora.hour();
int minuto = agora.minute();
int segundo = agora.second();


if (t1[4]==8);
{
if (hora==t1[0] && minuto==t1[1])
{
digitalWrite(7, HIGH);
delay(5000);
digitalWrite(9,HIGH);
delay(3600000);
digitalWrite(6,HIGH);
delay(5000);
digitalWrite(7,LOW);
delay(3600000);
digitalWrite(9,LOW);
digitalWrite(6,LOW);
t1[6]=1;
}
if (hora==t1[2] && minuto==t1[3])
{
digitalWrite(9, LOW);
digitalWrite(6,LOW);
digitalWrite(7,LOW);
t1[6]=0;
}
}
}


//============================================== CheckButton
char CheckButton() {
if (aMenu!=digitalRead(bMenu)) {
aMenu=!aMenu;
if (aMenu) return bMenu0; else return bMenu;
} else
if (aChange!=digitalRead(bChange)) {
aChange=!aChange;
if (aChange) return bChange0; else return bChange;
} else
if (aUp!=digitalRead(bUp)) {
aUp=!aUp;
if (aUp) return bUp0; else return bUp;
} else
if (aDown!=digitalRead(bDown)) {
aDown=!aDown;
if (aDown) return bDown0; else return bDown;
} else
if (aenter!=digitalRead(benter)) {
aenter=!aenter;
if (aenter) return benter0; else return benter;
} else
return 0;
}

//========================================================
//============================================== Set_state
void Set_state(char index) {
state = index; // Atualiza a variável state para a nova tela

DateTime agora = RTC.now();

String relogio_data = "DT: ";
String relogio_hora = "HR: ";

int dia = agora.day();
int mes = agora.month();
int ano = agora.year();



relogio_data += ArrumaZero(dia);
relogio_data += "/";
relogio_data += ArrumaZero(mes);
relogio_data += "/";
relogio_data += ano;

int hora = agora.hour();
int minuto = agora.minute();
int segundo = agora.second();

relogio_hora += ArrumaZero(hora);
relogio_hora += ":";
relogio_hora += ArrumaZero(minuto);
relogio_hora += ":";
relogio_hora += ArrumaZero(segundo);

switch (state) { // verifica qual a tela atual e exibe o conteúdo correspondente
case 1: //==================== state 1
lcd.setCursor(0, 0);
lcd.print(relogio_data);
lcd.setCursor(0, 1);
lcd.print(relogio_hora);
break;
case 2: //==================== state 2
lcd.setCursor(0,0);
lcd.print("Hor. Inicio");
lcd.setCursor(0,1);
lcd.print(horini);
break;
case 3: //==================== state 3
lcd.setCursor(0,0);
lcd.print("Min. Inicio");
lcd.setCursor(0,1);
lcd.print(minini);
break;
case 4: //==================== state 4
lcd.setCursor(0,0);
lcd.print("Hor. Fim");
lcd.setCursor(0,1);
lcd.print(horfim);
break;
case 5: //==================== state 5
lcd.setCursor(0,0);
lcd.print("Min. Fim");
lcd.setCursor(0,1);
lcd.print(minfim);
break;
case 6: //==================== state 6
lcd.setCursor(0,0);
lcd.print("Alarme:");
break;
case 7: //==================== state 7
lcd.setCursor(0,0);
lcd.print("Segundos:");
lcd.setCursor(0,1);
lcd.print( millis()/1000 , DEC); // mostra os segundos na tela
lcd.print(" s");
lcd.print(" ");
lcd.print(millis()/86400000, DEC); // mostra os dias na tela
lcd.print(" dias");

break;
default: ;
}
}

Exibições: 14028

Responder esta

Respostas a este tópico

Bom, sem analisar muito o código, já chuto que o erro está em uns delays de 360000, você pode estudar o código do blink without delay e implementar algo semelhante no seu código, sempre q coloca o delay o seu programa fica parado....

Nossa Marcelo,

pode ser isso mesmo. Eu não sei usar outra forma de continuar executando uma tarefa. Já estou estudando sobre o que sugeriu. Ao implementar o código fiquei com uma dúvida. Além do timer para despertar na hora programada gostaria de implantar um sistema de alarme para algumas variáveis como temperatura do motor e corrente elétrica. Você acha que eu deveria criar outra função como "Alarmes" e deixar ela completamente separada da função timer? 

Tenho um projeto parecido com isso eu uso assim

unsigned long Timer1_Inicio = milis();

int Timer1_Periodo = 30000;

unsigned long Timer2_Inicio = millis();

int Timer2_Periodo = 3500000;

if ((Timer1_Inicio + Timer1_Periodo) < millis())

{

// Executa as funções desse timer

}

if ((Timer2_Inicio + Timer2_Periodo) < millis())

{

// Executa as funções desse Timer.

}

Basicamente para cada um dos delays que você criou você cria um TIMER.

Os alarmes também terão seus próprios timers...

Esses caras ficam dentro do void loop()

Amigos,

tenho uma atualização da montagem. Olhem o video. Tive sucesso no funcionamento. Falta somente resolver a questão do congelamento do LCD durante o disparo do Timer.

Já me falaram a solução e vou trabalhar no assunto. Quem quiser ver o progresso assiste o filme.

http://www.youtube.com/watch?v=mYWUlj32wf8

Até

Sidney,

Como foi feita as conexões dos botões?

Tem como me mostrar pelo Fritzing?

Obrigado!

Abraços,

Amauri

Amauri,

foi usando um resistor de pull up externo. Vc entende um pouco?

Estou revisando o projeto para um upgrade e posso fazer um filminho se quiser.

até

Sidney,


entendo um pouco mas não conheço o conceito de pull up externo..

É o resitor por exemplo 10k conectado ao terra e obtenho meu

sinal entre o "começo" do resistor com a saída do botão?

Cara eu estou montando um projeto com MENU, LCD e DISPLAY.

Mas to apanhando um pouco para os menus e os botões..

Obrigado pela ajuda!

Abraços,

Amauri.

O conceito é esse mesmo.

ta apanhando, depois coloca aqui suas dúvidas. é o lugar certo.

Olá Sydney,

Belo trabalho!

Você conseguiu resolver o problema do congelamento do LCD?

No código acima, no void loop, o ultimo break dos switch case's é fora das { } mesmo?

to arrumando o codigo. Mas como to sem tempo ainda não implantei.

Não vi isso que falou. vou checar. as vezes da problema em copiar e colar aqui.

Aqui aparece assim:

void loop()
{
switch (state) { // Define checa qual tela atual
case 1: // executado quando na TELA 1
switch (CheckButton()) {
case bUp:
lcd.clear(); Set_state(7); // antes de mudar de tela, é necessário limpar o 
break; // display com a função lcd.clear()
case bDown:
lcd.clear(); Set_state(2);
break;
default: // Caso nenhum botão tenha sido apertado, ela executa a set_state
Set_state(1); // mesmo assim para atualizar o display.
}
break;  <-------

Aparece assim em vários cases, mas pode ser mesmo o problema de ctrl+C ctrl+V aqui.

Leonardo,

chequei aqui. Essa chave que aparece antes do break é para fechar a chave que começa no 

switch (state) { //

Então é assim mesmo. Pelo menos funciona na prática. Se vc achar que é melhor antes podemos fazer um teste. O objetivo aqui é sempre melhorar.

Agora onde vc sugere para colocar a execução dos timers sem usar delay?

Vamos trabalhar nisso?

RSS

© 2024   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço