Descrição:
Esse aí foi meu primeiro celular. Tudo bem que o produzido pela gradiente se chamava Strike, mas o display era o mesmo.
Que tal reutilizar esse display para seus projetos e ajudar o nosso ambiente (aqui o ambiente ainda é inteiro).
Vamos modificar um sketch fornecido na página da Sparkfun que de tão simples, nem precisa importar uma biblioteca. Acrescentando algumas linhas, poderemos "imprimir" valores float (ponto flutuante) no display Nokia 5110 ou 3310, que normalmente não era possível com o sketch original. De quebra, durante o processo, o leitor ganha um curso rápido de Wiring, a línguagem do Arduino. Na verdade, o sketch apresentado funciona como uma biblioteca, mas está integrada ao sketch principal. Seria bem elegante (palavra que não combina com este sketch em particular) separar em uma "aba" diferente as linhas de programa que servem para configurar o display e escrever nele, do resto do programa. Fica para outro dia.
No nosso projeto, vamos ligar o display Nokia 5110, comprado na Sparkfun, ao nosso Arduino Mega 2560 (ou 1268). Na figura abaixo temos um display reaproveitado de um velho celular da Nokia. O que nós usamos, foi soldado em uma placa de circuito impresso e tem um conector que facilita a nossa vida. Mas o que importa é que devemos ligar os pinos dessa forma:
Obs: 1. Mas para quem quer reutilizar o seu próprio display, dependendo do modelo, é possível soldar os fios de maneira bem fácil e vai funcionar muito bem. Cuidado com a alimentação dos displays, pois são, em geral, de 3.3V Isso é importante! A figura acima foi obtida de http://www.radiolocman.com/shem/schematics.html?di=44132. Esse link mostra esse e outros detalhes dos displays Nokia (dos modelos 5110 e 3310).
2. Na placa da Sparkfun, o Vout não é ligado ao conector. A sequência nesse caso é 1-Vdd,2-Gnd, 3- SCE, 4- RESET, 5- D_C, 6-SDIN,7-SCLK, 8-Backlight (deve ligar ao Vdd via resistor de 1K).
Vejam como ficou o projeto montado:
Material :
Sketch ( é o mesmo que "programa"): Para que serve? Esse programa transforma seu Arduino em um voltímetro. Como o display pode ser escrito e gerar elementos gráficos, é possível "customizar" a interface para apresentar, ao invés de números, um gráfico de barras feito aqueles displays em equipamentos de som, por exemplo. Ou mesmo o desenho de um termômetro de mercúrio...a sua imaginação faz o resto. Aqui ensinamos como programar o Arduino e o próprio display, além, é claro, mostramos os detalhes do hardware que para muita gente pode ser a parte mais difícil.
Obs: A quase totalidade do código foi obtida do fornecedor do display (www.sparkfun.com) e fizemos pequenos ajustes.
#include "Arduino.h"
#define PIN_SCE 7
#define PIN_RESET 6
#define PIN_DC 5
#define PIN_SDIN 4
#define PIN_SCLK 3
#define LCD_C LOW
#define LCD_D HIGH
#define LCD_X 84
#define LCD_Y 48
#define LCD_CMD 0
int a =0;
int temp;
int g,b,c;
int contraste=analogRead(1);
static const byte ASCII[][5] =
{
{0x00, 0x00, 0x00, 0x00, 0x00} // 20
,{0x00, 0x00, 0x5f, 0x00, 0x00} // 21 !
,{0x00, 0x07, 0x00, 0x07, 0x00} // 22 "
,{0x14, 0x7f, 0x14, 0x7f, 0x14} // 23 #
,{0x24, 0x2a, 0x7f, 0x2a, 0x12} // 24 $
,{0x23, 0x13, 0x08, 0x64, 0x62} // 25 %
,{0x36, 0x49, 0x55, 0x22, 0x50} // 26 &
,{0x00, 0x05, 0x03, 0x00, 0x00} // 27 '
,{0x00, 0x1c, 0x22, 0x41, 0x00} // 28 (
,{0x00, 0x41, 0x22, 0x1c, 0x00} // 29 )
,{0x14, 0x08, 0x3e, 0x08, 0x14} // 2a *
,{0x08, 0x08, 0x3e, 0x08, 0x08} // 2b +
,{0x00, 0x50, 0x30, 0x00, 0x00} // 2c ,
,{0x08, 0x08, 0x08, 0x08, 0x08} // 2d -
,{0x00, 0x60, 0x60, 0x00, 0x00} // 2e .
,{0x20, 0x10, 0x08, 0x04, 0x02} // 2f /
,{0x3e, 0x51, 0x49, 0x45, 0x3e} // 30 0
,{0x00, 0x42, 0x7f, 0x40, 0x00} // 31 1
,{0x42, 0x61, 0x51, 0x49, 0x46} // 32 2
,{0x21, 0x41, 0x45, 0x4b, 0x31} // 33 3
,{0x18, 0x14, 0x12, 0x7f, 0x10} // 34 4
,{0x27, 0x45, 0x45, 0x45, 0x39} // 35 5
,{0x3c, 0x4a, 0x49, 0x49, 0x30} // 36 6
,{0x01, 0x71, 0x09, 0x05, 0x03} // 37 7
,{0x36, 0x49, 0x49, 0x49, 0x36} // 38 8
,{0x06, 0x49, 0x49, 0x29, 0x1e} // 39 9
,{0x00, 0x36, 0x36, 0x00, 0x00} // 3a :
,{0x00, 0x56, 0x36, 0x00, 0x00} // 3b ;
,{0x08, 0x14, 0x22, 0x41, 0x00} // 3c <
,{0x14, 0x14, 0x14, 0x14, 0x14} // 3d =
,{0x00, 0x41, 0x22, 0x14, 0x08} // 3e >
,{0x02, 0x01, 0x51, 0x09, 0x06} // 3f ?
,{0x32, 0x49, 0x79, 0x41, 0x3e} // 40 @
,{0x7e, 0x11, 0x11, 0x11, 0x7e} // 41 A
,{0x7f, 0x49, 0x49, 0x49, 0x36} // 42 B
,{0x3e, 0x41, 0x41, 0x41, 0x22} // 43 C
,{0x7f, 0x41, 0x41, 0x22, 0x1c} // 44 D
,{0x7f, 0x49, 0x49, 0x49, 0x41} // 45 E
,{0x7f, 0x09, 0x09, 0x09, 0x01} // 46 F
,{0x3e, 0x41, 0x49, 0x49, 0x7a} // 47 G
,{0x7f, 0x08, 0x08, 0x08, 0x7f} // 48 H
,{0x00, 0x41, 0x7f, 0x41, 0x00} // 49 I
,{0x20, 0x40, 0x41, 0x3f, 0x01} // 4a J
,{0x7f, 0x08, 0x14, 0x22, 0x41} // 4b K
,{0x7f, 0x40, 0x40, 0x40, 0x40} // 4c L
,{0x7f, 0x02, 0x0c, 0x02, 0x7f} // 4d M
,{0x7f, 0x04, 0x08, 0x10, 0x7f} // 4e N
,{0x3e, 0x41, 0x41, 0x41, 0x3e} // 4f O
,{0x7f, 0x09, 0x09, 0x09, 0x06} // 50 P
,{0x3e, 0x41, 0x51, 0x21, 0x5e} // 51 Q
,{0x7f, 0x09, 0x19, 0x29, 0x46} // 52 R
,{0x46, 0x49, 0x49, 0x49, 0x31} // 53 S
,{0x01, 0x01, 0x7f, 0x01, 0x01} // 54 T
,{0x3f, 0x40, 0x40, 0x40, 0x3f} // 55 U
,{0x1f, 0x20, 0x40, 0x20, 0x1f} // 56 V
,{0x3f, 0x40, 0x38, 0x40, 0x3f} // 57 W
,{0x63, 0x14, 0x08, 0x14, 0x63} // 58 X
,{0x07, 0x08, 0x70, 0x08, 0x07} // 59 Y
,{0x61, 0x51, 0x49, 0x45, 0x43} // 5a Z
,{0x00, 0x7f, 0x41, 0x41, 0x00} // 5b [
,{0x02, 0x04, 0x08, 0x10, 0x20} // 5c ¥
,{0x00, 0x41, 0x41, 0x7f, 0x00} // 5d ]
,{0x04, 0x02, 0x01, 0x02, 0x04} // 5e ^
,{0x40, 0x40, 0x40, 0x40, 0x40} // 5f _
,{0x00, 0x01, 0x02, 0x04, 0x00} // 60 `
,{0x20, 0x54, 0x54, 0x54, 0x78} // 61 a
,{0x7f, 0x48, 0x44, 0x44, 0x38} // 62 b
,{0x38, 0x44, 0x44, 0x44, 0x20} // 63 c
,{0x38, 0x44, 0x44, 0x48, 0x7f} // 64 d
,{0x38, 0x54, 0x54, 0x54, 0x18} // 65 e
,{0x08, 0x7e, 0x09, 0x01, 0x02} // 66 f
,{0x0c, 0x52, 0x52, 0x52, 0x3e} // 67 g
,{0x7f, 0x08, 0x04, 0x04, 0x78} // 68 h
,{0x00, 0x44, 0x7d, 0x40, 0x00} // 69 i
,{0x20, 0x40, 0x44, 0x3d, 0x00} // 6a j
,{0x7f, 0x10, 0x28, 0x44, 0x00} // 6b k
,{0x00, 0x41, 0x7f, 0x40, 0x00} // 6c l
,{0x7c, 0x04, 0x18, 0x04, 0x78} // 6d m
,{0x7c, 0x08, 0x04, 0x04, 0x78} // 6e n
,{0x38, 0x44, 0x44, 0x44, 0x38} // 6f o
,{0x7c, 0x14, 0x14, 0x14, 0x08} // 70 p
,{0x08, 0x14, 0x14, 0x18, 0x7c} // 71 q
,{0x7c, 0x08, 0x04, 0x04, 0x08} // 72 r
,{0x48, 0x54, 0x54, 0x54, 0x20} // 73 s
,{0x04, 0x3f, 0x44, 0x40, 0x20} // 74 t
,{0x3c, 0x40, 0x40, 0x20, 0x7c} // 75 u
,{0x1c, 0x20, 0x40, 0x20, 0x1c} // 76 v
,{0x3c, 0x40, 0x30, 0x40, 0x3c} // 77 w
,{0x44, 0x28, 0x10, 0x28, 0x44} // 78 x
,{0x0c, 0x50, 0x50, 0x50, 0x3c} // 79 y
,{0x44, 0x64, 0x54, 0x4c, 0x44} // 7a z
,{0x00, 0x08, 0x36, 0x41, 0x00} // 7b {
,{0x00, 0x00, 0x7f, 0x00, 0x00} // 7c |
,{0x00, 0x41, 0x36, 0x08, 0x00} // 7d }
,{0x10, 0x08, 0x08, 0x10, 0x08} // 7e ←
,{0x78, 0x46, 0x41, 0x46, 0x78} // 7f →
};
void LcdCharacter(char character)
{
LcdWrite(LCD_D, 0x00);
for (int index = 0; index < 5; index++)
{
LcdWrite(LCD_D, ASCII[character - 0x20][index]);
}
LcdWrite(LCD_D, 0x00);
}
void LcdClear(void)
{
for (int index = 0; index < LCD_X * LCD_Y / 8; index++)
{
LcdWrite(LCD_D, 0x00);
}
}
void LcdInitialise(void)
{
pinMode(PIN_SCE, OUTPUT);
pinMode(PIN_RESET, OUTPUT);
pinMode(PIN_DC, OUTPUT);
pinMode(PIN_SDIN, OUTPUT);
pinMode(PIN_SCLK, OUTPUT);
digitalWrite(PIN_RESET, LOW);
delay(1);
digitalWrite(PIN_RESET, HIGH);
LcdWrite( LCD_CMD, 0x21 ); // LCD Extended Commands.
LcdWrite( LCD_CMD, 0xC4 ); // Set LCD Vop (Contrast). //B1
LcdWrite( LCD_CMD, 0x04 ); // Set Temp coefficent. //0x04
LcdWrite( LCD_CMD, 0x14 ); // LCD bias mode 1:48. //0x13
LcdWrite( LCD_CMD, 0x0C ); // LCD in normal mode. 0x0d for inverse
LcdWrite(LCD_C, 0x20);
LcdWrite(LCD_C, 0x0C);
}
void LcdString(char *characters)
{
while (*characters)
{
LcdCharacter(*characters++);
}
}
void LcdWrite(byte dc, byte data)
{
digitalWrite(PIN_DC, dc);
digitalWrite(PIN_SCE, LOW);
shiftOut(PIN_SDIN, PIN_SCLK, MSBFIRST, data);
digitalWrite(PIN_SCE, HIGH);
}
void gotoXY(int x, int y)
{
LcdWrite( 0, 0x80 | x); // Column.
LcdWrite( 0, 0x40 | y); // Row.
}
void setup(void)
{
LcdInitialise();
LcdClear();
LcdString("Voltagem");
LcdString("(V)");
gotoXY(0,42);
LcdString("no pino A0");
}
void loop(void)
{
temp = map(analogRead(0),0,1023,0,910);
contraste=map(analogRead(1),0,1023,byte(0xB0),byte(0xCF));
digitalWrite(PIN_RESET, HIGH);
LcdWrite( LCD_CMD, 0x21 ); // LCD Extended Commands.
LcdWrite( LCD_CMD, contraste ); // Set LCD Vop (Contrast). //B1
LcdWrite( LCD_CMD, 0x04 ); // Set Temp coefficent. //0x04
LcdWrite( LCD_CMD, 0x14 ); // LCD bias mode 1:48. //0x13
LcdWrite( LCD_CMD, 0x0C ); // LCD in normal mode. 0x0d for inverse
LcdWrite(LCD_C, 0x20);
LcdWrite(LCD_C, 0x0C);
float valor=temp*50;
g=int(valor/10000);
b=int(valor/1000-10*g);
c=int(valor/100-(100*g+10*b));
delay(30);
gotoXY (0,52);
LcdCharacter(map(g,0,3,48,51));
delay(30);
gotoXY (15,52);
LcdCharacter('.');
delay(30);
gotoXY (20,52);
delay(30);
LcdCharacter(map(b,0,9.0,48,57));
delay(30);
gotoXY (30,52);
delay(10);
LcdCharacter(map(c,0,9.0,48,57));
delay(50);
gotoXY(45,60);
delay(50);
}
Vamos entender o sketch - programa do Arduino escrito em Wiring - que serviu de base e foi emprestado de www.arduino.cc:
Solucionática em ação:
Esse sketch, originalmente, só aceitava variáveis dos tipos: byte ou inteiro (int); caracteres (character), entre aspas simples, p. ex '$'; string (cadeia de caracteres, também entre aspas simples, p.ex 'ABCD'). Os void (methods, procedures, rotinas etc, do Wiring/Processing) principais desse programa são:
Qual a problemática:
A nossa variável voltagem é o valor lido na porta analógica 0, por meio do comando analogRead (0) do Arduino. Esse comando retorna um valor do tipo byte entre 0 e 1023 (1024 intervalos discretos que equivale a 2^10, ou seja o conversor A/D é de 10 bits). Se mandarmos escrever diretamente no display o valor lido na porta não vai aparecer o valor da grandeza que estamos medindo, a tensão por exemplo, mas apenas um caracter que corresponda ao valor entre 0 e 1023 (só há caracteres ASCII entre 0 e 255!!!!).
O sketch foi feito para mostrar no display um caracter de cada vez, em uma matriz de 84X48. Ora, a tabela ASCII (extendida), como dissemos acima, representa os caracteres com valores de 0 a 255. Um valor byte de 0 a 1023 não tem como ser corretamente representado, sem uma adequação.
(obs: tabelas retiradas de http://www.asciitable.com/)
Mas o que queremos é que o nosso display mostre corretamente tanto letras, números e alguns caracteres especiais (p. ex.: Voltagem = 3,31 V ou Temperatura = 35°C). Para os textos e símbolos usar a rotina LcdCharacter (char) diretamente, onde char é o caractere que se quer escrever, por exemplo '°' (o símbolo de graus celsius). Assim, para que nosso display mostre grandezas elétricas, como temperatura e tensão, além de textos e alguns símbolos, precisamos adaptar o programa. Mas, na hora de mostrar o valor medido com duas casas decimais (uma tensão elétrica, p. ex) vai ser preciso fazer umas continhas que podem parecer, mas não são complicadas. Vamos entender como e por que isso é feito.
Vamos supor que o valor lido na porta analog (0) seja 345, pois como já dissemos quando a gente executa a instrução analogRead o resultado é um número entre 0 e 1023. Para obter o valor de tensão equivalente temos que fazer a conversão do digital para analógico, ou seja, vamos dividir a faixa de tensão(0 a 5V) em 1024 pedaços de aproximadamente 0,0048V (5/1024 =0,0048828125V). Logo, a variável que vai armazenar o valor convertido (chamamos de valor) do pedaço de número 345 é igual a valor=temp X 0,00488 = 345 X 0,00488=1,65 V. Notem algo importante: como desprezamos a partir da quinta casa decimal, houve um "erro de quantização" em nossa medida, pois 345 X 0,0048828125 = 1,68V , que nos dá um erro de 0,03V.
Para diminuir o erro, teríamos que usar dez casas decimais do nosso fator de conversão (0,0048828125) em nossa variável valor, assim o número 345, ou seja 1,68 V, pode ser escrito no display mais corretamente. Mas vamos conviver com esse erro, que é menor que 3%. O sketch que tomamos por base só representa um caracter por vez e só aceita números inteiros (byte ou int). No Wiring, para converter um número de um tipo para outro, usamos a seguinte sintaxe:V=int(temp), onde temp é igual a 1,65, no nosso exemplo.
Assim, quando trabalhamos com os decimais, ou melhor dizendo, com "ponto flutuante" (tipo float) é preciso fazer uma manobra matemática para obter a parte inteira, e os decimais, um de cada vez. Obviamente, perdemos em velocidade em aplicações mais críticas, o que não é o nosso caso, mas o float deve ser evitado sempre que possível.
E por que mesmos usamos o float no nosso sketch? O motivo é que os valores contínuos (analógicos) de tensão presentes no pino AnalogRead() do Arduino são representados com maior precisão em variáveis do tipo float do que em int. O nosso objetivo é apresentar valores entre 0,00 e 3,30, por exemplo. valores maiores podem também ser medidos, mas temos que alterar o hardware e colocar divisores de tensão e acrescentar os fatores de escala no sketch.
Desse modo, incluímos algumas modificações em um trecho do programa que permitirão ao display (que só entende caractere ASCII ) mostrar os valores contínuos de tensão que no nosso exemplo se referem à voltagem de 0 a 3,3V aplicada à entrada analógica 0 do Arduino por meio de um potenciômetro. E por quê não usamos 5V? Porque o display é alimentado com 3,3V. Mas nada impede que o potenciômetro receba 5V, basta alterar uma instrução do programa: de LcdCharacter(map(g,0,3,48,51)) para
LcdCharacter(map(g,0,5,48,53)).
Mais em baixo vamos comentar linha por linha. Quando acabar, o leitor terá aprendido um monte de coisa e tido a ideia de encontrar uma solução mais elegante, o que não foi o nosso caso.
Observação importante sobre o Wiring: todo sketch tem que ter o void loop. É chamada de ronda principal - termo antigo do tempo dos mainframes (você sabe o que é um mainframe?). Hoje, sem muito constrangimento, chamaremos de loop principal e pronto! O (void), após o nome dessa e de outras rotinas, quer dizer que não há nenhum valor de variável a ser passado para, ela é simplesmente executada ao ser chamada.
Agora vamos explicar algumas linhas do código:
void loop(void)
{
temp = analogRead(0);
Nessa linha o Arduino lê o valor da porta 0 (obs: a tensão de referência é 5V - a alimentação do Arduino - pois não estamos usando Vref! Assim e os valores vão de 0 a 1023, logo o passo é 5/1023 = 0.0048...
float valor=temp*48
Aqui é a instrução de conversão digital para analógica. Multiplicamos o valor lido (0 a 1023) por 48 (não diga!)
g=int(valor/10000);
Atribuímos à variável g o inteiro da conta valor/10000 para obter o primeiro dígito a ser mostrado. Por exemplo, para temp=345, vamos ter valor=345*48 = 16560. Assim, o valor da variável g, quando dividimos por 10000, vale o inteiro de 1.6560 que é igual a 1. Lembre-se que as linguagens de programação, em geral, usam a notação americana, onde o separador é o "." e não a "," (esse detalhe faz muita diferença). O separador de milhar é o contrário (",")
b=int(valor/1000-10*g);
Atribuímos à variável b o inteiro da conta valor/1000 - 10*g para obter o decimal, que é o segundo dígito. Vamos substituir os valores das variáveis para exemplificar melhor as contas? Nesse passo temos que temp=345; valor = 16560; g=1. Logo, a variável b será: b=int(16560/1000 - 10*1) = int(16.56-10)=int(6.56)=6. Pronto, temos o segundo número.
c=int(valor/100-(100*g+10*b)); aqui há uma diferença: somamos g e b, com seus respectivos pesos, ou seja 100 e 10. Para o exemplo dado, temos:
c=int(16560/100-(100*1+10*6))=int(165.6-(100+60))=int(165.6-160)=int(5.6)=5. Chegamos ao terceiro dígito: 5. Sabemos, agora, que o pedaço 345 representa 1,65 Volts de tensão!
delay(10);
Dá um tempinho pro display descansar....
gotoXY (20,42);
Manda o cursor para a posição coluna 20 e linha 42 (o display é de 84X48), onde será escrito o primeiro número!
LcdCharacter(map(g,0,3,48,51));
A instrução chama a subrotina que escreve uma caractere no display(LcdCharacter). Ela espera um valor decimal. Os caracteres ASCII estão entre 32 e 128 (20 a 7F em hexadecimal). Convertemos, então, o valor da medida do dígito mais significativo , que varia entre 0 e 3 (suponha o valor máximo de Vcc=3.3V) para a faixa de 48 a 51 ( o valor ASCII do caracter "0" é 48 em decimal, em hexadecimal é 32; o "1" é 49 em decimal e 33 em hexadecimal, 0 "2" é 50 em decimal e 34 em hexa e por aí vai...No nosso caso, vamos escrever 49 que equivale ao número 1, que é o nosso primeiro número da medida.
gotoXY (30,42);
Manda o cursor para coluna 30 e linha 42
LcdCharacter('.');
Escreve um ponto (".") nesse local, para separar o inteiro do decimal.
delay(10); sempre após um comando, é preciso dar um tempinho para o display aceitar um novo comando.
gotoXY (35,42); aqui vamos escrever o segundo algarismo, no caso um 6!
O cursor foi para onde?
LcdCharacter(map(b,0,9,48,57));
Prepara o decimal para a faixa de "0" a "9" ("0"=48; "1"=49; "2"=50..."9"= 57). No exemplo, temos o "6" que equivale em ASCII a 53 (decimal). Na dúvida pesquisa na tabela ASCII mais embaixo.
gotoXY (40,42); temos que enviar o cursor para a posição logo após o "6" que escrevemos a pouco.
LcdCharacter(map(c,0,9,48,57));
O processo poderia continuar para mais casas decimais. Contudo, essa precisão de duas casas já é suficiente para a maioria das aplicações.
Obs: As chaves ("{" e "}" ) são os delimitadores das rotinas, as tais void().
Note que a função float converte para ponto flutuante e já informa a precisão (0.000) igual na linguagem Python ( o "basic" dos anos 90). Quando se estuda física experimental aprendemos que precisão é o grau de variação de uma medida (0.3, 0.03 ou 0.003) que é diferente da exatidão, que se refere à conformidade com o valor real (Wikipedia).
Para quem quer montar seu circuito, eis o sketch completo. Quem se aventura a entender o resto do programa? Vale uma bala soft ou um pirulito de caramelo zorro! Só uma dica: a maior parte do programa é a tabela ASCII...
Outra dica : os pinos do Arduino onde vamos ligar o LCD estão indicados logo no início (76543). E cuidado com a tensão de alimentação do Arduino, pois se for de 5V é preciso equalizar o barramento , por meio de divisores de tensão,para que os 5V se transformem nos 3.3V, que é a tensão de alimentação do display. Assim, para cada uma das linhas de controle tem que colocar um divisor de tensão formado por um resistor de 33K e outro de 22K.
A conta é simples. Supondo 5V de entrada, teremos na saída do divisor: 33K/(22K+33K)*5V= (33/55)*5V= 0,6 * 5V= 3V. Os resistores são ligados em série, sendo o de 33K ligado ao terra e o de 22K ligado aos pinos do Arduino (7, 6, 5, 4 e 3). Mas pra quê isso?! Para que a tensão de 5V da saída do Arduino não danifique a entrada do display que foi feita para aguentar 3.3V!!! Alternativamente, é possível usar resistores de 10K em série.
Conclusão
O que aprendemos aqui? Primeiramente, travamos um "diálogo" com o passado, ou seja, conseguimos fazer funcionar um display que tem cerca de 15 anos de idade, ia parar no lixo, e agora pode servir em algum projeto.
Além disso, conhecemos um sketch do Arduino e tomamos conhecimento do funcionamento das subrotinas ("void"), aprendemos a tabela ASCII (American Standard Code for Information Interchange). Na nossa caminhada, também conhecemos o conversor A/D do Arduino.
Não esqueçam o desafio: melhorar o algoritmo que transforma uma variável do tipo BYTE (0 a 1023) em float com duas casas decimais. Lembre que o programa não aceita o argumento float. Para isso tem que modificar a subrotina lcdWrite, pelo menos. Fica a dica.
Quem chegou até aqui, é porque está interessado em aprender um pouco mais. Vou facilitar e detalhar a pinagem (pinout, em inglês, é a "senha" a ser usada nas ferramentas de busca...tá bom, no Google!, para localizar as pinagens dos componentes eletrônicos em geral, inclusive de displays de outros modelos de celular, p. ex façam uma busca por "Sony Ericsson T68i pinout" - nosso futuro display a ser testado).
(Obs: retirado de http://iteadstudio.com/userfiles/DATASHEET.jpg)
Vamos por partes:
1 - Vcc: aceita no mínimo 2,7V até 3,3V de tensão. Já falei que não pode alimentar com 5 V, vai queimar seu display!
2 - GND : terra.
3 - SCE: chip enable, ou simplesmente enable, significa que se estiver em GND o display está habilitado. Se ligado a Vcc (3.3V) o display não funciona.
4 - Res (Reset) - reinicializa o display. A rotina de reset obedece a temporizações que não podem ser desprezadas, sob pena de danificar o display. Logo, não fique resetando o display de qualquer jeito! Olhem a rotina de inicialização no sketch, para ver como foi feita no nosso projeto!
5 - D/C : Data/Command. Lembram das rotinas que configuram o display? Pois elas usam esse pino para mandar os dados/comandos para o display.
6 - SDIN Serial Input - entrada de dados seriais do protocolo I2C - o microcontrolador que está dentro desse display é o PCD8544 da Phillips, assim podemos chamar o protocolo de I2C mesmo, nada de TIW, por exemplo!
7 - SCLK Clock Input - é o clock. Também do protocolo I2C.
8 - LED. É a retroiluminação do display ou backligth.