Bom dia.

Estou fazendo um projeto com LCD 16x2 para monitorar tensão, corrente, temperatura, etc. Quanto as medições e mostrar no display está tudo certo, o que eu gostaria de fazer e não estou conseguindo se refere a programação. Eu queria usar um botão, e apenas um, para que quando for pressionado possa mudar o modo de exibição no display, como um Switch Case. Eu já fiz uma função para cada tipo de exibição que eu quero, só não sei (e pesquisei e não achei) como fazer para chamar essas funções usando apenas um botão (usando um botão para cada função eu sei como fazer, mas não é isso que eu quero).

ex:

Tensão xx,xx V

ao pressionar o botão mude para

Corrente xx,xx A

ao pressionar novamente o botão

Temp xx ºC

e novamente volte para a primeira exibição.

Resumindo, a cada aperto do botão o software chame uma função específica e no final volte para a primeira.

Agradeço qualquer ajuda.

Abs.

Exibições: 1411

Responder esta

Respostas a este tópico

Uma forma simples de fazer (ao meu ver). Seria cria uma variável de controle para guardar o índice do que está exibindo, testa se o botão foi pressionado, caso sim entra no switch para testar o índice pressionado, e chama a função equivalente. Fora do switch você incrementa o índice, e depois testa se ele é maior do que o último valor permitido, caso sim, reinicia o índice setando novamente para zero.

Um esboço sem testes seria algo parecido com:

unsigned char idx = 0;

int BOTAO = 10; // COLOCA AQUI O BOTÃO QUE ESTÁ TESTANDO

void loop(){

  if ( ! digitalRead(BOTAO) ){

     delay(100); // Evitar de ficar mudando muito rápido

     // caso queira aguardar que solte o botão poderia também colocar aqui (while ( ! digitalRead(BOTAO) ) delay(10);

    switch ( idx) {

       case 0: // mostra informação do indice zero

            chamaFuncaoExibeIdxZero();

            break;

       case 1: // mostra informação do indice um

             chamaFuncaoExibeIdxUm();

             break;

        ....

        case n: // mostra informação do indice N

             chamaFuncaoExibeIdxN();

              break;

   } 

    idx++; // Incrementa o indice

    if ( idx > n ) {// Testa se o valor é maior indice permitido (onde n esta representado isso)

       idx = 0;

    }

  }

}

Agora se precisa sempre trazer as informações atualizadas do sensor selecionado coloque o switch fora do if.

unsigned char idx = 0;

int BOTAO = 10; // COLOCA AQUI O BOTÃO QUE ESTÁ TESTANDO

void loop(){

  if ( ! digitalRead(BOTAO) ){

     delay(100); // Evitar de ficar mudando muito rápido

     // caso queira aguardar que solte o botão poderia também colocar aqui (while ( ! digitalRead(BOTAO) ) delay(10);    

    idx++; // Incrementa o indice

    if ( idx > n ) {// Testa se o valor é maior indice permitido (onde n esta representado isso)

       idx = 0;

    }

  }

  // Está fora do "if", sempre vai executar o switch   

   switch ( idx) {

       case 0: // mostra informação do indice zero

            chamaFuncaoExibeIdxZero();

            break;

       case 1: // mostra informação do indice um

             chamaFuncaoExibeIdxUm();

             break;

        ....

        case n: // mostra informação do indice N

             chamaFuncaoExibeIdxN();

              break;

   } 

}

Oi AFL, bom dia,

existem varias maneiras de fazer o que quer.

Vou citar uma.

Você cria uma variável e o apertar o botão incrementa o valor dela de 0 até 2, (usando por ex: um "for")

e verifique o valor dela para selecionar o que vai mostrar no display.

Rui

Muito obrigado Vitor e também ao Rui.

Vitor, seu código funcionou perfeitamente, só tive que mudar os nomes e algumas pequenas adaptações, mas fez exatamente o que eu queria.

Segue o meu código como está (ainda está em teste, falta fazer mais algumas coisas).

Segue também o arquivo do Protheus, se alguém se interessar em fazer. O esquema é de um monitor de tensão, corrente e temperatura para ser instalado numa fonte ajustável. Falta fazer a parte de controle do cooler de refrigeração de acordo com a temperatura.

//Carrega a biblioteca LiquidCrystal
#include <LiquidCrystal.h>

//Define os pinos que serão utilizados para ligação ao display
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

int botao = 8; //define o pino que o botao esta conectado
unsigned char idx = 0;

float tensaoA0;
float correnteA1;
float tempA2;

float aRef=5;
float relacaoA0=11.02;
float relacaoA1=10;
float relacaoA2=0.1;
#define AMOSTRAS 12

void setup() {

pinMode(botao, INPUT_PULLUP); // declara-se o interruptor como entrada

lcd.begin(16, 2);
lcd.setCursor(1,0);
lcd.print("Fonte 0 - 30 V");
lcd.setCursor(3,1);
lcd.print("2ma - 3 A");
delay(1000);

}

float lePorta(uint8_t portaAnalogica) {
float total=0;
for (int i=0; i<AMOSTRAS; i++) {
total += 1.0 * analogRead(portaAnalogica);
delay(5);
}
return total / (float)AMOSTRAS;
}

void mostrador1() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(tensaoA0 * relacaoA0);
lcd.print("V");

lcd.setCursor(1, 1);
lcd.print(correnteA1 * relacaoA1);
lcd.print("A");

lcd.setCursor(10, 0);
lcd.print((tensaoA0 * relacaoA0)*(correnteA1 * relacaoA1));
lcd.print("W");

lcd.setCursor(11, 1);
lcd.print(tempA2 * relacaoA2,0)/100 ;
lcd.print("C");

}

void mostrador2() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Tensao:");
lcd.setCursor(10, 0);
lcd.print(tensaoA0 * relacaoA0);
lcd.print("V");

lcd.setCursor(0, 1);
lcd.print("Corrente:");
lcd.setCursor(11, 1);
lcd.print(correnteA1 * relacaoA1);
lcd.print("A");
}

void mostrador3() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Potencia:");
lcd.setCursor(11, 0);
lcd.print((tensaoA0 * relacaoA0)*(correnteA1 * relacaoA1));
lcd.print("W");

lcd.setCursor(0, 1);
lcd.print("Temp:");
lcd.setCursor(12, 1);
lcd.print(tempA2 * relacaoA2,0)/100 ;
lcd.print("C");

}


void mostrador4() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Tempo de ");
lcd.setCursor(0, 1);
lcd.print("Operacao");
lcd.setCursor(10, 0);
lcd.print(millis()/60);
lcd.setCursor(15, 0);
lcd.print("s");


}

void loop() {

tensaoA0 = (lePorta(A0) * aRef) / 1024.0;
correnteA1 = (lePorta(A1) * aRef) / 1024.0;
tempA2 = (lePorta(A2) / 1024.0) * 5000;
// mostrador1();
// delay(500);

if ( ! digitalRead(botao) ){
delay(100); // Evitar de ficar mudando muito rápido
idx++; // Incrementa o indice
if ( idx > 4 ) {// Testa se o valor é maior indice permitido (onde n esta representado isso)
idx = 0;
// caso queira aguardar que solte o botão poderia também colocar aqui (while ( ! digitalRead(BOTAO) ) delay(10);

}
}

switch (idx) {
case 0: // mostra informação do indice zero
mostrador1();
break;
case 1: // mostra informação do indice um
mostrador2();
break;
case 2: // mostra informação do indice dois
mostrador3();
break;
case 3: // mostra informação do indice tres
mostrador4();
break;
}
}

Anexos

Pessoal, olá novamente.

A primeira parte do projeto deu certo, graças a ajuda que me deram. Agora estou aprimorando um pouco mais a visualização no display e quero fazer uma barra gráfica que aumente conforme o nível de tensão.

Eu consegui fazer usando if:

if(tensao <1.5){

lcd.print("________");

}

if(tensao >1.5){

lcd.print("||______");

}

if(tensao) > 3){

lcd.print("||||_____")

}

e assim até chegar nos 30V, com resolução de 1,5V.

Funcionou, mas acho que está muito "primitivo" e amador esse meu jeito, e seria melhor fazer isso de um jeito mais simples, sem tantos if´s no código, para poder usar uma resolução menor, como 0,5v por exemplo. Também estou tentando usar caracteres especiais na formação da barra, para usar o bloco inteiro de cada caracter e obter um resultado mais bonito e linear.

Você poderia usar a função map ( https://www.arduino.cc/en/Reference/Map) parra construir a sua barra.

Após obter o valor da função map, você poderia fazer um simples for e preencher a sua barra.

Ex:

   unsigned char i;

   for ( i = 0; i < result_map; i++){

      //Aqui você escreveria no LCD uma |

      lcd.print('|');

   }

Lembrando que teria o lcd antes e colocar o cursor na primeira coluna.

Obrigado mais uma vez Vitor.

Depois da sua sugestão, me veio uma ideia na cabeça, ainda não testei.

float barra;

barra = tensao / 1,5;   // define o tamanho da barra de acordo com a escala e tensão máxima

   for (i=0; i<barra; i++) {

        lcd.write(B11111111); // vou usar binario para preencher todo o bloco e não apenas uma barra fina

   }

É só um exemplo, tem que limpar o LCD, definir a posição do cursor.

Vou testar assim que der e volto com o resultado.

Obrigado.

Dando mais um feed back aqui, consegui fazer quase tudo funcionar a contento.

- Resolvi deixar as leitura com apenas uma casa decimal, pois ficava muito instável;

- Eliminei o trimpot que havia colocado na entrada analógica para realizar um calibração fina pois também causava instabilidades e o valor ficara oscilando. Deixei a calibração toda por software;

- Recebi um display 16x2, mas estou quase certo que o mesmo está com defeito (depois de uns 2 dias quebrando a cabeça). Ele buga toda a tela quando tento usar alguns caracteres, como a letra "o", a barra "/", e praticamente todos os caracteres especiais. Só está aceitando mostrar números e letras, menos a letra "o". Simulando o mesmo script no Protheus, funciona perfeitamente, mostrando todos os caracteres. Estou para receber outro display, de 20x4 e vou testar assim que chegar.

Segue o código:

//Carrega a biblioteca LiquidCrystal
#include <LiquidCrystal.h>

//Define os pinos que serão utilizados para ligação ao display
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

int botao = 8; //define o pino que o botao esta conectado
unsigned char idx = 0;

float tensaoA0;
float correnteA1;
float tempA2;
float potencia;
float temperatura;
float tensao;
float corrente;
float vbarra;
float abarra;
float tempo;

float aRef=5;
float relacaoA0=3.548;
float relacaoA1=0.6;
float relacaoA2=0.1;
#define AMOSTRAS 12


void setup() {

pinMode(9, OUTPUT); // pino para ligacao do cooler
digitalWrite(9, LOW);
pinMode(botao, INPUT_PULLUP); // declara o botao como entrada

lcd.begin(16, 2);
lcd.setCursor(1, 0);
lcd.print("Fnt Ajustavel");
lcd.setCursor(1, 1);
lcd.print("0-30V 2ma-3A");
delay(1000);

} // fecha void setup

float lePorta(uint8_t portaAnalogica) {
float total=0;
for (int i=0; i<AMOSTRAS; i++) {
total += 1.0 * analogRead(portaAnalogica);
delay(5);
}
return total / (float)AMOSTRAS;
}


void mostrador1() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(tensao,1);
lcd.print("V");

lcd.setCursor(0, 1);
lcd.print(corrente,1);
lcd.print("A");
if(corrente > 2.1) {
lcd.setCursor(5, 1);
lcd.print("HI");
}

lcd.setCursor(10, 0);
lcd.print(potencia,1);
lcd.print("W");

lcd.setCursor(11, 1);
lcd.print(temperatura,0) ;
lcd.print(" C");
}

void mostrador2() {
lcd.clear();
lcd.setCursor(0, 0);
unsigned char i;
for (i=0; i<vbarra; i++){ //cria a barra de tensao
lcd.print("-");
}

lcd.setCursor(0, 1);
lcd.print(tensao,1);
lcd.print("V");

lcd.setCursor(11, 1);
lcd.print(corrente,1);
lcd.print("A");
if(corrente > 2.1) {
lcd.setCursor(8, 1);
lcd.print("HI");
}

}

void loop() {

tensaoA0 = (lePorta(A0) * aRef) / 1024.0;
correnteA1 = (lePorta(A1) * aRef) / 1024.0;
tempA2 = (lePorta(A2) / 1024.0) * 5000;

tempo = (millis()/1000);
potencia = ((tensaoA0 * relacaoA0)*(correnteA1 * relacaoA1));
temperatura = (tempA2 * relacaoA2);
tensao = tensaoA0 * relacaoA0;
corrente = correnteA1 * relacaoA1;

vbarra = tensao / 1; // define a proporcao da barra em relacao a tensao
if(vbarra > 16){ // define o tamanho maximo da barra para nao extrapolar a linha
vbarra = 16;
}
abarra = corrente / 0.1875; // define a proporcao da barra em relacao a corrente
if(abarra > 16){ // define o tamanho maximo da barra para nao extrapolar a linha
abarra = 16;
}

// delay(500);

if ( ! digitalRead(botao) ){
delay(100); // Evitar de ficar mudando muito rápido
idx++; // Incrementa o indice
if ( idx > 2 ) { // Testa se o valor é maior indice permitido (onde n esta representado isso)
idx = 0;

// caso queira aguardar que solte o botão poderia também colocar aqui (while ( ! digitalRead(BOTAO) ) delay(10);
}
} // fecha if do botao
// switch case determinda os modos de exibicao do display
switch (idx) {
case 0: // mostra informação do indice zero
mostrador1();
break;
case 1: // mostra informação do indice um
mostrador2();
break;
} //fecha switch


if(temperatura > 60){ // ligar o pino 9 cooler quanda a temperatura exceder o valor determinado
digitalWrite(9, HIGH);
lcd.setCursor(9 ,1);
lcd.print("*");
}else{
digitalWrite(9, LOW);
}


} //fecha void loop

estava tentando fazer um voltimetro para minha fonte ajustavel com um display de 7SEG./3Dig. e a instabilidade reinava. percebi que a culpa era do display! ele faz ter uma queda de tenção na alimentação do arduino, assim sendo a referencia das entradas analogicas variam na casa dos milivolts, o suficiente para ficar instavel. não testei mas acredito que a solução seria pegar um regulador 78L05 (regulador 5V 150mA) e colocar uma fonte externa na sua entrada e sua saida ligada no AREF do arduino para desacoplar a referencia interna do circuito, assim resolvendo o problema de instabilidade na leitura das entradas analógicas! :)

 Wadeck Polli : Excelente dica. Fiz um teste aqui, e só de trocar a alimentação do arduino da porta USB por uma fonte externa já modificou as leituras. Agora já sei que só vou poder calibrar o circuito quando estiver montado na placa de CI final. Vou usar um 7805 para alimentar todo o circuito do voltimetro e ver como fica.

Aproveitando, alguém sabe como faço para exibir as variáveis no formato 00.00 ? Ele sempre corta o primeiro zero à esquerda, mas isso faz a informação se deslocar no display quando tem apenas 1 dígito, e não quero isso.

Consegui fazer o display mostrar no formato 00.00.

if(tensao < 10){

lcd.print("0");

}

Coloquei apenas esse if antes de mostrar a tensão lida.

Simples assim.

RSS

© 2024   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço