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?).
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.
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.