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.
Tags:
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;
}
}
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.
Bem-vindo a
Laboratorio de Garagem (arduino, eletrônica, robotica, hacking)
© 2024 Criado por Marcelo Rodrigues. Ativado por