Display Nokia 5110 sobre datasheet Philips PCD8544 |
Apesar de todo mundo se referir ao display como Nokia 5110, a parte importante para conhecer é o controlador que ele tem dentro, que na verdade é feito pela Philips! O controlador/driver é um Philips PCD8544.
O datasheet dele é bem extenso (32 páginas), mas você não precisa se preocupar, está numa linguagem bem acessível e tem até um exemplo de como desenhar uma palavra na tela, mostrando o que você deve enviar, bit a bit (página 22).
Para tentar entender o funcionamento do módulo, imprimi as páginas 14 e 22 e ainda montei uma "cola" para anotar o que cada byte representava em bits.
O problema que eu estava tendo com este módulo parecia estar na definição do contraste, então criei o código abaixo para vocês testarem o módulo de vocês. O que ele faz é desenhar uma barra que vai crescendo a medida que o contraste vai aumentando.
Este gif animado dá uma ideia do resultado. O contraste ideal é aquele em que a barra fica bem escura sobre um fundo claro. Se o fundo do seu LCD escurecer, é porque você passou da conta e deve diminuir um pouquinho.
//Controlador de Display LCD Nokia 5110 (84x48 pixels)
//em 13 de janeiro de 2014
//Mais informacoes: umcarneiro.blogspot.com
//Licenca: MIT (use como quiser!)
//Pinos utilizados no arduino
#define PIN_SCE 7 //pino 2 do display
#define PIN_RESET 6 //pino 1 do display
#define PIN_DC 5 //pino 3 do display
#define PIN_SDIN 4 //pino 4 do display
#define PIN_SCLK 3 //pino 5 do display
//Tamanho do LCD em pixels:
#define LCD_X 84
#define LCD_Y 48
//Estas variaveis restringem o menor e o maior contraste a ser testado
//Se sua tela estiver muito escura desde o inicio do teste, diminua este valor
const int MIN_CONTRAST = 175; //tem que ser maior que 128
//Se sua tela estiver muito clara no fim do teste, aumente este valor
const int MAX_CONTRAST = 200; //tem que ser menor que 255
void setup(void)
{
pinMode(PIN_SCE, OUTPUT); // Inicializa os pinos...
pinMode(PIN_RESET, OUTPUT);
pinMode(PIN_DC, OUTPUT);
pinMode(PIN_SDIN, OUTPUT);
pinMode(PIN_SCLK, OUTPUT);
digitalWrite(PIN_RESET, LOW); //RESET no controlador
digitalWrite(PIN_RESET, HIGH);
LcdWrite(LOW, 0x21 ); // Function set: PD=0 (On); V=0 (Horizontal); H=1 (Extended instruction set)
LcdWrite(LOW, 0xBA ); // Define o LCD Vop (Contraste). //XXXXXXXXXXXXXXX
LcdWrite(LOW, 0x04 ); // Define o coeficiente de temperatura (??)
LcdWrite(LOW, 0x14 ); // LCD bias mode 1:48 (??)
LcdWrite(LOW, 0x20 ); // Function set: PD=0 (On); V=0 (Horizontal); H=0 (Basic instruction set)
LcdWrite(LOW, 0x0C ); // Display control = 10 (Normal)
//Clear - apaga todas as posicoes
for (int index = 0; index < LCD_X * LCD_Y / 8; index++)
{
LcdWrite(HIGH, 0x00); //bit 0 em todo mundo!
}
}
//Cuida da burocracia: envia o comando ou dado seguindo o protocolo do chip
void LcdWrite(byte dc, byte data)
{
digitalWrite(PIN_DC, dc); //define se vai mandar dado ou comando
digitalWrite(PIN_SCE, LOW); //ativa o chip para receber dados
shiftOut(PIN_SDIN, PIN_SCLK, MSBFIRST, data); //envia um bit de cada vez, comecando pela esquerda
digitalWrite(PIN_SCE, HIGH); //desativa o envio de dados
}
//desenha uma barra repetindo o byte informado
void desenhaBarra(int largura, byte caracter)
{
//Coloca o cursor no local correto
LcdWrite( 0, 0x80 | 0); // Coluna 0
LcdWrite( 0, 0x40 | 2); // Linha 2
//barra horizontal
for (int index = 0; index < largura; index++)
{
LcdWrite(HIGH, caracter);
}
}
void loop(void)
{
//dentro dos limites que estabelecemos, define o contraste a mostrar
for (int contrast = MIN_CONTRAST; contrast < MAX_CONTRAST; contrast++)
{
LcdWrite(LOW, 0x21 ); // Function set: PD=0 (On); V=0 (Horizontal); H=1 (Extended instruction set)
LcdWrite(LOW, contrast ); // Define o contraste (VOP)
//define a largura da barra proporcional ao contraste
int largura = map(contrast, MIN_CONTRAST, MAX_CONTRAST, 0, LCD_X);
LcdWrite(LOW, 0x20 ); // Function set: PD=0 (On); V=0 (Horizontal); H=0 (Basic instruction set)
LcdWrite(LOW, 0x0C ); // Display control = 10
//desenha a barra horizontal na largura que definimos
desenhaBarra(largura, 0x7f);
delay(350); //dah um tempo para podermos ver o resultado
}
//desenha uma barra invisivel da largura da tela
desenhaBarra(LCD_X, 0x00); //ou seja, apaga a barra!
}
Juro que este foi o código mais simples que eu consegui fazer! Enchi de comentários para ver se conseguia torná-lo inteligível. Defini o contraste usando números decimais de propósito, para facilitar a leitura. Tem um ótimo conversor de números entre binário, decimal e hexa nesta página. Eu usei um bocado para tentar entender o que estava acontecendo.
O circuito ficou assim:
Pino LCD | Resistor | Arduino | Cor |
1-RST | 10k | Pino 6 | Vermelho |
2-CE | 10k | Pino 7 | Azul |
3-DC | 10k | Pino 5 | Amarelo |
4-DIN | 10k | Pino 4 | Verde |
5-CLK | 10k | Pino 3 | Azul |
6-VCC | - | 3.3v | Vermelho |
7-LIGHT | 330R | GND | Azul |
8-GND | - | GND | Preto |
O código que eu tinha usado da outra vez usava, obrigatoriamente os pinos 11 e 13, mas este é mais simples e não tem essa exigência.
Repare também que o backlight (pino 7 do LCD) foi para o GND. Confesso que não entendi bem a lógica disso, já que o backlight se acende quando colocamos +3V direto no pino 7 e GND no pino 8.
O desenho do módulo de LCD no Fritzing eu fiz por conta própria. Se quiser o arquivo ou aprender a fazer você mesmo, leia este outro post.
Espero que vocês consigam colocar as suas telinhas para funcionar!
Quem sabe em um próximo post a minha já terá virado um olho de brinquedo?
Aguardem!
UPDATE: Desenhei o olho para colocar no LCD. Vejam neste outro post.
Você pode ver todas as etapas deste projeto usando este link, ou clicando no marcador "olho_de_lcd", abaixo.
Consegui nem ligar a minha. não aparece nada na tela. Peguei um tutorial para usar a biblioteca Adafruit_GFX, mas deu pau e nem compilou
ResponderExcluirCalieno, na minha primeira tentativa também tentei uma biblioteca e não deu em nada... Esse código do meu post não usa biblioteca nenhuma, tenta com ele. Se não conseguir, procure o grupo arduino-brasilia (do Google Groups) e posta lá detalhes do seu projeto (que peças está usando, o código, etc), que o pessoal do grupo (eu, inclusive) tenta te ajudar. Boa sorte!
Excluirdesculpe, mias poderia me ajudar fazer apenas um código parecido com o do teste de contraste, preciso criar uma barra que de acordo com uma variavel que sera incrementada ou decrementada a barra aumente ou diminua.
ResponderExcluirOi, Pc. Não parece difícil. Faça o seguinte: use o código deste post do jeito que está aí para testar seu circuito, tela, etc. Se tudo funcionar, você pode adaptá-lo trocando todo o método "void loop(void)" por:
Excluirvoid loop(void)
{
int largura = analogRead(A0);
desenhaBarra(largura, 0x7f);
delay(350);
desenhaBarra(LCD_X, 0x00);
}
Na variável largura eu coloquei um analogRead(A0), imaginando que você poderia ler o valor de um potenciômetro, por exemplo.
Teste aí e conte para a gente!
Abs!
Otávio