Zapper: Controle remoto automático para a TV a cabo com Arduino

Com um Arduino e pouco mais do que um led infravermelho você pode fazer um robô para zapear automaticamente pelos seus canais favoritos da TV a Cabo.

Um aparelho simples ao qual você informa os números dos seus canais preferidos e, ao ligá-lo, pode aguardar enquanto ele faz o decodificador da TV a cabo passear por todos eles, parando por 8 segundos em cada um, e ainda exibindo na tela da TV o nome do próximo programa que irá começar no mesmo canal: foi isso que eu fiz em meia hora com um Arduino, um led infravermelho, um transistor e 2 resistores.

Ficou tão pequeno, que acabei montando o protótipo com fita adesiva diretamente na bateria de 9V que o alimenta. Na foto acima você pode notar que eu usei um econômico Arduino Pro Mini, mas não se preocupe: o mesmo projeto funcionará também em modelos de Arduino mais comuns, como o Uno ou o Nano.

A comunicação via infravermelho é o elemento básico da maioria dos controles remotos de TV e aparelhos associados, como DVD, TV a cabo, e outras caixinhas que moram em frente a nossos sofás.

Eu sou usuário da TV a cabo da Net Digital e, apesar da disponibilidade de mais de uma centena de canais, muitas vezes é difícil encontrar algo de bom passando na hora em que estou disposto a assistir. Assim, já que um led emissor de infravermelho é barato e fácil de encontrar, resolvi plugar um deles ao Arduino para poder programá-los como um controle remoto automático.

Esse controle automático usa uma lista de canais preparada por mim para trocar de canal automaticamente, parando em cada um apenas pelo tempo suficiente para dar de reconhecer o que está passando1, facilitando encontrar algum programa que preste, ou no mínimo oz menos piores.

Para fazer funcionar o meu controle automático, primeiro eu reconheci (com o programa-exemplo IRrecvDump, que acompanha a biblioteca IRRemote para o Arduino) e anotei os códigos gerados pelos botões de um controle da Net como o da foto acima, modelo CR2FU.

Segundo técnicos da Net me informaram, os demais modelos de controle da empresa usam exatamente os mesmos códigos, mas não verifiquei. Se o seu controle for diferente, ou mesmo se a sua TV a cabo for de outra marca, use o IRrecvDump para identificar os códigos gerados pelos botões dele usados no meu programa, e adapte o programa de acordo.

A montagem eletrônica é bem simples, e poderia ser ainda mais: dependendo do led emissor de infravermelho que for usado, suas características de tensão e potência poderiam permitir ligá-lo diretamente ao terra e a um pino digital de saída do Arduino.

Não é o caso do meu led: segundo a documentação mencionada pelo vendedor, ele pode fazer uso de até 100mA de corrente, o que – se for usado – o coloca bem além dos limites dos pinos digitais comuns do Arduino, mas ainda confortavelmente dentro da capacidade de fornecimento de corrente do pino VCC, bastando chaveá-lo por meio de um transistor conectado a um pino digital de saída, como já vimos no exemplo de controle de um relé.

O circuito completo ficou assim:

É bem simples, como você pode ver. Destaquei em vermelho os 2 terminais da pilha de 9V, e em verde os pinos do Arduino usados no projeto. Vamos a uma rápida descrição funcional:

  • S1 é uma chave liga/desliga, posicionada entre o positivo da pilha e o pino VIN (ou RAW, dependendo do modelo) do Arduino.
  • L1 é um led infravermelho
  • Q1 é um transistor NPN. Usei um 2N2222.
  • S2 é um botão normalmente aberto.
  • R1 e R2 são resistores que devem ser calculados a partir das características do led infravermelho e do transistor que você usar.

A escolha do pino 3 para controlar o transistor que chaveia o led IR não é casual: essa é a posição default considerada pela biblioteca IRRemote, ao menos no Arduino Nano, Uno e Pro Mini.

O programa é bem simples, embora não seja dos mais curtos. O que ele faz, basicamente, é – sempre que o Arduino estiver ligado, ou seja, que a chave S1 do esquema acima estiver ON – rotacionar entre os canais definidos no array favs (ou favs_alt). Sempre que ele muda de canal, grava na memória permanente (EEPROM) do Arduino a referência do canal atual, para que, numa próxima vez que for ligado, possa continuar de onde parou, sem recomeçar do primeiro canal da lista a cada vez.

O código completo você vê a seguir:

#include <EEPROM.h>
#include <IRremote.h>
IRsend irsend;
unsigned long NETdigitos[]={0xE17A00FF, 0xE17A807F, 0xE17A40BF, 0xE17AC03F, 
                            0xE17A20DF, 0xE17AA05F, 0xE17A609F, 0xE17AE01F,
                            0xE17A10EF, 0xE17A906F};

int favs[]={159, 535, 543, 580, 581, 583, 630, 631, 632, 633, 634, 635, 
            651, 652, 654, 655, 658, 86, 108, 110, 140, 157};
int favs_alt[]={512, 541, 543};
int pfavs=0;            // ponteiro dos canais
const int qfavs=22;     // quantidade de itens validos no favs
const int qfavsalt=3;   // quantidade de itens validos no favs_alt

const int pinoLed=13;   // melhor resultado se for um pino com PWM
const int chave_alt=2;  // pino em que esta' o botao/chave que 
                        // alterna entre favs e favs_alt

void mudaCanal(int canal) {
  delay(100);
  byte cdigitos[] = {0,0,0};  
  cdigitos[0]=canal/100;
  cdigitos[1]=canal%100/10;
  cdigitos[2]=canal%10;
  irsend.sendNEC(0xE17AFFFF, 32);  // spacer 
  for (int i=0;i<=2;i++) {
    delay(60);    
    irsend.sendNEC(NETdigitos[cdigitos[i]], 32); 
  }    
}  

void memorizaCanal() {
  EEPROM.write(100, pfavs);
  EEPROM.write(101, 65); // "A"
  EEPROM.write(102, 66); // "B" 
}  

void sobeCanal() {
  pfavs++;
  if (pfavs>=qfavs) pfavs=0;
  if (digitalRead(chave_alt)==HIGH) 
    mudaCanal(favs[pfavs]);
  else mudaCanal(favs_alt[pfavs % qfavsalt]);    
  memorizaCanal();
}

void setup()
{
  pinMode(3,OUTPUT); // posicao default do led IR TX
  pinMode(chave_alt,INPUT_PULLUP);
  pinMode(pinoLed,OUTPUT);
  // verifica se o ultimo canal da execucao anterior 
  // esta gravado na EEPROM
  if ((EEPROM.read(101)==65) & (EEPROM.read(102)==66)) { 
  	pfavs=EEPROM.read(100);
  }	
  if (pfavs>=qfavs) pfavs=0;
}

void loop() {
  sobeCanal();
  for (int i=0; i<80;i++) {
    if(i<15) digitalWrite(pinoLed,LOW); 
    else analogWrite(pinoLed,180-2*i);
    if (i==25) irsend.sendNEC(0xE17A38C7, 32);   // tecla seta para a direita
    delay(100);
  }  
}

A seguir vamos aos trechos em destaque colorido, como de hábito.

O trecho inicial, em cor laranja, inclui as 2 bibliotecas necessárias: a EEPROM, que vem com o Arduino e serve para gravar e ler na memória permanente, e a IRRemote, que você deve instalar e que serve para receber e enviar sinais infravermelhos (IR) de controle remoto. A terceira linha do trecho instancia na variável irsend as funções de transmissão de sinal que fazem parte da biblioteca IRRemote, e em seguida vem a definição do array NETdigitos, contendo o código de cada um dos botões numéricos (na ordem, de 0 a 9) do controle da Net2.

A seguir, em roxo, vem a definição das minhas listas de canais favoritos: a principal, no array favs, e a alternativa, no array favs_alt. A variável pfavs é um apontador para a lista de favoritos, indicando a posição do último a ter sido selecionado (observe o que acontece com ela na função setup()!). Já qfavs e qfavsalt indicam a quantidade de canais a serem considerados em cada uma das duas listas. Por um detalhe de implementação, a quantidade de canais na lista favs sempre precisa ser maior que a da lista favs_alt.

A função mudaCanal faz o que o nome indica: recebe como parâmetro um número de canal, e o envia pelo led infravermelho, ou seja: se passarmos como parâmetro o número 139, ele vai simular o pressionamento dos dígitos 1, 3 e 93. Essa separação de dígitos acontece nas 3 primeiras linhas em verde. A quarta linha verde manda um sinal "em branco" (porque eu notei que frequentemente o primeiro dígito estava se perdendo na transmissão), e a seguir temos um loop que manda os 3 dígitos do canal.

A função memorizaCanal, em marrom, faz algo bem simples: grava o índice do último canal selecionado (ou seja, a variável pfavs) no endereço 100 da memória permanente do Arduino, para que esteja disponível na próxima vez que ele for ligado, e assim o programa possa sempre recomeçar de onde parou, sem reiniciar a contagem a cada vez.

As linhas do final da função, que gravam os valores 65 e 66 nos endereços 101 e 102, são um método de assinatura, para que este mesmo programa possa saber, no futuro, que há um índice de canal gravado no endereço 100. Se houver os valores 65 e 66 nos endereços 101 e 102, o programa pode assumir que sim. Se houver qualquer outro valor lá, o programa pode assumir que se trata de um Arduino que nunca havia sido usado por ele, e no qual ainda não foi gravado um indicador de canal.

Vale destacar que os endereços 100 a 102 e o valor (65;66) da assinatura são arbitrários, escolhidos por mim4.

A função sobeCanal é singela: incrementa o apontador de canais (pfavs) e, caso ele ultrapasse o número de canais da lista de favoritos, retorna-o a zero. O trecho em rosa faz algo interessante: verifica se um botão conectado ao pino 2 do Arduino está pressionado: se estiver, usa os canais da lista favs_alt, no lugar dos canais da lista favs.

A seguir vem a tradicional função setup() do Arduino, com suas inicializações de pinos. Destaquei em marrom (mesma cor da função memorizaCanal(), que já vimos) o trecho que verifica na memória permanente se nossa assinatura está presente, para então inicializar o ponteiro da lista de canais (variável pfavs) com o valor armazenado lá. Como o número de canais da lista pode ter sido modificado desde a execução anterior, o trecho também verifica se ele ultrapassa o limite, zerando-o se necessário.

Para completar, temos o loop() do Arduino, que se limita a chamar nossa função sobeCanal() e depois fazer uma sequência de temporização, que destaquei em dourado. Durante a sequência, um led é usado para indicar o andamento (se o led estiver em um pino PWM, o efeito será mais bonito, mas a constante pinoLed no programa está ajustada para usar o led interno, sem PWM), e também para, pouco antes da metade do tempo, enviar pelo led infravermelho o código da tecla seta para a direita (do controle da Net), que tem o efeito de exibir na faixa de informações da tela o nome e horário do próximo programa.

Só falta fazer ter programação boa na TV, mas isso eu não garanto :)

 
  1.  Tudo seria mais fácil se as listas de programação e as mensagens de identificação da programação fossem mais confiáveis...

  2.  Eu obtive os códigos pressionando cada um dos botões enquanto apontava o controle para um receptor IR conectado ao Arduino, rodando nele o programa IRrecvDump, que vem como exemplo da biblioteca IRRemote

  3.  Se o canal fosse o 8, ele enviaria 0, 0, 8.

  4.  Na verdade a assinatura 65/66 ("AB") é uma singela homenagem à assinatura que identifica os cartuchos executáveis do MSX.

Comentar

Dos leds ao Arduino, ESP8266 e mais

Aprenda eletrônica com as experiências de um geek veterano dos bits e bytes que nunca tinha soldado um led na vida, e resolveu narrar para você o que descobre enquanto explora esse universo – a partir da eletrônica básica, até chegar aos circuitos modernos.

Por Augusto Campos, autor do BR-Linux e Efetividade.net.

Recomendados

Livro recomendado


Artigos já disponíveis

Comunidade Arduino

O BR-Arduino é integrante da comunidade internacional de entusiastas do Arduino, mas não tem relação com os criadores e distribuidores do produto, nem com os detentores das marcas registradas.

Livros recomendados