Aprenda neste post como controlar uma TV com um Keypad e um Arduino Mega. Os comandos são inseridos no Keypad e enviados para a TV via LED infravermelho. Um Receptor Infravermelho capta os sinais do controle remoto, facilitado pela biblioteca IRremote para cadastro das teclas do controle remoto no Arduino para posterior envio ao clique no Keypad.
As teclas que serão cadastradas são números de canal e ajustes de volume. Será fornecido ao usuário do sistema um Feedback visual oferecido através de um LED indicativo para cada tipo diferente de ação e status do sistema. Além disso, o post inclui um vídeo demonstrativo para complementar a explicação teórica.
Neste post foram utilizados os seguintes materiais:
A Biblioteca IRremote é uma ferramenta essencial para se trabalhar com a transmissão e recepção de sinais infravermelhos utilizando microcontroladores, como o Arduino. Essa biblioteca permite a criação de projetos que envolvem a comunicação por infravermelho (IR), abrindo um leque de possibilidades para o controle remoto de dispositivos eletrônicos, automação residencial, e até mesmo para o desenvolvimento de robôs. Através da IRremote, é possível enviar e receber sinais utilizando diversos protocolos, como NEC, Sony, RC5, Panasonic, entre outros, garantindo compatibilidade com uma ampla gama de dispositivos comerciais.
A documentação da biblioteca pode ser vista em seu repositório no Github: github.com/Arduino-IRremote/Arduino-IRremote.
Para instalar a biblioteca IRremote para utilização na Arduino IDE, siga os passos abaixo:
Para instalar a biblioteca IRremote para utilização em projetos no PlatformIO, siga os passos abaixo:
https://github.com/Arduino-IRremote/Arduino-IRremote.git#2.5.0
Esta biblioteca suporta os seguintes protocolos:
class IRrecv
: Classe para receber IR;int decode(decode_results *results);
: Tentativa de decodificar o sinal IR recebido recentemente;results
: instância retornando a decodificação, se houver.void enableIRIn();
: Habilita a recepção IR;void disableIRIn();
: Desativa a recepção IR;void resume();
: para reativar a recepção IR;bool isIdle();
: Retorna o status da recepção;
true
: se nenhuma recepção estiver em andamento.class IRsend
: Classe para enviar IR;void sendRaw(const unsigned int buf[], unsigned int len, unsigned int hz);
: utilizada para enviar códigos IR (infravermelhos) não codificados;buf
: um ponteiro para um array de inteiros que contém a sequência de tempos em microssegundos. Cada valor neste array representa a duração de um pulso ou de um espaço (tempo entre os pulsos) em microssegundos. A sequência alterna entre pulsos (emissor IR ligado) e espaços (emissor IR desligado).len
: indica o número de elementos no array buf.hz
: especifica a frequência da portadora IR em hertz. A maioria dos controles remotos utiliza frequências entre 30 e 60 kHz, sendo 38 kHz uma das frequências mais comuns.void sendRC5(unsigned long data, int nbits);
: utilizada para enviar códigos IR utilizando o protocolo RC5;
data
: um valor que contém os dados a serem enviados. Este valor representa o código IR em formato binário.nbits
: indica o número de bits do código RC5 a ser enviado.void sendRC6(unsigned long data, int nbits);
: utilizada para enviar códigos IR utilizando o protocolo RC6;
data
: um valor que contém os dados a serem enviados. Este valor representa o código IR em formato binário;nbits
: indica o número de bits do código RC6 a ser enviado.void sendNEC(unsigned long data, int nbits);
: utilizada para enviar códigos IR utilizando o protocolo NEC;
data
: um valor que contém os dados a serem enviados. Este valor representa o código IR em formato binário.nbits
: indica o número de bits do código NEC a ser enviado.void sendSony(unsigned long data, int nbits);
: utilizada para enviar códigos IR (infravermelhos) utilizando o protocolo Sony;
data
: um valor que contém os dados a serem enviados. Este valor representa o código IR em formato binário.nbits
: indica o número de bits do código Sony a ser enviado.void sendPanasonic(unsigned int address, unsigned long data);
: utilizada para enviar códigos IR utilizando o protocolo Panasonic;
address
: um valor que representa o endereço do dispositivo Panasonic.data
: um valor que contém os dados a serem enviados. Este valor representa o código IR em formato binário.void sendJVC(unsigned long data, int nbits, bool repeat);
: utilizada para enviar códigos IR utilizando o protocolo JVC;
data
: um valor que contém os dados a serem enviados. Este valor representa o código IR em formato binário.nbits
: indica o número de bits do código JVC a ser enviado.repeat
: um valor booleano que indica se o comando a ser enviado é uma repetição de um comando anterior. Se for verdadeiro (true), o comando será enviado como uma repetição. Se for falso (false), será enviado como um novo comando.void sendSAMSUNG(unsigned long data, int nbits);
: utilizada para enviar códigos IR utilizando o protocolo Samsung;
data
: um valor que contém os dados a serem enviados. Este valor representa o código IR em formato binário.nbits
: indica o número de bits do código Samsung a ser enviado.void sendWhynter(unsigned long data, int nbits);
: utilizada para enviar códigos IR utilizando o protocolo Whynter;
data
: um valor que contém os dados a serem enviados. Este valor representa o código IR em formato binário.nbits
: indica o número de bits do código Whynter a ser enviado.void sendAiwaRCT501(int code);
: utilizada para enviar códigos IR específicos para o controle remoto do modelo Aiwa RCT501;
code
: um valor inteiro que representa o código a ser enviado pelo controle remoto. Este código é específico para o modelo Aiwa RCT501 e pode variar dependendo da função desejada (como aumentar o volume, trocar de canal, etc.).void sendLG(unsigned long data, int nbits);
: utilizada para enviar códigos IR utilizando o protocolo LG;
data
: um valor que contém os dados a serem enviados. Este valor representa o código IR em formato binário.nbits
: indica o número de bits do código LG a ser enviado.void sendDISH(unsigned long data, int nbits);
: utilizada para enviar códigos IR (infravermelhos) utilizando o protocolo Diss;
data
: um valor unsigned long que contém os dados a serem enviados. Este valor representa o código IR em formato binário.nbits
: indica o número de bits do código Dish a ser enviado.void sendSharp(unsigned int address, unsigned int command);
: utilizada para enviar códigos IR utilizando o protocolo Sharp;
address
: um valor que representa o endereço do dispositivo Sharp.command
: um valor que representa o comando a ser enviado para o dispositivo Sharp.void sendSharpAlt(unsigned int address, unsigned long command);
: utilizada para enviar códigos IR utilizando uma alternativa do protocolo Sharp;
address
: um valor unsigned int que representa o endereço do dispositivo Sharp.command
: um valor unsigned long que representa o comando a ser enviado para o dispositivo Sharp.void sendDenon(unsigned long data, int nbits);
: utilizada para enviar códigos IR utilizando o protocolo Denon;
data
: um valor que contém os dados a serem enviados. Este valor representa o código IR em formato binário.nbits
: indica o número de bits do código Denon a ser enviado.void sendLegoPowerFunctions(uint16_t data, bool repeat = true);
: utilizada para enviar comandos IR utilizando o protocolo Lego Power Functions;
data
: um valor que contém os dados a serem enviados. Este valor representa o comando IR em formato binário.repeat
(opcional): um valor booleano que indica se o comando a ser enviado é uma repetição de um comando anterior. Por padrão, é verdadeiro (true), o que significa que o comando será enviado como uma repetição. Se for definido como falso (false), o comando será enviado como um novo comando.void sendBoseWave(unsigned char code);
: utilizada para enviar códigos IR utilizando o protocolo Bose Wave;
code
: um valor unsigned char que representa o código a ser enviado pelo controle remoto Bose Wave. Este código é específico para as funções suportadas pelo dispositivo Bose Wave, como ligar/desligar, ajustar o volume, trocar de faixa, etc.void sendMagiQuest(unsigned long wand_id, unsigned int magnitude);
: utilizada para enviar comandos IR utilizando o protocolo MagiQuest;
wand_id
: um valor que representa o identificador único da varinha utilizada no jogo MagiQuest.magnitude
: um valor unsigned int que representa a magnitude do comando a ser enviado. Este valor pode variar dependendo do tipo de comando e da implementação específica do jogo MagiQuest.Abaixo segue um exemplo para ler o código hexadecimal IR de uma tecla de um controle remoto. Crie um projeto PlatformIO (instruções aqui) e cole o seguinte código em main.cpp e faça upload para a placa Arduino Mega:
/****************************************************************************** Exemplo de Recepção de comandos IR usando IRremote Criado em 06 de Junho de 2024 por Michel Galvão (https://micsg.com.br) Eletrogate | Arduino, Robótica, IoT, Apostilas e Kits https://www.eletrogate.com/ ******************************************************************************/ #include "Arduino.h" // Inclui a biblioteca principal do Arduino (para compatibilidade com PlatformIO) #include <IRremote.h> // Inclui a biblioteca IRremote para comunicação IR #define IR_RECEIVE_PIN 11 // Define o pino de recebimento do IR como pino 11 IRrecv irrecv(IR_RECEIVE_PIN); // Inicializa o receptor IR no pino definido // Protótipo das funções String getProtocol(decode_type_t); void setup() { Serial.begin(115200); // Inicializa a comunicação serial com uma taxa de 115200 baud irrecv.enableIRIn(); // Ativa o receptor IR } void loop() { decode_results results; // Declara uma variável para armazenar os resultados decodificados if (irrecv.decode(&results)) { // Verifica se um sinal IR foi recebido, e se recebido, passa // os dados para a variável results // Se um sinal IR foi recebido, imprime os resultados Serial.print("Received "); Serial.print(results.bits, DEC); // Imprime o número de bits do sinal IR em decimal Serial.print(" bits "); Serial.print("Hex value: "); Serial.println(results.value, HEX); // Imprime o valor hexadecimal do sinal IR Serial.print("Protocol: "); Serial.println(getProtocol(results.decode_type)); // Imprime o protocolo do sinal IR Serial.println(""); irrecv.resume(); // Reinicia o receptor IR para receber o próximo sinal } } // Função que retorna o nome do protocolo IR obtido à partir do parâmetro informado String getProtocol(decode_type_t decode_type) { switch (decode_type) { case UNKNOWN: return "UNKNOWN"; break; case UNUSED: return "UNUSED"; break; case RC5: return "RC5"; break; case RC6: return "RC6"; break; case NEC: return "NEC"; break; case SONY: return "SONY"; break; case PANASONIC: return "PANASONIC"; break; case JVC: return "JVC"; break; case SAMSUNG: return "SAMSUNG"; break; case WHYNTER: return "WHYNTER"; break; case AIWA_RC_T501: return "AIWA_RC_T501"; break; case LG: return "LG"; break; case SANYO: return "SANYO"; break; case MITSUBISHI: return "MITSUBISHI"; break; case DISH: return "DISH"; break; case SHARP: return "SHARP"; break; case SHARP_ALT: return "SHARP_ALT"; break; case DENON: return "DENON"; break; case LEGO_PF: return "LEGO_PF"; break; case BOSEWAVE: return "BOSEWAVE"; break; case MAGIQUEST: return "MAGIQUEST"; break; } }
O seguinte código adicional também é necessário em platformio.ini:
; PlatformIO Project Configuration File ; ; Build options: build flags, source filter ; Upload options: custom upload port, speed and extra flags ; Library options: dependencies, extra library storages ; Advanced options: extra scripting ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html [env:megaatmega2560] platform = atmelavr board = megaatmega2560 framework = arduino monitor_speed = 115200 lib_deps = https://github.com/Arduino-IRremote/Arduino-IRremote.git#2.5.0
Monte o circuito com seu Arduino Mega de acordo com o seguinte esquemático:
Veja no GIF abaixo a saída do Monitor Serial do PlatformIO. Observe que ao clicar em uma tecla de um controle remoto apontando para o Receptor Infravermelho o código hexadecimail é impresso na tela. Caso fique pressionando a mesma tecla sem solta-la, o código hexadecimal fica como 0xFFFFFFFF
.
Abaixo segue um exemplo para enviar um código hexadecimal IR através de emissor infravermelho. Crie um projeto PlatformIO (instruções aqui) e cole o seguinte código em main.cpp e faça upload para a placa Arduino Mega.
Nota: o código hexadecimal 0xFFD827
que está na variável hexValue
foi obtido através do exemplo anterior (Exemplo de Uso – Ler Comando) após o pressionamento de uma tecla em um controle remoto de TV:
/****************************************************************************** Exemplo de Envio de comando IR usando IRremote Criado em 06 de Junho de 2024 por Michel Galvão (https://micsg.com.br) Eletrogate | Arduino, Robótica, IoT, Apostilas e Kits https://www.eletrogate.com/ ******************************************************************************/ #include "Arduino.h" // Inclui a biblioteca principal do Arduino (para compatibilidade com PlatformIO) #include <IRremote.h> // Inclui a biblioteca IRremote para comunicação IR IRsend irsend; void setup() { Serial.begin(115200); // Inicializa a comunicação serial com uma taxa de 115200 baud delay(100); Serial.println(F("START " __FILE__ " from " __DATE__)); Serial.print(F("Ready to send IR signals at pin ")); Serial.println(IR_SEND_PIN); // mostra na Serial o pino que está o emissor infravermelho } void loop() { unsigned long hexValue = 0xFFD827; // Define o valor hexadecimal a ser enviado Serial.print("Sending Hex value: "); Serial.println(hexValue, HEX); // Imprime o valor hexadecimal no monitor serial irsend.sendNEC(hexValue, 32); // Envia o sinal IR com o protocolo NEC e 32 bits delay(1000); // espera 1 segundo }
O seguinte código adicional também é necessário em platformio.ini:
; PlatformIO Project Configuration File ; ; Build options: build flags, source filter ; Upload options: custom upload port, speed and extra flags ; Library options: dependencies, extra library storages ; Advanced options: extra scripting ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html [env:megaatmega2560] platform = atmelavr board = megaatmega2560 framework = arduino monitor_speed = 115200 lib_deps = https://github.com/Arduino-IRremote/Arduino-IRremote.git#2.5.0
Monte o circuito com seu Arduino Mega de acordo com o seguinte esquemático:
Veja no GIF abaixo a saída do Monitor Serial do PlatformIO:
A Biblioteca EEPROM-Storage é uma ferramenta poderosa que simplifica o acesso e o gerenciamento de variáveis armazenadas na EEPROM em plataformas Arduino. Com esta biblioteca, é possível tratar variáveis armazenadas na EEPROM da mesma forma que tratamos variáveis na RAM, tornando o desenvolvimento de projetos que exigem a preservação de dados entre reinicializações muito mais intuitivo e eficiente. Essa funcionalidade é essencial para aplicações onde a persistência de dados é crucial, como em sistemas de automação residencial, contadores de tempo, registros de eventos, entre outros.
Um dos principais benefícios da Biblioteca EEPROM-Storage é a simplicidade com que se pode definir e manipular variáveis. Normalmente, trabalhar com EEPROM requer um cuidado especial para ler e escrever dados de forma precisa e eficiente. No entanto, com esta biblioteca, o processo é simplificado ao ponto de ser quase idêntico ao manuseio de variáveis comuns em RAM.
A documentação da biblioteca pode ser vista em seu repositório no Github: github.com/porrey/EEPROM-Storage.
Para instalar a biblioteca EEPROM-Storage para utilização na Arduino IDE, siga os passos abaixo:
Para instalar a biblioteca EEPROM-Storage para utilização em projetos no PlatformIO, siga os passos abaixo:
https://github.com/MicSG-dev/EEPROM-Storage-PlatformIO
:Uma instância de variável EEPROMStorage pode ser declarada globalmente, dentro de uma classe ou dentro de uma função.
É possível instanciar mais de uma instância utilizando o mesmo endereço, sendo que ambas as instâncias compartilharão o mesmo valor, mantendo as duas instâncias sincronizadas. Tenha cuidado com esse cenário, pois se duas instâncias forem criadas com um tipo base diferente, o resultado poderá ser inesperado.
A sintaxe para declaração é EEPROMStorage<tipoDoDado> nomeVariavel(endereco, valorPadrao);
, onde:
tipoDoDado
: especifica o tipo de dados para a instância;nomeVariavel
: especifica o nome da variável;endereco
: especifica o índice inicial do endereço na EEPROM onde o valor será armazenado;valorPadrao
: especifica o valor que será retornado pela instância quando o local da memória EEPROM não tiver sido inicializado (a inicialização é determinada pela soma de verificação. Veja mais sobre soma de verificação abaixo).Para inicializar uma instância de variável com o nome variavelQualquer, com um tipo de dados int, localizado na posição inicial 50 da EEPROM e que tenha um valor padrão de 10 (caso não inicializado), a sintaxe seria a seguinte:
EEPROMStorage<int> variavelQualquer(50, 10);
Ao definir uma variável de armazenamento EEPROM, é importante compreender o número de bytes necessários para o tipo utilizado e garantir que as variáveis sejam espaçadas adequadamente para que não colidam.
Cada variável requer memória suficiente para armazenar o tipo utilizado incrementado de mais um byte adicional para uma soma de verificação.
Considere a seguinte declaração de variável:
EEPROMStorage<uint8_t> variavel1(0, 0);
Nesta declaração de variável, a variável possui endereço inicial 0 (zero). Para definir o endereço de outra possível variável que será instanciada posteriormente à essa, é utilizada a seguinte fórmula matemática:
nextAddressVar = sizeVar + checksum + currentAddressVar
, onde:
nextAddressVar
: o resultado do cálculo, sendo este o endereço da próxima variável à ser gravada na memóriasizeVar
: o tamanho do tipo da variável;checksum
: byte adicional para uma soma de verificação (possui sempre o valor 1);currentAddressVar
: endereço da variável atual.Para descobrir o tamanho do tipo da variável, é necessário seguir os seguintes passos:
#include <Arduino.h> #define tipoVariavel String // Altere aqui o tipo de dado void setup() { Serial.begin(115200); Serial.print("O tamanho do tipo da variável é "); Serial.print(sizeof(tipoVariavel)); Serial.println(" bytes."); } void loop() { delay(10); }
variavel1
, substitua String
por uint8_t
);Saída do Monitor Serial do Wokwi
No exemplo anterior, o tipo de dado da variável variavel1
é o uint8_t
, o qual possui possui o tamanho de 1 byte.
Aplicando a fórmula matemática anterior, o endereço da próxima variável à ser gravada na memória é 2. Veja o cálculo:
nextAddressVar = sizeVar + checksum + currentAddressVar nextAddressVar = 1 + 1 + 0 nextAddressVar = 2
A instanciação da próxima variável seria assim:
EEPROMStorage<uint8_t> variavel2(2, 0);
Nota: Não é necessário alinhar variáveis no início da memória, ou seja, posicioná-las consecutivamente. Isso apenas torna mais fácil a implementação. Você é livre para organizá-los da maneira que melhor atenda às suas necessidades.
Veja abaixo como seria a continuação da instanciação das próximas variáveis após variavel1
(variável do exemplo anterior):
// Fórmula para próximo endereço de variável: nextAddressVar = sizeVar + checksum + currentAddressVar EEPROMStorage<uint8_t> variavel1(0, 0); // endereço 0. tamanho 1 byte. Próx. endereço: 1 + 1 + 0 = 2 EEPROMStorage<uint8_t> variavel2(2, 0); // endereço 2. tamanho 1 byte. Próx. endereço: 1 + 1 + 2 = 4 EEPROMStorage<uint16_t> variavel3(4, 0); // endereço 4. tamanho 2 bytes. Próx. endereço: 2 + 1 + 4 = 7 EEPROMStorage<uint32_t> variavel4(7, 0); // endereço 7. tamanho 4 bytes. Próx. endereço: 4 + 1 + 7 = 12 EEPROMStorage<float> variavel5(12, 0.0); // endereço 12. tamanho 4 bytes. Próx. endereço: 4 + 1 + 12 = 17 EEPROMStorage<bool> variavel6(17, false); // endereço 17. tamanho 1 byte. Próx. endereço: 1 + 1 + 17 = 19
Usando o exemplo anterior, atribuir um valor à instância é tão simples quanto a seguinte atribuição mostrada:
variavelQualquer = 100; // define o valor 100 para a variável
A biblioteca EEPROMStorage também disponibiliza um método para fazer atribuição do valor:
void set(T const& value) const
, onde:value
: o valor que será salvo na memória EEPROM.Exemplo:
variavelQualquer.set(100); // define o valor 100 para a variável
Para obter o valor da instância de uma variável, atribua-o a uma variável, conforme mostrado abaixo:
int outraVariavel = variavelQualquer;
ou passe-o como argumento em qualquer função que receba um argumento int conforme mostrado abaixo:
Serial.print("variavelQualquer= "); Serial.println(variavelQualquer);
A biblioteca EEPROMStorage também disponibiliza um método que pode ser usado para fazer recuperação do valor:
int outraVariavel = variavelQualquer.get();
Os chips em que a memória EEPROM fica alocada possuem limites de gravações. Por exemplo, o chip ATmega328P (do Arduino Uno) especifica um limite de 100000 (cem mil) gravações por localização de endereço. Por esta questão siga as seguintes recomendações:
A velocidade de leitura e gravação da EEPROM é muito mais lenta que a da memória flash. Verifique e otimize o uso de variáveis EEPROM para não afetar o desempenho (velocidade) de seu algoritmo Arduino.
Ao gravar um valor em uma variável EEPROM e você tentar gravar o mesmo valor novamente, a biblioteca não executará a segunda gravação (pois o valor não é alterado). Lembre-se de que há código extra para realizar essa verificação, o que pode causar alguns problemas de desempenho em seu aplicativo.
Ler um valor da EEPROM é mais rápido do que escrever um valor na EEPROM, mas a leitura da EEPROM é mais lenta do que a leitura de uma variável da memória flash.
Crie um projeto PlatformIO (instruções aqui) e cole o seguinte código em main.cpp. Lembre-se também de colar o código de platformio.ini no arquivo de mesmo nome do seu projeto.
Antes de fazer upload para sua placa Arduino Mega, é necessário alterar o protocolo de seu Controle Remoto da sua TV:
protocolo
, altere para o protocolo IR do controle remoto de sua TV. Neste exemplo, o controle de minha TV possuía o protocolo NEC. Para descobrir o protocolo de seu controle remoto carregue o sketch do Exemplo de Uso IRremote – Ler Comando e veja o protocolo na saída do Monitor Serial após apertar uma tecla de seu controle remoto;Após a alteração, faça upload para sua placa Arduino Mega.
Código a ser colado no arquivo main.cpp:
/****************************************************************************** Controle sua TV com Keypad e Arduino Mega Sketch Principal Criado em 11 de Março de 2024 por Michel Galvão (https://micsg.com.br) Eletrogate | Arduino, Robótica, IoT, Apostilas e Kits https://www.eletrogate.com/ ******************************************************************************/ // Inclusão das Bibliotecas #include <Arduino.h> // Inclui a biblioteca padrão do Arduino #include "IRremote.h" // Inclui a biblioteca IRremote para controle remoto #include "EEPROM-Storage.h" // Inclui a biblioteca EEPROM-Storage para armazenamento em EEPROM #include "Keypad.h" // Inclui a biblioteca Keypad para uso de teclado matricial #define protocolo NEC // Define o protocolo como NEC // Estrutura para armazenar códigos de teclas da TV struct TeclasTv { unsigned long _1 = 999; // Código da tecla 1 unsigned long _2 = 999; // Código da tecla 2 unsigned long _3 = 999; // Código da tecla 3 unsigned long _4 = 999; // Código da tecla 4 unsigned long _5 = 999; // Código da tecla 5 unsigned long _6 = 999; // Código da tecla 6 unsigned long _7 = 999; // Código da tecla 7 unsigned long _8 = 999; // Código da tecla 8 unsigned long _9 = 999; // Código da tecla 9 unsigned long _0 = 999; // Código da tecla 0 unsigned long _asterisco = 999; // Código da tecla asterisco unsigned long _cerquilha = 999; // Código da tecla cerquilha }; const byte ROWS = 4; // Quatro linhas do teclado const byte COLS = 4; // Quatro colunas do teclado char keys[ROWS][COLS] = { // Definição das teclas no teclado matricial {'1', '2', '3', 'A'}, // Linha 1 {'4', '5', '6', 'B'}, // Linha 2 {'7', '8', '9', 'C'}, // Linha 3 {'*', '0', '#', 'D'}}; // Linha 4 byte rowPins[ROWS] = {10, 12, 8, 7}; // Pinos das linhas do teclado byte colPins[COLS] = {6, 5, 4, 3}; // Pinos das colunas do teclado Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS); // Inicializa o objeto keypad com as configurações fornecidas #define IR_RECEIVE_PIN 11 // Define o pino de recebimento do IR como pino 11 IRsend irsend; // Criação do objeto para envio de comandos IR // Definições de armazenamento em EEPROM para códigos de teclas da TV e de tamanho do código de tecla // ----- // ----- Cálculo do endereço de variável na EEPROM: // ----- sizeVar + checksum + previousAddressVar = nextAddressVar // ----- // ----- Variáveis da Fórmula: // ----- sizeVar: tamanho da variável; // ----- checksum: byte adicional para uma soma de verificação // ----- currentAddressVar: endereço da variável atual; // ----- nextAddressVar: o resultado do cálculo, sendo este o endereço da próxima variável à ser gravada na memória // ----- EEPROMStorage<int> tamanhoCode(0, 999); // variável armazenada na EEPROM no endereço 0 e que tem 2 bytes. Cálculo endereço próxima variável: 2 + 1 + 0 = 3 bytes EEPROMStorage<unsigned long> tecla1(3, 999); // variável armazenada na EEPROM no endereço 3 e que tem 4 bytes. Cálculo endereço próxima variável: 4 + 1 + 3 = 8 bytes EEPROMStorage<unsigned long> tecla2(8, 999); // variável armazenada na EEPROM no endereço 8 e que tem 4 bytes. Cálculo endereço próxima variável: 4 + 1 + 8 = 13 bytes EEPROMStorage<unsigned long> tecla3(13, 999); // variável armazenada na EEPROM no endereço 13 e que tem 4 bytes. Cálculo endereço próxima variável: 4 + 1 + 13 = 18 bytes EEPROMStorage<unsigned long> tecla4(18, 999); // variável armazenada na EEPROM no endereço 18 e que tem 4 bytes. Cálculo endereço próxima variável: 4 + 1 + 18 = 23 bytes EEPROMStorage<unsigned long> tecla5(23, 999); // variável armazenada na EEPROM no endereço 23 e que tem 4 bytes. Cálculo endereço próxima variável: 4 + 1 + 23 = 28 bytes EEPROMStorage<unsigned long> tecla6(28, 999); // variável armazenada na EEPROM no endereço 28 e que tem 4 bytes. Cálculo endereço próxima variável: 4 + 1 + 28 = 33 bytes EEPROMStorage<unsigned long> tecla7(33, 999); // variável armazenada na EEPROM no endereço 33 e que tem 4 bytes. Cálculo endereço próxima variável: 4 + 1 + 33 = 38 bytes EEPROMStorage<unsigned long> tecla8(38, 999); // variável armazenada na EEPROM no endereço 38 e que tem 4 bytes. Cálculo endereço próxima variável: 4 + 1 + 38 = 43 bytes EEPROMStorage<unsigned long> tecla9(43, 999); // variável armazenada na EEPROM no endereço 43 e que tem 4 bytes. Cálculo endereço próxima variável: 4 + 1 + 43 = 48 bytes EEPROMStorage<unsigned long> tecla0(48, 999); // variável armazenada na EEPROM no endereço 48 e que tem 4 bytes. Cálculo endereço próxima variável: 4 + 1 + 48 = 53 bytes EEPROMStorage<unsigned long> teclaAsterisco(53, 999); // variável armazenada na EEPROM no endereço 53 e que tem 4 bytes. Cálculo endereço próxima variável: 4 + 1 + 53 = 58 bytes EEPROMStorage<unsigned long> teclaCerquilha(58, 999); // variável armazenada na EEPROM no endereço 58 e que tem 4 bytes. unsigned long getTeclaControleRemoto(); // Declaração da função para obter código de tecla do controle remoto void enviarComando(unsigned long data, int nbits); // Declaração da função para enviar comando IR const int pinoLed = 2; // Define o pino do LED como pino 2 void setup() { pinMode(pinoLed, OUTPUT); // define o pino do LED como saída // algoritmo para o STATUS DO LED (Apagado): sem fazer nenhuma ação, esperando o usuário executar algo; // o LED fica apagado digitalWrite(pinoLed, LOW); // inicia o led no modo APAGADO Serial.begin(115200); // Define a taxa de baudrate da interface Serial com 115200 bits por segundo } unsigned long timerLED; // timer para controle de status (aceso/apagado) do LED indicador const int tempoLimite = 5000; // tempo limite para operações no teclado (5 segundos) unsigned long timerTeclado; // timer para controle de tempo limite em operações no teclado void loop() { char teclaPressionada = keypad.getKey(); // obtém a tecla pressionada pelo usuário if (teclaPressionada != NO_KEY) // se alguma tecla foi pressionada, ... { // algoritmo para o STATUS DO LED (Pisca 1 vez e apaga): ao usuário pressionar algum botão (será aceso o LED) e após soltar o botão (será apagado o LED); digitalWrite(pinoLed, HIGH); timerLED = millis(); while (millis() - timerLED <= 250) // durante 250 milissegundos o led ficará acesso { delay(1); } digitalWrite(pinoLed, LOW); // verifica qual tecla foi pressioanda e executa algum algoritmo dependendo da tecla pressionada switch (teclaPressionada) { case 'A': // caso seja a tecla A, entra no modo de cadastro de códigos IR nas teclas { timerTeclado = millis(); // armazena o valor atual do temporizador millis bool permanecerNoMenu = true; // variável que controla se o loop do 'menu' deve ser interrompido ou não Serial.println("Cadastrar teclas. Pressione alguma tecla de 0 a 9, * ou # para iniciar o cadastramento."); TeclasTv teclasTv; // instancia a estrutura que armazenará as tecals da TV while (permanecerNoMenu) // loop do 'menu' de cadastro de códigos IR nas teclas { // algoritmo para o STATUS DO LED (Pisca-pisca lento): Cadastrando novas teclas; // a cada 1 segundo (1000 milissegundos) o LED inverte seu estado: ora fica aceso, ora fica apagado if (millis() - timerLED >= 1000) { digitalWrite(pinoLed, !digitalRead(pinoLed)); timerLED = millis(); } // obtém a tecla pressionada pelo usuário teclaPressionada = keypad.getKey(); if (teclaPressionada != NO_KEY) // se alguma tecla foi pressionada, ... { unsigned long tecla; // variável para armazenar a tecla do controle da TV pressionada pelo usuário switch (teclaPressionada) // se a tecla pressionada do Keypad pelo usuário { case 'B': // caso a tecla pressionada do Keypad seja a B (FUNÇÃO: Salvar teclas modificadas), ... timerLED = millis(); // atualiza o valor do temporizador de controle do estado do LED Serial.println("Teclas modificadas foram salvas. Saindo do menu..."); // algoritmo para o LED indicador de status: Aceso por um período de tempo, Teclas modificadas salvas; // durante 2 segundos (2000 millisegundos) o LED permanece aceso. Após este período, o led apaga digitalWrite(pinoLed, HIGH); while (millis() - timerLED <= 2000) { delay(1); } digitalWrite(pinoLed, LOW); // se o membro _0 (tecla 0) da estrutura TeclasTv possuir um valor diferente de 999 (alterado), salva na EEPROM o seu valor if (teclasTv._0 != 999) { tecla0 = teclasTv._0; } // se o membro _1 (tecla 1) da estrutura TeclasTv possuir um valor diferente de 999 (alterado), salva na EEPROM o seu valor if (teclasTv._1 != 999) { tecla1 = teclasTv._1; } // se o membro _2 (tecla 2) da estrutura TeclasTv possuir um valor diferente de 999 (alterado), salva na EEPROM o seu valor if (teclasTv._2 != 999) { tecla2 = teclasTv._2; } // se o membro _3 (tecla 3) da estrutura TeclasTv possuir um valor diferente de 999 (alterado), salva na EEPROM o seu valor if (teclasTv._3 != 999) { tecla3 = teclasTv._3; } // se o membro _4 (tecla 4) da estrutura TeclasTv possuir um valor diferente de 999 (alterado), salva na EEPROM o seu valor if (teclasTv._4 != 999) { tecla4 = teclasTv._4; } // se o membro _5 (tecla 5) da estrutura TeclasTv possuir um valor diferente de 999 (alterado), salva na EEPROM o seu valor if (teclasTv._5 != 999) { tecla5 = teclasTv._5; } // se o membro _6 (tecla 6) da estrutura TeclasTv possuir um valor diferente de 999 (alterado), salva na EEPROM o seu valor if (teclasTv._6 != 999) { tecla6 = teclasTv._6; } // se o membro _7 (tecla 7) da estrutura TeclasTv possuir um valor diferente de 999 (alterado), salva na EEPROM o seu valor if (teclasTv._7 != 999) { tecla7 = teclasTv._7; } // se o membro _8 (tecla 8) da estrutura TeclasTv possuir um valor diferente de 999 (alterado), salva na EEPROM o seu valor if (teclasTv._8 != 999) { tecla8 = teclasTv._8; } // se o membro _9 (tecla 9) da estrutura TeclasTv possuir um valor diferente de 999 (alterado), salva na EEPROM o seu valor if (teclasTv._9 != 999) { tecla9 = teclasTv._9; } // se o membro _asterisco (tecla diminuir volume) da estrutura TeclasTv possuir um valor diferente de 999 (alterado), salva na EEPROM o seu valor if (teclasTv._asterisco != 999) { teclaAsterisco = teclasTv._asterisco; } // se o membro _cerquilha (tecla aumentar volume) da estrutura TeclasTv possuir um valor diferente de 999 (alterado), salva na EEPROM o seu valor if (teclasTv._cerquilha != 999) { teclaCerquilha = teclasTv._cerquilha; } // reseta os valores dos membros da estrutura TeclasTv teclasTv._0 = 999; teclasTv._1 = 999; teclasTv._2 = 999; teclasTv._3 = 999; teclasTv._4 = 999; teclasTv._5 = 999; teclasTv._6 = 999; teclasTv._7 = 999; teclasTv._8 = 999; teclasTv._9 = 999; teclasTv._0 = 999; teclasTv._asterisco = 999; teclasTv._cerquilha = 999; permanecerNoMenu = false; // interrompe o loop do 'menu' (sair fora do menu) break; case '1': Serial.println("Pressione a tecla 1 do controle remoto"); tecla = getTeclaControleRemoto(); if (tecla != 999) { teclasTv._1 = tecla; } break; case '2': Serial.println("Pressione a tecla 2 do controle remoto"); tecla = getTeclaControleRemoto(); if (tecla != 999) { teclasTv._2 = tecla; } break; case '3': Serial.println("Pressione a tecla 3 do controle remoto"); tecla = getTeclaControleRemoto(); if (tecla != 999) { teclasTv._3 = tecla; } break; case '4': Serial.println("Pressione a tecla 4 do controle remoto"); tecla = getTeclaControleRemoto(); if (tecla != 999) { teclasTv._4 = tecla; } break; case '5': Serial.println("Pressione a tecla 5 do controle remoto"); tecla = getTeclaControleRemoto(); if (tecla != 999) { teclasTv._5 = tecla; } break; case '6': Serial.println("Pressione a tecla 6 do controle remoto"); tecla = getTeclaControleRemoto(); if (tecla != 999) { teclasTv._6 = tecla; } break; case '7': Serial.println("Pressione a tecla 7 do controle remoto"); tecla = getTeclaControleRemoto(); if (tecla != 999) { Serial.print("0x"); Serial.println(tecla, HEX); teclasTv._7 = tecla; } break; case '8': Serial.println("Pressione a tecla 8 do controle remoto"); tecla = getTeclaControleRemoto(); if (tecla != 999) { teclasTv._8 = tecla; } break; case '9': Serial.println("Pressione a tecla 9 do controle remoto"); tecla = getTeclaControleRemoto(); if (tecla != 999) { teclasTv._9 = tecla; } break; case '0': Serial.println("Pressione a tecla 0 do controle remoto"); tecla = getTeclaControleRemoto(); if (tecla != 999) { teclasTv._0 = tecla; } break; case '*': Serial.println("Pressione a tecla ABAIXAR VOLUME do controle remoto"); tecla = getTeclaControleRemoto(); if (tecla != 999) { teclasTv._asterisco = tecla; } break; case '#': Serial.println("Pressione a tecla AUMENTAR VOLUME do controle remoto"); tecla = getTeclaControleRemoto(); if (tecla != 999) { teclasTv._cerquilha = tecla; } break; } } } digitalWrite(pinoLed, LOW); break; } case 'C': // caso seja a tecla C, entra no modo de exclusão de todos os códigos IR das teclas cadastrados { timerLED = millis(); // Armazena o tempo atual em milissegundos // Exibe mensagem informando que todos os cadastros de teclas estão sendo excluídos Serial.println("Excluir cadastro de todas teclas"); // algoritmo para o STATUS DO LED (Pisca-pisca rápido): Limpando toda memória contendo o cadastro de teclas. // a cada 100 milissegundos o LED inverte seu estado: ora fica aceso, ora fica apagado while (millis() - timerLED <= 2000) { for (int i = 0; i < 25; i++) // 2,5 segundos { delay(100); digitalWrite(pinoLed, !digitalRead(pinoLed)); } } digitalWrite(pinoLed, LOW); // Reseta os códigos IR das teclas para o valor 999, indicando que estão "vazios" tecla1 = 999; tecla2 = 999; tecla3 = 999; tecla4 = 999; tecla5 = 999; tecla6 = 999; tecla7 = 999; tecla8 = 999; tecla9 = 999; tecla0 = 999; teclaAsterisco = 999; teclaCerquilha = 999; break; } case 'D': // caso seja a tecla D, entra no modo de exibição de todos os códigos IR das teclas cadastrados { Serial.println("Dados das teclas cadastradas:\n"); // Exibe mensagem inicial indicando o início da exibição dos dados // Exibe o código cadastrado para a tecla 1 Serial.print("Tecla 1: "); if (tecla1 != 999) // Verifica se a tecla 1 está cadastrada { // Exibe o valor decimal e hexadecimal do código IR da tecla 1 Serial.print(tecla1); Serial.print(" (0x"); Serial.print(tecla1, HEX); Serial.println(")"); } else // caso a tecla não esteja cadastrada { // Indica que a tecla 1 não está cadastrada Serial.println("-"); } // Exibe o código cadastrado para a tecla 2 Serial.print("Tecla 2: "); if (tecla2 != 999) // Verifica se a tecla 2 está cadastrada { // Exibe o valor decimal e hexadecimal do código IR da tecla 2 Serial.print(tecla2); Serial.print(" (0x"); Serial.print(tecla2, HEX); Serial.println(")"); } else // caso a tecla não esteja cadastrada { Serial.println("-"); } // Exibe o código cadastrado para a tecla 3 Serial.print("Tecla 3: "); if (tecla3 != 999) // Verifica se a tecla 3 está cadastrada { // Exibe o valor decimal e hexadecimal do código IR da tecla 3 Serial.print(tecla3); Serial.print(" (0x"); Serial.print(tecla3, HEX); Serial.println(")"); } else // caso a tecla não esteja cadastrada { // Indica que a tecla 3 não está cadastrada Serial.println("-"); } // Exibe o código cadastrado para a tecla 4 Serial.print("Tecla 4: "); if (tecla4 != 999) // Verifica se a tecla 4 está cadastrada { // Exibe o valor decimal e hexadecimal do código IR da tecla 4 Serial.print(tecla4); Serial.print(" (0x"); Serial.print(tecla4, HEX); Serial.println(")"); } else // caso a tecla não esteja cadastrada { // Indica que a tecla 4 não está cadastrada Serial.println("-"); } // Exibe o código cadastrado para a tecla 5 Serial.print("Tecla 5: "); if (tecla5 != 999) // Verifica se a tecla 5 está cadastrada { // Exibe o valor decimal e hexadecimal do código IR da tecla 5 Serial.print(tecla5); Serial.print(" (0x"); Serial.print(tecla5, HEX); Serial.println(")"); } else // caso a tecla não esteja cadastrada { // Indica que a tecla 5 não está cadastrada Serial.println("-"); } // Exibe o código cadastrado para a tecla 6 Serial.print("Tecla 6: "); if (tecla6 != 999) // Verifica se a tecla 6 está cadastrada { // Exibe o valor decimal e hexadecimal do código IR da tecla 6 Serial.print(tecla6); Serial.print(" (0x"); Serial.print(tecla6, HEX); Serial.println(")"); } else // caso a tecla não esteja cadastrada { // Indica que a tecla 6 não está cadastrada Serial.println("-"); } // Exibe o código cadastrado para a tecla 7 Serial.print("Tecla 7: "); if (tecla7 != 999) // Verifica se a tecla 7 está cadastrada { // Exibe o valor decimal e hexadecimal do código IR da tecla 7 Serial.print(tecla7); Serial.print(" (0x"); Serial.print(tecla7, HEX); Serial.println(")"); } else // caso a tecla não esteja cadastrada { // Indica que a tecla 7 não está cadastrada Serial.println("-"); } // Exibe o código cadastrado para a tecla 8 Serial.print("Tecla 8: "); if (tecla8 != 999) // Verifica se a tecla 8 está cadastrada { // Exibe o valor decimal e hexadecimal do código IR da tecla 8 Serial.print(tecla8); Serial.print(" (0x"); Serial.print(tecla8, HEX); Serial.println(")"); } else // caso a tecla não esteja cadastrada { // Indica que a tecla 8 não está cadastrada Serial.println("-"); } // Exibe o código cadastrado para a tecla 9 Serial.print("Tecla 9: "); if (tecla9 != 999) // Verifica se a tecla 9 está cadastrada { // Exibe o valor decimal e hexadecimal do código IR da tecla 9 Serial.print(tecla9); Serial.print(" (0x"); Serial.print(tecla9, HEX); Serial.println(")"); } else // caso a tecla não esteja cadastrada { // Indica que a tecla 9 não está cadastrada Serial.println("-"); } // Exibe o código cadastrado para a tecla 0 Serial.print("Tecla 0: "); if (tecla0 != 999) // Verifica se a tecla 0 está cadastrada { // Exibe o valor decimal e hexadecimal do código IR da tecla 0 Serial.print(tecla0); Serial.print(" (0x"); Serial.print(tecla0, HEX); Serial.println(")"); } else // caso a tecla não esteja cadastrada { // Indica que a tecla 0 não está cadastrada Serial.println("-"); } // Exibe o código cadastrado para a tecla de reduzir volume (tecla *) Serial.print("Tecla REDUZIR VOLUME: "); if (teclaAsterisco != 999) // Verifica se a tecla de reduzir volume está cadastrada { // Exibe o valor decimal e hexadecimal do código IR da tecla de reduzir volume Serial.print(teclaAsterisco); Serial.print(" (0x"); Serial.print(teclaAsterisco, HEX); Serial.println(")"); } else // caso a tecla não esteja cadastrada { // Indica que a tecla de reduzir volume não está cadastrada Serial.println("-"); } // Exibe o código cadastrado para a tecla de aumentar volume (tecla #) Serial.print("Tecla AUMENTAR VOLUME: "); if (teclaCerquilha != 999) // Verifica se a tecla de aumentar volume está cadastrada { // Exibe o valor decimal e hexadecimal do código IR da tecla de aumentar volume Serial.print(teclaCerquilha); Serial.print(" (0x"); Serial.print(teclaCerquilha, HEX); Serial.println(")"); } else // caso a tecla não esteja cadastrada { // Indica que a tecla de aumentar volume não está cadastrada Serial.println("-"); } // Linha em branco para separar a exibição Serial.println(); break; } case '*': // caso seja a tecla *, tenta enviar o código IR desta tecla { // Exibe mensagem informando que o sinal para reduzir o volume da TV está sendo enviado Serial.println("Enviando sinal para Reduzir volume TV"); if (teclaAsterisco != 999) // Verifica se a tecla de reduzir volume está cadastrada { enviarComando(teclaAsterisco, tamanhoCode); // Envia o comando IR usando a função enviarComando com o código da tecla e o tamanho do código } else // caso não esteja cadastrada { // Exibe mensagem informando que não foi possível enviar o comando pois a tecla não está cadastrada Serial.println("Nao foi possivel enviar esta tecla para a TV. Tente cadastrar a tecla antes."); } break; } case '#': // caso seja a tecla #, tenta enviar o código IR desta tecla { // Exibe mensagem informando que o sinal para aumentar o volume da TV está sendo enviado Serial.println("Enviando sinal para Aumentar volume TV"); if (teclaCerquilha != 999) // Verifica se a tecla de aumentar volume está cadastrada { // Envia o comando IR usando a função enviarComando com o código da tecla e o tamanho do código enviarComando(teclaCerquilha, tamanhoCode); } else // caso não esteja cadastrada { // Exibe mensagem informando que não foi possível enviar o comando pois a tecla não está cadastrada Serial.println("Nao foi possivel enviar esta tecla para a TV. Tente cadastrar a tecla antes."); } break; } case '1': // caso seja a tecla 1, tenta enviar o código IR desta tecla { // Exibe mensagem informando que o sinal da tecla 1 está sendo enviado Serial.println("Enviando sinal da tecla 1"); if (tecla1 != 999) // Verifica se a tecla 1 está cadastrada { // Envia o comando IR usando a função enviarComando com o código da tecla 1 e o tamanho do código enviarComando(tecla1, tamanhoCode); } else // caso não esteja cadastrada { // Exibe mensagem informando que não foi possível enviar o comando pois a tecla não está cadastrada Serial.println("Nao foi possivel enviar esta tecla para a TV. Tente cadastrar a tecla antes."); } break; } case '2': // caso seja a tecla 2, tenta enviar o código IR desta tecla { // Exibe mensagem informando que o sinal da tecla 2 está sendo enviado Serial.println("Enviando sinal da tecla 2"); if (tecla2 != 999) // Verifica se a tecla 2 está cadastrada { // Envia o comando IR usando a função enviarComando com o código da tecla 2 e o tamanho do código enviarComando(tecla2, tamanhoCode); } else // caso não esteja cadastrada { // Exibe mensagem informando que não foi possível enviar o comando pois a tecla não está cadastrada Serial.println("Nao foi possivel enviar esta tecla para a TV. Tente cadastrar a tecla antes."); } break; } case '3': // caso seja a tecla 3, tenta enviar o código IR desta tecla { // Exibe mensagem informando que o sinal da tecla 3 está sendo enviado Serial.println("Enviando sinal da tecla 3"); if (tecla3 != 999) // Verifica se a tecla 3 está cadastrada { // Envia o comando IR usando a função enviarComando com o código da tecla 3 e o tamanho do código enviarComando(tecla3, tamanhoCode); } else // caso não esteja cadastrada { // Exibe mensagem informando que não foi possível enviar o comando pois a tecla não está cadastrada Serial.println("Nao foi possivel enviar esta tecla para a TV. Tente cadastrar a tecla antes."); } break; } case '4': // caso seja a tecla 4, tenta enviar o código IR desta tecla { // Exibe mensagem informando que o sinal da tecla 4 está sendo enviado Serial.println("Enviando sinal da tecla 4"); if (tecla4 != 999) // Verifica se a tecla 4 está cadastrada { // Envia o comando IR usando a função enviarComando com o código da tecla 4 e o tamanho do código enviarComando(tecla4, tamanhoCode); } else // caso não esteja cadastrada { // Exibe mensagem informando que não foi possível enviar o comando pois a tecla não está cadastrada Serial.println("Nao foi possivel enviar esta tecla para a TV. Tente cadastrar a tecla antes."); } break; } case '5': // caso seja a tecla 5, tenta enviar o código IR desta tecla { // Exibe mensagem informando que o sinal da tecla 5 está sendo enviado Serial.println("Enviando sinal da tecla 5"); if (tecla5 != 999) // Verifica se a tecla 5 está cadastrada { // Envia o comando IR usando a função enviarComando com o código da tecla 5 e o tamanho do código enviarComando(tecla5, tamanhoCode); } else // caso não esteja cadastrada { // Exibe mensagem informando que não foi possível enviar o comando pois a tecla não está cadastrada Serial.println("Nao foi possivel enviar esta tecla para a TV. Tente cadastrar a tecla antes."); } break; } case '6': // caso seja a tecla 6, tenta enviar o código IR desta tecla { // Exibe mensagem informando que o sinal da tecla 6 está sendo enviado Serial.println("Enviando sinal da tecla 6"); if (tecla6 != 999) // Verifica se a tecla 6 está cadastrada { // Envia o comando IR usando a função enviarComando com o código da tecla 6 e o tamanho do código enviarComando(tecla6, tamanhoCode); } else // caso não esteja cadastrada { // Exibe mensagem informando que não foi possível enviar o comando pois a tecla não está cadastrada Serial.println("Nao foi possivel enviar esta tecla para a TV. Tente cadastrar a tecla antes."); } break; } case '7': // caso seja a tecla 7, tenta enviar o código IR desta tecla { // Exibe mensagem informando que o sinal da tecla 7 está sendo enviado Serial.println("Enviando sinal da tecla 7"); if (tecla7 != 999) // Verifica se a tecla 7 está cadastrada { // Envia o comando IR usando a função enviarComando com o código da tecla 7 e o tamanho do código enviarComando(tecla7, tamanhoCode); } else // caso não esteja cadastrada { // Exibe mensagem informando que não foi possível enviar o comando pois a tecla não está cadastrada Serial.println("Nao foi possivel enviar esta tecla para a TV. Tente cadastrar a tecla antes."); } break; } case '8': // caso seja a tecla 8, tenta enviar o código IR desta tecla { // Exibe mensagem informando que o sinal da tecla 8 está sendo enviado Serial.println("Enviando sinal da tecla 8"); if (tecla8 != 999) // Verifica se a tecla 8 está cadastrada { // Envia o comando IR usando a função enviarComando com o código da tecla 8 e o tamanho do código enviarComando(tecla8, tamanhoCode); } else // caso não esteja cadastrada { // Exibe mensagem informando que não foi possível enviar o comando porque a tecla não está cadastrada Serial.println("Nao foi possivel enviar esta tecla para a TV. Tente cadastrar a tecla antes."); } break; } case '9': // caso seja a tecla 9, tenta enviar o código IR desta tecla { // Exibe mensagem informando que o sinal da tecla 9 está sendo enviado Serial.println("Enviando sinal da tecla 9"); if (tecla9 != 999) // Verifica se a tecla 9 está cadastrada { // Envia o comando IR usando a função enviarComando com o código da tecla 9 e o tamanho do código enviarComando(tecla9, tamanhoCode); } else // caso não esteja cadastrada { // Exibe mensagem informando que não foi possível enviar o comando porque a tecla não está cadastrada Serial.println("Nao foi possivel enviar esta tecla para a TV. Tente cadastrar a tecla antes."); } break; } case '0': // caso seja a tecla 0, tenta enviar o código IR desta tecla { // Exibe mensagem informando que o sinal da tecla 0 está sendo enviado Serial.println("Enviando sinal da tecla 0"); if (tecla0 != 999) // Verifica se a tecla 0 está cadastrada { // Envia o comando IR usando a função enviarComando com o código da tecla 0 e o tamanho do código enviarComando(tecla0, tamanhoCode); } else // caso não esteja cadastrada { // Exibe mensagem informando que não foi possível enviar o comando porque a tecla não está cadastrada Serial.println("Nao foi possivel enviar esta tecla para a TV. Tente cadastrar a tecla antes."); } break; } } } } // Função para obter a tecla pressionada no controle remoto unsigned long getTeclaControleRemoto() { timerTeclado = millis(); // Armazena o tempo atual em milissegundos IRrecv irrecv(IR_RECEIVE_PIN); // Inicializa o receptor IR no pino especificado irrecv.enableIRIn(); // Habilita a recepção de sinais IR decode_results results; // Estrutura para armazenar os resultados da decodificação IR unsigned long teclaApertada_temp = 999; // Variável temporária para armazenar a tecla pressionada inicialmente unsigned long teclaApertada = 999; // Variável final para armazenar a tecla confirmada bool permanecerNoSubMenu = true; // Variável de controle para manter o loop enquanto estiver no submenu while (millis() - timerTeclado <= tempoLimite && permanecerNoSubMenu) // Loop que continua enquanto o tempo limite não for atingido e estiver no submenu { // algoritmo para o STATUS DO LED (Aceso por um período de tempo): Teclas modificadas salvas; // durante 1 segundo (1000 milissegundos) o LED fica aceso e após é apagado if (millis() - timerLED >= 1000) // Verifica se 1 segundo se passou para alternar o estado do LED { digitalWrite(pinoLed, !digitalRead(pinoLed)); // Alterna o estado do LED timerLED = millis(); // Atualiza o timer do LED } if (irrecv.decode(&results)) // Verifica se um comando IR foi recebido { if (results.value != 0xFFFFFFFF) // Verifica se o valor recebido não é um código repetido { if (teclaApertada_temp == 999) // Se ainda não há tecla temporária armazenada { teclaApertada_temp = results.value; // Armazena o valor recebido temporariamente // Solicita confirmação da tecla pressionada ao usuário Serial.print("Aperte novamente a mesma tecla para confirmar: 0x"); Serial.println(results.value, HEX); timerTeclado = millis(); // Reinicia o timer do teclado } else // caso já haja uma tecla temporária armazenada { if (teclaApertada_temp == results.value) // Se o valor recebido é igual ao valor temporário (CONFIRMADO), ... { // Informa ao usuário sobre a confirmação da tecla pressionada Serial.print("Tecla confirmada: 0x"); Serial.println(results.value, HEX); teclaApertada = teclaApertada_temp; // atribui à variável de retorno o valor da tecla confirmada permanecerNoSubMenu = false; // Sai do submenu } else // caso a confirmação de tecla falhe, ... { // Informa que a tecla pressionada é diferente Serial.println("Chave de Tecla diferente."); permanecerNoSubMenu = false; // Sai do submenu } } } irrecv.resume(); // Prepara o receptor IR para receber o próximo valor } delay(100); // Atraso de 100 ms antes de verificar novamente se um comando IR foi recebido } // Verifica se nenhuma tecla foi confirmada dentro do tempo limite if (teclaApertada == 999) { if (teclaApertada_temp == 999) // Se nenhuma tecla foi pressionada { Serial.print("Nenhuma tecla pressionada dentro do tempo limite. Tente novamente selecionando "); } else // se não, caso a tecla pressionada não foi confirmada { Serial.print("Nao houve confirmacao de tecla. Tente novamente selecionando "); } } else // se não, se ocorreu tudo certo { Serial.print("Insercao de dado finalizada. Pressione "); // Informa que a inserção de dados foi finalizada } Serial.println("alguma tecla para cadastrar ou pressione B para salvar."); // Informa ao usuário para continuar cadastrando novas teclas ou para finalizar salvando as tecclas com a opção B // Verifica se o protocolo da tecla pressionada é diferente do esperado if (results.decode_type != protocolo && teclaApertada_temp == results.value) { // informa ao usuário que ocorreu um erro Serial.print('\n'); Serial.println("!!! ERRO !!!"); Serial.print("Nao sera possivel continuar. A codigo da tecla pressionada esta em um protocolo diferente para o qual este sketch foi construido. Por favor, va ate a linha 6 e altere para o protocolo adequado. O protocolo da tecla possui o indice "); Serial.print(results.decode_type); Serial.print(". Alem disso, altere o conteudo da funcao enviarComando() para o do protocolo compativel\n Se achar que isto é um erro, reinicie o Arduino MEGA."); // Liga o LED para indicar erro e entra em loop infinito digitalWrite(pinoLed, HIGH); while (1) { } } tamanhoCode = results.bits; // Armazena o número de bits do código IR return teclaApertada; // Retorna a tecla pressionada e confirmada } // Função para enviar um comando IR (infravermelho) void enviarComando(unsigned long data, int nbits) { // ALTERE ESTE MÉTODO CASO O PROTOCOLO DE SEU CONTROLE REMOTO SEJA DIFERENTE DE NEC // Chama o método sendNEC para enviar os dados IR usando o protocolo NEC // 'data' é o comando que será enviado e 'nbits' é o número de bits desse comando irsend.sendNEC(data, nbits); }
Código a ser colado no arquivo platformio.ini:
; PlatformIO Project Configuration File ; ; Build options: build flags, source filter ; Upload options: custom upload port, speed and extra flags ; Library options: dependencies, extra library storages ; Advanced options: extra scripting ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html [env:megaatmega2560] platform = atmelavr board = megaatmega2560 framework = arduino monitor_speed = 115200 lib_deps = https://github.com/Arduino-IRremote/Arduino-IRremote.git#2.5.0 chris--a/Keypad@^3.1.1 https://github.com/MicSG-dev/EEPROM-Storage-PlatformIO
Veja no vídeo abaixo o projeto funcionando:
Em um passo além do projeto original, pode-se utilizar como base este projeto para automatizar uma variedade de aparelhos domésticos que possuam comunicação por infravermelho. É possível pensar em diversas outras aplicações:
Esses são apenas alguns exemplos de como ampliar o uso deste projeto para tornar a automação residencial mais inteligente e conveniente. Se gostou da postagem, por favor, avalie e deixe um comentário! Não se esqueça de nos seguir também no Instagram e de nos marcar quando realizar algum projeto inspirado em nossos conteúdos: @eletrogate. Até a próxima!
|
A Eletrogate é uma loja virtual de componentes eletrônicos do Brasil e possui diversos produtos relacionados à Arduino, Automação, Robótica e Eletrônica em geral.
Conheça a Metodologia Eletrogate e Lecione um Curso de Robótica nas Escolas da sua Região!