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.
Introducción
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.
Compatibilidad
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.
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.
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:
Ejemplo
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:
Tecla | Valor |
---|---|
Ninguna | 825 a 829 |
SELECT | 629 a 632 |
LEFT | 466 a 470 |
DOWN | 328 a 330 |
UP | 149 a 152 |
RIGHT | 8 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
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:
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.