Como usar um display LCD I2C com Raspberry Pi

Faz tempo que não falamos de Raspberry Pi aqui no Arduino e Cia… e vamos voltar com um assunto que deve interessar muita gente: como usar um display LCD I2C com Raspberry Pi.

Nós já falamos em um post anterior como ligar o display LCD 16×2 no Raspberry Pi utilizando a conexão normal que no total tem 12 fios ligados no display: controle, alimentação e ajuste de contraste com potenciômetro. Com um display LCD I2C, você usa apenas dois pinos de alimentação e os dois pinos I2C (SDA e SCL) para conexão.

O display LCD I2C

O display LCD I2C é um display comum com um módulo como esse da imagem abaixo soldado na parte de trás:

Esse módulo faz a conexão entre o sinal I2C recebido do microcontrolador/processador e os 16 pinos do display, facilitando a conexão física, já que usamos somente 4 pinos, e deixando o circuito muito mais “limpo”, além de eliminar eventuais erros de conexão.

Conexão do display I2C na Raspberry Pi

Na imagem abaixo temos o esquema de conexão do display LCD I2C 16×2 na Raspberry Pi 3. Note que entre o display e os pinos da GPIO do Raspberry usamos um conversor de nível lógico bidirecional, já que o display trabalha com tensão de 5V e os pinos do Raspberry trabalham com 3.3V.

Finalizada a montagem, vamos passar para a parte de configuração do Raspbian.

Atualização e configuração do Raspbian

Antes de instalar os pacotes necessários para uso da interface I2C no RPi, vamos atualizar o Sistema Operacional:

sudo apt-get update
sudo apt-get upgrade

Esse processo pode demorar um pouco, mas é sempre indicado para garantir que temos a última versão dos pacotes do Raspbian.

Primeiramente, vamos habilitar a interface I2C no Raspbian. Abra uma janela de terminal e execute o comando sudo raspi-config, que vai apresentar a tela abaixo:

Vá até a opção 5 (Interfacing Options), depois selecione a opção P5 I2C, que vai habilitar a interface I2C no Raspbian:

Reinicie o sistema operacional.

Agora vamos instalar o I2C-Tools e o smbus. Com eles vamos utilizar o barramento I2C com Python e também descobrir o endereço I2C do display conectado ao Raspberry. Use os comandos abaixo:

sudo apt-get install i2c-tools
sudo apt-get install python-smbus

Para mostrar o endereço I2C do nosso display, execute o comando

i2cdetect -y 1

O endereço do nosso display é 27, conforme destacado na imagem acima. Esse endereço deve ser posteriormente configurado na biblioteca que vamos utilizar no programa.

Programa Python display LCD I2C

Antes do programa de teste vamos criar um arquivo chamado I2C_LCD_driver.py e colocar dentro dele o código abaixo, que é a biblioteca I2C (créditos DenisFromHR).

Modifique a linha 22 para que contenha o endereço I2C do seu display, obtido no passo anterior. No nosso caso, o endereço é 27 e a linha ficou assim:

ADDRESS = 0x27

# -*- coding: utf-8 -*-
# Original code found at:
# https://gist.github.com/DenisFromHR/cc863375a6e19dce359d

"""
Compiled, mashed and generally mutilated 2014-2015 by Denis Pleic
Made available under GNU GENERAL PUBLIC LICENSE

# Modified Python I2C library for Raspberry Pi
# as found on http://www.recantha.co.uk/blog/?p=4849
# Joined existing 'i2c_lib.py' and 'lcddriver.py' into a single library
# added bits and pieces from various sources
# By DenisFromHR (Denis Pleic)
# 2015-02-10, ver 0.1

"""

# i2c bus (0 -- original Pi, 1 -- Rev 2 Pi)
I2CBUS = 1

# LCD Address
ADDRESS = 0x27

import smbus
from time import sleep

class i2c_device:
   def __init__(self, addr, port=I2CBUS):
      self.addr = addr
      self.bus = smbus.SMBus(port)

# Write a single command
   def write_cmd(self, cmd):
      self.bus.write_byte(self.addr, cmd)
      sleep(0.0001)

# Write a command and argument
   def write_cmd_arg(self, cmd, data):
      self.bus.write_byte_data(self.addr, cmd, data)
      sleep(0.0001)

# Write a block of data
   def write_block_data(self, cmd, data):
      self.bus.write_block_data(self.addr, cmd, data)
      sleep(0.0001)

# Read a single byte
   def read(self):
      return self.bus.read_byte(self.addr)

# Read
   def read_data(self, cmd):
      return self.bus.read_byte_data(self.addr, cmd)

# Read a block of data
   def read_block_data(self, cmd):
      return self.bus.read_block_data(self.addr, cmd)


# commands
LCD_CLEARDISPLAY = 0x01
LCD_RETURNHOME = 0x02
LCD_ENTRYMODESET = 0x04
LCD_DISPLAYCONTROL = 0x08
LCD_CURSORSHIFT = 0x10
LCD_FUNCTIONSET = 0x20
LCD_SETCGRAMADDR = 0x40
LCD_SETDDRAMADDR = 0x80

# flags for display entry mode
LCD_ENTRYRIGHT = 0x00
LCD_ENTRYLEFT = 0x02
LCD_ENTRYSHIFTINCREMENT = 0x01
LCD_ENTRYSHIFTDECREMENT = 0x00

# flags for display on/off control
LCD_DISPLAYON = 0x04
LCD_DISPLAYOFF = 0x00
LCD_CURSORON = 0x02
LCD_CURSOROFF = 0x00
LCD_BLINKON = 0x01
LCD_BLINKOFF = 0x00

# flags for display/cursor shift
LCD_DISPLAYMOVE = 0x08
LCD_CURSORMOVE = 0x00
LCD_MOVERIGHT = 0x04
LCD_MOVELEFT = 0x00

# flags for function set
LCD_8BITMODE = 0x10
LCD_4BITMODE = 0x00
LCD_2LINE = 0x08
LCD_1LINE = 0x00
LCD_5x10DOTS = 0x04
LCD_5x8DOTS = 0x00

# flags for backlight control
LCD_BACKLIGHT = 0x08
LCD_NOBACKLIGHT = 0x00

En = 0b00000100 # Enable bit
Rw = 0b00000010 # Read/Write bit
Rs = 0b00000001 # Register select bit

class lcd:
   #initializes objects and lcd
   def __init__(self):
      self.lcd_device = i2c_device(ADDRESS)

      self.lcd_write(0x03)
      self.lcd_write(0x03)
      self.lcd_write(0x03)
      self.lcd_write(0x02)

      self.lcd_write(LCD_FUNCTIONSET | LCD_2LINE | LCD_5x8DOTS | LCD_4BITMODE)
      self.lcd_write(LCD_DISPLAYCONTROL | LCD_DISPLAYON)
      self.lcd_write(LCD_CLEARDISPLAY)
      self.lcd_write(LCD_ENTRYMODESET | LCD_ENTRYLEFT)
      sleep(0.2)


   # clocks EN to latch command
   def lcd_strobe(self, data):
      self.lcd_device.write_cmd(data | En | LCD_BACKLIGHT)
      sleep(.0005)
      self.lcd_device.write_cmd(((data & ~En) | LCD_BACKLIGHT))
      sleep(.0001)

   def lcd_write_four_bits(self, data):
      self.lcd_device.write_cmd(data | LCD_BACKLIGHT)
      self.lcd_strobe(data)

   # write a command to lcd
   def lcd_write(self, cmd, mode=0):
      self.lcd_write_four_bits(mode | (cmd & 0xF0))
      self.lcd_write_four_bits(mode | ((cmd << 4) & 0xF0))

   # write a character to lcd (or character rom) 0x09: backlight | RS=DR<
   # works!
   def lcd_write_char(self, charvalue, mode=1):
      self.lcd_write_four_bits(mode | (charvalue & 0xF0))
      self.lcd_write_four_bits(mode | ((charvalue << 4) & 0xF0))
  
   # put string function with optional char positioning
   def lcd_display_string(self, string, line=1, pos=0):
    if line == 1:
      pos_new = pos
    elif line == 2:
      pos_new = 0x40 + pos
    elif line == 3:
      pos_new = 0x14 + pos
    elif line == 4:
      pos_new = 0x54 + pos

    self.lcd_write(0x80 + pos_new)

    for char in string:
      self.lcd_write(ord(char), Rs)

   # clear lcd and set to home
   def lcd_clear(self):
      self.lcd_write(LCD_CLEARDISPLAY)
      self.lcd_write(LCD_RETURNHOME)

   # define backlight on/off (lcd.backlight(1); off= lcd.backlight(0)
   def backlight(self, state): # for state, 1 = on, 0 = off
      if state == 1:
         self.lcd_device.write_cmd(LCD_BACKLIGHT)
      elif state == 0:
         self.lcd_device.write_cmd(LCD_NOBACKLIGHT)

   # add custom characters (0 - 7)
   def lcd_load_custom_chars(self, fontdata):
      self.lcd_write(0x40);
      for char in fontdata:
         for line in char:
            self.lcd_write_char(line)         
         

Agora vamos criar um outro programa, que é o teste do display. Utilize o código abaixo:

#Programa: Display LCD I2C com Raspberry Pi
#Autor: Arduino e Cia

import I2C_LCD_driver
import socket
import fcntl
import struct
import time

lcdi2c = I2C_LCD_driver.lcd()

#Exibe informacoes iniciais
lcdi2c.lcd_display_string("Arduino e Cia", 1,1)
lcdi2c.lcd_display_string("LCD I2C e RPi", 2,1)
time.sleep(4)

#Apaga o display
lcdi2c.lcd_clear()

def get_ip_address(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915, 
        struct.pack('256s', ifname[:15])
    )[20:24])

#Mostra o endereco IP
lcdi2c.lcd_display_string("IP", 1)
lcdi2c.lcd_display_string(get_ip_address('wlan0'), 1,3)
 
while True:
#Mostra a data no display
    lcdi2c.lcd_display_string("Data: %s" %time.strftime("%d/%m/%y"), 2,1)

O programa carrega as bibliotecas necessárias para acessar o display, mostrar as informações iniciais e depois o endereço IP da placa Raspberry Pi e a data atual do sistema.

Para posicionar o texto no display, utilize os 2 parâmetros numéricos, como na linha 14:

lcdi2c.lcd_display_string(“LCD I2C e RPi”, 2,1)

O valor 2 corresponde à linha do display (linha 2, inferior), e o número 1 corresponde à coluna, lembrando que as colunas são numeradas de 0 a 15.

Gostou? Confira outros posts com Raspberry Pi aqui mesmo no Arduino e Cia!

2.5/5 - (2 votos)

Related posts

Monitor de temperatura com Raspberry Pi e Thingspeak

by Arduino e Cia
4 anos ago

Livro Linux para Makers (com Raspberry Pi)

by Arduino e Cia
6 anos ago

Livro Arduino – Primeiros Passos com Sensores

by Arduino e Cia
10 anos ago
Sair da versão mobile