terça-feira, setembro 29, 2015

Outra Opção de Display Alfanumérico com Interface I2C

Já vimos aqui um display alfanumérico com interface I2C. A aparência e legibilidade deste modelo são ótimas, mas é um display relativamente frágil e com um conector com espaçamento reduzido, o que dificulta a montagem. A Deal Extreme (e outros lugares) possui um display alfanumércio 2x16 "comum" já acoplado a um adaptador I2C. Vamos exercitá-lo aqui.



Examinando a placa do adaptador, observamos que:
  • Tem um trimpot para regular o contraste do display
  • Tem um jumper para habilitar/inibir o backlight
  • A conversão I2C paralelo é feita por um PCF8574
  • Tem três ilhas de configuração marcadas com A0, A1 e A2
  • O conector para ligação ao microcontrolador tem, como esperado, quatro sinais: GND, VCC, SDA e SCL.

 O PCF8574 é  um integrado bastante popular para expandir a capacidade de E/S e saída digital de microcontroladores. O seu endereço I2C é 0 1 0 0 A2 A1 A0. Ou seja, varia entre 0x20 e 0x27, dependendo dos pinos A2, A1 e A0. No caso da minha placa, as ilhas de configuração estão desconectadas e o endereço de fábrica é 0x27. A velocidade máxima no I2C é 100KHz.

O funcionamento do PCF8574 é muito simples: o valor escrito via I2C vai para os pinos P0 a P7; uma leitura via I2C retorna o valor nestes mesmos pinos.

Portanto, a única questão é saber a qual sinal do LCD corresponde cada um dos pinos P0 a P7 do PCF8574. Para isto eu liguei o display ao Arduino: GND em GND, VCC em 5V, SDA em A4 e SCL em A5 (Arduino UNO ou Nano, se for outra versão veja aqui) , carreguei no Arduino o programa abaixo e abri o Serial Monitor:
  1. // Programa para acionar uma a uma as saída do  
  2. // conversor I2C / Paralelo PCF8574  
  3. // DQ, Set/2015  
  4.   
  5. #include <Wire.h>  
  6.   
  7. void setup()  
  8. {  
  9.   Serial.begin (9600);  
  10.   Wire.begin();  
  11. }  
  12.   
  13. void loop()  
  14. {  
  15.   byte x = 1;  
  16.     
  17.   delay (10000);  
  18.   for (int i = 0; i < 8; i++)  
  19.   {  
  20.     Serial.println (i);  
  21.     Wire.beginTransmission(0x27);  
  22.     Wire.write(x);  
  23.     Wire.endTransmission();  
  24.     delay (3000);  
  25.     x = x << 1;  
  26.   }  
  27.   Serial.println();  
  28. }  
Usando um multímetro para ler tensão, liguei uma ponta ao terra e a outra ao sinal RS do display. Olhando o Serial Monitor e o multímetro, descobri que o sinal RS correspondia ao pino P0. Fazendo o mesmo com os demais pinos do LCD, obtive:
  • RS = P0
  • RW = P1
  • E = P2
  • A = P3 (backlight)
  • D4 = P4
  • D5 = P5
  • D6 = P6
  • D7 = P7

Existem algumas bibliotecas já prontas para displays com interface I2, mas nem todas tem a flexibilidade de configuração da conexão do PCF8574 ao display. Acabei usando a biblioteca NewLiquidCrystal de F Malpartida. É uma biblioteca que suporta vários tipos de conexão de display, o que pode ser confuso no início.

Após baixar o ZIP expanda a pasta NewliquidCrystal  dentro da pasta libraries do diretório onde ficam os seus sketches e renomeie-a para LiquidCrystal_I2c (para não confundir a IDE).O programa abaixo mostra a biblioteca funcionando:
  1. // Exemplo simples de uso da biblioteca  
  2. // NewliquidCrystal   
  3. //   (https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads)  
  4. // com um display com conexão I2C   
  5. //   (http://www.dx.com/p/i2c-iic-lcd-1602-display-module-with-white-backlight-4-pin-cable-for-arduino-raspberry-pi-374741)  
  6.   
  7. #include <Wire.h>   
  8. #include <LiquidCrystal_I2C.h>  
  9.   
  10. LiquidCrystal_I2C lcd(  
  11.   0x27,    // Endereço do PCF8574  
  12.   2,       // bit que controla o sinal E(nable) do LCD  
  13.   1,       // bit que controla o sinal RW do LCD  
  14.   0,       // bit que controla o sinal RS do LCD  
  15.   4,       // bit que controla o sinal D4 do LCD  
  16.   5,       // bit que controla o sinal D5 do LCD  
  17.   6,       // bit que controla o sinal D6 do LCD  
  18.   7,       // bit que controla o sinal D7 do LCD  
  19.   3,       // bit que controla o Backlight do LCD  
  20.   POSITIVE  // Backlight acende quando o sinal está em nível Alto  
  21. );  
  22.   
  23. byte seg, minuto, hora;   
  24.   
  25. void setup()  
  26. {  
  27.   lcd.begin(16,2);    // Inicia o LCD  
  28.   DisplayWrite (0, 0, "DQSoft");     
  29.   DisplayWrite (1, 0, "00:00:00");      
  30. }  
  31.   
  32. void loop()  
  33. {  
  34.   if (++seg == 60)    
  35.   {    
  36.     seg = 0;    
  37.     if (++minuto == 60)    
  38.     {    
  39.       minuto = 0;    
  40.       if (++hora == 99)    
  41.         hora = 0;    
  42.       DisplayWriteDec (1, 0, hora);    
  43.     }    
  44.     DisplayWriteDec (1, 3, minuto);    
  45.   }    
  46.   DisplayWriteDec (1, 6, seg);    
  47.   delay (1000);   // aguarda um segundo    
  48. }  
  49.   
  50. // Mostra número decimal de 00 a 99    
  51. void DisplayWriteDec (byte l, byte c, byte num)    
  52. {    
  53.   char aux[3];    
  54.       
  55.   aux[0] = 0x30 + num / 10;    
  56.   aux[1] = 0x30 + num % 10;    
  57.   aux[2] = 0;    
  58.   DisplayWrite (l, c, aux);    
  59. }    
  60.     
  61. // Posiciona o cursor e mostra mensagem    
  62. void DisplayWrite (int l, int c, char *msg)  
  63. {  
  64.   lcd.setCursor(c,l);  
  65.   lcd.print(msg);  
  66. }  

Nenhum comentário: