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.

terça-feira, 17 de dezembro de 2013

Os 2Carneiros também fazem entrega com drones

A Amazon fez o maior estardalhaço com sua proposta de utilizar drones nas suas entregas. E o pior é que a ideia nem é nova, a pizzaria Domino's já tinha feito um vídeo semelhante.

Como todo mundo parece estar entrando nessa onda, os 2Carneiros resolveram lançar seu próprio serviço de entregas com drones!

Vejam o vídeo:

sábado, 24 de agosto de 2013

Manjaro - Um Arch Linux para Iniciantes, com Interface Gráfica de Fábrica!!

ATUALIZAÇÃO (em 18/06/2014): sugiro olhar meu post mais recente sobre o assunto, em que ensino a instalar a versão 0.8.9 do Manjaro.

Depois de ler meus posts sobre o Arch Linux (como instalar a versão 2012.09.07 e versão 2013.01.04), muita gente ficou esperando (em vão, foi mal!) um post sobre como colocar uma interface gráfica nele.

E agora, depois de mais de 6 meses apanhando (e fazendo outras coisas, confesso!), finalmente consegui! Não é exatamente o Arch Linux, mas é quase... E o melhor: funciona no meu netbook velho, um ASUS EeePC 2g Surf, lançado em 2007.

Estou falando do Manjaro, uma distribuição Linux que tenta aproveitar as vantagens do Arch Linux de uma forma mais acessível a iniciantes.

O que os desenvolvedores dessa distribuição almejam é disponibilizar um sistema 100% compatível com o Arch Linux, mas que já venha pronto para usar, com interface gráfica e tudo.

E não é que os caras conseguiram? Claro que nem tudo são flores, se não eu não teria levado tanto tempo, não teria escrito este post e você não estaria lendo, mas vou dar o bizú completo para vocês agora.


Se vocês não leram meus posts anteriores, vou resumir. Eu já tinha tentado instalar o Arch Linux duas vezes. Na primeira, sofri um bocado só para conseguir dar boot usando o UNetbootin. Na segunda, sofri bem menos, mas levei um tempão só para colocar o sistema básico rodando (sem interface gráfica).

Com o Manjaro, a coisa foi um pouco mais fácil, mas tive meus percalços. Esse post se destina a te ajudar a evitar esses percalços. Se tiver outras dúvidas, coloque nos comentários, que vou complementando o post.

A versão 0.8.6 é boa. Vai com fé!
- Eu havia tentado instalar o Manjaro 0.8.5, mas o instalador gráfico não funcionava bem na versão 32 bits. Para a versão 0.8.6 isso foi corrigido. Eu usei a versão OpenBox. Acho que li em algum lugar que ela era mais leve, agora não me lembro.
- No momento em que estou escrevendo este post, a versão 0.8.6 é a versão atual. Se você estiver lendo depois e a versão 0.8.6 não estiver disponível, tente uma versão anterior e veja se obtém sucesso. Novas versões tendem a levar algum tempo para estabilizar. No mundo do Linux, muitas vezes as versões com número ímpar apresentam inovações e as versões com número par são mais estáveis. Na dúvida, procure a versão par.

Use a versão i686, isso quer dizer 32 bits!
- Eu sempre me confundo com essas denominações de versões. Quando estava tentando instalar o Arch, ele tinha uma versão "dual", mas depois fiquei na dúvida: i686 ou x86_64? Eu devia ter sacado que "x86_64" é 64 bits, né? Mas achei que i686 era Pentium e x86 era não Pentium (Celeron inclusive?), sei lá... Maluquice minha. Se você está procurando uma distribuição que sirva num computador velho, vá de i686.

2GB não são suficientes! Você precisa de pelo menos 4GB!
- Meu netbook só tem 2GB de SSD internamente. O cartão de memória que eu estava tentando usar também só tinha 2GB. Pode esquecer. Arrumem um cartão SD de 4GB ou um pendrive de pelo menos esse tamanho.

ImageWriter não serve. Use o UNetBootin.
- O manual do Manjaro fala nesse ImageWriter para colocar a mídia ISO do instalador no pendrive. Eu cheguei a instalar esse ImageWriter, mas acabei usando meu bom e velho UNetBootin.
- Na minha primeira tentativa de instalação do Arch Linux, tive que alterar o arquivo syslinux.cfg depois de usar o UNetBootin, mas desta vez, com o Manjaro 0.8.6, não precisei de nada disso. Foi gravar a imagem e partir para a instalação.

GRUB não instala - Path `/boot/grub' is not readable by GRUB on boot. Installation is impossible. Aborting.
- Se você mudou o tipo de filesystem usado pelo cartão SD durante a instalação (de ext3 para ext4, por exemplo), o GRUB vai se perder e não vai conseguir instalar.
- O que você precisa fazer é já estar com o disco particionado quando começar a instalação. Se precisar particionar para instalar, faça assim: comece a instalação e vá até o particionamento. Pare. Reinicie o netbook e comece de novo a instalação, dessa vez pulando o particionamento.
- Lembre-se de, ao particionar, deixar 1MB no início da partição para o GRUB, ou terá o problema abaixo (embedding too small).
Leia mais sobre o assunto aqui (em inglês)


GRUB não instala - "embedding area is unusually small, core.img won't fit in it":
- Você precisa deixar um pequeno espaço no início do cartão SD (ou pendrive) para o boot loader. Se você não fez isso (eu não fiz), você receberá uma tela de erro como esta, dizendo que sua área de "embedding" é muito pequena e que o "core.img" não vai caber nela.
- Aí você tem duas opções: ou começa tudo de novo deixando um espaço vazio no início do cartão SD na hora de particionar; ou
- de dentro do próprio Manjaro, você pode rodar o GParted e mover a primeira partição 1MB para a frente. Você pode fazer isso com a tela do instalador aberta, e depois retomar a instalação. Eu fiz a alteração e voltei no passo "2. Disk Preparation" só para informar qual partição eu estava usando. Depois pulei direto para o passo "5. Install Bootloader" para terminar a instalação.
- A primeira alternativa (começar de novo) não é tão mal, já que a segunda (mover a partição) leva uns 15 minutos. Claro que, se você está lendo isso antes de começar, não vai precisar passar por este problema.
Leia mais aqui (em inglês)

Login não funciona:
- Quando finalmente consegui fazer a instalação completa, descobri que as senhas que informei durante a instalação não funcionavam... O teclado do meu netbook (Asus 2g Surf) é bem pequeno e eu acho que o Num Lock é ligado pelo Manjaro durante o boot, o que muda a letra "o" para "6", o "j" para "1" e outras maluquices que tornam quase impossível digitar uma senha corretamente.
- O problema é que há alguns caracteres que não aparecem na tela, mas o Linux registra na senha e depois você não consegue mais digitar exatamente estes caracteres na hora de logar.
- Para evitar que isso aconteça com você, teste o teclado quando ele te pedir para colocar a senha. Aperte Ctrl+Alt+F1 e vá para o console (tela preta). Se precisar de senha, o usuário padrão é manjaro e a senha é manjaro. Digite qualquer coisa aí e veja se o teclado está funcionando como deveria. Desligue o Num Lock com Fn+F11, se for o caso. Para voltar para a interface gráfica, aperte Alt+F7.
- Se você fez como eu e instalou tudo para descobrir depois que não consegue acertar a senha de jeito nenhum, há uma solução. Siga os passos abaixo.
- Coloque o cartão de memória em outro computador, de preferência um linux em que você tenha acesso como root.
- Procure, no cartão de memória (não no seu computador), o arquivo etc/passwd. Provavelmente vai ser algo como /media/SDCard/etc/passwd. Atenção: não confunda com o /etc/passwd do computador onde você colocou o cartão SD (ou pendrive).
- Altere esse arquivo, onde aparece root:*****:0:0:root (**** é um monte de caracteres, que podem ir até a outra linha). Altere para:
    root::0:0:root
- Isso vai zerar a senha do root, deixando você entrar sem senha. Você pode fazer o mesmo para o usuário manjaro (ou o que você criou). Vai ficar:
    manjaro::1000:100::/home/manjar:/bin/bash
- Altere também o arquivo /media/SDCard/etc/shadow. O procedimento é mesmo, eliminar o campo de senha, deixando o vazio. Algo como:
root::15930::::::
manjaro::15930:0:99999:7:::
- Isso deve resolver. Agora você conseguirá acessar o Manjaro. Recomendo que você coloque senhas nos dois usuários assim que conseguir usá-los.
Leia mais aqui (em inglês)

Próximos passos:
- Com a máquina devidamente instalada, eu recomendaria algumas ações:
- Desligar o Num Lock na inicialização. Ainda não descobri como fazer isso, mas tenho certeza de que há uma maneira. É muito irritante ficar brigando com o tecladinho do netbook. Se você estiver usando um teclado USB plugado nele, acho que nem vai perceber.
- Desligar a inicialização automática da interface gráfica. Meu netbook não é exatamente uma bala e eu me viro bem no console, então acho que deixaria para rodar a interface gráfica quando ela fosse realmente necessária. Depende do que eu for fazer com ele.
- Instalar a IDE do Arduino. Eu tenho brincado muito com o Arduino e acho que esse netbook seria o acompanhamento perfeito para ele, mas ainda não me aventurei a instalar a IDE. Se alguém lendo isso já tiver instalado o Arduino no Manjaro (ou no Arch) e quiser me dar a dica nos comentários, agradeço.

Para ver outros posts similares, clique nas tags manjaro, linux ou netbook, abaixo.

ATUALIZAÇÃO (em 18/06/2014): se você leu tudo e se animou a experimentar o Manjaro, sugiro olhar meu post mais recente sobre o assunto, em que ensino a instalar a versão 0.8.9.


Abraços,
Otávio