Manual
do
Maker
.
com
Antes de começarmos, caso deseje controlar um display desse com I2C, o link é esse. Como prometi no post sobre o sensor de temperatura LM35, vamos aprimorar o projeto de controle de temperaturas utilizando um display LCD.
Esse display possui 5 botões, mas todos eles utilizam a porta analógica 0. O que faz com que seja possível reconhecer qual botão foi pressionado é a frequẽncia que ele gera; cada botão possui uma resistência diferente.
Além disso, pode-se ver no esquema os pinos utilizados. Porém, mesmo sem o esquemático, não só para esse LCD shield mas também para outros shields, existe uma referência do site oficial do Arduino que mostra a pinagem em uma lista, nesse link
Então para testar, vamos usar a biblioteca disponível para download no próprio site (e obviamente recomendo a compra na WebTronico). Baixe e descomprima a biblioteca dentro do sub-diretório libraries do diretório arduino-1.0 (que é a versão disponível até o momento que escrevi esse post).
Ao ligar, automaticamente o display se acende e a matriz fica preenchida por quadrados pretos, então, não se assuste; não há nada de anormal com ele.
Ao tentar compilar o programa, obtive um erro de comprimento da string. Diminua 2 bytes a partir da linha 12 do array. No meu caso, deixei a variável em uma só linha dessa forma:
char msgs[5][15] = {"Direita OK ","Cima OK ","Baixo OK ","Esquerda OK ", "Select OK " };
Após compilar e subir o programa, o display exibirá a mensagem "Keypad testing...". Pressionando cada um dos botões, a mensagem se alterará. Na imagem acima, ao apertar o botão para baixo, surgiu a mensagem "Baixo OK".
Trabalharemos duas etapas distintas. Primeiramente, será necessário criar um método que possa tratar os resultados dos botões e manipular o array de mensagens também. Isso será feito porque há um objetivo principal; criar um menu para poder escolher qual sensor exibir a temperatura.
O segundo objetivo é exibir mensagens de temperatura na tela. Para converter esse valor em um array de char utilizaremos a função dtostrf(), mas não se preocupe com isso, estará claro no código de exemplo.
Para não virar um mega-projeto, utilizarei apenas 2 sensores LM35 para a temperatura, mas é possível adicionar outros tipos de sensores funcionando juntamente.
Esse fabuloso display tem lá suas deficiências. Não sei porque, mas infelizmente ele não vem com os slots para utilizar os demais pinos analógicos e os digitais, além de energia e terra. Então, foi necessário soldar os demais slots e obtive o resultado da imagem inicial desse post.
Não há muito que se possa fazer de verdade, mas é possível colocar um pouco de charme no display, gerando um delay para a exibição do texto, de uma forma mais suave como se pode ver no video. Para isso, foi necessário mexer diretamente na biblioteca do display. Entre no diretório libraries/LCD4Bit_mod do Arduino e edite o arquivo LCD4Bit_mod.cpp.
No método pulseEnablePin()
, troque os delays por 100,100 e 10. É só o que dá para fazer.
Aproveitei todo o código do exemplo da biblioteca do LCD, apenas adicionando algumas linhas. Claro que pode-se criar um menu extenso, com muitos ítens de submenu, mas o que fiz foi simplesmente adicionar um submenu a cada botão de direção; apertando esquerda, aparece Esquerda: 4. Apertando então Select, aparece Submenu 4.
Agora trocarei a mensagem de esquerda e direita para Sensor 1 e Sensor 2 respectivamente. Quando pressionados, exibirão a mensagem "Exibir valor". Pressionando então select, exibirá o valor do sensor correspondente.
Para aproveitar exatamente o mesmo código, pensei em criar alguns artifícios que me permitissem interagir com o fluxo original. Antes de Setup() adicionei algumas variáveis:
int veryOldKey = -1;
char submenu[5][16] = {"submenu 1 ",
"submenu 2 ",
"submenu 3 ",
"submenu 4 ",
"submenu 5 "};
int keyRepeated = 9;
No final do código, criei uma função para trocar a mensagem do display. Depois de testado, fiz com que exibisse o valor do sensor:
void menu(int botaoX, int lastClicked){
int i;
//se for select...
if (botaoX == 4 && oldkey != -1){
if (lastClicked == 3){
temperatura = (5.0 * freq1 * 100.0)/1024.0;
}
else if (lastClicked == 0){
temperatura = (5.0 * freq2 * 100.0)/1024.0;
}
if (lastClicked == 3 || lastClicked == 0){
mensagem = dtostrf(temperatura,2,2,buf);
Serial.println(mensagem);
//mensagem.toCharArray(conversor,16);
mensagem.getBytes(justBytes,7);
//strcpy(msgs[botaoX],submenu[lastClicked]);
for (i=0;i<17;i++){
msgs[botaoX][i] = ' ';
}
for (i=0;i<5;i++){
msgs[botaoX][i] = justBytes[i];
}
}
else{
for (i=0;i<5;i++){
msgs[botaoX][i] = ' ';
}
}
}
keyRepeated = botaoX;
}
Tem dois "ifs" no código verificando a mesma condição (ok, entendi, mas o código não é meu):
if (key != oldkey)
Logo abaixo dessa segunda condicional, deixei com as seguintes linhas:
veryOldKey = oldkey;
oldkey = key;
menu(key,veryOldKey);
Além disso, tive que modificar a classe do display em alguns lugares. Não vou entrar em detalhes sobre as mudanças.
Para fazer uso dos botões (C)ima e (B)aixo, coloquei a função de acender e apagar um LED. O display está devidamente configurado para a exibição da mensagem, mas por algum motivo ainda não descoberto, não acendi o LED. Quer tentar?
O código utilizado no display é esse:
#include <LCD4Bit_mod.h>
//create object to control an LCD.
//number of lines in display=1
LCD4Bit_mod lcd = LCD4Bit_mod(2);
//Key message
unsigned char msgs[5][17] = {"(D) Sensor 2 ","(C) LED On ","(B) LED Off ","(E) Sensor 1 "," "};
int adc_key_val[5] ={30, 150, 360, 535,760 };
int NUM_KEYS = 5;
int adc_key_in;
int key=-1;
int oldkey=-1;
int veryOldKey = -1;
unsigned char submenu[5][16] = {"submenu 1 ","submenu 2 ","submenu 3 ","submenu 4 ","submenu 5 "};
int keyRepeated = 9;
String mensagem = " ";
unsigned char justBytes[16] = {''};
unsigned char titulo[] = " suhanko.com ";
char buf[50];
//sensor1
float temperatura;
int freq1 = 0;
//sensor2
int freq2 = 0;
void setup() {
pinMode(13, OUTPUT); //we'll use the debug LED to output a heartbeat
Serial.begin(9600);
lcd.init();
//optionally, now set up our application-specific display settings, overriding whatever the lcd did in lcd.init()
//lcd.commandWrite(0x0F);//cursor on, display on, blink on. (nasty!)
lcd.clear();
lcd.printIn(titulo);
}
void loop() {
//leitura do sensor1
freq1 = analogRead(1);
freq2 = analogRead(2);
adc_key_in = analogRead(0); // read the value from the sensor
digitalWrite(13, HIGH);
key = get_key(adc_key_in); // convert into key press
if (key != oldkey){ // if keypress is detected
delay(50); // wait for debounce time
adc_key_in = analogRead(0); // read the value from the sensor
key = get_key(adc_key_in); // convert into key press
if (key == -1){key = oldkey;}
if (key != oldkey){
veryOldKey = oldkey;
oldkey = key;
menu(key,veryOldKey);
Serial.println(key);
Serial.println(veryOldKey);
if (key >=0){
lcd.cursorTo(2, 0); //line=2, x=0
/*
De 0 a 4 sao as chaves. A partir daqui pode-se
chamar um metodo que trate, gerencie uma matriz
e trate um menu.
Para trocar a mensagem sera necessario trocar a
mensagem da matriz msgs
*/
lcd.printIn(msgs[key]);
}
}
}
//delay(1000);
digitalWrite(13, LOW);
}
// Convert ADC value to key number
int get_key(unsigned int input)
{
// return 30;
int k;
for (k = 0; k < NUM_KEYS; k++){
if (input < adc_key_val[k]){
return k;
}
}
if (k >= NUM_KEYS)
k = -1; // No valid key pressed
return k;
}
void menu(int botaoX, int lastClicked){
int i;
//se for select...
if (botaoX == 4 && oldkey != -1){
if (lastClicked == 3){
temperatura = (5.0 * freq1 * 100.0)/1024.0;
}
else if (lastClicked == 0){
temperatura = (5.0 * freq2 * 100.0)/1024.0;
}
if (lastClicked == 3 || lastClicked == 0){
mensagem = dtostrf(temperatura,2,2,buf);
Serial.println(mensagem);
//mensagem.toCharArray(conversor,16);
mensagem.getBytes(justBytes,7);
//strcpy(msgs[botaoX],submenu[lastClicked]);
for (i=0;i<17;i++){
msgs[botaoX][i] = ' ';
}
for (i=0;i<5;i++){
msgs[botaoX][i] = justBytes[i];
}
}
else{
for (i=0;i<5;i++){
msgs[botaoX][i] = ' ';
}
if (lastClicked == 1){
digitalWrite(5,HIGH);
}
else if (lastClicked == 2){
digitalWrite(5,LOW);
}
}
}
keyRepeated = botaoX;
}
Quando corrigir o problema, atualizo o post; como está certamente já é útil. Eis o video.
Autor do blog "Do bit Ao Byte / Manual do Maker".
Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.