Ir al contenido principal

CONTROL CON ARDUINO LECCION III. CREAR MENÚ


ALGORITMO PARA CREACIÓN DE MENÚ


Hola a todos, en esta ocasión les traigo un algoritmo para crear un menú interactivo en el LCD, básicamente es la continuación de la lección II, ya que utilizamos el mismo material,  con la diferencia de que esta vez, ya se tiene un menú en forma.


Material:
1 encoder
1 LCD con interfaz I2C
1 Placa arduino 1
10 cables dupont

Conexiones:
Encoder  -  Arduino
GND ------- GND
   + ---------- Vcc (5V)
SW ---------  4
DT ---------- 3
CLK -------- 2

LCD  -  Arduino
GND -------- GND
  Vcc -------- Vcc (5V)
 SDA -------  A4
 SCL -------  A5


Circuito



Algoritmo


#include <Timer.h>  
#include <LiquidCrystal_I2C.h>
Timer t;  //Declaramos un timer, para dar base de tiempo

//Definición de pines de entrada
#define encoder0PinA  2
#define encoder0PinB  3
#define encoder0Pulse 4

//Variables utilizadas tanto en la ISR, como en el void loop
volatile unsigned int encoder0Pos = 6;
volatile char indicadorDegiro;
volatile boolean flagLCD=0;  //Bandera indicadora de interrupción

boolean flagPulse=0; //Bandera indicadora de pulsador presionado
String mensaje1,mensaje2; //Variables para almacenar mensajes que se desplegará en LCD
int conteoInt=0; //Variable para conteo de interrupciones, es necesario puesto que se interrumpe en dos ocasiones, ya que existen 2 flancos de bajada por por giro
boolean renglonLCD=0; //indica el renglon actual
unsigned int indexLCD=6; //Apuntador de LCD; indica el "item" actual

LiquidCrystal_I2C lcd(0x27, 16, 2);  // Configura LCD

void setup() { 

   lcd.begin(); 
   pinMode(encoder0PinA, INPUT_PULLUP); //Habilita pull ups, para contrar siempre con un voltaje de referencia
  pinMode(encoder0PinB, INPUT_PULLUP); 
  pinMode(encoder0Pulse,INPUT_PULLUP); 

  //Inicializar menú
  mensaje1="Item1";
  mensaje2="Item2";
  lcd.setCursor(0,0); 
  lcd.print(">");
  lcd.print(mensaje1);
  lcd.setCursor(1,1);  
  lcd.print(mensaje2);

  attachInterrupt(0, task1,FALLING);  // Habilita interrupción en pin 2, por flanco descendente
  attachInterrupt(1, task1,FALLING);  // Habilita interrupción en pin 3, por flanco descendente





void loop(){

  t.update();
  
if (flagLCD==1 && conteoInt==0){
  flagLCD=0;
  conteoInt++; //Incrementa contador de interrupciones. 
  t.after(170,esperaCambio); //Da tiempo para que se estabilice el encoder, antes de habilitar nuevamente las interrupciones
}
  

 else if (flagLCD==1 && conteoInt>0){
    flagLCD=0;
    lcd.clear();
    imprimeLCD();   
    conteoInt=0; //Limpia contador de interrupciones
    t.after(170,esperaCambio); //Da tiempo para que se estabilice el encoder, antes de habilitar nuevamente las interrupciones
                       }


if (digitalRead(encoder0Pulse)==0 && flagPulse==0){ //Si pulso botón y flag=0 entonces
      t.after(250,verificaPulso); //Llama a rutina verificaPulso despues de 150 ms, para evitar rebote
      flagPulse=1;
       }


}





void task1() {
      // Deshabilitar ambas interrupciones para evitar falsas lecturas en el LCD
    detachInterrupt(0);
    detachInterrupt(1);
  
    if (digitalRead(encoder0PinA)==0 && digitalRead(encoder0PinB)==1) {
              if (encoder0Pos<6){
              encoder0Pos++;
                                }
                           
              indicadorDegiro='+';
              
                            } 
               
    if (digitalRead(encoder0PinA)==1 && digitalRead(encoder0PinB)==0) {
      if (encoder0Pos>0){
    encoder0Pos--;
                        }
      
    
     indicadorDegiro='-';
          }
             
    indexLCD=encoder0Pos; //Instrucción necesaria, porque el compilador no permite leer la variable volatile dentro del switch case
    flagLCD=1;
              }




void esperaCambio(){
attachInterrupt(0, task1,FALLING);  // Habilita interrupción en pin 2, por cambio de nivel
attachInterrupt(1, task1,FALLING);  // Habilita interrupción en pin 2, por cambio de nivel  

}




void verificaPulso(){
 static boolean conmutador1=0, conmutador2=0; //Variable para conmutar brillo del LCD
  

  if (renglonLCD==0){ //Si el índice es par, significa que estoy en el renglon 0
    if (conmutador1==0){
      lcd.setCursor(8,0);
      lcd.print("OK");
    }

    else{
      lcd.setCursor(8,0);
      lcd.print("  ");
    }

      conmutador1=!conmutador1;// Cambia de estado (conmuta)
        
  }




if (renglonLCD==1){ //Si el índice es par, significa que estoy en el renglon 0
    if (conmutador2==0){
      lcd.setCursor(8,1);
      lcd.print("OK");
    }

    else{
      lcd.setCursor(8,1);
      lcd.print("  ");
    }

      conmutador2=!conmutador2;// Cambia de estado (conmuta)
        
  }

     flagPulse=0;
}


void imprimeLCD(){

if (indicadorDegiro=='+' && renglonLCD==0 && indexLCD<6){ //Si está en item1 y mueve hacia "-"
    lcd.setCursor(0,1); //Celda y línea
     renglonLCD=1;
       } 
                  



 else if (indicadorDegiro=='+' && renglonLCD==1 && indexLCD<=6){
    lcd.setCursor(0,0); //Celda y línea
    renglonLCD=0; 
   
}

                   
 else if (indicadorDegiro=='-' && renglonLCD==0 && indexLCD>0){
    lcd.setCursor(0,1); //Celda y línea
    renglonLCD=1;
            } 
                  

 else if (indicadorDegiro=='-' && renglonLCD==1 && indexLCD>=0){
    lcd.setCursor(0,0); //Celda y línea
    renglonLCD=0; 
 }


if (indexLCD==5 || indexLCD==6){
  mensaje1="Item1";
  mensaje2="Item2";
}


if (indexLCD==3 || indexLCD==4){
  mensaje1="Item3";
  mensaje2="Item4";
}

if (indexLCD==1 || indexLCD==2){
  mensaje1="Item5";
  mensaje2="Item6";
}

if (indexLCD==0){
  mensaje1="Item7";
  mensaje2="";
}




lcd.print(">");
lcd.setCursor(1,0); 
lcd.print(mensaje1);
lcd.setCursor(1,1); 
lcd.print(mensaje2);
}




Análisis de algoritmo





Dudas o sugerencias:

talleresarduino@gmail.com
facebook.com/ConsultorMic

Ing. Francisco Galindo.



Comentarios