arduino-mando-a-distancia-infrarrojo

Controlar Arduino con un mando a distancia infrarrojo

¿Qué es un mando a distancia infrarrojo?

Un mando a distancia es un dispositivo de control que emplea un LED infrarrojo para enviar una señal al receptor. La señal puede ser detectada para controlar un autómata o procesador como Arduino.

Todos estamos acostumbrado a emplear mandos a distancia infrarrojos, para la televisión, Dvd, equipos de música… De hecho, es posible emular cualquiera de estos mandos, lo que permite controlar estos dispositivos desde Arduino.

Un mando a distancia emplea un emisor de luz en el infrarrojo cercano, invisible para el ojo humano, pero que puede ser captado con facilidad por un receptor infrarrojo.

Es posible ver la luz del mando mirando el LED infrarrojo con una cámara digital, por ejemplo de un móvil. La luz del led de muestra como un resplandor morado. Esto puede ser útil para detectar si el mando funciona correctamente.

Al emplear luz como medio de transmisión, los mandos a distancia necesitan una línea de visión directa con el receptor. El haz puede ser reflejado por superficies reflectantes, como espejos.

El alcance es limitado, típicamente inferior a 3m. La distancia depende fuertemente del ángulo de emisión, disminuyendo rápidamente a medida que nos desviamos de la dirección frontal.

Podemos emplear un mando a distancia como control remoto para controlar Arduino. Podemos, por ejemplo, encender o apagar un sistema de luces o sonido, encender o apagar un dispositivo por relé, o controlar un robot o un vehículo.

Por otro lado, también es posible emplear Arduino para clonar un mando a distancia y, por ejemplo, controlar el encendido de la televisión a través de un smartphone, temporizar el encendido de un equipo de música, o encender el aire acondicionado a través de internet.

Precio

En el campo de los hobbies y la electrónica casera podemos encontrar kits especialmente diseñados para Arduino, que incluyen mando y receptor HX1838 o similar, instalado en un módulo para conectar fácilmente a Arduino.

Podemos encontrar este tipo de kits por 0.75, buscando en vendedores internacionales en eBay o AliExpress.

arduino-mando-a-distancia-componente

Si únicamente queremos el receptor, por ejemplo, porque queremos controlar más de un dispositivo o porque queremos emplear el mando de algún aparato (TV, dvd, etc), podemos adquirir únicamente el receptor HX1838 por unos 0.10€.

arduino-receptor-hx1838

¿Cómo funciona un mando a distancia infrarrojo?

Un mando a distancia transmita un cierto mensaje al receptor empleando luz infrarroja como sistema de transmisión. La luz empleada típicamente está en el rango de 940 nm.

Como en cualquier transmisión el mensaje tiene que seguir unas determinadas normas (forma de los pulsos, duración, contenido…) que deben ser conocidas tanto por el emisor como por el receptor para que la comunicación sea correcta.

Sin embargo, no existe un único protocolo adoptado como estándar. En su lugar cada fabricante ha desarrollado los suyos propios. Así, tenemos el RC-5 y RC-6 de Philips, el SIRC de Sony, el protocolo NEC desarrollado por la compañía japonesa Nippon Electronic Company, entre muchos otros.

Por otro lado, el mensaje nunca se envía directamente como un pulso, si no que se envía modulada sobre una onda portadora. Esto se hace para mejorar el rechazo al ruido y a la luz ambiental la señal de control se envía modulada en una onda portadora. La frecuencia de la onda portadora depende de protocolo empleado pero, en general, varía entre 36-50 kHz, siendo el más habitual en torno a los 38 kHz.

Uno de los protocolos más habituales, que es el que emplearemos con Arduino, es el protocolo NEC, que emplea una onda portadora de 38 kHz y modulación por distancia de pulsos (PDM Pulse Distance Modulation).

La onda portadora tiene un periodo de 26µs, y la señal transmitida distingue entre 0 y 1 por la duración de los pulsos, siendo.

  • Logical 0 – Un pulso de 562.5µs seguido por un espacio de 562.5µs.

  • Logical 1 – Un pulso de 562.5µs seguido por un espacio de 1.675µs.

arduino-mando-a-distancia-NEC-portadora

En cuanto al contenido del mensaje enviado, el protocolo NEC envía una dirección 8 bits y un comando de 8 bits. Esto significa que pueden controlarse hasta 256 dispositivos sin interferir entre ellos, y enviar hasta 256 comandos diferentes.

Una particularidad del protocolo NEC es que se envía cada bloque dos veces, una normal y una negada, como sistemas de prevención de errores. La transmisión comienza con una señal de 9ms, seguido de un espacio de 4.5ms.

arduino-mando-a-distancia-NEC-mensaje

Por tanto, la señal completa es a señal completa

  • Pulso 9ms + espacio 4.5ms
  • 8 bits, dirección del receptor
  • 8 bits, dirección del receptor invertida
  • 8 bits, comando enviado
  • 8 bits, comando enviado invertido

Finalmente recibir la señal de control se emplean receptores específicos como el AX-1838HS (HX1838). Estos receptores son dispositivos normalmente de tres de terminales, que consisten en un sensor infrarrojo que incluyen un demodulador en la banda de 36-38kHz, un filtro PCM (Pulse Code Modulation) y preamplificación rechazo de luz ambiental.

arduino-mando-a-distancia-curvas

De esta forma, la salida que llega a Arduino es la señal digital ya demodulada, lo que simplifica enormemente el proceso respecto a tener que emplear un fotodiodo y realizar los cálculos nosotros.

Esquema de montaje

Si usamos un módulo con el receptor integrado la conexión es sencilla. Alimentamos el módulo conectando Vcc y Gnd, respectivamente, a 5V y Vcc de Arduino.

Por otro lado, conectamos la salida del módulo Sig a una entrada digital cualquiera de Arduino. En el ejemplo usaremos la D9, pero podéis usar cualquier entrada digital.

Por tanto, la conexión queda como en el siguiente esquema,

arduino-mando-a-distancia-esquema

Que vista desde el lado de Arduino resulta,

arduino-mando-a-distancia-conexion

Si queréis usar el receptor directamente, deberéis consultar el datasheet del mismo para verificar su esquema de montaje. En el caso del AX-1838HS (HX1838) es el siguiente, donde, al menos, la resistencia de 100Ω es obligatoria y el resto opcionales (los módulos comerciales sólo incorporan la resistencia de 100Ω).

arduino-hx1838

Ejemplos de código

Existen múltiples librerías para emplear mandos a distancia con Arduino. Nosotros usaremos la librería Arduino-IRremote desarrollada por Rafi Khan (z3t0) disponible en este enlace.

El siguiente código realiza la lectura del valor recibido por el mando, y lo muestra por pantalla. El código se muestra en formato hexadecimal.

#include <IRremote.h>

const int RECV_PIN = 9;

IRrecv irrecv(RECV_PIN);
decode_results results;

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

void loop()
{
  if (irrecv.decode(&results))
  {
    Serial.println(results.value, HEX);
    irrecv.resume();
  }
}

El siguiente ejemplo emplea el comando hexadecimal para imprimir por puerto serie la tecla pulsada. La tecla dependerá del mando que estemos usando, pero sirve como ejemplo de como actuar en caso de recibir diferentes códigos.

#include <IRremote.h>

const int KEY_UP = 0xFF629D;
const int KEY_LEFT = 0xFF22DD;
const int KEY_OK = 0xFF02FD;
const int KEY_RIGHT = 0xFFC23D;
const int KEY_DOWN = 0xFFA857;
const int KEY_1 = 0xFF6897;
const int KEY_2 = 0xFF9867;
const int KEY_3 = 0xFFB04F;
const int KEY_4 = 0xFF30CF;
const int KEY_5 = 0xFF18E7;
const int KEY_6 = 0xFF7A85;
const int KEY_7 = 0xFF10EF;
const int KEY_8 = 0xFF38C7;
const int KEY_9 = 0xFF5AA5;
const int KEY_0 = 0xFF4AB5;
const int KEY_ASTERISK = 0xFF42BD;
const int KEY_POUND = 0xFF52AD;
const int KEY_REPEAT = 0xFFFFFFFF;

const int RECV_PIN = 9;

IRrecv irrecv(RECV_PIN);
decode_results results;

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

void loop()
{
  if (irrecv.decode(&results))
  {
    switch (results.value)
    {
    case KEY_UP:
      Serial.println("KEY_UP");
      break;
    case KEY_LEFT:
      Serial.println("KEY_LEFT");
      break;
    case KEY_OK:
      Serial.println("KEY_OK");
      break;
    case KEY_RIGHT:
      Serial.println("KEY_RIGHT");
      break;
    case KEY_DOWN:
      Serial.println("KEY_DOWN");
      break;
    case KEY_1:
      Serial.println("KEY_1");
      break;
    case KEY_2:
      Serial.println("KEY_2");
      break;
    case KEY_3:
      Serial.println("KEY_3");
      break;
    case KEY_4:
      Serial.println("KEY_4");
      break;
    case KEY_5:
      Serial.println("KEY_5");
      break;
    case KEY_6:
      Serial.println("KEY_6");
      break;
    case KEY_7:
      Serial.println("KEY_7");
      break;
    case KEY_8:
      Serial.println("KEY_8");
      break;
    case KEY_9:
      Serial.println("KEY_9");
      break;
    case KEY_0:
      Serial.println("KEY_0");
      break;
    case KEY_ASTERISK:
      Serial.println("KEY_ASTERISK");
      break;
    case KEY_POUND:
      Serial.println("KEY_POUND");
      break;
    case KEY_REPEAT:
      Serial.println("KEY_REPEAT");
      break;
    }
    irrecv.resume();
  }
}

Descarga el código

Todo el código de esta entrada está disponible para su descarga en Github. github-full