Os LCDs (Liquid-Crystal Display) são módulos simples de serem conectados aos microcontroladores, sendo assim muito úteis em projetos que necessitam de uma comunicação com o usuário. Os LCDs mais comuns possuem 16 colunas por 2 linhas, normalmente indicados por 16×2 ou 1602 e podem possuir 14 ou 16 pinos, sem e com backlight (luz de fundo) respectivamente e são equipados com um controlador compatível com o chip HD44780 da Hitachi. E é exatamente este modelo que vamos ver a seguir.
Disposição das Linhas e Colunas
Tomando como exemplo um display de 16×2, a disposição dos caracteres estão numa matriz com as colunas numeradas de 0 a 15 e linhas numeradas 0 e 1.
Pinos
A numeração e descrição dos pinos:
Pino | Descrição | |
1 | VSS | GND (terra) |
2 | VDD | +5V |
3 | VO | Ajuste do contraste – utilizar com um resistor fixo ou variável (potenciômetro ou trimpot) |
4 | RS | Register Select – sinaliza a instrução ou caractere que está sendo escrito (linha de controle) |
5 | R/W | Read/Write – sinaliza ao microcontrolador do LCD se a operação é de escrita ou gravação (linha de controle) |
6 | Enable | Ativação do LCD – se nível baixo, ignora RS e R/W (linha de controle) |
7 | D0 | Linha de dado |
8 | D1 | Linha de dado |
9 | D2 | Linha de dado |
10 | D3 | Linha de dado |
11 | D4 | Linha de dado |
12 | D5 | Linha de dado |
13 | D6 | Linha de dado |
14 | D7 | Linha de dado |
15 | LED + | backlight (anodo) +5V |
16 | LED – | backlight (catodo) GND |
Nos LCDs sem backlight não temos os pinos 15 e 16.
Módulo I2C para LCD
Uma outra opção, bem mais interessante, é a utilizar um módulo I2C acoplado ao display LCD, como o da figura a seguir.
Este módulo conta com um trimpot para ajuste do contraste e um jumper para ligar/desligar o LED de luz de fundo (backlight). Porém, podemos ligar e desligar este LED por software.
I2C
I2C (IIC – Inter Integrated Circuit) é um barramento de comunicação desenvolvido pela Philips, hoje NXP Semiconductors, para permitir troca de dados entre os componentes que residem na mesma placa de circuito impresso. A vantagem de usar este tipo de barramento é que precisamos de apenas dois pinos para comunicação, além do pino de alimentação (5V) e o pino terra (GND).
Este módulo em específico possui o chip PCF8574.
Vamos usar a biblioteca Wire (nativa no software Arduino) para facilitar o desenvolvimento com o protocolo I2C. Os dois fios de comunicação são conhecidos por SDA (Serial Data Line) e SCL (Serial Clock Line).
Nas placas Arduino Uno e compatíveis, o
SDA é o pino analógico 4 (A4) e o
SCL é o pino analógico 5 (A5).
No Arduino Mega o SDA é o pino digital 20 e o SCL é o pino digital 21.
Os módulos I2C possuem um endereço único para cada módulo. A seleção do endereço é feita pela combinação dos pads A0, A1 e A2. No caso deste módulo, o endereço padrão é 0x27 (os três pads isolados). Para configurar outro endereço, conforme a tabela abaixo, solde (coloque em curto) os pads desejados. Por exemplo: pad sem solda é igual a 0 (zero), pad em curto é igual a 1.
A0 | A1 | A2 | endereço |
0 | 0 | 0 | 0x27 |
1 | 0 | 0 | 0x26 |
0 | 1 | 0 | 0x25 |
1 | 1 | 0 | 0x24 |
0 | 0 | 1 | 0x23 |
1 | 0 | 1 | 0x22 |
0 | 1 | 1 | 0x21 |
1 | 1 | 1 | 0x20 |
Quer dizer que poderíamos ligar até oito módulos LCD no mesmo Arduino, combinando os pads? Sim, mas lembre-se que existem outros módulos I2C no mercado, como módulos de relógio (RTC) e cada um deverá ter o seu próprio endereço.
Exemplo prático – monitor de temperatura com o LM35.
Vamos mostrar dois exemplos: sem e com o módulo I2C.
Providencie:
- 1 sensor de temperatura LM35
- 1 potenciômetro ou trimpot de 1KΩ (caso monte com a opção sem módulo I2C)
- 1 módulo LCD 16 x 2 *
- 1 protoboard
- e muitos (muitos) fios jumpers.
* é muito mais econômico, caso você não possua um módulo LCD, comprá-lo com o módulo I2C já acoplado (soldado). Se você já possui um ou mais LCDs sem este módulo talvez seja vantajoso comprar o módulo I2C separado, mas terá que soldá-lo ao módulo LCD caso queira uma conexão definitiva entre os módulos.
Conectando o LCD no Arduino – sem módulo I2C
A biblioteca LiquidCrystal (nativa no software Arduino) utiliza apenas as linhas de dados D4 a D7, ou seja, apenas 4 bits. Para controle/ajuste do contraste utilizamos um trimpot ou um potenciômetro de 1KΩ.
O sketch deverá incluir a biblioteca LiquiCrystal através da diretiva #include e para facilitar a manutenção, os pinos associados ao LCD estarão definidos pela diretiva #define.
Obs.: toda diretiva de pré-processamento começa com o símbolo #. As diretivas não são comandos da linguagem C ou Arduino. São instruções que antes da compilação efetiva, são tratadas (processadas) no código fonte (sketch) e posteriormente entregues ao compilador. Ah, a sintaxe também difere dos comandos/declarações C/Arduino. Não temos o ponto e virgula (;) ao termino de uma diretiva. Por convenção, o nome das constantes da diretiva #define são escritas em maiúsculas. |
A principal linha do sketch (mais adiante) é
LiquidCrystal lcd( RS, RW, EN, D4, D5, D6, D7 );
onde lcd é a representação da classe LiquidCrystal (pode ser qualquer nome, mas lcd nos parece mais apropriado 😉 ). Também indicamos os pinos de controle e os pinos de dados.
Outro destaque é a função sprintf() da linguagem C (consulte a apostila do mini curso Linguagem C), que formata dados e copia-os para um array de caracteres. Isto facilita muito o trabalho, porém da forma como esta função está implementada no Arduino, não conseguimos manipular dados do tipo float, por isso temperatura foi definido como int.
Métodos usados no exemplo:
begin( num_colunas, num_ linhas )
Inicializa o LCD e especifica o seu tamanho (linhas e colunas). Note que a ordem dos parâmetros são número de colunas por número de linhas.
clear()
“Limpa” o LCD e posiciona o cursor nas coordenadas 0,0.
setCursor( coluna, linha )
Posiciona o cursor nas coordenadas coluna e linha.
print( dados, [base] )
Imprime dados no LCD a partir do posicionamento do cursor. O parâmetro base é opcional e só se aplica quando dados for numérico (consulte a apostila do curso Linguagem Arduino), tópico Serial.print).
print() também retorna o número de bytes impressos no LCD.
Acompanhe o diagrama abaixo para montagem. São muitos fios jumpers e nossa sugestão é começar pelo módulo LCD.
Olhando o LCD de frente, da esquerda para direita, temos:
pino LCD | pino Arduino |
VSS | GND |
VDD | 5V |
VO | pino central do potenciômetro |
RS | 6 |
RW | 7 |
E | 8 |
D0 | GND |
D1 | GND |
D2 | GND |
D3 | GND |
D4 | 2 |
D5 | 3 |
D6 | 4 |
D7 | 5 |
A (LED backlight anodo) | 5V |
K (LED backlight catodo) | GND |
LM35 – oriente-se pela figura a seguir.
pino LM35 | pino Arduino |
VS | 5V |
Vout | A0 (pino analógico zero) |
GND | GND |
Exemplo
#include <LiquidCrystal.h> #define RS 6 #define RW 7 #define EN 8 #define D4 2 #define D5 3 #define D6 4 #define D7 5 #define TEMP A0 float leitura; int temperatura; char msg[255]; LiquidCrystal lcd(RS, RW, EN, D4, D5, D6, D7); void setup() { lcd.begin(2, 16); lcd.setCursor(2, 0); lcd.print("* EADuino *"); delay(3000); lcd.clear(); lcd.setCursor(0, 0); lcd.print("Temperatura"); } void loop() { leitura = analogRead( TEMP ); temperatura = (5 * leitura * 100) / 1024; sprintf( msg, "%2d C", temperatura ); lcd.setCursor(0, 1); lcd.print(msg); delay(5000); }
Conectando o LCD no Arduino – com módulo I2C
Primeiro, verifique se você tem instalado a biblioteca LiquidCrystal_I2C. Vá até o gerenciador de bibliotecas (atalho CTRL-SHIFT-i), digite liquidcrystal. Optamos por instalar esta mostrada na figura. Caso não encontre, uma boa fonte é o site Arduino Library List (link no final deste artigo), porém para este módulo faça o download aqui https://www.arduinolibraries.info/libraries/liquid-crystal-i2-c
Oriente-se pela imagem abaixo.
pino I2C | pino Arduino |
GND | GND |
VCC | 5V |
SDA | A4 |
SCL | A5 |
Note como o circuito fica muito (mas muito) mais simples. Além da economia de pinos Arduino.
No sketch a seguir instanciamos a classe
LiquidCrystal_I2C lcd( 0x27, 16, 2 );
e informamos o endereço do módulo, quantidade de colunas e linhas. Na função setup() iniciamos o módulo e na função loop() mantemos o backlight aceso por 10 segundos e em seguida desligamos o backlight por 20 segundos.
Métodos usados no exemplo:
init( )
Inicializa o LCD.
clear( ) – idêntico ao exemplo anterior
setCursor( ) – idêntico ao exemplo anterior
print( ) – idêntico ao exemplo anterior
noBacklight( )
desliga luz de fundo
backlight( )
liga luz de fundo
setBacklight( HIGH | LOW )
liga/desliga luz de fundo
Exemplo
#include <Wire.h> #include <LiquidCrystal_I2C.h> #define TEMP A0 float leitura; int temperatura; LiquidCrystal_I2C lcd(0x27, 16, 2); void setup() { lcd.init(); } void loop() { leitura = analogRead( TEMP ); temperatura = (5 * leitura * 100) / 1024; lcd.clear(); lcd.backlight(); // ou setBacklight( HIGH ); lcd.setCursor(0, 0); lcd.print("Temperatura"); lcd.setCursor(10, 1); lcd.print(temperatura); lcd.print("C"); delay(10000); lcd.noBacklight(); // ou setBacklight( LOW ); delay(20000); }
Criando novos caracteres (custom chars)
Com o método createChar( ) é possível criar e exibir caracteres personalizados no LCD. Isso é especialmente útil se você deseja exibir um caractere que não faz parte do conjunto de caracteres ASCII padrão.
Em módulos LCDs baseados no controlador HD44780 temos dois tipos de memórias: CGROM e CGRAM (memórias do gerador de caracteres).
- O CGROM gera todos os padrões de caracteres de 5 x 8 pontos.
- O CGRAM pode gerar até 8 padrões de caracteres definidos pelo usuário (personalizados).
Como sugestão utilize uma folha de papel quadriculado, separe os quadrados em grupos de 8 por 5 e preencha os quadrados que deseja mostrar ou, melhor ainda, acesse este site https://maxpromer.github.io/LCD-Character-Creator/. Você pode escolher se é um LCD com ou sem I2C e ainda gerar os valores em binário ou hexadecimal. Depois é só colar o código 😎 .
Métodos usados no exemplo:
createChar( posiçao, mapa de bits )
armazena na memória CGRAM, na posição de 0 a 7, o mapa de bits do caractere customizado.
write( posição )
exibe no display o caractere customizado na posição de memória de 0 a 7.
Carregue e execute o sketch a seguir.
Exemplo
#include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); // caracteres personalizados - os vetores abaixo foram populados com numeros binarios byte Heart[] = { B00000, B01010, B11111, B11111, B01110, B00100, B00000, B00000 }; byte Bell[] = { B00100, B01110, B01110, B01110, B11111, B00000, B00100, B00000 }; byte Alien[] = { B11111, B10101, B11111, B11111, B01110, B01010, B11011, B00000 }; byte Check[] = { B00000, B00001, B00011, B10110, B11100, B01000, B00000, B00000 }; byte Speaker[] = { B00001, B00011, B01111, B01111, B01111, B00011, B00001, B00000 }; byte Sound[] = { B00001, B00011, B00101, B01001, B01001, B01011, B11011, B11000 }; byte Skull[] = { B00000, B01110, B10101, B11011, B01110, B01110, B00000, B00000 }; byte Lock[] = { B01110, B10001, B10001, B11111, B11011, B11011, B11111, B00000 }; void setup() { lcd.init(); lcd.backlight(); // cria os novos caracteres lcd.createChar(0, Heart); lcd.createChar(1, Bell); lcd.createChar(2, Alien); lcd.createChar(3, Check); lcd.createChar(4, Speaker); lcd.createChar(5, Sound); lcd.createChar(6, Skull); lcd.createChar(7, Lock); lcd.clear(); } void loop() { byte coluna = 0; for ( byte indice = 0; indice <= 7; indice++ ) { lcd.setCursor(coluna, 1); lcd.write( indice ); coluna += 2; //incrementa a variavel de dois em dois } }
Um outro exemplo com os vetores populados com números hexadecimais. Preferimos com números binários, pois praticamente você transcreve o que desenhou para o valor binário.
#include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); // caracteres personalizados - os vetores abaixo foram populados com numeros hexadecimais byte sino[] = {0x4, 0xe, 0xe, 0xe, 0x1f, 0x0, 0x4}; byte nota[] = {0x2, 0x3, 0x2, 0xe, 0x1e, 0xc, 0x0}; byte relogio[] = {0x0, 0xe, 0x15, 0x17, 0x11, 0xe, 0x0}; byte coracao[] = {0x0, 0xa, 0x1f, 0x1f, 0xe, 0x4, 0x0}; byte pato[] = {0x0, 0xc, 0x1d, 0xf, 0xf, 0x6, 0x0}; byte checklist[]= {0x0, 0x1, 0x3, 0x16, 0x1c, 0x8, 0x0}; byte cruz[] = {0x0, 0x1b, 0xe, 0x4, 0xe, 0x1b, 0x0}; byte enter[] = {0x1, 0x1, 0x5, 0x9, 0x1f, 0x8, 0x4}; void setup() { lcd.init(); lcd.backlight(); // cria os novos caracteres lcd.createChar(0, sino); lcd.createChar(1, nota); lcd.createChar(2, relogio); lcd.createChar(3, coracao); lcd.createChar(4, pato); lcd.createChar(5, checklist); lcd.createChar(6, cruz); lcd.createChar(7, enter); lcd.clear(); } void loop() { byte coluna = 0; for ( byte indice = 0; indice <= 7; indice++ ) { lcd.setCursor(coluna, 1); lcd.write( indice ); coluna += 2; //incrementa a variavel de dois em dois } }
Outros Métodos
home()
posiciona o cursor no topo/esquerda do display – não limpa a tela.
blink()
noBlink()
exibe/esconde cursor em formato de bloco na próxima coluna disponível.
cursor()
noCursor()
exibe/esconde cursor em formato sublinhado (underscore) na próxima coluna disponível.
display()
noDisplay()
liga/desliga o display, mas não apaga o conteúdo em memória.
scrollDisplayLeft()
scrollDisplayRight()
desloca toda a tela do display uma posição a esquerda/direta.
Exemplo
#include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); void setup() { lcd.init(); lcd.backlight(); } void loop() { lcd.clear(); lcd.setCursor(0, 0); lcd.print("EADuino"); lcd.setCursor(0, 1); lcd.print("Bem-vindo(a)!"); delay(5000); lcd.clear(); lcd.print("cursor "); lcd.cursor(); delay(5000); lcd.home(); lcd.print("sem cursor "); lcd.noCursor(); delay(5000); lcd.clear(); lcd.print("cursor - bloco"); lcd.blink(); delay(5000); lcd.print("sem cursor "); lcd.noBlink(); delay(5000); lcd.clear(); lcd.print("EADuino!"); delay(2000); lcd.noDisplay(); delay(2000); lcd.display(); delay(5000); lcd.clear(); int bloco, tamanho, quantidade_blocos, caracteres_restantes; tamanho = lcd.print("EADuino - Cursos de Arduino Online!"); delay(3000); quantidade_blocos = tamanho / 16; caracteres_restantes = tamanho % 16; for (bloco = 1; bloco <= quantidade_blocos - 1; bloco++) { for (byte scroll = 0; scroll < 16; scroll++) { lcd.scrollDisplayLeft(); delay(200); } delay(3000); } if ( caracteres_restantes > 0 ) { for (byte scroll = 0; scroll <= caracteres_restantes; scroll++) { lcd.scrollDisplayLeft(); delay(200); } delay(3000); } }
Links úteis
- http://en.wikipedia.org/wiki/Liquid-crystal_display
- https://en.wikipedia.org/wiki/Hitachi_HD44780_LCD_controller
- https://www.nxp.com/docs/en/data-sheet/PCF8574_PCF8574A.pdf
- https://en.wikipedia.org/wiki/I%C2%B2C
- https://www.arduinolibraries.info/
- https://www.arduino.cc/en/Reference/LiquidCrystal