No post anterior mostrei como digitar texto em um display LCD com um teclado matricial 4x3. Nesse vídeo mostro como fazer a mesma coisa, mas utilizando um controle remoto.
Código-Fonte:
obs. 01: O Controle remoto utilizado foi o da Claro TV. Caso for usar outro tipo de controle remoto, é necessário descobrir a codificação de cada uma das teclas e fazer as alterações na função get_tecla. Esse controle remoto, retorna dois códigos diferentes para a mesma tecla (em alguns casos), como pode ser visto no código.
obs. 02: o controle remoto ao ser mantido pressionado, não fica enviando a informação de maneira continua, então o arduino, por um pequeno período de tempo, entende que o botão foi solto e pressionado várias vezes, causando um comportamento indesejado, por isso foi criada a variável global time_read = 150; 150, significa que 150 milissegundos após o botão ser "solto" a função get_tecla, ainda vai continuar retornando o ultimo caractere pressionado. é possível que em diferentes controles remotos, esse tempo varie. Não fiz nenhum teste com outros controles, mas que for usar, é interessante testar isso antes.
obs. 03: é preciso baixar e instalar a biblioteca IRRemote. Não vou entrar em detalhes aqui de como instalar e configurar a biblioteca, pois uma rápida busca no google, certamente irá ajudar.
#include <IRremote.h>
const int RECV_PIN = 11;
unsigned long last = millis();
IRrecv irrecv(RECV_PIN);
decode_results results;
unsigned long millis_last_read = 0;
char char_last_read = '\0';
unsigned long time_read = 150;
char get_tecla() {
char c = '\0';
if ( (millis() - time_read) > millis_last_read ){
if (irrecv.decode(&results)) {
if (results.value == 2152998656 || results.value == 2153031424){ c = '0'; }
if (results.value == 2152998657 || results.value == 2153031425){ c = '1'; }
if (results.value == 2152998658 || results.value == 2153031426){ c = '2'; }
if (results.value == 2152998659 || results.value == 2153031427){ c = '3'; }
if (results.value == 2152998660 || results.value == 2153031428){ c = '4'; }
if (results.value == 2152998661 || results.value == 2153031429){ c = '5'; }
if (results.value == 2152998662 || results.value == 2153031430){ c = '6'; }
if (results.value == 2152998663 || results.value == 2153031431){ c = '7'; }
if (results.value == 2152998664 || results.value == 2153031432){ c = '8'; }
if (results.value == 2152998665 || results.value == 2153031433){ c = '9'; }
if (results.value == 551538735) { c = '*'; }
if (results.value == 2152998666 || results.value == 2153031434){ c = '#'; }
irrecv.resume(); // Receive the next value
millis_last_read = millis();
char_last_read = c;
}
} else {
c = char_last_read;
}
//Serial.println(c);
return c;
}
const char teclas[][12] = {"1 ", "2abc", "3def", "4ghi", "5jkl", "6mno", "7pqrs", "8tuv", "9wxyz", "*", "0", "#"};
const unsigned long time_char = 1200; //1200 milissegundos pra desconsiderar a ultima tecla
class TecladoTelefone{
private:
unsigned long _millis_last_char;
char _last_char;
String _palavra;
void _set_last_char(char c, int ind_palavra){
if ( ind_palavra == 1 && _last_char != '\0' ) {
_palavra += _last_char;
}
_last_char = c;
_millis_last_char = millis();
}
void _back_space(){
if (_palavra.length() >= 1){
_last_char = _palavra[_palavra.length()-1];
_palavra = _palavra.substring(0, _palavra.length()-1);
} else {
_last_char = '\0';
}
}
public:
TecladoTelefone(){
_millis_last_char = millis();
_last_char = '\0';
}
int is_timing(){
return ( (millis() - time_char) < _millis_last_char );
}
void add(char c){
int pos = -1;
if (c == '1'){ pos = 0;}
if (c == '2'){ pos = 1;}
if (c == '3'){ pos = 2;}
if (c == '4'){ pos = 3;}
if (c == '5'){ pos = 4;}
if (c == '6'){ pos = 5;}
if (c == '7'){ pos = 6;}
if (c == '8'){ pos = 7;}
if (c == '9'){ pos = 8;}
if (c == '*'){ pos = 9;}
if (c == '0'){ pos = 10;}
if (c == '#'){ pos = 11;}
if (pos == -1){ return; }
if (pos == 9){
_back_space();
return;
}
const char * t = teclas[pos];
if ( is_timing() ) {
int i = 0;
while (t[i] != '\0'){
if (_last_char == t[i]){
_set_last_char( (t[i+1] == '\0') ? _last_char = t[0] : _last_char = t[i+1] , 0 );
return ;
}
i++;
}
}
_set_last_char ( c, 1);
}
char get_last_char(){ return _last_char; }
String get_palavra( ) {
if (_last_char != '\0') {
return _palavra + _last_char;
}
return _palavra;
}
};
#include <LiquidCrystal.h>
LiquidCrystal lcd(9, 8, 10, 7, 6, 5); //Configura os pinos do Arduino para se comunicar com o LCD
TecladoTelefone * teclado;
void setup() {
Serial.begin(9600);
irrecv.enableIRIn();
teclado = new TecladoTelefone();
lcd.begin(16, 2);
}
char tecla_anterior = '\0';
void loop() {
char tecla = get_tecla();
if (tecla != tecla_anterior){
if (tecla) {
teclado->add(tecla);
}
}
tecla_anterior = tecla;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(teclado->get_palavra());
lcd.cursor();
lcd.setCursor(teclado->get_palavra().length() - (teclado->is_timing() ? 1 : 0 ), 0);
delay(10);
lcd.noCursor();
}
Nesse video mostro dois exemplos, no primeiro é mostrado como ligar um teclado matricial de 4 linhas e 3 colunas no Arduino. Nesse exemplo utilizo um teclado feito a partir de um teclado de telefone, que foi cortado, e identificadas as linhas e colunas, furada a placa e soldado um fio pra cada linha e pra cada coluna. A outra extremidade do fio foi soldada em uma placa, para que fosse possível conectar o teclado numa protoboard para entao utilizá-la com o Arduino.
Vídeo
Imagens do teclado
Na imagem abaixo é possível ver como foi feita a ligação. Os fios foram soldados em um placa, os 3 fios brancos são os fios das colunas, e os 4 fios amarelos são os fios das linhas, sendo o fio amarelo mais da direita referente a linha 1, conforme identificado pelo L1 na placa, e mais a esquerda, a coluna 3, conforme identificado pelo C3 na placa.
Os fios referentes às linhas (fios amarelos) foram ligados diretamente ao Arduino, nos pinos 3, 4, 5 e 6. Os fios referentes às colunas foram ligados na protoboard no qual cada fio é ligado a um resistor de pulldown (10K cada um), e então ligados ao Arduino nos pinos 10, 11 e 12.
Código 01
Nesse código é mostrado como ligar um teclado matricial 4x3 no Arduino.
#define col1 10
#define col2 11
#define col3 12
#define lin1 3
#define lin2 4
#define lin3 5
#define lin4 6
char get_tecla(){
int l[]={lin1, lin2, lin3, lin4}; // Array de 4 posições contendo os 4 pinos de linhas
int i = 0, k = 0, t = 0;
for (i=0; i<4; i++) {
digitalWrite(lin1,LOW);
digitalWrite(lin2,LOW);
digitalWrite(lin3,LOW);
digitalWrite(lin4,LOW);
digitalWrite(l[i],HIGH);
if(digitalRead(col1)) { t = i*3+1; break; }
if(digitalRead(col2)) { t = i*3+2; break; }
if(digitalRead(col3)) { t = i*3+3; break; }
}
if (t > 0 ){
if (t >= 1 && t<=9){ return char(t+48); } //48--> ASCII: o charactere '1' na tabela ascii é 49º item, o '2' é o 50º item e assim por diante
if (t==10) { return '*'; }
if (t==11) { return '0'; }
if (t==12) { return '#'; }
}
return '\0';
}
void setup() {
// colunas INPUT
pinMode(col1,INPUT);
pinMode(col2,INPUT);
pinMode(col3,INPUT);
// linhas OUTPUT
pinMode(lin1,OUTPUT);
pinMode(lin2,OUTPUT);
pinMode(lin3,OUTPUT);
pinMode(lin4,OUTPUT);
Serial.begin(9600);
}
void loop() {
if (get_tecla() != '\0'){
Serial.println( get_tecla() );
}
}
Código 02
Código referente a digitação de texto através do teclado Matricial.
o Código não está completo, não tendo informado letras Maisúsculas, nem caracteres especiais, mas facilmente adicionados, modificando a constante teclas, introduzindo os demais caracteres que sejam desejados. Também não foi implementado nenhuma função referente a Backspace (para apagar o texto), nem para limpar. Talvez futuramente eu venha implementar essas melhorias no código, e assim que eu for fazendo, vou disponibilzando o código aqui no blog.
#define col1 10
#define col2 11
#define col3 12
#define lin1 3
#define lin2 4
#define lin3 5
#define lin4 6
char get_tecla(){
int l[]={lin1, lin2, lin3, lin4}; // Array de 4 posições contendo os 4 pinos de linhas
int i = 0, k = 0, t = 0;
for (i=0; i<4; i++) {
digitalWrite(lin1,LOW);
digitalWrite(lin2,LOW);
digitalWrite(lin3,LOW);
digitalWrite(lin4,LOW);
digitalWrite(l[i],HIGH);
if(digitalRead(col1)) { t = i*3+1; break; }
if(digitalRead(col2)) { t = i*3+2; break; }
if(digitalRead(col3)) { t = i*3+3; break; }
}
if (t > 0 ){
if (t >= 1 && t<=9){ return char(t+48); } //48--> ASCII: o charactere '1' na tabela ascii é 49º item, o '2' é o 50º item e assim por diante
if (t==10) { return '*'; }
if (t==11) { return '0'; }
if (t==12) { return '#'; }
}
return '\0';
}
const char teclas[][12] = {"1 ", "2abc", "3def", "4ghi", "5jkl", "6mno", "7pqrs", "8tuv", "9wxyz", "*", "0", "#"};
const unsigned long time_char = 1200; //1200 milissegundos pra desconsiderar a ultima tecla
class TecladoTelefone{
private:
unsigned long _millis_last_char;
char _last_char;
String _palavra;
void _set_last_char(char c, int ind_palavra){
if ( ind_palavra == 1 && _last_char != '\0' ) {
_palavra += _last_char;
}
_last_char = c;
_millis_last_char = millis();
}
public:
TecladoTelefone(){
_millis_last_char = millis();
_last_char = '\0';
}
void add(char c){
int pos = -1;
if (c == '1'){ pos = 0;}
if (c == '2'){ pos = 1;}
if (c == '3'){ pos = 2;}
if (c == '4'){ pos = 3;}
if (c == '5'){ pos = 4;}
if (c == '6'){ pos = 5;}
if (c == '7'){ pos = 6;}
if (c == '8'){ pos = 7;}
if (c == '9'){ pos = 8;}
if (c == '*'){ pos = 9;}
if (c == '0'){ pos = 10;}
if (c == '#'){ pos = 11;}
if (pos == -1){ return; }
const char * t = teclas[pos];
if ( (millis() - time_char) < _millis_last_char ) {
int i = 0;
while (t[i] != '\0'){
if (_last_char == t[i]){
_set_last_char( (t[i+1] == '\0') ? _last_char = t[0] : _last_char = t[i+1] , 0 );
return ;
}
i++;
}
}
_set_last_char ( c, 1);
}
char get_last_char(){ return _last_char; }
String get_palavra( ) {
return _palavra + _last_char;
}
};
TecladoTelefone * teclado;
void setup() {
Serial.begin(9600);
// colunas INPUT
pinMode(col1,INPUT);
pinMode(col2,INPUT);
pinMode(col3,INPUT);
// linhas OUTPUT
pinMode(lin1,OUTPUT);
pinMode(lin2,OUTPUT);
pinMode(lin3,OUTPUT);
pinMode(lin4,OUTPUT);
teclado = new TecladoTelefone();
}
char tecla_anterior = '\0';
void loop() {
char tecla = get_tecla();
if (tecla != tecla_anterior){
if (tecla) {
teclado->add(tecla);
}
}
tecla_anterior = tecla;
Serial.println(teclado->get_palavra());
}