sábado, 26 de julho de 2014

Emissor e receptor infravermelho

Olá pessoal,

Hoje vamos ver o funcionamento do emissor e receptor infravermelho e será de importância vital para o projeto de acionamento automático de ar condicionado. Não preciso comentar muito sobre a utilização de leds emissores infrared (tem bastante material na Internet explicando o funcionamento) e este tipo de acionamento remoto está presente em quase todos os aparelhos eletrônicos. O que é mais interessante é que existe uma biblioteca para Arduino que permite capturar os códigos dos controles remotos dos aparelhos e reproduzí-los através de um led emissor infrared. Vamos ver os passos para se fazer isso:

1) Baixar a biblioteca IRRemote (http://github.com/shirriff/Arduino-IRremote) e instalá-la:

2) Esquema de ligação:



Fonte: GRobotronics Learning

Emissor infravermelho:


Receptor infravermelho:


Neste circuito há o led receptor que está ligado da seguinte forma:

Pino 1 do receptor --> pino 11 do Arduino (fio azul da imagem)
Pino 2 do receptor --> Ground do Arduino (fio preto da imagem)
Pino 3 do receptor -->  5V do Arduino (fio vermelho da imagem)

Já o led emissor está ligado assim:

Positivo do led --> pino 9 do Arduino (fio branco da imagem)
Negativo do led --> Ground do Arduino (fio preto da imagem)

Há um resistor de 100 ohms em série no ground do emissor IR. 

Cabe aqui uma observação: verificar no arquivo IRRemoteInt.h na pasta da biblioteca IRRemote, aproximadamente na linha 69 se o pino que está sendo usado é mesmo o pino 9. Veja o trecho deste arquivo:

// Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, etc
#else
  #define IR_USE_TIMER1   // tx = pin 9
  //#define IR_USE_TIMER2     // tx = pin 3
#endif


No meu caso estou usando o Arduino Uno e também já testei no Arduino Duemilanove. Não sei ainda o porquê mas eu usava o TIMER2 (pino 3) e não funcionou. Aí mudei para o TIMER1 e funcionou certinho.

Testando o circuito RECEPTOR infravermelho:

Primeiro, vamos utilizar o exemplo IRRecvDump que já vem com a biblioteca:

#include <IRremote.h>

int RECV_PIN = 11;

IRrecv irrecv(RECV_PIN);

decode_results results;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Inicia o receptor
}

// Dumps out the decode_results structure.
// Call this after IRrecv::decode()
// void * to work around compiler issue
//void dump(void *v) {
//  decode_results *results = (decode_results *)v
void dump(decode_results *results) {
  int count = results->rawlen;
  if (results->decode_type == UNKNOWN) {
    Serial.print("Unknown encoding: ");
  } 
  else if (results->decode_type == NEC) {
    Serial.print("Decoded NEC: ");
  } 
  else if (results->decode_type == SONY) {
    Serial.print("Decoded SONY: ");
  } 
  else if (results->decode_type == RC5) {
    Serial.print("Decoded RC5: ");
  } 
  else if (results->decode_type == RC6) {
    Serial.print("Decoded RC6: ");
  }
  else if (results->decode_type == PANASONIC) {
    Serial.print("Decoded PANASONIC - Address: ");
    Serial.print(results->panasonicAddress,HEX);
    Serial.print(" Value: ");
  }
  else if (results->decode_type == JVC) {
     Serial.print("Decoded JVC: ");
  }
  Serial.print(results->value, HEX);
  Serial.print(" (");
  Serial.print(results->bits, DEC);
  Serial.println(" bits)");
  Serial.print("Raw (");
  Serial.print(count, DEC);
  Serial.print("): ");

  for (int i = 0; i < count; i++) {
    if ((i % 2) == 1) {
      Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
    } 
    else {
      Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC);
    }
    Serial.print(" ");
  }
  Serial.println("");
}


void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    dump(&results);
    irrecv.resume(); // Receive the next value
  }
}


Basta apontar um controle remoto para o receptor IR, apertar um botão e acompanhar no Monitor Serial. Lá veremos o respectivo código IR do botão do controle remoto decodificado. Há duas formas de se usar o código IR: quando o circuito receptor consegue decodificar ele vai mostrar a marca (Sony, NEC, etc) e um código reduzido. Por exemplo o botão de Power das TV Sony o código IR para ligar é o A90 (em hexadecimal). Há também possibilidade de se utilizar o código Rawcode que também é mostrado no Monitor Serial. Isto é especialmente útil quando não se consegue utilizar o código reduzido. No caso do projeto do ar condicionado tive que utilizar o código rawcode. Você deve pegar todo o código rawcode e separar cada número por vírgula e deixá-los todos positivos e colocar em uma array unsigned int. 
Veja este exemplo de saída do Monitor Serial:


Fonte: Blog Microcontrolandos

Nesta imagem você vê a marca (NEC) e o código reduzido (807608F7) em hexadecimal e o tamanho (32 bits). Logo abaixo você tem o rawcode (linha Raw (68): onde 68 é o número de elementos) composto de vários números positivos e negativos.

Dica para usar o rawcode: copie a linha do rawcode com os números negativos e positivos e cole-a em um software de planilha. Em uma linha teremos cada célula que conterá um elemento do rawcode. Modifique as células com valores negativos para valores positivos. Depois com todos os números positivos salve a planilha no formato .csv (valores separados por vírgula). Abra o arquivo .csv com um editor de textos. Todos os números estarão separados por vírgulas e basta copiar a linha para o trecho do código que conterá a array. Certifique-se que não há espaços entre os números e entre as vírgulas.


Veja este exemplo da variável que contém o código rawcode do ar condicionado que capturei:

unsigned int powerOn[92] = {8950,4300,650,500,700,450,650,1600,650,500,600,1650,700,450,650,500,650,500,650,450,600,1700,600,550,550,550,600,1700,600,500,600,550,600,550,600,550,600,500,700,450,600,550,600,550,600,500,600,550,600,550,600,550,550,550,600,550,600,550,600,550,550,550,600,550,600,550,600,500,600,550,650,500,600,550,600,500,600,550,600,550,600,550,550,1700,600,550,600,550,550,1700,700};


Criei uma array de 92 elementos contendo o código de power on do ar condicionado. Notem que todos os elementos estão positivos e estes foram capturados com o circuito de recepção IR e com o sketch IRRemote.

Testando o circuito EMISSOR infravermelho:

A biblioteca IRRemote tem um exemplo chamado IRsendDemo. Se você tem uma TV Sony pode testar diretamente com este exemplo:


#include <IRremote.h>

IRsend irsend;

void setup()
{
  Serial.begin(9600);
}

void loop() {
  if (Serial.read() != -1) {
    for (int i = 0; i < 3; i++) {
      irsend.sendSony(0xa90, 12); // Sony TV power code
      delay(40);
    }
  }
}


Resumindo a brincadeira: capture os códigos de IR com o receptor IR e com o sketch IRRecvDump e para testar o emissor basta enviar o código IR com alguma função send<>  do objeto irsend (do tipo IRsend). No caso do exemplo acima utilizamos a função sendSony passando como parâmetro o código IR(0xa90) e o tamanho em bits do código(12). Note que esse código foi enviado três vezes para conseguir ligar a TV (alguns códigos exigem que sejam acionados mais de uma vez).
No caso de envio de códigos IR como rawcode você deve usar a funçao sendraw como neste exemplo:

irsend.sendRaw(powerOn,92,38);

Onde powerOn é a variável unsigned int contendo o rawcode do botão liga do ar condicionado que capturei, 92 é a quantidade de elementos do rawcode e 38 é a frequência em Hz).

Dica sobre o EMISSOR infravermelho: se você observar que o emissor não aciona em distâncias um pouco maiores experimente retirar o resistor do esquema ou diminuir o valor da resistência. Retirei o resistor e funcionou tranquilamente.

No próximo post vamos mostrar como executar sons utilizando um buzzer ou alto-falante de PC e depois vamos juntar todos os componentes para implementar o projeto de acionamento de ar condicionado via infravermelho.

Até a próxima,



12 comentários:

  1. fala fernando tudo bem? muito obrigado por seu artigo, graças a sua ajuda consegui conseguir transmitir via IR.. o engraçado é que meu led ir nao da pra ver com a camera. ja viu isso? estranho neh

    consegui transmitir mas ainda nao consegui controlar nada.. nem raw nem nec.. peguei um segundo arduino e fiz um receptor pra testar e notei que o codigo que eu transmito ta vindo com pequenas diferenças entre o que envio e o que recebo
    ex:
    enviado: 8900,4300,650,1600,600,1550,650,1600,600,500,600,500 ...
    recebido: 8800,4250,650,1400,800,1550,650,1550,600,500,650,450 ...

    nao sei se isso seria o motivo deu nao conseguir controlar nada

    usei um shield emissor IR entao ja veio led ir e resistor junto, simplesmente plugo no arduino com jump e pronto.

    alguma dica em relação a isso? muito obrigado
    Caio

    ResponderExcluir
    Respostas
    1. Vê primeiro esse LED IR direito. Testou com várias câmeras pra ver se consegue ver alguma coisa? Se não ver nada, deve estar queimado.

      Excluir
    2. todos leds IR sao visiveis na camera?

      meu problema é que o codigo raw no receptor nao bate com o enviado. o fato deu receber o codigo me prova que o emissor esta funcionando mesmo eu nao vendo ele pela camera.

      Excluir
  2. Melhor código que achei pra IR, valeu mesmo!

    ResponderExcluir
  3. Olá, muito bom o seu trabalho, estou tendo-o como base para o meu projeto, mas estou com problemas com a interferência no receptor infravermelho no arduino. eu estou tentando copiar o código do RAW mas sempre recebe vários códigos diferentes, tenho um capacitor ceramico 150nf para filtrar, adiantou um pouco, mas não totalmente. Você teria como me ajudar nisso?

    ResponderExcluir
    Respostas
    1. dependendo do ambiente com muita luz ou alguma interferência externa faça uma pequena proteção, pode ser com a mão mesmo ou algum material enquanto tenta copiar o código

      Excluir
  4. ola, você ou alguém poderia me passar o código do controle de ar condicionado? sou iniciante e não entendo muito sobre IR, obrigado desde ja!

    ResponderExcluir
    Respostas
    1. Você tem que capturar o código do ar condicionado como descrevemos acima.

      Excluir
  5. Olá, eu estou tentando fazer um projeto para automação de portão com emissão de um codigo IR, porém, não tenho muito conhecimento sobre a programação, vi vários exemplos de enviar um codigo ou reatransmitir o mesmo, minha dúvida é, posso criar um Irsend, com um codigo qualquer que determinar? Qual função utilizar?

    ResponderExcluir
  6. Este comentário foi removido pelo autor.

    ResponderExcluir
  7. Amigão, na linha:
    irsend.sendSony(0xa90, 12); // Sony TV power code
    delay(40);
    é que envia o codigo propriamente dito, pois bem...
    Mas se eu tiver que enviar um codigo com 2 ( ou mais ) digitos, por exemplo um canal com 2 digitos )
    como ficaria ?

    ResponderExcluir
  8. Parabéns pelo trabalho! Consegui fazer funcionar aqui!
    Gostaria de colocar o emissor e receptor no mesmo arduino!
    Assim o emissor envia um unico código full time (Ex: o código de liga de um controle qualquer) e o receptor ao receber este único código executa uma função (ligar um led por exemplo) tudo no mesmo arduino!
    Resumindo toda vez que o receptor enxergar o emissor acende o Led!
    Obrigado

    ResponderExcluir