IR Remote

Este projecto tem como objectivo utilizar um receptor Infravermelho e o Arduino para receber sinais IR, por exemplo de comandos de TVs, Vídeos, etc. e usar os mesmos como um objecto de controlo a um qualquer circuito.

O receptor usado foi retirado de um leitor de DVDs (de mesa) semelhante a este:

O esquema de ligação ao Arduino é muito básico:

(neste caso o pino de dados do receptor foi ligado ao pino digital 2 do Arduino)

Quanto ao código a utilizar optei pelo exemplo para um comando Sony, disponível no site: http://www.miklos.blog.br/2010/05/ir-receiver-controle-remoto-de-tv.html

/* 

Program that reads key presses of a sony remote control

Created by Kurtis Waterston, March 6 2010

Realesed into the public domain

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1267950229

*/

int irDet = 2;

int key = 0;

int data[12];

int state;

void setup() {

 Serial.begin(9600);                         //For debugging

 pinMode(irDet, INPUT);                      //IR detector connected to digital pin 2

}

void loop() {                                //Main loop

 if (pulseIn(irDet, LOW) > 2200) {          //Check for start pulse

   getIRkey();

   Serial.print("Key press is = ");

   Serial.println(key);

 }

}

int getIRkey() {                             //Read pulses

 data[0] = pulseIn(irDet, LOW);

 data[1] = pulseIn(irDet, LOW);

 data[2] = pulseIn(irDet, LOW);

 data[3] = pulseIn(irDet, LOW);

 data[4] = pulseIn(irDet, LOW);

 data[5] = pulseIn(irDet, LOW);

 data[6] = pulseIn(irDet, LOW);

 data[7] = pulseIn(irDet, LOW);

 data[8] = pulseIn(irDet, LOW);

 data[9] = pulseIn(irDet, LOW);

 data[10] = pulseIn(irDet, LOW);

 data[11] = pulseIn(irDet, LOW);

 for(int x = 0; x <= 11; x++) {              //Decide wether pulses are 1's or 0's

   if(data[x] > 1000) {

     data[x] = 1;

   }

   else {

     data[x] = 0;

   }

 }

 int result = 0;                            //Convert array into interger

 int seed = 1;

 for(int i=0;i<11;i++) {

   if(data[i] == 1) {

     result += seed;

   }

   seed = seed * 2;

 }

 key = result;

 return result;

}

No entanto, para conseguir utilizar qualquer comando sem ser apenas um da Sony, descobri o site http://www.arcfn.com/2010/01/using-arbitrary-remotes-with-arduino.html 

Aqui podemos encontrar a biblioteca "IRremote" e o código que nos permite identificar as teclas de qualquer comando remoto:

/*

 * IRhashdecode - decode an arbitrary IR code.

 * Instead of decoding using a standard encoding scheme

 * (e.g. Sony, NEC, RC5), the code is hashed to a 32-bit value.

 *

 * An IR detector/demodulator must be connected to the input RECV_PIN.

 * This uses the IRremote library: http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html

 *

 * The algorithm: look at the sequence of MARK signals, and see if each one

 * is shorter (0), the same length (1), or longer (2) than the previous.

 * Do the same with the SPACE signals.  Hszh the resulting sequence of 0's,

 * 1's, and 2's to a 32-bit value.  This will give a unique value for each

 * different code (probably), for most code systems.

 *

 * You're better off using real decoding than this technique, but this is

 * useful if you don't have a decoding algorithm.

 *

 * Copyright 2010 Ken Shirriff

 * http://arcfn.com

 */

#include <IRremote.h>

int RECV_PIN = 2;

IRrecv irrecv(RECV_PIN);

decode_results results;

void setup()

{

  irrecv.enableIRIn(); // Start the receiver

  Serial.begin(9600);

}

// Compare two tick values, returning 0 if newval is shorter,

// 1 if newval is equal, and 2 if newval is longer

// Use a tolerance of 20%

int compare(unsigned int oldval, unsigned int newval) {

  if (newval < oldval * .8) {

    return 0;

  } 

  else if (oldval < newval * .8) {

    return 2;

  } 

  else {

    return 1;

  }

}

// Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param

#define FNV_PRIME_32 16777619

#define FNV_BASIS_32 2166136261

/* Converts the raw code values into a 32-bit hash code.

 * Hopefully this code is unique for each button.

 */

unsigned long decodeHash(decode_results *results) {

  unsigned long hash = FNV_BASIS_32;

  for (int i = 1; i+2 < results->rawlen; i++) {

    int value =  compare(results->rawbuf[i], results->rawbuf[i+2]);

    // Add value into the hash

    hash = (hash * FNV_PRIME_32) ^ value;

  }

  return hash;

}

void loop() {

  if (irrecv.decode(&results)) {

    Serial.print("'real' decode: ");

    Serial.print(results.value, HEX);    //!!!!!!!PARA IDENTIFICAR AS TEClAS :)

    Serial.print(", hash decode: ");

    Serial.println(decodeHash(&results), HEX); // Do something interesting with this value  

    irrecv.resume(); // Resume decoding (necessary!)

  }

}

#define LEDPIN 13

void blink() {

  digitalWrite(LEDPIN, HIGH);

  delay(200);

  digitalWrite(LEDPIN, LOW);

  delay(200);

}  

// Blink the LED the number of times indicated by the Philips remote control

// Replace loop() with this for the blinking LED example.

void blink_example_loop() {

  if (irrecv.decode(&results)) {

    unsigned long hash = decodeHash(&results);

    switch (hash) {

    case 0x322ddc47: // 0 (10)

      blink(); // fallthrough

    case 0xdb78c103: // 9

      blink();

    case 0xab57dd3b: // 8

      blink();

    case 0x715cc13f: // 7

      blink();

    case 0xdc685a5f: // 6

      blink();

    case 0x85b33f1b: // 5

      blink();

    case 0x4ff51b3f: // 4

      blink();

    case 0x15f9ff43: // 3

      blink();

    case 0x2e81ea9b: // 2

      blink();

    case 0x260a8662: // 1

      blink();

      break;

    default:

      Serial.print("Unknown ");

      Serial.println(hash, HEX);    

    }

    irrecv.resume(); // Resume decoding (necessary!)

  }

}

Resultado:

Update 30-12-2011:

Para usar a biblioteca 'IRemote' com a nova versão IDE 1.0 do Arduino, temos de alterar o seguinte no ficheiro IRremoteInt.h:

Change the "#include WProgram.h" in IRremoteInt.h to this:

#if defined(ARDUINO) && ARDUINO >= 100

#include "Arduino.h"

#else

#include "WProgram.h"

#endif