sexta-feira, 31 de janeiro de 2014

Olho de LCD com Arduino e Nokia 5110 - #sucesso

E... voilá!!


Consegui fazer o Olho de LCD usando um display Nokia 5110 e o Arduino!!!


De início eu havia pensado em gerar um arquivo bitmap (BMP) e convertê-lo depois em código usando uma ferramenta automatizada. Ou pelo menos foi o que eu escrevi que ia fazer no meu último post...

Acabei fazendo uma coisa bem diferente... Foi um trabalho mais braçal, mas deu certo.

Primeiro, marquei com uma canetinha vermelha as divisas das linhas do display, a cada 8 quadradinhos. O display recebe os dados a exibir na forma de bytes. Cada byte contém oito bits, então os dados chegam ao display na forma de linhas com oito bits de espessura. Foram essas linhas que marquei.

Para cada uma das 6 linhas, montei uma sequência de bytes. Para ficar bem claro no código, escrevi os bytes usando o sistema binário, assim:

0b00000000 //uma linha em branco
0b11111111 //uma linha preta

O "0b" no início diz ao Arduino que estou usando o sistema binário, ou seja, só zeros e uns.
Tive que escrever o correspondente de 0 ou 1 para cada quadradinho da grade que forma o display. Ou seja, 84 x 48 = 4032. Claro que usei um bocado de Ctrl + C, Ctrl + V e escrevi em linhas de 8 bits, então foram apenas 504 linhas de código para descrever o desenho... ;)
O código inteiro está aí embaixo, usem à vontade!


Se fizerem melhorias para ele olhar para os lados, piscar, etc, por favor compartilhem! Eu quero fazer isso também, mas se forem mais rápidos que eu, vai me poupar um bocado de trabalho!

Abraços!


//Olho de LCD - v1
//Controlador de Display LCD Nokia 5110 (84x48 pixels)
//em 31 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

byte linhaUm[84] = {
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //5
      0b00000000,
      0b00000001,
      0b00000010,
      0b00000100,
      0b00000100,  //10
      0b00001000,
      0b00001000,
      0b00010000,
      0b00100000,
      0b00100000,  //15
      0b00100000,
      0b01000000,
      0b01000000,
      0b01000000,
      0b01000000,  //20
      0b01000000,
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,  //25
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,  //30
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,  //35
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,  //40
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,  //45
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,  //50
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,  //55
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,  //60
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,
      0b01000000,  //65
      0b01000000,
      0b00100000,
      0b00100000,
      0b00010000,
      0b00010000,  //70
      0b00001000,
      0b00001000,
      0b00000100,
      0b00000010,
      0b00000010,  //75
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //80
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000
};

byte linhaDois[84] = {
      0b00000000,
      0b00000011,
      0b00001100,
      0b00110000,
      0b01000000,  //5
      0b10000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //10
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //15
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //20
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //25
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //30
      0b00000000,
      0b00000000,
      0b00000001,
      0b00000011,
      0b00000111,  //35
      0b00000111,
      0b00001111,
      0b00001111,
      0b00001110,
      0b00011110,  //40
      0b00011111,
      0b00011111,
      0b00011111,
      0b00011111,
      0b00011111,  //45
      0b00011111,
      0b00011111,
      0b00011111,
      0b00011111,
      0b00011111,  //50
      0b00011111,
      0b00011111,
      0b00011111,
      0b00011111,
      0b00011111,  //55
      0b00011111,
      0b00011111,
      0b00011111,
      0b00001111,
      0b00001111,  //60
      0b00001111,
      0b00001111,
      0b00001111,
      0b00001111,
      0b00000111,  //65
      0b00000111,
      0b00000011,
      0b00000001,
      0b00000000,
      0b00000000,  //70
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //75
      0b00000000,
      0b10000000,
      0b01000000,
      0b00100000,
      0b00010000,  //80
      0b00001000,
      0b00000110,
      0b00000001,
      0b00000000
};

byte linhaTres[84] = {
      0b11111111,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //5
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //10
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //15
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //20
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //25
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00001111,  //30
      0b00111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,  //35
      0b10001111,
      0b00000111,
      0b00000111,
      0b00000011,
      0b00000011,  //40
      0b00000011,
      0b00000111,
      0b00001111,
      0b11111111,
      0b11111111,  //45
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,  //50
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,  //55
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,  //60
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,  //65
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b00111111,  //70
      0b00001111,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //75
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //80
      0b00000000,
      0b00000000,
      0b10000000,
      0b01111111
};

byte linhaQuatro[84] = {
      0b11111000,
      0b00000110,
      0b00000001,
      0b00000000,
      0b00000000,  //5
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //10
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //15
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //20
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //25
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b11100000,  //30
      0b11111000,
      0b11111100,
      0b11111111,
      0b11111111,
      0b11111111,  //35
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,  //40
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,  //45
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,  //50
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,  //55
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,  //60
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111001,
      0b11111001,  //65
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111110,  //70
      0111111000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //75
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //80
      0b00000000,
      0b00000000,
      0b00001111,
      0b11110000
};

byte linhaCinco[84] = {
      0b00000000,
      0b00000000,
      0b00000000,
      0b11000000,
      0b00110000,  //5
      0b00001100,
      0b00000010,
      0b00000001,
      0b00000000,
      0b00000000,  //10
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //15
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //20
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //25
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //30
      0b00000000,
      0b00000000,
      0b00000000,
      0b10000000,
      0b11000000,  //35
      0b11000000,
      0b11100000,
      0b11100000,
      0b11110000,
      0b11110000,  //40
      0b11110000,
      0b11111000,
      0b11111000,
      0b11111000,
      0b11111000,  //45
      0b11111000,
      0b11111000,
      0b11111000,
      0b11111000,
      0b11111000,  //50
      0b11111000,
      0b11111000,
      0b11111000,
      0b11111000,
      0b11111000,  //55
      0b11111000,
      0b11111000,
      0b11111000,
      0b11111000,
      0b11111000,  //60
      0b11110000,
      0b11110000,
      0b11110000,
      0b11110000,
      0b11100000,  //65
      0b11100000,
      0b11000000,
      0b11000000,
      0b10000000,
      0b00000000,  //70      
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //75
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000011,
      0b00000100,  //80
      0b00011000,
      0b01100000,
      0b10000000,
      0b00000000
};

byte linhaSeis[84] = {
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //5
      0b00000000,
      0b00000000,
      0b00000000,
      0b10000000,
      0b01000000,  //10
      0b00100000,
      0b00010000,
      0b00010000,
      0b00001000,
      0b00001000,  //15
      0b00001000,
      0b00000100,
      0b00000100,
      0b00000100,
      0b00000010,  //20
      0b00000010,
      0b00000010,
      0b00000010,
      0b00000010,
      0b00000001,  //25
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,  //30
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,  //35
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,  //40
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,  //45
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,  //50
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,  //55
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,  //60
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000010,
      0b00000010,  //65
      0b00000010,
      0b00000010,
      0b00000010,
      0b00000010,
      0b00000100,  //70
      0b00000100,
      0b00000100,
      0b00001000,
      0b00010000,
      0b00100000,  //75
      0b00100000,
      0b01000000,
      0b10000000,
      0b00000000,
      0b00000000,  //80
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000
};

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)
  
  limpaTela();
  
  desenhaLinha(linhaSeis);
  desenhaLinha(linhaCinco);
  desenhaLinha(linhaQuatro);
  desenhaLinha(linhaTres);
  desenhaLinha(linhaDois);
  desenhaLinha(linhaUm);   
}
  
void limpaTela(void) {
  //Percorre todas as posicoes
  for (int index = 0; index < LCD_X * LCD_Y / 8; index++)
  {
    LcdWrite(HIGH, 0);
  }
}

void desenhaLinha(byte linha[]) {
  //Percorre as colunas
  for (int coluna = 0; coluna < LCD_X; coluna++)
  {
    LcdWrite(HIGH, linha[coluna]);
  }
}


//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
}

void loop(void)
{  
  //nada
}


Você pode ver todas as etapas deste projeto usando este link, ou clicando no marcador "olho_de_lcd", abaixo.

segunda-feira, 27 de janeiro de 2014

Criando um bitmap para LCD Gráfico

Há algum tempo comecei um projeto para fazer um olho de brinquedo usando um LCD Gráfico Nokia 5110. A primeira tentativa falhou, mas depois entendi como o display funciona. Resta agora colocar o meu desenho nele.

Mas que desenho?

Pois bem, como é que você desenha algo para ficar bem em determinada resolução? Eu tive que testar imprimindo uma grade na resolução do display (84x48) para rabiscar em cima.

Claro que eu poderia criar uma imagem de 84 por 48 pixels e rabiscar no computador, mas de que jeito minha filha e nossa cachorrinha participariam do projeto?


Então, para permitir mais participação, criei a grade no computador e imprimi para desenhar. Minha primeira escolha de software seria o Inkscape, mas achei mais fácil fazer no Gimp.

A primeira coisa que descobri é que uma grade de 24 por 24 pixels permite você numerar os quadrados numa boa, então usei esse tamanho. Assim, minha imagem tinha que ter 24 vezes 84 de altura e 24 vezes 48 de largura, o que dá 1152 x 2016 pixels.

Com a imagem no tamanho certo, basta criar a grade. Vá em:
Filtros -> Renderizar -> Padrão -> Grade



Achou o caminho estranho? Pois é, eu também achei...

Nas opções da grade você só precisa alterar os campos  de "Espaçamento". O padrão é 16x16, mas eu usei 24x24, como mencionei acima.

Salvei um arquivo PNG e mandei imprimir a partir do visualizador de imagens. Não sei se dava para imprimir direto do Gimp. Estou tão acostumado a fazer desse jeito que nem tentei...

O resultado final está aí do lado. Talvez, se eu tivesse usado um scanner, daria para pegar a imagem direto e redimensionar para 48x84 e já jogar em um conversor de bitmap para bytes e partir para o abraço, mas...

Não tenho um scanner e o conversor de bitmaps indicado pela Sparkfun está fora do ar... Isso quer dizer que ainda terei mais algum trabalho com esse projeto e que teremos mais posts no blog sobre o assunto.

Nos vemos em breve!

Você pode ver todas as etapas deste projeto usando este link, ou clicando no marcador "olho_de_lcd", abaixo.

quinta-feira, 16 de janeiro de 2014

LCD Nokia 5110 com Arduino #sucesso

No meu post anterior eu falei que comprei um display LCD Nokia 5110 no MercadoLivre e, inicialmente não consegui fazê-lo funcionar... Depois eu atualizei o post dizendo que ele funcionou e fiquei de dar mais detalhes depois. Bom, aqui estão os detalhes!

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 LCDResistorArduinoCor
1-RST10kPino 6Vermelho
2-CE10kPino 7Azul
3-DC10kPino 5Amarelo
4-DIN10kPino 4Verde
5-CLK10kPino 3Azul
6-VCC-3.3vVermelho
7-LIGHT330RGNDAzul
8-GND-GNDPreto

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.

sexta-feira, 10 de janeiro de 2014

Como criar um componente para o Fritzing

Quando fui documentar o meu projeto de criar um olho de brinquedo usando um display LCD Nokia 5110, descobri que o Fritzing não tem um desenho deste display. E agora? Como fazer para desenhar?

A referência oficial do Fritzing que achei na internet dizia estar desatualizada e mandava ir procurar no blog deles, mas não tinha um link direto.


Na verdade, a instrução estava desatualizada por existir um novo editor de partes dentro do Fritzing desde a versão 0.7.9, mas a versão que eu tinha (0.6.3, a que você encontra na Central de Programas do Ubuntu) ainda não vinha com esse editor.

Fritzing 0.8.5
Dei uma pesquisada e o editor novo me pareceu bem melhor que o anterior, então baixei a versão atual do Fritzing, a 0.8.5. Se estiver usando o Ubuntu, recomendo você baixar a versão disponível na Central de Programas do Ubuntu primeiro e depois instalar essa, isso garante que as dependências estarão atendidas.

O post do blog do Fritzing que detalha como usar o novo editor de componentes está neste link:
http://blog.fritzing.org/2012/10/09/new-parts-editor-released/

Tudo o que escrevi aqui aprendi lendo esse post, então se tiverem dúvidas, vão ali primeiro.

O editor de componentes (parts) do Fritzing precisa começar sempre de um componente existente. Como estamos trabalhando com um display de LCD, faz todo sentido partir de outro display de LCD. O Nokia 5110 é um display gráfico, então eu inseri um display gráfico 128 x 64.

A partir daí, você pode clicar no componente com o botão direito e selecionar Editar ou ir em Componente -> Editar (Criador de Novos Componentes).

Para criar as imagens, eu exportei para SVG o desenho do display de 128x64 (verde) e o abri no Inkscape. O desenho já chegou no Inkscape com medidas corretas (para um display grande). Usando medidas em mm, consegui redesenhar o meu display. Tomei alguns cuidados para conseguir importá-lo de volta no Fritzing:
  • Não mexi na posição inicial do desenho (que começa nas coordenadas 0,0);
  • Alterei o tamanho total do desenho SVG (Propriedades do Documento) e o deixei do tamanho do meu componente (43,5x43mm);
  • Não mexi nos pinos que já existiam, só removi os que estavam sobrando.
O que eu fiz foi basicamente desagrupá-lo todo, mudar a cor, apagar vários dos pinos e aplicar as medidas que eu mesmo obtive com uma régua. Evitei tentar colocar os pinos de cima, já que não iria precisar deles.

Ao voltar para o Fritzing, carreguei minha imagem (Ctrl+O) e ele magicamente já identificou os pinos, deixando os que apaguei desmarcados (não encontrados).


Fui até a aba "Conectores" e apaguei os conectores de 1 a 12 (os mesmos que eu tinha apagado do desenho) e reajustei os demais conforme a realidade (1 a 8, RST, CE, DC, etc.)

Na aba "Metadado", preenchi as informações sobre o componente. Na aba "Ícone", fui em Arquivo -> "Reusar imagem do protoboard".


Para a aba "PCB" você tem que gerar um novo arquivo SVG. Você faz o mesmo processo da visão Protoboard: exportar o desenho existente e editar.

A única coisa diferente é que os pontos de solda têm que estar em um grupo chamado "copper0". Para isso, você agrupa os circulos que representam os pontos de solda (Ctrl+G) e edita o nome do grupo apertando Ctrl+Shift+X e alterando a propriedade "id" para "copper0". Ctrl+Enter grava a alteração do nome no campo. Salve o arquivo e o importe no Fritzing que ele vai reconhecer.


A aba Esquemático você pode fazer como quiser, basta usar as fontes corretas. Se não usar, não tem problema, o Fritzing troca para você.

Pronto! Agora você já pode usar o componente que você desenhou no seu projeto!


O componente que eu criei você pode pegar aqui e usar como quiser.

UPDATE: No dia 16/01/2014, postei um exemplo de como colocar o display para funcionar, com código e tudo. Veja aqui.

Você pode ver todas as etapas deste projeto usando este link, ou clicando no marcador "olho_de_lcd", abaixo.



terça-feira, 7 de janeiro de 2014

Olho de LCD com Arduino e Nokia 5110 - #fail

Minha filha tem um brinquedo com olhos muito expressivos feitos de LCD, vejam:


Eu fiquei tão fascinado por estes olhos que quis reproduzí-los com o Arduino, então comprei um display LCD Nokia 5110.

Para este projeto, contei com a colaboração da dona do brinquedo:


ATENÇÃO: Se você é fã dos 2Carneiros e esperava encontrar aqui um vídeo nosso montando o projeto, você não precisa ler mais nada. Vá direto aos comentários e peça um vídeo, aqui eu só postei esse gif animado. Se isso não resolver, se inscreva no blog e no canal do YouTube, peça pelo Facebook, me aborde na rua ou xingue muito no Twitter. O resto deste post é para as pessoas interessadas em Arduino e afins.

 O display que comprei vem em um mini kit feito de uma tela de LCD com uma moldura que o fixa em uma placa de circuito (breakout board). Esta placa tem furos identificados de 1 a 8 na frente e por suas funções, no verso. Nestes furos você pode soldar uma barra de pinos (fornecida no kit).



Para soldar os pinos na placa eu usei um conector jacaré para segurá-los no lugar e uma terceira mão para manter uma altura confortável. Depois de soldar os pinos no lugar, você já pode encaixar o seu display na breadboard.

Como as indicações das funções dos pinos ficam no verso, recomendo você anotar em um papel para deixar à mão. Isso vai te poupar de ficar virando o display de um lado para o outro enquanto monta o circuito.

Existem muitas referências na internet de como utilizar esse display de LCD. Eu utilizei as orientações da página da Sparkfun.

Se for utilizar a mesma referência, você deve ficar atento para a localização dos pinos. O produto que você comprou pode ter pinos em locais diferentes do que os do produto da Sparkfun.

No meu caso, fazendo as devidas substituições, ficou assim:




Pino LCDResistorArduinoCor
1-RST10kPino 6Vermelho
2-CE1kPino 7Azul
3-DC10kPino 5Amarelo
4-DIN10kPino 11Verde
5-CLK10kPino 13Azul
6-VCC-3.3vVermelho
7-LIGHT330Pino 9Amarelo
8-GND-GNDPreto

Indiquei as cores só para facilitar o entendimento da foto e do esquema que desenhei no Fritzing. Se for fazer em casa, use a cor que quiser.



Baixei o código sugerido na página da Sparkfun, compilei, subi para o arduino e... nada!

Mentira, o backlight acendeu. E para minha surpresa, ele era azul! Não sei por que, mas achei que seria branco.

O display de LCD deveria ter mostrado várias animações bacanas e até uma chargezinha, mas não vi nada disso.

E aí, desisto?

Ainda não, estou conversando sobre garantia com o fornecedor da peça. Se eu conseguir uma reposição, posto aqui o resultado. Se não, vou recorrer aos chineses...

Aguardem cenas do próximo episódio!

UPDATE (em 10/01/2014): O fornecedor do display (EletroKits, no MercadoLivre) foi muito atencioso e me mandou uma foto do circuito que ele fez para testar a peça e até um código de teste personalizado, que me permitiu fazer a peça funcionar. Vejam:


UPDATE (em 16/01/2014) Documentei melhor para mostrar para vocês neste post.

UPDATE (em 27/01/2014): 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.