Abaixo você encontra o esquema elétrico, código-fonte e lista de materiais para a utilização de um display 16 x 2 com a sua Pi Pico.
Temos um vídeo com a explicação completa do funcionamento.
Acesse -> https://youtu.be/TgpKOB0a4T4
Material Usado
Raspberry Pi Pico (pode ser a versão 1 e 2)
4 jumpers
1 display LCD de 16 x 2 linhas
1 módulo I2C para displays
Código fonte
Código para escanear o endereçamento do módulo. Salvar como scan_i2c.py
import machine
sda = machine.Pin(0)
scl = machine.Pin(1)
i2c = machine.I2C(0,sda=sda,scl=scl, freq=400000)
print('I2C address:')
print(i2c.scan(),' (decimal)')
Código com as classes e funções para o acionamento do display LCD. Salvar como lcd_api.py
import time
class LcdApi:
# HD44780 LCD
LCD_CLR = 0x01 # DB0: clear display
LCD_HOME = 0x02 # DB1: return to home position
LCD_ENTRY_MODE = 0x04 # DB2: set entry mode
LCD_ENTRY_INC = 0x02 # DB1: increment
LCD_ENTRY_SHIFT = 0x01 # DB0: shift
LCD_ON_CTRL = 0x08 # DB3: turn lcd/cursor on
LCD_ON_DISPLAY = 0x04 # DB2: turn display on
LCD_ON_CURSOR = 0x02 # DB1: turn cursor on
LCD_ON_BLINK = 0x01 # DB0: blinking cursor
LCD_MOVE = 0x10 # DB4: move cursor/display
LCD_MOVE_DISP = 0x08 # DB3: move display (0-> move cursor)
LCD_MOVE_RIGHT = 0x04 # DB2: move right (0-> left)
LCD_FUNCTION = 0x20 # DB5: function set
LCD_FUNCTION_8BIT = 0x10 # DB4: set 8BIT mode (0->4BIT mode)
LCD_FUNCTION_2LINES = 0x08 # DB3: two lines (0->one line)
LCD_FUNCTION_10DOTS = 0x04 # DB2: 5x10 font (0->5x7 font)
LCD_FUNCTION_RESET = 0x30 # See "Initializing by Instruction" section
LCD_CGRAM = 0x40 # DB6: set CG RAM address
LCD_DDRAM = 0x80 # DB7: set DD RAM address
LCD_RS_CMD = 0
LCD_RS_DATA = 1
LCD_RW_WRITE = 0
LCD_RW_READ = 1
def __init__(self, num_lines, num_columns):
self.num_lines = num_lines
if self.num_lines > 4:
self.num_lines = 4
self.num_columns = num_columns
if self.num_columns > 40:
self.num_columns = 40
self.cursor_x = 0
self.cursor_y = 0
self.implied_newline = False
self.backlight = True
self.display_off()
self.backlight_on()
self.clear()
self.hal_write_command(self.LCD_ENTRY_MODE | self.LCD_ENTRY_INC)
self.hide_cursor()
self.display_on()
def clear(self):
self.hal_write_command(self.LCD_CLR)
self.hal_write_command(self.LCD_HOME)
self.cursor_x = 0
self.cursor_y = 0
def show_cursor(self):
self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY |
self.LCD_ON_CURSOR)
def hide_cursor(self):
self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY)
def blink_cursor_on(self):
self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY |
self.LCD_ON_CURSOR | self.LCD_ON_BLINK)
def blink_cursor_off(self):
self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY |
self.LCD_ON_CURSOR)
def display_on(self):
self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY)
def display_off(self):
self.hal_write_command(self.LCD_ON_CTRL)
def backlight_on(self):
self.backlight = True
self.hal_backlight_on()
def backlight_off(self):
self.backlight = False
self.hal_backlight_off()
def move_to(self, cursor_x, cursor_y):
self.cursor_x = cursor_x
self.cursor_y = cursor_y
addr = cursor_x & 0x3f
if cursor_y & 1:
addr += 0x40 # Lines 1 & 3 add 0x40
if cursor_y & 2: # Lines 2 & 3 add number of columns
addr += self.num_columns
self.hal_write_command(self.LCD_DDRAM | addr)
def putchar(self, char):
if char == '\n':
if self.implied_newline:
pass
else:
self.cursor_x = self.num_columns
else:
self.hal_write_data(ord(char))
self.cursor_x += 1
if self.cursor_x >= self.num_columns:
self.cursor_x = 0
self.cursor_y += 1
self.implied_newline = (char != '\n')
if self.cursor_y >= self.num_lines:
self.cursor_y = 0
self.move_to(self.cursor_x, self.cursor_y)
def putstr(self, string):
for char in string:
self.putchar(char)
def custom_char(self, location, charmap):
location &= 0x7
self.hal_write_command(self.LCD_CGRAM | (location << 3))
self.hal_sleep_us(40)
for i in range(8):
self.hal_write_data(charmap[i])
self.hal_sleep_us(40)
self.move_to(self.cursor_x, self.cursor_y)
def hal_backlight_on(self):
pass
def hal_backlight_off(self):
pass
def hal_write_command(self, cmd):
raise NotImplementedError
def hal_write_data(self, data):
raise NotImplementedError
def hal_sleep_us(self, usecs):
time.sleep_us(usecs)
Código com as classes e funções para o acionamento do módulo I2C. Salvar como pico_i2c_lcd.py
import utime
import gc
from lcd_api import LcdApi
from machine import I2C
# Definições dos pinos do PCF8574
MASK_RS = 0x01 # P0
MASK_RW = 0x02 # P1
MASK_E = 0x04 # P2
SHIFT_BACKLIGHT = 3 # P3
SHIFT_DATA = 4 # P4-P7
class I2cLcd(LcdApi):
def __init__(self, i2c, i2c_addr, num_lines, num_columns):
self.i2c = i2c
self.i2c_addr = i2c_addr
self.i2c.writeto(self.i2c_addr, bytes([0]))
utime.sleep_ms(20)
# Send reset 3 times
self.hal_write_init_nibble(self.LCD_FUNCTION_RESET)
utime.sleep_ms(5)
self.hal_write_init_nibble(self.LCD_FUNCTION_RESET)
utime.sleep_ms(1)
self.hal_write_init_nibble(self.LCD_FUNCTION_RESET)
utime.sleep_ms(1)
self.hal_write_init_nibble(self.LCD_FUNCTION)
utime.sleep_ms(1)
LcdApi.__init__(self, num_lines, num_columns)
cmd = self.LCD_FUNCTION
if num_lines > 1:
cmd |= self.LCD_FUNCTION_2LINES
self.hal_write_command(cmd)
gc.collect()
def hal_write_init_nibble(self, nibble):
byte = ((nibble >> 4) & 0x0f) << SHIFT_DATA
self.i2c.writeto(self.i2c_addr, bytes([byte | MASK_E]))
self.i2c.writeto(self.i2c_addr, bytes([byte]))
gc.collect()
def hal_backlight_on(self):
self.i2c.writeto(self.i2c_addr, bytes([1 << SHIFT_BACKLIGHT]))
gc.collect()
def hal_backlight_off(self):
self.i2c.writeto(self.i2c_addr, bytes([0]))
gc.collect()
def hal_write_command(self, cmd):
byte = ((self.backlight << SHIFT_BACKLIGHT) |
(((cmd >> 4) & 0x0f) << SHIFT_DATA))
self.i2c.writeto(self.i2c_addr, bytes([byte | MASK_E]))
self.i2c.writeto(self.i2c_addr, bytes([byte]))
byte = ((self.backlight << SHIFT_BACKLIGHT) |
((cmd & 0x0f) << SHIFT_DATA))
self.i2c.writeto(self.i2c_addr, bytes([byte | MASK_E]))
self.i2c.writeto(self.i2c_addr, bytes([byte]))
if cmd <= 3:
utime.sleep_ms(5)
gc.collect()
def hal_write_data(self, data):
byte = (MASK_RS |
(self.backlight << SHIFT_BACKLIGHT) |
(((data >> 4) & 0x0f) << SHIFT_DATA))
self.i2c.writeto(self.i2c_addr, bytes([byte | MASK_E]))
self.i2c.writeto(self.i2c_addr, bytes([byte]))
byte = (MASK_RS |
(self.backlight << SHIFT_BACKLIGHT) |
((data & 0x0f) << SHIFT_DATA))
self.i2c.writeto(self.i2c_addr, bytes([byte | MASK_E]))
self.i2c.writeto(self.i2c_addr, bytes([byte]))
gc.collect()
Código de exemplo para a exibição de caracteres no display. Salvar como lcd_01.py.
import utime
from machine import I2C, Pin
from lcd_api import LcdApi
from pico_i2c_lcd import I2cLcd
I2C_ADDR = 39
I2C_NUM_ROWS = 2
I2C_NUM_COLS = 16
i2c = I2C(0, sda=machine.Pin(0), scl=machine.Pin(1), freq=400000)
lcd = I2cLcd(i2c, I2C_ADDR, I2C_NUM_ROWS, I2C_NUM_COLS)
def Tela_MJ():
lcd.clear()
lcd.move_to(0,0)
lcd.putstr("MECATRONICA")
lcd.move_to(3,1)
lcd.putstr("JOVEM")
utime.sleep(2)
#Tela_MJ() # chama funçao de Tela MJ
def customcharacter():
#character
lcd.custom_char(0, bytearray([
0x0E,
0x0E,
0x04,
0x1F,
0x04,
0x0E,
0x0A,
0x0A
]))
#character2
lcd.custom_char(1, bytearray([
0x1F,
0x15,
0x1F,
0x1F,
0x1F,
0x0A,
0x0A,
0x1B
]))
#smiley
lcd.custom_char(2, bytearray([
0x00,
0x00,
0x0A,
0x00,
0x15,
0x11,
0x0E,
0x00
]))
#heart
lcd.custom_char(3, bytearray([
0x00,
0x00,
0x0A,
0x15,
0x11,
0x0A,
0x04,
0x00
]))
#note
lcd.custom_char(4, bytearray([
0x01,
0x03,
0x05,
0x09,
0x09,
0x0B,
0x1B,
0x18
]))
#celcius
lcd.custom_char(5, bytearray([
0x07,
0x05,
0x07,
0x00,
0x00,
0x00,
0x00,
0x00
]))
Tela_MJ()
lcd.clear()
customcharacter()
lcd.move_to(0,0)
lcd.putstr("Mecatronica Jovem")
lcd.move_to(0,1)
lcd.putchar(chr(0))
lcd.move_to(4,1)
lcd.putchar(chr(1))
lcd.move_to(8,1)
lcd.putchar(chr(2))
lcd.move_to(12,1)
lcd.putchar(chr(3))
lcd.move_to(15,1)
lcd.putchar(chr(4))
Ordem de execução
Depois de conectar todos os pinos, carregar os códigos para a Pi Pico, execute primeiramente o código scan_i2c.py para descobrir qual é o endereço que precisa ser utilizado. Com o valor obtido no shell você deverá colocar este valor na variável I2C_ADDR, que se encontra no código de exemplo lcd_01.py. Salve o código e execute, o display deverá apresentar as palavras colocadas dentro do comando lcd.putstr().