En este artículo vamos a analizar y aprender a utilizar un shield que nos provee de un display LCD y cinco teclas de uso múltiple, sumamente útil para nuestros proyectos con Arduino
Es muy común que en nuestros proyectos con Arduino debamos tener alguna comunicación con un usuario humano a través de algún tipo de interfaz para interactuar mostrando y recibiendo información del mismo. Como dispositivo de salida de información podemos usar desde un simple led que nos avisa que se puso en marcha un motor o que se produjo una condición de error, hasta sofisticados displays gráficos que pueden mostrar la evolución de una medición a través de una curva. Lo mismo sucede con los dispositivos de entrada, que permiten recabar información del usuario a través de pulsadores, teclados de distintos tipos o pantallas sensibles al tacto.
Fig. 1. Distintos dispositivos para visualizar información: 1) Leds, 2) Displays de 7 segmentos, 3) Matriz de leds, 4) LCD alfanumérico, 5) LCD gráfico
Si nuestras necesidades no son muy exigentes y queremos mostrar mas información de la que nos permiten unos cuantos leds, los display LCD alfanuméricos son una excelente opción debido a su bajo costo y facilidad de uso. Además, existe una gran variedad, de distintos tamaños, cantidad de caracteres y colores, están muy bien documentados, son fáciles de conectar y de programar.
Aunque no es difícil conectar directamente un LCD de este tipo a un Arduino, en este artículo describiré solamente como usar un Shield en particular que resuelve estos detalles, además de proveernos de teclas que podemos aprovechar para el ingreso de información por parte del usuario. Este shield, conocido como LCD Keypad Shield es fabricado por la empresa DFRobot, aunque parecen existir distintos clones muy similares. Quienes deseen aprender a conectar el LCD en forma directa, pueden consultar este otro artículo.
Descripción
El shield consiste de un LCD alfanumérico de 2 filas de 16 caracteres cada una, de color azul con un backlight (luz trasera) a led de color blanco [1]. El contraste del LCD se puede controlar manualmente a través de un trimpot accesible desde el frente de la placa. Además, cuenta con cinco teclas del tipo “touch switch” de uso múltiple [3] y una tecla de reset [4]. El Shield se conecta a la placa Arduino a través de dos tiras de pines macho [5] y cuenta con conexiones en la parte superior para dar accesibilidad al resto de las señales no utilizadas por el shield [6] y un conector de programación (ICSP) [7].
Esquemático
El esquemático del shield, provisto por el fabricante, se puede ver en la siguiente imagen (click aquí para ver en tamaño completo). Como se puede apreciar, el LCD usa 4 pines de datos (D4, D5, D6 y D7) y dos de control (D8 y D9). Las teclas se conectan a la entrada analógica AD0 y están dispuestas de una manera bastante poco convencional, formando parte de un divisor resistivo que cambia el valor de tensión según la tecla que se pulse, con lo que se ahorran cuatro entradas. El transistor Q1 tiene por objeto permitir el encendido y el apagado del backlight a través del pin D10, pero hay un error en el shield ya que se omitió conectar una resistencia serie entre este pin y la base del transistor, por lo que se puede producir un daño en el pin si se lo programa como salida y se lo lleva a nivel alto, ya que circulará una corriente excesiva. Lo mejor es dejar D10 como entrada, lo que deja permanentemente prendido el baklight.
Programación
Aunque pueden encontrarse varias librerías para este shield y sus versiones posteriores, luego de varias pruebas y algunos fracasos he llegado a la conclusión de que la solución mas simple y sencilla es emplear una función que lea las teclas accediendo directamente a la entrada analógica. A continuación pueden ver un código de ejemplo que va mostrando las teclas que se pulsan, derivado de otro ejemplo que se encuentra en la wiki del fabricante.
Este código emplea la librería LiquidCrystal que está incluida en el IDE de Arduino y que contiene todas las funciones necesarias para controlar el LCD y una función denominada “read_LCD_buttons” que lee las teclas de un modo rudimentario.
#include <LiquidCrystal.h> //Funciones del LCD
//Indica a la librería los pines de conexión del shield
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
//Variables para leer las teclas y el ADC
int lcd_key = 0;
int adc_key_in = 0;
//Contantes para identificar las teclas
#define btnDERECHA 0
#define btnARRIBA 1
#define btnABAJO 2
#define btnIZQUIERDA 3
#define btnSELECT 4
#define btnNADA 5
//Función que lee las teclas
int read_LCD_buttons()
{
adc_key_in = analogRead(0); // Leer la entrada analógica
//Las teclas se conectan a un divisor resistivo que produce distintos valores de tensión
//según la tecla pulsada
if (adc_key_in > 1000) return btnNADA; //Si no hay ninguna tecla pulsada, sale para demorar menos tiempo
if (adc_key_in < 50) return btnDERECHA;
if (adc_key_in < 195) return btnARRIBA;
if (adc_key_in < 380) return btnABAJO;
if (adc_key_in < 555) return btnIZQUIERDA;
if (adc_key_in < 790) return btnSELECT;
return btnNADA; // No debería llegar aquí, pero por las dudas retorna este valor.
}
void setup() {
// Inicializaciones
lcd.begin(16, 2); //LCD de 16 columnas y 2 filas
lcd.clear(); //Borrar la pantalla
lcd.setCursor(0, 0); //Llevar el cursor al inicio
lcd.print("Prueba de teclas:");
}
void loop() {
// Bucle principal del programa
lcd.setCursor(0,1); // Lleva el cursor al inicio de la segunda linea
lcd_key = read_LCD_buttons(); // Lee las teclas
switch (lcd_key) // Imprime un texto según el valor de la tecla detectada
{
case btnDERECHA:
{
lcd.print("DERECHA ");
break;
}
case btnIZQUIERDA:
{
lcd.print("IZQUIERDA");
break;
}
case btnARRIBA:
{
lcd.print("ARRIBA ");
break;
}
case btnABAJO:
{
lcd.print("ABAJO ");
break;
}
case btnSELECT:
{
lcd.print("SELECT ");
break;
}
case btnNADA:
{
lcd.print("NINGUNA ");
break;
}
}
}
Mas información
Página del fabricante del shield
Funciones de la librería Liquid Crystal. Referencia en inglés y en español
Hoja de datos del HD44780, controlador del LCD alfanumérico
Cualquier boton que apriete me sale NINGUNA
hola buenas tardes,quisiera saber si con este circuito o placa conectada a arduino uno, puedo mover dos motores pap,uno de izquierda a derecha y otro arriba-a bajo
usando los botones que tiene.
Gracias
Hola Sebastian, tengo la misma duda tuya, pudiste encontrar información al respecto?
Álvaro y Sebastián, está placa no tiene la circuitería para controlar un motor pap, pero si servirian las teclas para moverlo
gracias me sirvió mucho
Hola:
Eso hice y me sale en el Monitor Serie cada vez que pulso un botón muchos botones como repetido, es decir, pulso el pulsador ARRIBA y me sale mucho esto.
Ver imagen:
https://forum.arduino.cc/index.php?action=dlattach;topic=697589.0;attach=375117
Código:
#include
// Seleccionado los pines del LCD.
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
// Definir algunos valores utilizados por el LCD y los botones.
int lcd_key = 0;
int adc_key_in = 0;
#define botonDERECHO 0
#define botonARRIBA 1
#define botonABAJO 2
#define botonIZQUIERDA 3
#define botonSELECT 4
#define botonNADA 5
int pinLed10 = 10; // Luz de fondo.
int pinLed13 = 13; // Declaramos la variable pin del Led.
char caracter;
String comando;
// Leeer todos los botones.
int read_LCD_buttons()
{
adc_key_in = analogRead(A0); //Leer el valor desde el sensor.
// Los botones cuando se leen están centrados en estos valores: 0, 144, 329, 504, 741.
// Agregamos aproximadamente 50 a esos valores y verificamos si estamos cerca.
// Hacemos de esta la primera opción por razones de velocidad,
// ya que será el resultado más probable.
if (adc_key_in > 1000) return botonNADA;
// Para V1.1 nosotros este umbral.
/*
if (adc_key_in < 50) return botonDERECHO; if (adc_key_in < 250) return botonARRIBA; if (adc_key_in < 450) return botonABAJO; if (adc_key_in < 650) return botonIZQUIERDA; if (adc_key_in < 850) return botonSELECT; */ // Para V1.0, comente el otro umbral y use el siguiente: if (adc_key_in < 50) return botonDERECHO; if (adc_key_in < 195) return botonARRIBA; if (adc_key_in < 380) return botonABAJO; if (adc_key_in < 555) return botonIZQUIERDA; if (adc_key_in 0) { caracter = Serial.read(); comando.concat(caracter); delay(10); } /* Unavez ya tengo la cadena “acabada”, compruebo su valor y hago que la placa Arduino reaccione según sea este. Aquí podríamos hacer lo que quiesiéramos: si el comando es “tal”, enciende un Led, si es cual, mueve un motor… y así. */ if (comando.equals(“Led_13_ON”) == true) // Led_ON. { digitalWrite(pinLed13, HIGH); // Enciende el Led. lcd.setCursor(0, 1); lcd.print(“Led 13: ON “); Serial.println(“Led 13 encendido.”); } if (comando.equals(“Led_13_OFF”) == true) // Led_OFF. { digitalWrite(pinLed13, LOW); // Apaga el Led. lcd.setCursor(0, 1); lcd.print(“Led 13: OFF”); Serial.println(“Led 13 apagado.”); } if (comando.equals(“Led_10_ON”) == true) // Led_ON. { digitalWrite(pinLed10, HIGH); // Enciende el Led. lcd.setCursor(14, 1); lcd.print(“F1”); Serial.println(“Led 10 encendido.”); } if (comando.equals(“Led_10_OFF”) == true) // Led_OFF. { digitalWrite(pinLed10, LOW); // Apaga el Led. lcd.setCursor(14, 1); lcd.print(“F0”); Serial.println(“Led 10 apagado.”); } // Limpiamos la cadena para volver a recibir el siguiente comando. comando = “”; // Dependiendo de qué botón se presionó, realizamos una acción. switch (lcd_key) { case botonDERECHO: { lcd.print(“Derecha “); Serial.write(“Derecha.”); break; } case botonIZQUIERDA: { lcd.print(“Izquierda”); Serial.write(“Izquierda.”); break; } case botonARRIBA: { lcd.print(“Arriba “); Serial.write(“Arriba.”); break; } case botonABAJO: { lcd.print(“Abajo “); Serial.write(“Abajo.”); break; } case botonSELECT: { lcd.print(“SELECT “); Serial.write(“SELECT”); break; } case botonNADA: { //lcd.print(“Nada “); break; } } } Saludos.