Framework Arduino II: Aula 08 Display LCD 16 x 2 I2C

 Imagem meramente ilustrativa

Recapitulando

    Na aula passada vimos a utilização do Display LCD 16 x 2 como dispositivo de saída no Arduino, como também vimos a necessidade de incluir uma biblioteca específica para sua utilização. Mostrei que esse dispositivo utiliza normalmente seis pinos do Arduino e o consumo de corrente de seu Led de fundo pode vir a ser um problema para o conjunto de alimentação.

    Também tinha comentado que havia a possibilidade de utilizar um desses display associados a um módulo I2C que permitiria sua utilização com apenas dois pinos. Hoje falaremos mais disso.

Conhecendo o protocolo I2C.

    O I²C é um protocolo criado pela Philips para conectar vários dispositivos em um mesmo barramento serial através de duas vias: uma chamada de Serial Data e outra de Serial Clock. O serial clock seria responsável emitir pulsos e o data pela troca de dados entre o dispositivo e a placa.

    Nesse protocolo os dispositivos estaria livres de conflitos porque todos teriam um endereço de memória exclusivo para serem acessados. Sendo assim, para acessar um dispositivo I²C é necessário conhecer o seu endereço Hexadecimal.

    Esse endereço muitas vezes pode ser configurado através de chaves dip switchs nos próprios módulos do dispositivo. Na falta de informações sobre esse endereço, podemos rodar um código para scannear dispositivos conectados ao Arduino e descobrir o endereço.

Conhecendo a Biblioteca Wire

     Wire é a biblioteca usada pelo Arduino para se comunicar com dispositivos I²C. Ela possui um conjunto de métodos para a classe Wire, dos quais selecionamos alguns para conhecer:

  • start() - Inicializa o barramento I2C
  • end() - Fecha o barramento I2C
  • requestFrom()- Solicita bytes de um dispositivo periférico
  • BeginTransmission() - Começa a enfileirar uma transmissão
  • endTransmission() - Transmite os bytes que foram enfileirados e finaliza a transmissão
  • write() - Grava dados do periférico para o controlador ou vice-versa
  • available() - retorna o número de bytes disponíveis para recuperação
  • read() - Lê um byte que foi transmitido de um periférico para um controlador.
  • setClock() - Modifica a frequência do clock
  • onReceive() - Registra uma função a ser chamada quando um periférico recebe uma transmissão
  • onRequest() - Registra uma função a ser chamada quando um controlador solicitar dados
  • setWireTimeout() - Define o tempo limite para transmissões no modo controlador
  • clearWireTimeoutFlag() – Limpa o sinalizador de tempo limite
  • getWireTimeoutFlag() - Verifica se ocorreu um tempo limite desde a última vez que o sinalizador foi apagado.

    Hoje nos interessa apenas conhecer como essa biblioteca pode ser útil para identificar o endereço HEX de um dispositivo. No caso do Wokwi, o Display LCD 16 x 2 com I²C tem como endereço de memória o hexadecimal 0x27, mas usaremos um código para confirma isso.

Pinos para I²C

    Assim como outras placas, o Arduino Uno possui dois pinos especializados para o uso do protocolo I²C que são as entradas analógicas A4 e A5. Se não utilizar esses pinos o LCD apenas ficará com a luz de fundo ligada.

Montagens

    Para ganhar tempo estou disponibilizando as montagens prontas que o estudante poderá salvar uma cópia no seu perfil. Na primeira montagem faremos um projeto para repetir as mesmas instruções da aula passada, porém agora com o uso do Display I²C. Repare que os pinos usados foram A4 e A5

Primeira Montagem

Montagem para o Display LCD 16 x 2 I²C
Montagem para o Display LCD 16 x 2 I²C

     Link: https://wokwi.com/projects/413746745564011521

Primeiro Sketch

    De importante nesse Sketch está a inclusão de um biblioteca sugerida pelo próprio Wokwi chamada LiquidCrystal I2C feita por Frank de Brabander e agora mantida por outras pessoas. Cabe esclarecer que essa não é a única biblioteca disponível na Web para uso em displays I²C, mas vamos usa-la já que foi testada pela própria plataforma de simulação.

    Depois da primeira linha com a inclusão da biblioteca, temos na linha 3 o instanciamento do objeto lcd, com base na classe liquid, utilizando como parâmetros o endereço Hex do display, o número de coluna e o número de linhas do dispositivo. Lembrando que eu disse anteriormente que no Wokwi, o hexadecimal do display era 0x27.

    Veja que esta é a primeira diferença entre essa biblioteca e a biblioteca da aula passada, isto é, na biblioteca anterior eu não tinha o endereço de memória, mas tinha colunas e linhas.

    Outra diferença entre essa biblioteca e a anterior, é que eu tenho um método chamado init() ao invés de begin() para inicializar o objeto. Note também que a luz de fundo precisa ser acionada através de um método chamado backlight.

    Fora isso, eu posso utilizar todos as instruções vistas na aula passada na minha função loop. Caso você tenha visto ou não se lembre das explicações, sugiro uma olhada na aula anterior clicando aqui.

  1. #include <LiquidCrystal_I2C.h>

  2. LiquidCrystal_I2C lcd(0x27, 16, 2);

  3. void setup() {
  4.   lcd.init();
  5.   lcd.backlight() ;
  6. }

  7. void loop() {
  8.   lcd.setCursor(0, 0);
  9.   lcd.print("Escrevendo em L1");
  10.   delay(1000);
  11.   lcd.setCursor(0, 1);
  12.   lcd.print("Escrevendo em L2");
  13.   delay(1000);
  14.   lcd.clear();
  15.   String texto="centro";
  16.   int coluna=(16-texto.length())/2;
  17.   lcd.setCursor(coluna,0);
  18.   lcd.print(texto);
  19.   delay(3000);
  20.   lcd.clear();
  21.   lcd.blink();
  22.   lcd.print("Pisca cursor");
  23.   delay(3000);
  24.   lcd.clear();
  25.   lcd.noBlink();
  26.   lcd.print("underline");
  27.   lcd.cursor();
  28.   delay(3000);
  29.   lcd.clear();
  30.   lcd.noCursor();
  31.   lcd.print("scroll");
  32.   delay(1000);
  33.   for (int i= 0; i <= 3; i++){
  34.     lcd.scrollDisplayRight();
  35.     delay(1000);  
  36.   }
  37.   for (int i= 0; i <= 3; i++){
  38.     lcd.scrollDisplayLeft();
  39.     delay(1000);  
  40.   }
  41.   lcd.clear();
  42.   lcd.print("Desligando em 3s");
  43.   delay(3000);
  44.   lcd.noDisplay();
  45.   delay(3000);
  46.     for (int i= 0; i < 3; i++){
  47.     lcd.scrollDisplayLeft();
  48.     delay(1000);  
  49.   }
  50.   lcd.display();
  51.   delay(3000);
  52.   lcd.clear();  
  53. }

Segunda montagem e seu Sketch

    Fiz outra montagem igual apenas para testar um código de escaneamento de dispositivos I²C feito por um colaborador do Wokwi chamado Urish e disponibilizado pela própria plataforma. 

Simulação mostrando o escaneamento de dispositivos
Simulação mostrando o escaneamento de dispositivos

    Link: https://wokwi.com/projects/413759840663719937

    Note que a simulação encontra o display no endereço 0x27 do qual falamos.

    Nesse Sketch temos inclusão da biblioteca Wire e no setup inicializamos o objeto Wire e o monitor serial. Em loop declaramos as variáveis que serão utilizadas no processo de escaneamento de dispositivos I²C: uma para coletar possíveis erros na busca, outra para armazenar o endereço e uma última para armazenar a quantidade de dispositivos encontrados na busca.

    Da linha 16 a 38 eu tenho um laço que repete o processo de busca através de uma transmissão de sinal em cada endereço de memória estabelecido pelo contador do laço for. Em cada passagem do laço eu coleto um possível erro e testo com if para ver que tipo de erro aconteceu.

    Se erro for igual a zero, significa que eu encontrei um dispositivo naquele endereço vasculhado e imprimo o endereço na tela e incremento a variável quantidade. Se o erro for igual a 4, aconteceu um erro naquele endereço e ele é impresso. No final eu imprimo a quantidade de dispositivos encontrados.

  1. #include <Wire.h>

  2. void setup() {
  3.   Wire.begin();
  4.   Serial.begin(9600);
  5.   Serial.println("\nEscaneando dispositivos I2C");
  6. }

  7. void loop() {
  8.   byte erro, endereco;
  9.   int quantidade;

  10.   Serial.println("Escaneando...");

  11.   quantidade = 0;
  12.   for(endereco = 1; endereco < 127; endereco++) {
  13.     Wire.beginTransmission(endereco);
  14.     erro = Wire.endTransmission();

  15.     if (erro == 0)
  16.     {
  17.       Serial.print("Dispositivo I2C encontrado no endereço 0x");
  18.       if (endereco<16) {
  19.         Serial.print("0");
  20.       }
  21.       Serial.print(endereco,HEX);
  22.       Serial.println("  !");

  23.       quantidade++;
  24.     }
  25.     else if (erro==4) {
  26.       Serial.print("Erro no endereço 0x");
  27.       if (endereco<16) {
  28.         Serial.print("0");
  29.       }
  30.       Serial.println(endereco,HEX);
  31.     }
  32.   }
  33.   if (quantidade== 0) {
  34.     Serial.println("Nenhum dispositivo I2C encontrado\n");
  35.   } 
  36.   else {
  37.     Serial.println("Fim\n");
  38.   }
  39.   delay(5000);
  40. }       
    Hoje conhecemos o protocolo I²C, a biblioteca Wire, como vasculhar dispositivos I²C conectados na placa e também como usar um Display I²C. Aula que vem continuaremos.

Próxima Aula                                                                                                                        Aula Anterior

Referências

ARDUINO. LiquidCrystal I2C. Disponível em <https://docs.arduino.cc/learn/communication/wire/> Acesso em 05 nov 2024.

ARDUINO LIBRARY LIST. LiquidCrystal I2C. Disponível em <https://www.arduinolibraries.info/libraries/liquid-crystal-i2-c> Acesso em 05 nov 2024.

BLOG ELETROGRATE. Guia Completo do Display LCD – Arduino. Disponível em <https://blog.eletrogate.com/guia-completo-do-display-lcd-arduino/> Acesso em 04 nov 2024.

BLOG DA ROBÓTICA. Como utilizar o display LCD 16×02 com módulo I2C no Arduino. Disponível em <https://www.blogdarobotica.com/2022/05/02/como-utilizar-o-display-lcd-16x02-com-modulo-i2c-no-arduino/> Acesso em 05 nov 2024.

I²C. In: WIKIPÉDIA, a enciclopédia livre. Flórida: Wikimedia Foundation, 2022. Disponível em: <https://pt.wikipedia.org/w/index.php?title=I%C2%B2C&oldid=63938380>. Acesso em: 5 nov 2024.

ROBO CORE. Módulo I2C - Primeiros Passos. Disponível em <https://www.robocore.net/tutoriais/primeiros-passos-com-modulo-i2c> Acesso em 04 nov 2024.


WOKWI. Referência do wokwi-lcd1602. Disponível em <https://docs.wokwi.com/pt-BR/parts/wokwi-lcd1602/> Acesso em 04 nov 2024.