Micropython: Usando el LCD y Keypad shield en la Wemos D1

La placa Wemos D1 tiene la interesante característica de soportar shields diseñados para el Arduino UNO. Sin embargo no todos los shields son compatibles de forma directa. En este artículo les mostraré como adaptar un LCD y Keypad shield y como programarlo en Micropython.

Las placas Wemos D1, en sus versiones R1 y R2, que analicé hace un tiempo en este blog tienen esta función sumamente útil de estar diseñadas en un formato compatible con el del Arduino UNO, por lo que pueden conectarse, al menos en teoría, con los Shields diseñados para él. En teoría digo porque debido a algunas diferencias en los pines disponibles y a las tensiones de funcionamiento (el Arduino funciona con 5 voltios y el ESP8266 de la placa Wemos lo hace a 3,3V) aparecen problemas de compatibilidad que hacen necesario analizar cuidadosamente el circuito del shield antes de conectarlo.

Como tenía algunas de estas placas disponibles, busqué entre los shields de Arduino alguno que pudiera ser de utilidad para algún proyecto interesante y me encontré con el LCD y Keypad shield, una placa sumamente útil que nos provee de un LCD de texto de 2 líneas y 16 columnas junto a 5 teclas de uso múltiple, que también analicé aquí hace un tiempo. Una búsqueda en Internet sobre experiencias con este shield me llevó hasta esta página donde el autor precisamente utiliza este shield con una placa Wemos D1.

El problema de compatibilidad de este shield es que la lectura de las teclas se hace empleando la entrada analógica A0 del Arduino, a través de una serie de resistencias que forman distintos divisores resistivos según la tecla que se pulse, introduciendo distintos valores de tensión a la entrada. El problema es que las resistencias se conectan a +5V y cuando ninguna tecla esta pulsada, ese valor de tensión ingresa a la entrada analógica. Esto no es un problema en el Arduino, pero si en el ESP8266, cuya entrada analógica soporta una tensión máxima de 3,3 Voltios.

Esto significa que si conectamos el shield de manera directa, aplicaremos 5V a la entrada analógica de la Wemos D1 corriendo el riesgo de dañar el ADC del ESP8266.

Fig. 1. Conexión de las teclas en el shield

La solución propuesta en la página es añadir una resistencia de 3K3 como se ve en la imagen a continuación, con lo que se forma otro divisor resistivo que disminuye el valor de tensión en la entrada por debajo de un valor riesgoso.

Fig. 2. Circuito modificado

Con esta nueva resistencia, la tensión máxima (cuando no se pulsan teclas) será de:

En la siguiente imagen pueden ver el shield con la modificación:

Fig. 3. Resistencia entre A0 y GND

Para conocer los valores de referencia correspondientes a cada tecla, escribimos en Thonny un sencillo programa que lee el ADC e imprime el valor leído mientras apretamos las distintas teclas

from machine import ADC, Pin
from time import sleep

#Programa GPIO15 (D10) como entrada
#para prender el backlight
pinBL = Pin (15, Pin.IN)

#Instancia objeto del conversor
conversor = ADC (0)

while (True):
     print (conversor.read ())
     sleep (1)

Los valores que yo relevé fueron los siguientes:

TeclaValor
Ninguna825 a 829
SELECT629 a 632
LEFT466 a 470
DOWN328 a 330
UP149 a 152
RIGHT8 a 10

Con estos datos podemos crear una función que lea el conversor y según el valor nos devuelva la tecla presionada:

from machine import ADC, Pin
from time import sleep

btnUP     = 1
btnDOWN   = 2
btnRIGHT  = 3
btnLEFT   = 4
btnSELECT = 5

#Programa GPIO15 (D10) como entrada
#para prender el backlight
pinBL = Pin (15, Pin.IN)

#Instancia objeto del conversor
conversor = ADC (0)

#Función leerTecla
#Lee un valor del ADC y lo asocia con un código de tecla
#Entra: Nada
#Sale: Código de tecla. Si no hay tecla pulsada devuelve 0
def leerTecla ():
     lecturaADC = conversor.read()
     if (lecturaADC < 20):  return btnRIGHT
     if (lecturaADC < 160): return btnUP
     if (lecturaADC < 350): return btnDOWN
     if (lecturaADC < 490): return btnLEFT
     if (lecturaADC < 650): return btnSELECT
     return 0

while (True):
     print (leerTecla())
     sleep (1)

Con la lectura de las teclas resuelta, veamos que podemos hacer con el LCD.

En Arduino, una librería muy popular para este tipo de display es la llamada LiquidCrystal. Afortunadamente en Micropython también disponemos de varias librerías o módulos con la misma funcionalidad. Una de ellas ya la utilicé en un artículo anterior al conectar un LCD a través de I2C y también la podemos emplear en esta ocasión con nuestro shield.

Para utilizar la librería primero debemos descargarla de su repositorio haciendo click sobre el botón Code y Download ZIP.

Dentro del archivo ZIP descargado veremos varios archivos, ya que esta librería se puede usar en distintas placas y de distintas formas, con el LCD conectado a los pines GPIO (como en el shield) o a través de un adaptador I2C basado en el PCF8574. En esta ocasión nos interesan sólo dos de esos archivos:

nodemcu_gpio_lcd.py: Contiene todas las funciones de bajo nivel para acceder al LCD

lcd_api.py: Contiene las funciones de alto nivel del LCD

Debemos copiar ambos archivos al sistema de archivos de la placa para poder utilizarlos

Fig. 4. Módulos en el sistema de archivos de la placa

Para usar el LCD debemos importar la clase GpioLcd desde el módulo nodemcu_gpio_lcd

from nodemcu_gpio_lcd import GpioLcd

Y luego instanciar un objeto de esa clase. El formato del constructor es el siguiente:

objeto = GpioLcd (rs_pin=RS, enable_pin=E, d0pin=D0, d1pin=D1, d2pin=D2, d3pin=D3, d4pin=D4, d5pin=D5, d6pin=D6, d7pin=D7, rw_pin=RW, backlight_pin=BL, num_lines=lineas, num_columns=columnas)

En el shield se usa el display con sólo 4 bits, así que no es necesario especificar las conexiones de d0pin, d1pin, d2pin y d3pin.

El programa completo queda de la siguiente forma:

from machine import ADC, Pin
from time import sleep
from nodemcu_gpio_lcd import GpioLcd

btnUP     = 1
btnDOWN   = 2
btnRIGHT  = 3
btnLEFT   = 4
btnSELECT = 5

#Mapeo de la placa Wemos D1 R1
#Nombre Arduino - GPIO
D0 = 13
D1 = 1
D2 = 16
D3 = 5
D4 = 4
D5 = 14
D6 = 12
D7 = 13
D8 = 0
D9 = 2
D10 = 15
D11 = 13
D12 = 12
D13 = 14

#Programa GPIO15 (D10) como entrada
#para prender el backlight
pinBL = Pin (D10, Pin.IN)

#Instancia objeto del conversor
conversor = ADC (0)

#Función leerTecla
#Lee un valor del ADC y lo asocia con un código de tecla
#Entra: Nada
#Sale: Código de tecla. Si no hay tecla pulsada devuelve 0
def leerTecla ():
    lecturaADC = conversor.read()
    if (lecturaADC < 20):  return btnRIGHT
    if (lecturaADC < 160): return btnUP
    if (lecturaADC < 350): return btnDOWN
    if (lecturaADC < 490): return btnLEFT
    if (lecturaADC < 650): return btnSELECT
    return 0

#Instanciar objeto del LCD
lcd = GpioLcd(rs_pin=Pin(D8),
              enable_pin=Pin(D9),
              d4_pin=Pin(D4),
              d5_pin=Pin(D5),
              d6_pin=Pin(D6),
              d7_pin=Pin(D7),
              num_lines=2, 
              num_columns=16)

lcd.clear ()
lcd.putstr ("Tecla: ")

while (True):
    lcd.move_to (7,0)
    
    tecla = leerTecla ()

    if (tecla==btnUP): lcd.putstr ("UP    ")
    if (tecla==btnDOWN): lcd.putstr ("DOWN  ")
    if (tecla==btnLEFT): lcd.putstr ("LEFT  ")
    if (tecla==btnRIGHT): lcd.putstr ("RIGHT ")
    if (tecla==btnSELECT): lcd.putstr ("SELECT")

Aquí se puede ver el programa en funcionamiento:

Fig. 5. Programa de ejemplo

Conclusión

La placa Wemos D1 acepta el empleo de shields para Arduino UNO pero con algunas excepciones. En el caso del LCD y Keypad shield se lo puede utilizar siempre y cuando le hagamos una pequeña modificación para reducir el valor de tensión que ingresa a la entrada analógica. En este artículo vimos como realizar esa modificación y cómo escribir un programa en Micropython para utilizar todas las funciones del shield.

Como siempre, espero que la información les haya sido de utilidad. Cualquier duda o sugerencia pueden dejarla en la sección de comentarios mas abajo.

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

A %d blogueros les gusta esto: