As tentativas de previsão ao futuro acontecem desde quando há registros históricos. Essas “consultas espirituais” tem ocorridos de várias formas e em diversas culturas, por exemplo, cartas de tarô, astrologia, oráculos, entre outros. Para as pessoas que afirmam conseguir prever o futuro, um dos métodos utilizados são bolas de cristal, que fornecem informações sobre a finanças, amor, casamento e negócios.

Nesta aula, vamos criar uma bola mágica com o Arduino que mostra previsões do futuro … na verdade vai exibir informações aleatórias pré escolhidas (alguma semelhança com a realidade?).

Imagens meramente ilustrativas

O display de LCD (Liquid-crystal display) que vamos usar nessa aula, é feito de cristal líquido, mas não possui propriedades mágicas ou exotéricas.

Esse display é muito utilizado e é um gigantesco um avanço tecnológico comparado com os displays de sete segmentos. Nesse display, é possível mostrar para o usuário as informações que estávamos mostrando, apenas, no monitor serial do Arduíno. Os displays são vendidos baseados na quantidade de caracteres que podem ser exibidos em cada linha e na quantidade de linhas disponíveis.Por exemplo, na imagem acima, o display é de 20×04, já que cada linha pode ter 20 caracteres e há 4 linhas disponíveis. De forma análoga, o display abaixo é 16×02, pois possui capacidade para exibir 16 caracteres em cada linha e 2 linhas para exibir seu conteúdo.

Já viu esse filme?

Para fazer a atividade prática desta aula, vamos utilizar o modelo 1602 sem o circuito integrador I2C. Isso significa que ele é 16×02 e não possui esse módulo I2C. No entanto, na sessão “Para saber mais” também vamos mostrar como configurar e utilizar o o display LCD 1602 I2C. A partir desse módulo, a pinagem, isto é, o significado de cada pino torna-se extremamente importante. Por isso, deve-se ter em mãos o datasheet do componente escolhido.

Quanto a pinagem desse componente, vamos analisar a figura ao lado:

  • O pino 1 e 2 se referem a alimentação do display, ou seja, os pinos que fazem o componente funcionar.
  • O pino 3 é utilizado para definir o contraste da tela.
  • O pino 4 possibilita a seleção entre o envio de dados e os comandos que são fornecidos ao componente.
  • O pino 5 possibilita a seleção entre a escrita e o leitura de dados pelo LCD.
  • O pino 6 habilita o funcionamento do display.
  • Os pinos 7-10 não serão utilizados.
  • Os pinos 11-14 transmitem os dados para mostrar no display.
  • O pino 15 é o anodo dos LEDs presentes na luz de fundo do LCD.
  • O pino 16 é o catodo dos LEDs presentes na luz de fundo do LCD.

Importante: Nunca ligue a fonte de alimentação diretamente nos terminais de backlight (pino 15).

Isto provocará o aquecimento excessivo do display e a queima prematura do componente.

Durante a programação do display de LCD, você vai precisar entender como a biblioteca enxerga o display. Para isso, vamos analisar a imagem abaixo e a função “lcd.setCursor(coluna,linha);”que descreve o posicionamento do cursor. Como visto anteriormente, o Arduino é indexado em Zero. Assim, os componentes compatíveis com ele também são, ou seja, o display de LCD tem espaço para 16 caracteres e para escrever nesses espaços devemos escolher escolher as posições de Zero a 15. Para escrever na primeira posição do display, precisamos escolher a posição (0,0).

Novos componentes:
  • Resistores variáveis:

Dentro do grupo de resistores variáveis, temos os potenciômetros comuns, reostatos, trimpots, potenciômetros deslizantes e potenciômetros digitais. A diferença entre eles está no tamanho, aplicação ou mecânico. Nesta aula, vamos te usar o potenciômetro comum. No entanto, o funcionamento dos outros é o mesmo. Todos são resistências como as que já conhecemos, mas a resistência deles não é fixa, ou seja, você pode a mudar a resistência de Zero até o valor máximo permitido. Por exemplo, o potenciômetro da imagem ao lado é de 10 kΩ. Assim, a resistência elétrica dele vai de Zero a 10 kΩ. Mas como que liga essas três perninhas no circuito?

Como demonstrado na figura abaixo, existem 3 formas de ligar o potenciômetro no circuito:

  • Potenciômetro A: Nessa configuração, o potenciômetro vai de Zero a até seu valor máximo. Quando gira-se o eixo para esquerda, a resistência diminui e chega mais próxima de Zero. Analogamente, quando roda-se o mesmo eixo para a direita, a resistência aumenta até o valor máximo.
  • Potenciômetro B: Dessa maneira, o potenciômetro continua indo de Zero até o valor máximo. No entanto, quando vira-se o eixo, ocorre, exatamente, o oposto da configuração anterior, ou seja, rodar o eixo para a esquerda faz com que a resistência aumente e quando gira-se o eixo para direita, a resistência diminui.
  • Potenciômetro C: Com esse ajuste, o giro do eixo não importa e o valor da resistência é sempre o máximo.

Na imagem ao lado, vemos como o potenciômetro é construído. Perceba que, quando ligamos no terminal 2, podemos ajustar a resistência dele. Nesse caso, o cursor move-se pelo material resistivo quando rodamos o eixo. Assim, quanto maior for a quantidade de material resistivo envolvido pelo cursor, maior é a resistência ajustada. Analogamente, quanto mais próximo o terminal 2 estiver do 1, ou seja, o cursor inclui pouco material resistivo, menor é a resistência ajustado no potenciômetro. Mas se ligamos o terminal 1 e o 3, a resistência fica fixada no valor máximo. Esse componente é utilizado em vários projetos. No exemplo a seguir, ele vai ser usado para controlar o contraste do display. Além disso, esse componente pode ser usado para controlar braços robóticos e a velocidade de motores, por exemplo.

  •  CI PCF8574

Esse código estranho que está escrito acima é o módulo que facilita nossa vida com o display de LCD. A função dele é diminuir o número de portas utilizadas no Arduíno. Com esse módulo, você consegue controlar um display LCD, seja ele 16×2 ou 20×4,  utilizando apenas dois pinos analógicos do Arduíno: o pino analógico 4 (SDA) e o pino analógico 5  (SCL), que formam a interface de comunicação I2C. Para saber mais sobre esse componente, consulte o datasheet dele.

Nesta aula, você vai precisar:

  • Display LCD com I2C ou sem I2C.
  • Arduíno
  • Protoboard
  • Jumper macho-macho
  • Resistor de 220 Ω
  • Potenciômetro 10 kΩ

Simulação

Vamos começar conectando a alimentação do Arduíno e o backlight do LCD, isto é, a luz de fundo do LCD. Assim como em outras aulas, Usamos os jumpers pretos e vermelhos para conectar os pinos de alimentação na protoboard. Para ligar o backlight, conecte o anodo do LED e um resistor de 220Ω na trilha de 5 V da protoboard. Para não queimar o LCD, é necessário colocar esse resistor. O pino de catodo no LCD é conectado no GND do circuito.

Agora, vamos ligar a voltagem no LCD e conectar o pino de contraste. Para conectar a alimentação do LCD, conecte os pinos Vcc e GND do LCD nas portas 5 V e GND do Arduíno, respectivamente. O contraste é ajustado com um potenciômetro. Assim, conecte os fios Vcc e GND nas extremidades do potenciômetro e, no terminal central, coloque o pino do Arduíno.

Nesse momento, vamos ligar os pinos de transmissão de dados. Para facilitar a programação, colocamos os pinos de 4 a 7 do LCD nas portas correspondentes do Arduino, isto é, porta 7 do Arduino no pino 7 do LCD e, assim, em diante.

Para terminar a montagem do LCD no circuito, temos que ligar os pinos RS, RW e o Enable. Escolhemos a porta 11 para o RS e a porta 12 para o Enable. O pino RW deve ser conectado no GND.

Colocamos o mesmo botão PULL-DOWN das aulas anteriores no pino 2 do Arduíno. Assim, a resposta da bola mágica aparecerá quando apertarmos o botão.

A biblioteca dos cristais líquidos sem I2C já estão pré instaladas no Arduíno, ou seja, não precisa baixar uma nova biblioteca para controlar o display. Mesmo assim, para programar, é necessário incluir a biblioteca em cada novo programa. Como em aulas anteriores, é recomendável que se escreva em quais portas do Arduíno os pinos do LCD estão conectados. Mais tarde, fica mais fácil para analisar o que foi feito. Em seguida, para iniciar o display é necessário escrever em que porta do Arduíno estão conectados os pinos de dados, RS e Enable. Se você quiser mudar o posicionamento dos fios, vai precisar informar o Arduíno da mudança. Para isso na linha 13, altere o posicionamento das portas dentro da função. No entanto, lembre-se que essa linha deve ser escrita da seguinte forma: “LiquidCrystal lcd(RS, E, D4, D5, D6, D7);”.

Para programar as configurações iniciais do display de LCD, temos que usar a função “lcd.begin(caracteres por linha, linhas)”. Nessa função, temos que fornecer a quantidade de caracteres e a quantidade de linhas do nosso display. Como nosso display tem 16 caracteres e 2 linhas, vamos atribuir esses valores na função. Em seguida, temos que iniciar o botão. Para isso, precisamos escrever em que pino o botão está conectado e defini-lo como entrada, já que é ele quem vai fornecer informações para o Arduíno.

Com isso, terminamos de definir as configurações iniciais do Arduino. Agora, vamos começar a programar as instruções que vão ser executadas para sempre. Assim, definimos uma variável para guardar a informação se o botão está ou não pressionado. Para escrever a mensagem inicial no LCD, vamos usar a função “lcd.print(“Mensagem”);”. Essa função, simplesmente, escreve uma mensagem no display de LCD. Lembre que nosso display só tem 16 caracteres de espaço visível e essa biblioteca não tem suporte para acentuação. Como usamos todos os espaços na primeira linha, usamos a função “lcd.set.Cursor(0,1)” para mudar o cursor para escrever na segunda linha. Para posicionar o cursor é necessário lembrar que o display é indexado em Zero e o primeiro número se refere a coluna do display e a segunda linha se refere a linha do display. Assim, escrevemos (0,1) para colocar o cursor no inicio da segunda linha. Agora, colocamos na variável “estado_botao” a condição em que está o botão, ou seja, se o botão está pressionado ou não.

A estratégia desse código será associar cada mensagem do mostrada na tela a um número. Por exemplo, vinculamos para a resposta “sim” o número Zero. Dessa forma, vamos usar a função “random” do Arduino para gerar números aleatórios. Assim, o Arduino vai gerar um número aleatório toda vez que o usuário apertar o botão. Esse número aleatório estará vinculado com uma mensagem no Arduino e essa mensagem será mostrada para o usuário.

Então, antes de começar a programar o que acontece quando o botão é pressionado, vamos declarar uma variável para armazenar o número aleatório que será dada para o usuário. Queremos que a mensagem do Arduino mágico mude quando o botão seja pressionado. Então, colocamos o condicional “if” com a condição HIGH, para que a instruções dentro do “if” só sejam executadas quando o botão for apertado. A primeira instrução dentro do “if” será para limpar o display e, para tanto, usamos a função “lcd.clear();”. Como o cursor estava colocado no inicio da segunda linha, temos que faze-lo voltar para a primeira com o comando “setCursor(0,0);”.Escrevemos a mensagem com o comando “lcd.print(“Mensagem”);” e deslocamos o cursor para escrever a resposta na segunda linha. Em seguida, colocamos o resultado da função “random(0,7);” na variável “resposta”. A função “random(0,7);”  gera um número aleatório entre Zero e 6,ou seja, 7 possibilidades.

Depois de colocar um número aleatório na variável “resposta”, temos que checar qual número o Arduino nos forneceu. Para isso, vamos usar uma sequencia de “if”, um para número aleatório que a função “random” pode nos dar. Por exemplo, no primeiro “if” nós verificamos se o número dentro da variável “resposta” é o número Zero e escrevemos “sim” se for. Em seguida, repetimos esse trecho de código para todos as possibilidades. No final do código colocamos um delay de 2000 milisegundos, ou seja, 2 segundos. Assim, a mensagem fica travada na tela durante esse tempo e dá tempo par que o usuário leia. No final, limpamos o display novamente com o comando “lcd.clear();”para que a mensagem “Pergunte para o Arduino Mágico” apareça novamente na tela.

Abaixo, temos o código final do programa:

#include <LiquidCrystal.h>

/*
LCD RS no pino 11;
LCD Enable no pino 12;
LCD D4 no pino 4;
LCD D5 no pino 5;
LCD D6 no pino 6;
LCD D7 no pino 7;
*/
  

LiquidCrystal lcd(11,12,4,5,6,7);

void setup()
{
  lcd.begin(16,2); //Inicia o LCD com 16 caracteres e 2 linhas
  pinMode(2,INPUT);// Inicia o botão no pino 2    
}

void loop()
{
  int estado_botao;
  lcd.print("Pergunte para o");// Mostra a mensagem no display
  lcd.setCursor(0,1);//muda o cursor para o primeiro espaço da segunda linha.
  lcd.print("Arduino Magico!!");// Mostra a mensagem no display
 
  estado_botao = digitalRead(2);
  
  int resposta = 0;
  if( estado_botao == HIGH){
    
    lcd.clear(); // Limpa o display 
    lcd.setCursor(0,0); // coloca o cursor na primeira posição da primeira linha
    lcd.print("A bola diz:");// Mostra a mensagem no display
    lcd.setCursor(0,1);//muda o cursor para o primeiro espaço da segunda linha.    
    resposta = random(0,7);// associa um número qualquer entre 0 e 6
    
    if(resposta == 0){
      lcd.print("Sim");      
    }
    if(resposta == 1){
      lcd.print("Nah");      
    }
    if(resposta == 2){
      lcd.print("Talvez");      
    }
    if(resposta == 3){
      lcd.print("Com certeza");      
    }
    if(resposta == 4){
      lcd.print("Provavelmente");      
    }
    if(resposta == 5){
      lcd.print("As vezes");      
    }
    if(resposta == 6){
      lcd.print("Jamais");      
    }
 
    delay(2000);
    lcd.clear(); // Limpa o display
  }  
}

Para saber mais:

Da mesma forma como foi feito em programas anteriores, vamos retirar a declaração de variáveis e colocar os comandos diretamente no dentro do “if”. Isso poupa memória do Arduino para execução do código. Além dessa mudança, mudamos a sequencia de “if” para uma nova sintaxe condicional semelhante ao “if”, o “switch… case”. Como o “if”, essa sintaxe também necessita de uma condição, mas ela é mais eficiente para comparar valores pre determinados. Assim, pode-se colocar a variável resposta dentro da condição do switch e fazer a mesma análise que fizemos da primeira vez.

#include <LiquidCrystal.h>

/*
LCD RS no pino 11;
LCD Enable no pino 12;
LCD D4 no pino 4;
LCD D5 no pino 5;
LCD D6 no pino 6;
LCD D7 no pino 7;
*/
  

LiquidCrystal lcd(11,12,4,5,6,7);

void setup()
{
  lcd.begin(16,2); //Inicia o LCD com 16 caracteres e 2 linhas
  pinMode(2,INPUT);// Inicia o botão no pino 2    
}

void loop()
{
  
  lcd.print("Pergunte para o");// Mostra a mensagem no display
  lcd.setCursor(0,1);//muda o cursor para o primeiro espaço da segunda linha.
  lcd.print("Arduino Magico!!");// Mostra a mensagem no display
  int resposta = 0;
  
  if( digitalRead(2) == HIGH){
    
    lcd.clear(); // Limpa o display 
    lcd.setCursor(0,0); // coloca o cursor na primeira posição da primeira linha
    lcd.print("A bola diz:");// Mostra a mensagem no display
    lcd.setCursor(0,1);//muda o cursor para o primeiro espaço da segunda linha.    
    resposta = random(0,7);// associa um número qualquer entre 0 e 6
    
   	switch (resposta){
    	case 0:
      	lcd.print("Sim");
      	break;
      
     	case 1:
     	lcd.print("Nah");
     	break;
      
     	case 2:
     	lcd.print("Talvez");
     	break;
      
     	case 3:
     	lcd.print("Com certeza");
     	break;
      
     	case 4:
     	lcd.print("Provavelmente");
     	break;
      
     	case 5:
     	lcd.print("As vezes");
     	break;
      
     	case 6:
     	lcd.print("Jamais");
     	break;
    }
 
    delay(2000);
    lcd.clear(); // Limpa o display
  }  
}

O uso do “Switch…case “tem o mesmo resultado do que o uso de “if”. Mas com o “switch…case”, temos um código mais eficiente, enxuto e fácil de entender. Perceba que retiramos, no código acima, a variável “estado_botao” e colocamos o comando do Arduino diretamente no primeiro “ïf”. Por fim, vamos fazer a mesma coisa com a variável “resposta”. Assim, seu programa deve ficar semelhante ao código abaixo.

#include <LiquidCrystal.h>

/*
LCD RS no pino 11;
LCD Enable no pino 12;
LCD D4 no pino 4;
LCD D5 no pino 5;
LCD D6 no pino 6;
LCD D7 no pino 7;
*/
  

LiquidCrystal lcd(11,12,4,5,6,7);

void setup()
{
  lcd.begin(16,2); //Inicia o LCD com 16 caracteres e 2 linhas
  pinMode(2,INPUT);// Inicia o botão no pino 2    
}

void loop()
{
  
  lcd.print("Pergunte para o");// Mostra a mensagem no display
  lcd.setCursor(0,1);//muda o cursor para o primeiro espaço da segunda linha.
  lcd.print("Arduino Magico!!");// Mostra a mensagem no display
  int resposta = 0;
  
  if( digitalRead(2) == HIGH){
    
    lcd.clear(); // Limpa o display 
    lcd.setCursor(0,0); // coloca o cursor na primeira posição da primeira linha
    lcd.print("A bola diz:");// Mostra a mensagem no display
    lcd.setCursor(0,1);//muda o cursor para o primeiro espaço da segunda linha.    
   
    
   	switch (random(0,7)){
    	case 0:
      	lcd.print("Sim");
      	break;
      
     	case 1:
     	lcd.print("Nah");
     	break;
      
     	case 2:
     	lcd.print("Talvez");
     	break;
      
     	case 3:
     	lcd.print("Com certeza");
     	break;
      
     	case 4:
     	lcd.print("Provavelmente");
     	break;
      
     	case 5:
     	lcd.print("As vezes");
     	break;
      
     	case 6:
     	lcd.print("Jamais");
     	break;
    }
 
    delay(2000);
    lcd.clear(); // Limpa o display
  }  
}

Para futuros projetos,disponibilizamos todas as funções disponíveis na biblioteca “LiquidCrystal.h”. Assim, quando quiser fazer alguma coisa diferente o display de LCD, veja o que a biblioteca é capaz de fazer.