Dispositivos I2C con ESP32 y MicroPython (código)

Anterior: Dispositivos I2C con ESP32 y MicroPython

Siguiente: Conectar ESP32 al WiFi con MicroPython

Vamos a aprovechar el montaje que ya tenemos hecho, con nuestro ESP32 conectado al display de 16×2, para en próximas entregas dar un pasito más y conectar el microcontrolador al WiFi de nuestra casa (o de nuestro teléfono, etc. Las posibilidades empiezan a ser muy amplias a partir de este momento).

Repaso del código anterior

Pero antes de meternos en harina, vamos a repasar el código de la entrega anterior, para entender mejor lo que estamos haciendo:

| boot.py
from machine import Pin, SoftI2C
from lcd_api import LcdApi
from pico_i2c_lcd import I2cLcd
from time import sleep
from random import randint
 
I2C_ADDR = 0x27
filas = 2
columnas = 16
i2c = SoftI2C(scl=Pin(22), sda=Pin(21), freq=10000)
lcd = I2cLcd(i2c, I2C_ADDR, filas, columnas)
 
while True:
    f = randint(0,1)
    c = randint(0,6)
    lcd.move_to(c,f)
    lcd.putstr('Hola Pep! ')
    sleep(1)
    lcd.clear()

Importación de librerías

Lo primero que vemos en este código es la llamada a las diferentes librerías que vamos a utilizar:

from machine import Pin, SoftI2C
from lcd_api import LcdApi
from pico_i2c_lcd import I2cLcd
from time import sleep
from random import randint

Aunque podemos importar una librería completa, simplemente escribiendo algo como:

import machine

Las limitaciones de memoria de los microcontroladores aconsejan importar sólo aquellos elementos de las librerías que vayamos a necesitar. En este caso, de la librería «machine» importamos las clases «Pin» y «SoftI2C»; de la librería «lcd_api» importamos la clase «LcdApi»; de la librería «pico_i2c» importamos la clase «I2cLcd»; de la librería «time» importamos la función «sleep», y de la librería «random» importamos la función «randint».

La estructura de archivos dentro del ESP32 debería ser la siguiente:

En el directorio raíz:

El el directorio «lib»:

Aunque no es imprescindible que las librerías «lcd_api.py» y «pico_i2c.py» estén en el directorio «lib», siempre es conveniente organizar las librerías por directorios para que cuando las cosas se compliquen (y con el tiempo se complicarán), conservemos todo lo posible la limpieza y la legibilidad de los programas que tengamos en el microcontrolador.

Declaración de variables y objetos

Y de momento, esto será todo en cuando a librerías e importaciones se refiere. Ahora pasemos a la sección de declaraciones:

I2C_ADDR = 0x27
filas = 2
columnas = 16
i2c = SoftI2C(scl=Pin(22), sda=Pin(21), freq=10000)
lcd = I2cLcd(i2c, I2C_ADDR, filas, columnas)

Cuando hicimos el montaje del ESP32 con display I2C, pasamos un programa escaneador de dispositivos I2C que nos dio una dirección 0x27 para el display, así que la variable «I2C_ADDR» tomará ese valor para pasarla posteriormente al constructor del objeto «lcd», entre otros parámetros, como el número de filas (2), el número de columnas (16) y el objeto i2C, que se declara en esta línea:

i2c = SoftI2C(scl=Pin(22), sda=Pin(21), freq=10000)

Aquí podemos ver una declaración un poquito «florida»: i2C será un objeto de la clase SoftI2C, para cuyo constructor se han declarado a su vez los objetos «sda» y «sdl» de la clase «Pin», con valores 21 y 22 respectivamente, y la frecuencia a la que debe funcionar el bus I2C. Esto también se podría haber declarado de la siguiente forma:

sda = Pin(21)
sdl = Pin(22)
freq = 10000
i2c = SoftI2C(scl, sda, freq)

Finalmente declaramos el objeto de la clase «I2CLcd» que contendrá todas las funciones y parámetros (métodos y atributos) que nos serán muy necesarios para controlar el display LCD:

lcd = I2cLcd(i2c, I2C_ADDR, filas, columnas)

Como ya comentamos antes, «I2C_ADDR», «filas» y «columnas» están declaradas unas líneas más arriba.

Sección de ejecución

Aquí es donde toda la magia que hemos estado preparando se pone en funcionamiento.

while True:
    f = randint(0,1)
    c = randint(0,6)
    lcd.move_to(c,f)
    lcd.putstr('Hola Pep! ')
    sleep(1)
    lcd.clear()

Empezamos con un bucle «while True:», que repetirá todo lo que se encuentre incluido dentro del mismo una y otra vez sin fin. El bucle «while» se repite mientras la condición siguiente sea True, por lo que la condición para salir del bucle nunca se producirá. Si por el contrario hubiéramos escrito:

while contador < 100:

El bucle se repetiría mientras la variable contador tuviera un valor menor que 100.

Posteriormente damos valores a las variables f y c con la función randint que hemos importado de la librería random, y que nos devolverá un valor entero aleatorio entre el primer y el segundo parámetro proporcionados. Por ejemplo:

f = randint(0,1)
c = randint(0,6)

Nos dará un valor aleatorio entre 0 y 1 para «f» y un valor entre 0 y 6 para «c». Esos valores nos van a servir para mover el cursor del display a la posición (c,f) con:

lcd.move_to(c,f)

A continuación vamos a escribir un texto en el display con la línea:

lcd.putstr('Hola Pep! ')

Esperamos durante un segundo gracias a la función «sleep» de la librería «time»:

sleep(1)

Y limpiamos el display, borrando cualquier cosa que haya escrita con:

lcd.clear()

Tras lo cual se repetirá el bucle, c y f tomarán nuevos valores (o los mismos, ¿quién sabe?), etc.

Anterior: Dispositivos I2C con ESP32 y MicroPython

Siguiente: Conectar ESP32 al WiFi con MicroPython