ESP32 et écran LCD
Un écran LCD avec un backpack I2C est très simple à utiliser avec un ESP32 sous micropython. On peut y afficher du texte et aussi quelques logos personnalisés en définition 5x8 pixels. Dans ce tuto j’utilise un LCD (avec backpack I2C) de 2 lignes de 16 caractères, et le microcontrôleur made in France PYBSTICK ESP32-C3. En fonction du microcontrôleur que vous utilisez, seul le schéma électronique doit être adapté.
Circuit électronique
Très simple: il faut relier VCC au +5V, GND à la masse, et SDA et SCL aux entrées soft I2C SDA et SCL de votre ESP32.
Code micropython
Bibliothèques
Pour pouvoir gérer l’écran LCD via I2C, il faut tout d’abord installer ces deux bibliothèques sur votre ESP32: copiez/collez le code micropython de ces 2 programmes, et nommez les exactement comme sur cette source Github:
Afficher un logo
Nous pouvons définir 8 petits logos personnalisés 5x8 pixels à l’aide d’un tableau de 8 codes hexadécimaux (8 lignes) qui codent les 5 pixels de chaque ligne. Il y a cet outil en ligne LCD Character Creator très pratique pour dessiner à l’écran votre logo et récupérer les codes hexadécimaux correspondants. Utilisez bien Data Type = Hex (et non pas Binary) pour récupérer les codes Hexa.
Si vous créez ce logo de robot, vous devriez obtenir cette liste de 8 codes hexa: 0x0E, 0x1F, 0x15, x1F, 0x1F, 0x11, 0x1F, 0x0E
code micropython
Le code ci-dessous défini une classe LCD dans laquelle des logos perso sont définis dans un dictionnaire de logos dic_char. C’est ici que l’on recopie les codes hexadécimaux récupérés depuis l’outil LCD Character Creator.
- dic_char: dictionnaire des logo {‘nom du logo’: ( id_logo de 0 à 7 , [liste des codes hexadécimaux] ) }
- get_char(self, name:str) ->chr: retourne un logo à partir de son nom.
- scroll(self, s:str, lig:int, col:int): scroll un texte de droite à gauche jusqu’en position (lig, col).
- get_i2c(self, sda_pin:int, scl_pin:int) ->SoftI2C : retourne l’adresse I2C du LCD branché sur les pin sda_pin et scl-pin. En cas de mauvais branchement, des messages d’erreur sont affichés dans la console si vous exécutez ce programme depuis un ordi.
from machine import Pin, SoftI2C
from lcd_api import LcdApi
from i2c_lcd import I2cLcd
from time import sleep
from sys import exit
I2C_ADDR = 0x27
SDA_PIN = 0
SCL_PIN = 1
TOTAL_ROWS = 2
TOTAL_COLUMNS = 16
class LCD(I2cLcd):
def __init__(self, sda_pin:int=SDA_PIN, scl_pin:int=SCL_PIN):
""" constructor """
self.i2c = self.get_i2c(sda_pin, scl_pin)
if self.i2c is not None:
I2cLcd.__init__(self, self.i2c, I2C_ADDR, TOTAL_ROWS, TOTAL_COLUMNS)
self.clear()
# generator custom character: https://maxpromer.github.io/LCD-Character-Creator/
self.dic_char={'wifi' : (0, bytearray([0x0E, 0x11, 0x00, 0x1F, 0x00, 0x0E, 0x00, 0x04]) ),
'thermometre': (1, bytearray([0x04, 0x0B, 0x0A, 0x0B, 0x0A, 0x17, 0x1F, 0x0E]) ),
'soleil' : (2, bytearray([0x00, 0x15, 0x0E, 0x11, 0x11, 0x11, 0x0E, 0x15]) ),
'pluie' : (3, bytearray([0x15, 0x00, 0x0E, 0x1F, 0x04, 0x04, 0x14, 0x08]) ),
'nuages' : (4, bytearray([0x03, 0x0F, 0x1E, 0x1E, 0x0C, 0x00, 0x00, 0x00]) ),
'neige' : (5, bytearray([0x10, 0x05, 0x02, 0x05, 0x00, 0x14, 0x08, 0x14]) ),
'brouillard' : (6, bytearray([0x0E, 0x1F, 0x0A, 0x15, 0x0A, 0x15, 0x0A, 0x15]) ),
'papsdroid' : (7, bytearray([0x0E, 0x1F, 0x15, 0x1F, 0x1F, 0x11, 0x1F, 0x0E]) ),
}
for __cle, val in self.dic_char.items():
self.custom_char(val[0], val[1])
else:
print('Revoir branchements écran LCD')
exit(1)
def get_char(self, name:str) ->chr :
''' return chr of named special char '''
try:
c = chr(self.dic_char[name][0])
except:
c = chr(0)
return c
def scroll(self, s:str, lig:int, col:int):
""" scroll string s rigth to left at (lig, col) """
padding = ' ' * (16-col)
padded_s = padding + s
for i in range(len(padded_s)):
lcd_text = padded_s[i:(i+16-col)]
self.move_to(col,lig)
self.putstr(lcd_text)
sleep(0.3)
self.move_to(col,lig)
self.putstr(padding)
def get_i2c(self, sda_pin:int, scl_pin:int) ->SoftI2C :
''' get i2c '''
i2c = SoftI2C(scl=Pin(scl_pin), sda=Pin(sda_pin), freq=400000)
devices =i2c.scan()
if len(devices) == 0:
print("No i2c device !")
return None
else:
print('i2c devices found:',len(devices))
for device in devices:
print("At address: ",hex(device))
return i2c
if __name__ == '__main__':
print('test lcd')
screen=LCD()
screen.putstr(screen.get_char('papsdroid') + " papsdroid " + screen.get_char('papsdroid'))
screen.move_to(0,1) #second line
#print symbols
screen.putstr(' '+screen.get_char('wifi'))
screen.putstr(' '+screen.get_char('thermometre'))
screen.putstr(' '+screen.get_char('soleil'))
screen.putstr(' '+screen.get_char('nuages'))
screen.putstr(' '+screen.get_char('pluie'))
screen.putstr(' '+screen.get_char('neige'))
screen.putstr(' '+screen.get_char('brouillard'))
sleep(1)
screen.scroll('https://papsdroidfr.github.io/', lig=0, col=2)
screen.move_to(0,0)
screen.putstr(screen.get_char('papsdroid') + " papsdroid " + screen.get_char('papsdroid'))