domingo, 22 de maio de 2016

Usando Infravermelho para controlar um aparelho de TV

Olá, neste post iremos mostrar como enviar e receber informações através de emissores e receptores de IR, para controlar um aparelho de TV.

Segue lista de materiais utilizados:
  • 1 Arduíno nano
  • 1 Arduíno UNO
  • 1 Receptor de IR LNF
  • 1 LED Emissor de IR
  • 1 Resistor de 200 ohms
  • 1 Protoboard
  • Alguns fios
Seguem as fotos dos sensores de IR:

Iremos montar a aplicação que faz a leitura e escreve na serial os códigos de IR do controle remoto de um aparelho de TV e depois, iremos montar uma aplicação que envia esses códigos para o aparelho de TV. Assim, você poderá controlar a sua TV ou outro equipamento através de um Arduíno.
Receptor LNF de IR

LED Emissor de IR


Utilizaremos a biblioteca IRremote para enviar e receber os códigos em infravermelho. Para mais informações sobre ela, clique aqui.

Segue abaixo a documentação dos método da biblioteca, que utilizaremos. Para mais detalhes acesse aqui.

Receiving 

IRrecv irrecv(receivePin)
Create the receiver object, using a name of your choice.
irrecv.enableIRIn()
Begin the receiving process. This will enable the timer interrupt which consumes a small amount of CPU every 50 µs.
irrecv.decode(&results)
Attempt to receive a IR code. Returns true if a code was received, or false if nothing received yet. When a code is received, information is stored into "results".
results.decode_type: Will be one of the following: NECSONYRC5RC6, or UNKNOWN.
results.value: The actual IR code (0 if type is UNKNOWN)
results.bits: The number of bits used by this code
results.rawbuf: An array of IR pulse times
results.rawlen: The number of items stored in the array
irrecv.resume()
After receiving, this must be called to reset the receiver and prepare it to receive another code.
irrecv.blink13(true)
Enable blinking the LED when during reception. Because you can't see infrared light, blinking the LED can be useful while troubleshooting, or just to give visual feedback.

Transmitting
IRsend irsend;
Create the transmit object. A fixed pin number is always used, depending on which timer the library is utilizing.
irsend.sendNEC(IRcode, numBits);
Send a code in NEC format.
irsend.sendSony(IRcode, numBits);
Send a code in Sony format.
irsend.sendRC5(IRcode, numBits);
Send a code in RC5 format.
irsend.sendRC6(IRcode, numBits);
Send a code in RC6
irsend.sendRaw(rawbuf, rawlen, frequency);
Send a raw code. Normally you would obtain the contents of rawbuf and rawlen by using the receiver many times and averaging the results. Some adjustments may be necessary for best performance. The frequency is the expected bandpass filter frequency at the receiver, where 38 is the most commonly used.

Cada fabricante utiliza um protocolo para codificar seus códigos de IR e temos basicamente os protocolos a seguir que são reconhecidos por essa biblioteca: NEC, SONY, RC5, RC6 e desconhecido(UNKNOWN) - para mais informações sobre os protocolos de IR, clique aqui.

Leitor de IR

Segue abaixo o esquema de ligação do receptor de IR ao Arduíno Nano


Esquema feito no aplicativo Fritzing

O esquema é muito simples, dispensando uma protoboard. Segue abaixo a pinagem do sensor:
Pinos do sensor LFN IR Receiver 

O pino 01(Out) do sensor será ligado ao pino D11 do Nano.

Vamos ao código para o Arduíno:

       
#include ‹irremote .h›

const int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN); 
decode_results results;


void setup(void) 
{ 

 Serial.begin(115200);
 irrecv.enableIRIn();
 
}
char buf[20];
void loop()
{
    if (irrecv.decode(&results)) {
      
      if (results.decode_type == NEC) {
          Serial.print("NEC: ");
      } else if (results.decode_type == SONY) {
        Serial.print("SONY: ");
      } else if (results.decode_type == RC5) {
        Serial.print("RC5: ");
      } else if (results.decode_type == RC6) {
        Serial.print("RC6: ");
      } else if (results.decode_type == UNKNOWN) {
        Serial.print("UNKNOWN: ");
      }
      Serial.print(results.value, HEX);
      Serial.print(" ");
      Serial.print(" size: ");
      Serial.println(results.bits);
      irrecv.resume(); // Receive the next value
    }
 }

No programa acima, definimos o pino 11 como pino de leitura de dados. No setup é feita a inicialização do IR e serial e no loop, se houver dados, as informações serão impressas na serial (código e tamanho).

Após a carga do programa, utilizei o controle da minha TV como emissor e anotei a saída dos principais botões dele. Segue abaixo um trecho da saída da Serial:


A minha TV é da marca Philips e ela utiliza o protocolo RC-5 para a transmissão de IR. Os códigos acima 0x80C e 0xC (em hexadecimal) são referentes a pressionar o botão power do controle. Ele envia alternadamente cada um desses comandos quando o botão é pressionado. Um deles liga e o outro desliga a TV.

Emissor de IR

Agora vamos montar o emissor de IR. Segue abaixo o esquema de ligação.

Esquema feito no aplicativo Fritzing

O resistor de 200 ohms é para evitar que o LED queime, pois ele não suporta 5V. Por padrão, a biblioteca de envio utiliza o pino D3 do Arduíno como pino de saída.

Vamos ao programa:

       
#include ‹IRremote.h›

//definicoes para TV PHILIPS
#define PHILIPS_LENGHT 12
#define BTN_PHILIPS_PWD_ON 0xC
#define BTN_PHILIPS_PWD_OFF 0x80C
#define BTN_PHILIPS_SOURCE_ON 0x838 
#define BTN_PHILIPS_SOURCE_OFF 0x38
#define BTN_PHILIPS_SLEEP1 0x826
#define BTN_PHILIPS_SLEEP2 0x26
#define BTN_PHILIPS_VOLUP1 0x810
#define BTN_PHILIPS_VOLUP2 0x10
#define BTN_PHILIPS_VOLDOWN1 0x811
#define BTN_PHILIPS_VOLDOWN2 0x11
#define BTN_PHILIPS_MUTE1 0x80D
#define BTN_PHILIPS_MUTE2 0xD

int buff;
char cBuff[4];

int command[100];
int inicializado;

IRsend irsend;

void setup() {

  //PHILIPS COMMANDS 0 - 19
  command[0] = BTN_PHILIPS_PWD_ON;
  command[1] = BTN_PHILIPS_PWD_OFF;
  command[2] = BTN_PHILIPS_SOURCE_ON;
  command[3] = BTN_PHILIPS_SOURCE_OFF;
  command[4] = BTN_PHILIPS_SLEEP1;
  command[5] = BTN_PHILIPS_SLEEP2;
  command[6] = BTN_PHILIPS_VOLUP1;
  command[7] = BTN_PHILIPS_VOLUP2;
  command[8] = BTN_PHILIPS_VOLDOWN1;
  command[9] = BTN_PHILIPS_VOLDOWN2;
  command[10] = BTN_PHILIPS_MUTE1;
  command[11] = BTN_PHILIPS_MUTE2;
    
  Serial.begin(115200);
  inicializado = 0;
}



void loop() {
   
    while (Serial.available() >= 3)//loop de leitura/escrita da serial
    {
      cBuff[0] = Serial.read();
      cBuff[1] = Serial.read();
      cBuff[2] = Serial.read();
      cBuff[3] = '\0';
      Serial.read();
      buff = atoi(cBuff);//convertendo char[] em int
      Serial.write(cBuff);
              
      if(inicializado==1)
      {
        //PHILIPS -> 0 - 19
        if(buff <=19){
          Serial.write("PHILIPS....\n");
          irsend.sendRC5(command[buff],PHILIPS_LENGHT);
        }
       
        Serial.write("comando executado....\n");
      }
      
      if(buff == 999){
        Serial.write("Aguardando comando....\n");
        inicializado = 1;
      }
      if(buff== 998){
        Serial.write("Nao aguardando comando....\n");
        inicializado = 0;      
      }
      
    }
}

Originalmente, esse programa estava preparado para os equipamentos da minha casa (TVs, Console da NET e Home Theater) e recebendo comandos via serial através de um Raspberry PI. Mas, para efeitos didáticos, eu deixei somente os códigos referentes a TV Philips, que estão definidos nos primeiros #define, onde temos o mapeamento de alguns comandos do controle da TV como: ligar/desligar, volume, mudo e outros.  Além dos comandos da TV temos o 999 e 998 que habilitam ou não a interpretação de comandos.

Os comandos são colocados em um array (command[100] na função setup). A aplicação fica em loop esperando dados na serial. A cada 3 bytes disponíveis na serial, ele os converte em número e utiliza esse número como índice do array (exceto 999 e 998) comandos e envia através do IR para a TV.


Foram digitados os seguintes comandos na sequência: 999, 001, 000.

Observações

Você pode utilizar o mesmo Arduíno para fazer ambos os projetos. Utilizei dois, por tê-los disponíveis.
A princípio, é possível controlar qualquer dispositivo IR, bastando ler e reenviar o comando lido.
Assim como temos um sensor receptor pronto, é possível achar um emissor "pronto", dispensando a protoboard e resistor.


2 comentários:

  1. LEGAL, to iniciando em arduino e gostaria de saber se vc pode me ajudar,acha que é possivel enviar IR e receber IR no mesmo arduino,tipo
    quero realizar um combate e os ois dispositivos precisam atirar e receber tiros na formna de IR cod.

    ResponderEliminar
  2. Muito legal. Estou desenvolvendo um projeto similar a esse, em meio a um TCC de pós-graduação e também na escola em que leciono informática. Mesmo agora em 2019, me ajudou bastante. Obrigado!

    ResponderEliminar