Eletrônica Por Equipe DevBras

Capa do artigo: Controle remoto infravermelho no Arduino: decodifique o botão e use o código

Controle remoto infravermelho no Arduino: decodifique o botão e use o código

Como ler o código de cada botão com o receptor de 38 kHz e a IRremote, ignorar repetição e ruído, e transformar o número em comando confiável.

Você aponta o controle da TV para o robô, filma o LED com a câmera do celular, vê a luz roxa piscando e o robô continua parado. A luz existe, mas o Arduino não sabe o que fazer com ela. A resposta curta: o receptor infravermelho entrega um código por botão, e o seu programa precisa conhecer esse código antes de agir. Primeiro você decodifica e anota o número de cada tecla; só depois escreve o if que move o motor.

Ao longo deste guia, o exemplo é um carrinho com quatro comandos (frente, ré, esquerda, direita) e um botão de parar, usando aquele controle pequeno de 21 teclas que vem em kits de Arduino e um receptor de três pinos do tipo VS1838B ou TSOP38238.

Por que filmar o LED não prova nada

O controle não "acende" de forma contínua. Ele liga e desliga o LED infravermelho numa frequência portadora, quase sempre perto de 38 kHz, e agrupa esses pulsos em rajadas longas e curtas. A sequência de rajadas forma um quadro digital com o endereço do aparelho e o número do comando. Cada fabricante usa um protocolo: NEC, Sony, RC5, Samsung e vários outros.

O receptor de três pinos faz a parte difícil. Ele filtra a luz que não está na portadora, demodula o sinal e entrega no pino de saída um nível lógico que acompanha as rajadas. A câmera do celular só mostra que há luz infravermelha; ela não diz se a portadora bate com o receptor, se o protocolo é conhecido ou se o quadro chegou inteiro.

Por isso o passo zero é sempre o mesmo: ler o que chega no pino, deixar uma biblioteca identificar o protocolo e imprimir o comando na Serial.

Como ligar o receptor

O receptor tem três pinos: saída de sinal, GND e alimentação. A ordem muda entre modelos e entre módulos montados em plaquinha, então confira a folha de dados ou a serigrafia antes de ligar. Inverter alimentação e GND costuma esquentar o componente em segundos.

  1. Ligue a alimentação em 5 V (ou 3,3 V, se a placa for de 3,3 V e o receptor aceitar essa tensão).
  2. Ligue o GND no GND do Arduino.
  3. Ligue a saída num pino digital. Aqui, o pino 2.
  4. Se o fio for longo ou a fonte ruidosa, coloque um capacitor de desacoplamento perto do receptor, como recomendam as folhas de dados desses componentes.

Como descobrir o código de cada botão

A biblioteca mais usada é a IRremote, instalável pelo gerenciador de bibliotecas da IDE. Nas versões recentes, a interface mudou: o objeto global IrReceiver substituiu o antigo IRrecv, e o cabeçalho recomendado é IRremote.hpp. Tutoriais antigos com irrecv.enableIRIn() e results.value não compilam do mesmo jeito; use os exemplos que vêm com a versão instalada.

Este sketch só lê e imprime:

#include <IRremote.hpp>

const uint8_t PINO_IR = 2;

void setup() {
  Serial.begin(115200);
  IrReceiver.begin(PINO_IR, ENABLE_LED_FEEDBACK);
  Serial.println("Aponte o controle e aperte um botao por vez");
}

void loop() {
  if (IrReceiver.decode()) {
    IrReceiver.printIRResultShort(&Serial);
    IrReceiver.resume();
  }
}

Abra o Monitor Serial em 115200 e aperte cada botão uma vez, devagar. Você verá linhas com o protocolo, o endereço e o comando, algo como Protocol=NEC Address=0x0 Command=0x18. Os seus números serão outros; o que importa é anotar os pares em uma tabela no próprio código.

Se aparecer UNKNOWN, o protocolo não foi reconhecido ou o quadro chegou corrompido. Aproxime o controle, afaste o receptor da janela e tente de novo. Se continuar desconhecido em todas as tentativas, o controle provavelmente usa um protocolo que a biblioteca não decodifica, e é mais simples trocar de controle do que lutar com o sinal cru.

Como transformar o código em comando sem disparar duas vezes

Segurar um botão não repete o quadro inteiro em todos os protocolos. No NEC, por exemplo, o controle manda o quadro completo uma vez e depois quadros curtos de repetição enquanto o dedo estiver apertado. A IRremote marca essas repetições com uma flag. Para o carrinho, você quer duas coisas: andar enquanto o botão está apertado e parar quando as repetições cessam.

#include <IRremote.hpp>

const uint8_t PINO_IR = 2;

// Valores anotados com o sketch de leitura. Troque pelos seus.
const uint16_t ENDERECO_CONTROLE = 0x00;
const uint8_t CMD_FRENTE   = 0x18;
const uint8_t CMD_RE       = 0x52;
const uint8_t CMD_ESQUERDA = 0x08;
const uint8_t CMD_DIREITA  = 0x5A;
const uint8_t CMD_PARAR    = 0x1C;

const unsigned long TEMPO_SEM_SINAL_MS = 200;

uint8_t ultimoComando = CMD_PARAR;
unsigned long ultimoSinal = 0;

void executar(uint8_t cmd) {
  switch (cmd) {
    case CMD_FRENTE:   Serial.println("frente");   break;
    case CMD_RE:       Serial.println("re");       break;
    case CMD_ESQUERDA: Serial.println("esquerda"); break;
    case CMD_DIREITA:  Serial.println("direita");  break;
    default:           Serial.println("parar");    break;
  }
}

void setup() {
  Serial.begin(115200);
  IrReceiver.begin(PINO_IR, DISABLE_LED_FEEDBACK);
}

void loop() {
  if (IrReceiver.decode()) {
    IRData &d = IrReceiver.decodedIRData;
    bool repeticao = d.flags & IRDATA_FLAGS_IS_REPEAT;

    if (d.protocol == NEC && d.address == ENDERECO_CONTROLE) {
      if (!repeticao) {
        ultimoComando = d.command;
        executar(ultimoComando);
      }
      ultimoSinal = millis();
    }
    IrReceiver.resume();
  }

  if (ultimoComando != CMD_PARAR && millis() - ultimoSinal > TEMPO_SEM_SINAL_MS) {
    ultimoComando = CMD_PARAR;
    executar(CMD_PARAR);
  }
}

Três detalhes fazem esse código ser confiável. O filtro de protocolo e endereço descarta o controle do ar-condicionado que alguém aperta na mesma sala. A repetição só renova o tempo, não executa a ação de novo. E o tempo limite sem sinal para o carrinho se o controle sair do alcance, em vez de deixá-lo andando até bater. Em qualquer coisa que se mova, a falta de sinal precisa significar parar. O mesmo raciocínio de "um evento, uma ação" aparece no guia sobre botão no Arduino sem repetir.

O valor de 200 ms é um ponto de partida. Se o carrinho engasgar enquanto você segura o botão, meça o intervalo entre repetições do seu controle imprimindo millis() e ajuste com folga.

Sol, lâmpada e alcance

A luz do sol tem muito infravermelho, e algumas lâmpadas fluorescentes e de LED com driver barato emitem ruído que o receptor tenta interpretar. O sintoma é decodificação intermitente ou códigos desconhecidos aparecendo sem ninguém apertar nada. Teste primeiro à sombra, depois no lugar de uso. Um tubinho opaco em volta do receptor, deixando só a frente aberta, já reduz bastante a luz lateral.

Lembre também que infravermelho precisa de linha de visada ou de reflexo em parede clara. Atrás de acrílico escuro, o alcance cai; atrás de metal, some.

Erros comuns

  • Copiar códigos de outro tutorial: controles parecidos podem mandar endereços e comandos diferentes, e o programa nunca reconhece o botão.
  • Executar a ação a cada quadro de repetição: um toque de meio segundo vira cinco comandos, e o servo ou o motor dá trancos.
  • Esquecer o resume(): o receptor para de aceitar novos quadros depois do primeiro, e parece que o controle "funcionou uma vez só".
  • Usar outra biblioteca que disputa o mesmo timer: tone(), PWM em certos pinos ou uma segunda biblioteca de infravermelho deixam de funcionar. O assunto está detalhado em duas bibliotecas de infravermelho brigando pelo timer.
  • Não tratar ausência de sinal: o robô continua executando o último comando quando o controle sai do alcance.
  • Bloquear o loop com delay() longo: enquanto o programa dorme, quadros chegam e se perdem, e a resposta fica lenta.

Checklist

  • A pinagem do receptor foi conferida na folha de dados ou na plaquinha antes de ligar.
  • O sketch de leitura imprime protocolo, endereço e comando para cada botão usado.
  • Os códigos estão em constantes com nome, não espalhados como números soltos.
  • O programa filtra protocolo e endereço do seu controle.
  • Repetições não disparam a ação de novo.
  • Sem sinal por um tempo definido, o sistema volta ao estado seguro.
  • O teste foi repetido no local real, com a iluminação real.

Abra o seu sketch agora: se você apertar um botão que não está na sua tabela, ou se o controle sair da sala no meio de um comando, o que o seu projeto faz?

Avalie este artigo

Referência: http://www.criandorobocomarduino.com/2013/12/como-fazer-um-controle-remoto-de-tv-com.html