Go Down

Topic: Alternar dados no LCD a cada 2 segundos (Read 4580 times) previous topic - next topic

NJPinheiro

Boas pll,

no meu código fonte tenho uma parte em que alterno dados no LCD a cada 2 segundos:

Code: [Select]

{switch (Key)
case 'B' :
                             digitalWrite(buzzer, LOW);
                             delay(100);
                             digitalWrite(buzzer, HIGH);
                             do{lcd.clear();
                             MostraInfo(TARGET, 0, 0,"Temperatura Max");
                             MostraInfo(TARGET, 1, 1,"do dia");
                             lcd.setCursor(8,1);
                             lcd.print(max_temp_dia);
                             MostraInfo(TARGET, 13,1,"C");
                             delay(2000);
                             lcd.clear();
                             MostraInfo(TARGET, 0, 0,"Temperatura Min");
                             MostraInfo(TARGET, 1, 1,"do dia");
                             lcd.setCursor(8,1);
                             lcd.print(min_temp_dia);
                             MostraInfo(TARGET, 13,1,"C");
                             delay(2000);}
                             while(keypad.getKey() == NO_KEY);
                             tempo = millis();
                         break;


O que pretendia era substituir a função delay pela função millis, já andei para aqui a "inventar" utilizando:

millis() - tempo > 1000

mas ele não alterna entre o 1º ecrã e o 2º, alguém pode dar uma dica?

Obg
NJPinheiro

NJPinheiro

#1
Aug 31, 2014, 07:56 pm Last Edit: Aug 31, 2014, 09:19 pm by NJPinheiro Reason: 1
Pll,
isto assim não devia funcionar?

Code: [Select]
int menuEcra;

void loop() {
......
........
..........case 'B' :
                           digitalWrite(buzzer, LOW);
                             delay(100);
                             digitalWrite(buzzer, HIGH);
                             tempo = millis();
                             if (millis() - tempo > 4000)
                             menuEcra = 3;
                             if (millis()- tempo > 2000 || millis()-tempo <=4000)
                             menuEcra = 2;
                             if(millis() -tempo <=2000)
                             menuEcra = 1;
                          switch (menuEcra) {
                                 case 1:
                                     lcd.clear();
                                     MostraInfo(TARGET, 0, 0,"Temperatura Max");
                                     MostraInfo(TARGET, 1, 1,"do dia");
                                     lcd.setCursor(8,1);
                                     lcd.print(max_temp_dia);
                                     MostraInfo(TARGET, 13,1,"C");
                                   break;
                                  case 2:
                                     lcd.clear();
                                     MostraInfo(TARGET, 0, 0,"Temperatura Min");
                                     MostraInfo(TARGET, 1, 1,"do dia");
                                     lcd.setCursor(8,1);
                                     lcd.print(min_temp_dia);
                                     MostraInfo(TARGET, 13,1,"C");
                                    break;
                                   case 3:
                                     tempo - millis();
                                    break;}
                            tempo = millis();
                        break;
}



Que grande dor de cabeça que arranjei :P

Obg NJPinheiro

luisilva

Não gosto. Esta instrução:
Code: [Select]
tempo = millis();
tem que estar em outro lugar. Assim, nos if's a differença entre millis() e tempo, é um valor muito pequeno.

Depois está esta instrução:
Code: [Select]

                                   case 3:
                                     tempo - millis();
                                    break;


que não faz absolutamente nada (e até penso que deve dar erro de compilação).

Sem pensar muito, o que digo que pode dar, é:
Code: [Select]

                             if (millis() - tempo > 2000) {
                                menuEcra++;
                                if (menuEcra > 3) {
                                   menuEcra = 1;
                                }
                                tempo=millis();
                             }

no início deste processo, a variável tempo tem que ter um valor pequeno, por exemplo 0 (isto pode ser feito na função setup() ou na inicialização da variável) e a variável menuEcra deve ter o valor 1.


NJPinheiro

Boas,
isto não está facil :0

comecei por declarar no inicio do código:
Code: [Select]

int menuEcra = 1;


.....
......
.......
........
if (Key >= 'A' && Key <= 'D')
                {switch (Key)
                    {case 'A' :
                                xxxxxx
                        else
                                xxxxxx
                         break;
                     case 'B' :
                             digitalWrite(buzzer, LOW);
                             delay(100);
                             digitalWrite(buzzer, HIGH);
                             if (millis() - tempo > 2000)
                                {menuEcra++;
                                  if (menuEcra >= 3)
                                     {menuEcra = 1;}
                                     tempo=millis();
                                }
                             switch (menuEcra)
                                {case 1:
                                     lcd.clear();
                                     MostraInfo(TARGET, 0, 0,"Temperatura Max");
                                     MostraInfo(TARGET, 1, 1,"do dia");
                                     lcd.setCursor(8,1);
                                     lcd.print(max_temp_dia);
                                     MostraInfo(TARGET, 13,1,"C");
                                   break;
                                  case 2:
                                     lcd.clear();
                                     MostraInfo(TARGET, 0, 0,"Temperatura Min");
                                     MostraInfo(TARGET, 1, 1,"do dia");
                                     lcd.setCursor(8,1);
                                     lcd.print(min_temp_dia);
                                     MostraInfo(TARGET, 13,1,"C");
                                    break;}
                             tempo = millis();
                         break;       
                     default:
                     estado = false;
                     password.reset();                    // vai ler novamente a password, por isso elimina os valores anteriores
                     Serial.print(indisponibilidade);
                     digitalWrite(buzzer, LOW);
                     lcd.clear();
                     MostraInfo(TARGET, 5, 0, "Funcao");
                     MostraInfo(TARGET, 2, 1, "Indisponivel");
                     delay(1500);
                     lcd.clear();
                     MostraInfo(TARGET, 3, 0,"Bloqueado");
                     delay(1000);
                     digitalWrite(buzzer, HIGH);
                    }
                 value = 0;
                }



Só que ele salta logo para o "case 2" e não estou a conseguir "passar" no "case 1"

Alguma dica de onde a coisa pode estar a falhar?
eu tenho ideia que será na utilização da função millis(), mas...

Outra pergunta, (se calhar parva, mas um maçarico como eu deve poder fazer:) )
quando fazemos:
Code: [Select]
if (millis() - tempo > 2000)
                                {menuEcra++;
                                  if (menuEcra >= 3)
                                     {menuEcra = 1;}
                                     tempo=millis();
                                }


algures no código não deveria fazer qualquer coisa do genero:
Code: [Select]

menuEcra1 = lcd.clear();
                                     MostraInfo(TARGET, 0, 0,"Temperatura Max");
                                     MostraInfo(TARGET, 1, 1,"do dia");
                                     lcd.setCursor(8,1);
                                     lcd.print(max_temp_dia);
                                     MostraInfo(TARGET, 13,1,"C");

menuEcra2 = lcd.clear();
                                     MostraInfo(TARGET, 0, 0,"Temperatura Min");
                                     MostraInfo(TARGET, 1, 1,"do dia");
                                     lcd.setCursor(8,1);
                                     lcd.print(min_temp_dia);
                                     MostraInfo(TARGET, 13,1,"C");

etc...



agradeço todo o contributo que possam dar :)

NJPinheiro

bubulindo

Estás a baralhar-te todo...

Eu vejo teclas e temporizações a mexer no ecra... Tenta colocar o codigo de forma a podermos entender e também completo.
Meter aos bocados não dá para perceber o que se passa.
This... is a hobby.

luisilva

O que está a fazer, nesta parte:
Code: [Select]
                                  case 2:
                                     lcd.clear();
                                     MostraInfo(TARGET, 0, 0,"Temperatura Min");
                                     MostraInfo(TARGET, 1, 1,"do dia");
                                     lcd.setCursor(8,1);
                                     lcd.print(min_temp_dia);
                                     MostraInfo(TARGET, 13,1,"C");
                                    break;}
                             tempo = millis();


Outro tempo = millis();?

Em relação à questão:
Quote
Outra pergunta, (se calhar parva, mas um maçarico como eu deve poder fazer:) )
quando fazemos(...)

não faz sentido, uma vez que isso está a ser feito na parte:
Code: [Select]

                             switch (menuEcra)
                                {case 1:
                                     lcd.clear();
                                     MostraInfo(TARGET, 0, 0,"Temperatura Max");
                                     MostraInfo(TARGET, 1, 1,"do dia");
                                     lcd.setCursor(8,1);
                                     lcd.print(max_temp_dia);
                                     MostraInfo(TARGET, 13,1,"C");
                                   break;
                                  case 2:
                                     lcd.clear();
                                     MostraInfo(TARGET, 0, 0,"Temperatura Min");
                                     MostraInfo(TARGET, 1, 1,"do dia");
                                     lcd.setCursor(8,1);
                                     lcd.print(min_temp_dia);
                                     MostraInfo(TARGET, 13,1,"C");
                                    break;}
(...)


Em relação à questão:
Quote
Só que ele salta logo para o "case 2" e não estou a conseguir "passar" no "case 1"

se não me engano, basta alterar, no início do código:
Code: [Select]
int menuEcra = 1;
(...)


para:
Code: [Select]
int menuEcra = 0;
(...)

NJPinheiro


Estás a baralhar-te todo...


E não é pouco :~ ...mas acho que faz parte de quem está a aprender :)



Eu vejo teclas e temporizações a mexer no ecra... Tenta colocar o codigo de forma a podermos entender e também completo.
Meter aos bocados não dá para perceber o que se passa.


Pois, acredito que o código não esteja nada bonito...mas é aquilo que tenho conseguido fazer, (com a vossa ajuda claro), e acredita que tenho muitas horas investidas aqui. É qualquer coisa como queres ir de Lisboa ao Algarve, mas só saberes partes do caminho, e por isso fazes Lisboa/Evora/Beja/Aljustrel/Faro, mas chegas lá  :)

Quanto ao código deixo abaixo o link:
https://googledrive.com/host/0B-Pv876wR5B1OVFDdF9rYjZ6UFk

As teclas que vês é um teclado matricial que tenho, que "normalmente" está num estado bloqueado, desbloqueando com a introdução da password, e tornando a bloquear ao fim de 3 minutos sem que nenhuma tecla seja pressionada, (os tais temporizadores).

Agora estou a tentar fazer com que ao carregares na tecla "B" apareça no LCD a temperatura maxima do dia, passados 2 segundos mude para a temperatura minima, e se mantenha em ciclo até uma de duas coisas acontecerem:
- seja carregada outra tecla;
- passem 3 minutos sem que nenhuma tecla seja carregada

É nesta parte que estou todo baralhado com a função millis()

PS: Também já andei de volta das funções while e do...while, mas não tive sorte nenhuma  :smiley-fat:

Obg
NJPinheiro

NJPinheiro


O que está a fazer, nesta parte:

Code: [Select]
                                  case 2:
                                     lcd.clear();
                                     MostraInfo(TARGET, 0, 0,"Temperatura Min");
                                     MostraInfo(TARGET, 1, 1,"do dia");
                                     lcd.setCursor(8,1);
                                     lcd.print(min_temp_dia);
                                     MostraInfo(TARGET, 13,1,"C");
                                    break;}
                             tempo = millis();


Code: [Select]
  Outro [tt]tempo = millis();[/tt]?


Pode não estar percéptivel aqui, mas esse "tempo=millis()", o que me esta a fazer, (acho e espero eu), é zerar-me o contador quando carrego na tecla "B", para começar a contar os 3 minutos para bloquear o sistema se nenhuma tecla for pressionada.


Em relação à questão:
Quote
Outra pergunta, (se calhar parva, mas um maçarico como eu deve poder fazer:) )
quando fazemos(...)

não faz sentido, uma vez que isso está a ser feito na parte:
Code: [Select]

                             switch (menuEcra)
                                {case 1:
                                     lcd.clear();
                                     MostraInfo(TARGET, 0, 0,"Temperatura Max");
                                     MostraInfo(TARGET, 1, 1,"do dia");
                                     lcd.setCursor(8,1);
                                     lcd.print(max_temp_dia);
                                     MostraInfo(TARGET, 13,1,"C");
                                   break;
                                  case 2:
                                     lcd.clear();
                                     MostraInfo(TARGET, 0, 0,"Temperatura Min");
                                     MostraInfo(TARGET, 1, 1,"do dia");
                                     lcd.setCursor(8,1);
                                     lcd.print(min_temp_dia);
                                     MostraInfo(TARGET, 13,1,"C");
                                    break;}
(...)


Ok, percebi, mas então onde está:
Code: [Select]
if (menuEcra > 3)

Deveria estar:
Code: [Select]
if (menuEcra >= 3)

certo?


Em relação à questão:
se não me engano, basta alterar, no início do código:
Code: [Select]
int menuEcra = 1;
(...)


para:
Code: [Select]
int menuEcra = 0;
(...)



Alterei e não resultou :~ :~

Não sei porquê mas estou com a ideia de que é na função millis() que a coisa não está a correr bem, só não sei é aonde  :0 :0 :0

Obg
NJPinheiro

luisilva

Quote
Ok, percebi, mas então onde está:
Code: [Select]
if (menuEcra > 3)


Deveria estar:
Code: [Select]

if (menuEcra >= 3)


certo?


Sim, isto é verdade. Eu devo ter visto 3 opções no case em vez de apenas duas, como está agora.

Estive a olhar para o código e está pelo menos outra coisa mal. O que se passa agora é que tem que se estar constantemente a carregar na tecla 'B' para que a informação esteja a passar, e penso que não é essa a ideia. Outra coisa é a confusão entre o "tempo" para que seja bloqueado o ecrã e o "tempo" para passar a informação. Podem ser o mesmo, mas penso que tem que ser pensado de outra forma, e não como aqui está. Por isso, penso que o melhor será separar isso criando duas variáveis diferentes, uma para cada situação.

Sendo assim, penso que o melhor é criar um novo estado para o caso de estar a "passar a informação" e entra-se nesse estado, quando se prime a tecla 'B'.

NJPinheiro



Estive a olhar para o código e está pelo menos outra coisa mal. O que se passa agora é que tem que se estar constantemente a carregar na tecla 'B' para que a informação esteja a passar, e penso que não é essa a ideia. Outra coisa é a confusão entre o "tempo" para que seja bloqueado o ecrã e o "tempo" para passar a informação. Podem ser o mesmo, mas penso que tem que ser pensado de outra forma, e não como aqui está. Por isso, penso que o melhor será separar isso criando duas variáveis diferentes, uma para cada situação.

Sendo assim, penso que o melhor é criar um novo estado para o caso de estar a "passar a informação" e entra-se nesse estado, quando se prime a tecla 'B'.


luisilva,
Antes de mais começo por dizer que sem a sua ajuda, ( e de outros membros do forum), não teria chegado aqui, e por isso estou grato.
A sua ajuda tem-se revelado adequada, porque não me dá o peixe, mas tem-me dado a cana, e depois como eu tenho de "correr atrás do prejuízo" a cada post vou sempre aprendendo qualquer coisa.

Dito isto, tenho-lhe de pedir se "troca por miúdos"  o que apresento citado neste post, porque tenho mesmo tentado "dissecar" a informação que me está a dar, mas sem sorte :smiley-fat:

Obg
NJPinheiro

luisilva

#10
Sep 02, 2014, 10:17 pm Last Edit: Sep 02, 2014, 11:37 pm by luisilva Reason: 1
Sendo assim, trocando por miúdos, o código, é o que está no anexo.

Criei 2 novas variáveis, uma para o estado de passagem de informação e outra para o tempo para alteração dessa informação. No final do código, foi acrescentado este novo estado:
Code: [Select]
 else if (estado==true && Key==NO_KEY && passaInfo == true) {
É necessário para mostrar a informação, que o teclado esteja desbloqueado (estado==true) que não tenha sido premida nenhuma tecla e que esteja neste estado de passar informação. A entrada neste estado é feita quando é premida a tecla 'B':
Code: [Select]

         digitalWrite(buzzer, LOW);
         delay(100);
         digitalWrite(buzzer, HIGH);

         passaInfo = true;
         tempo = millis();

Toca o buzzer, é activado este estado e é "anotado" o tempo em que foi premida a tecla, para que o teclado possa bloquear novamente.

Quando é premida qualquer tecla, sai-se do estado de "passa Informação", mesmo que essa tecla seja a tecla 'B':
Code: [Select]

 else if (estado == true && Key != NO_KEY)
 {  passaInfo = false;


Uma última nota. Não gosto desta linha:
Code: [Select]
 if ((keypad.getKey() == NO_KEY)  && millis() - tempo > 180000)
Porque é que nos outros locais do programa é utilizada a tecla que é lida no início da função loop() e aqui é feito novamente uma leitura? Esta linha deveria ser:
Code: [Select]
 if ((Key == NO_KEY)  && millis() - tempo > 180000)

para ser coerente com aquilo que é feito, por exemplo aqui:
Code: [Select]
 else if (estado == true && Key != NO_KEY)
também só faz sentido fazer isto, se estado == true (porque basicamente é aquilo que está a ser feito aqui):
Code: [Select]
   estado = false;
sendo assim, deveria ficar:
Code: [Select]
 if (Key == NO_KEY  && estado==true && millis() - tempo > 180000)
certo?

Não testei, porque não devo ter as bibliotecas todas instaladas e não tenho o hardware todo para poder testar no Arduino, mas a menos que tenha cometido um erro por distracção, deve funcionar.

EDIT: Exactamente após clicar no botão "post", lembrei-me que o código devia ficar melhor fazendo uma pequena alteração:
Code: [Select]

       case 'B' :
         digitalWrite(buzzer, LOW);
         delay(100);
         digitalWrite(buzzer, HIGH);

         passaInfo = true;
         tempoInfo = millis();
         tempo = millis();
         break;


NJPinheiro

luisilva,
A ideia que fico ao ler o seu post é que "pegou" no meu código e alterou com as sugestões que me dá, no ficheiro que anexou não deve ter ficado gravado, está igual ao meu.



Sendo assim, trocando por miúdos, o código, é o que está no anexo.

Criei 2 novas variáveis, uma para o estado de passagem de informação e outra para o tempo para alteração dessa informação. No final do código, foi acrescentado este novo estado:
Code: [Select]
 else if (estado==true && Key==NO_KEY && passaInfo == true) {
É necessário para mostrar a informação, que o teclado esteja desbloqueado (estado==true) que não tenha sido premida nenhuma tecla e que esteja neste estado de passar informação. A entrada neste estado é feita quando é premida a tecla 'B':
Code: [Select]

         digitalWrite(buzzer, LOW);
         delay(100);
         digitalWrite(buzzer, HIGH);

         passaInfo = true;
         tempo = millis();

Toca o buzzer, é activado este estado e é "anotado" o tempo em que foi premida a tecla, para que o teclado possa bloquear novamente.

Quando é premida qualquer tecla, sai-se do estado de "passa Informação", mesmo que essa tecla seja a tecla 'B':
Code: [Select]

 else if (estado == true && Key != NO_KEY)
 {  passaInfo = false;





Estou tentar por em pratica o que me está a sugerir, mas logo no principio fico perdido :~

Quando diz:

No final do código, foi acrescentado este novo estado:
Code: [Select]
 else if (estado==true && Key==NO_KEY && passaInfo == true) {

está a referir-se  a esta linha?
Code: [Select]
else if (estado == true && Key != NO_KEY)

É que se sim, eu tenho Key!= .....   e o sr tem Key==....

Estou mesmo todo baralhado :~ :~

HELP !!

luisilva

Realmente, anexei o ficheiro em que trabalhei no Arduino IDE, mas como o IDE não vai gravando o ficheiro anexei o ficheiro original. Já corrigi o ficheiro no post antigo, veja se funciona.

NJPinheiro


Realmente, anexei o ficheiro em que trabalhei no Arduino IDE, mas como o IDE não vai gravando o ficheiro anexei o ficheiro original. Já corrigi o ficheiro no post antigo, veja se funciona.


Perfeito :) :)

ou quase, a única questão é que carregando na tecla "B" ele faz o que se pretende, mas aparece como que a imagem a "tremer".

Agora tenho que "dissecar" as alterações que fez para que eu possa perceber o que está a ser feito, para avançar mais uma etapa.

Obrigado luisilva pelo se contributo, e é provável que o volte a "chatear", (a si e ao resto do pll do forum), mas já tenho "matéria" para me entreter até amanhã....ou depois de amanhã...ou até mais, pois para um maçarico isto não é facil =(

Obg
NJPinheiro

luisilva


(..)
a única questão é que carregando na tecla "B" ele faz o que se pretende, mas aparece como que a imagem a "tremer".
(...)


Isso pode ser facilmente contornado, fazendo uma alteração simples:

Code: [Select]

 else if (estado == true && Key == NO_KEY && passaInfo == true) {
   if (millis() - tempoInfo > 2000) {
     menuEcra++;
     if (menuEcra >= 3) {
       menuEcra = 1;
     }
     
     tempoInfo = millis();
     
     switch (menuEcra) {
       case 1:
         lcd.clear();
         MostraInfo(TARGET, 0, 0, "Temperatura Max");
         MostraInfo(TARGET, 1, 1, "do dia");
         lcd.setCursor(8, 1);
         lcd.print(max_temp_dia);
         MostraInfo(TARGET, 13, 1, "C");
         break;
       case 2:
         lcd.clear();
         MostraInfo(TARGET, 0, 0, "Temperatura Min");
         MostraInfo(TARGET, 1, 1, "do dia");
         lcd.setCursor(8, 1);
         lcd.print(min_temp_dia);
         MostraInfo(TARGET, 13, 1, "C");
         break;
     }
   }
 }


Veja se entende a alteração e as implicações.

Go Up