29 de mayo de 2012

Arduino: Emisor y Receptor RF

La idea es emitir una onda concreta desde una tarjeta Arduino, recibirla en otra y, si la onda es la correcta, encender una LED. En un post anterior ya habíamos indicado cómo emitir esa onda y esta vez será de una forma similar. De hecho, utilizaremos la misma forma:

He utilizado un módulo receptor y un módulo emisor que podemos encontrar en Cebek.

Para el módulo emisor he utilizado la patilla 3 para la modulación y, como no era suficiente la energía proporcionada por el USB de nuestra tarjeta Arduino, he optado por utilizar una fuente de alimentación externa a 9v. Debemos tener en cuenta que necesitamos conexión de masa desde el emisor hasta la tarjeta Arduino y también a la fuente de alimentación, ya que para el envío de los pulsos necesitamos esa referencia en la tarjeta.

Para facilitar las cosas, vamos a comprobar solamente la llegada de los unos. Otro detalle a tener en cuenta, es que usaremos el mismo programa para emisor y receptor, controlando con ifdef si es uno o es otro.

Este es el código que hemos utilizado:

// Aquí definimos si vamos a cargar el programa al emisor o al receptor:
 
#define EMISOR // Esta línea debe ser un comentario si es un RECEPTOR
//#define RECEPTOR // Esta línea debe ser un comentario si es un EMISOR
 
const int pinDatos = 2; // pin por el que recibimos/emitimos datos
 
#ifdef RECEPTOR // Si hemos definido el RECEPTOR...
 
const int LED1 = 7; // LED roja que activaré si recibo el pulso de control (1111)
const int LED2 = 8; // LED amarilla que activare si recibo 0110100110100
int pulso = 0; // variable en la que recojo el tamaño del pulso "alto" (1)
 
void setup() // Inicializamos variables y pines. Solo se ejecuta una vez.
{
  pinMode(pinDatos, INPUT); // de entrada
  pinMode(LED1, OUTPUT);   // de salida
  pinMode(LED2, OUTPUT);   // de salida
}
 
void loop() // Se repite hasta apagar la Arduino
{
  // Cuando emito un 1 se envia un pulso de 250ms, si emito 2 serian 500ms
  // Pero no llegan exactos, asi que necesito un margen de error, por ello divido
  // entre 200. Si me han llegado 1111 (pulso de 1seg) tendria que darme un valor
  // entre 4 y 5, 11 (pulso de 500ms) daria 2 y un 1 (250ms) daria 1.
pulso = pulseIn(pinDatos, HIGH) / 200;
if(pulso >=4)
   {
    digitalWrite(LED1, HIGH); // Si ha sido el 1111, enciendo la luz roja
    pulso = pulseIn(pinDatos, HIGH) / 200;
    if(pulso == 2)
      {
       pulso = pulseIn(pinDatos, HIGH) / 200;
       if(pulso == 1)
         {
          pulso = pulseIn(pinDatos, HIGH) / 200;
          if(pulso == 2)
            {
             pulso = pulseIn(pinDatos, HIGH) / 200;
             if(pulso == 1)
               {
                digitalWrite(LED2, HIGH); // si he recibido 0110100110100 
                                          // (no he mirado los 0)
               }
            }
         }
      }
    delay(10);  // Una pequeña pausa
   }
else
   {
    // Si no he recibido 1111 apago las dos LED:
    digitalWrite(LED1, LOW);
    digitalWrite(LED2, LOW);
   }
}
#endif // FIN DEL RECEPTOR
 
#ifdef EMISOR // Si hemos definido el EMISOR...
 
const int pulsoCorto = 250; // Este será el tamaño de un 1. Si fuera 11 valdría 500
 
void setup()
{
  pinMode(pinDatos, OUTPUT); // de salida
}
 
void loop()
{
  digitalWrite(pinDatos, HIGH); // Envío pulso alto
  delayMicroseconds(pulsoCorto * 4); // 1111
  digitalWrite(pinDatos, LOW); // Pulso bajo
  delayMicroseconds(pulsoCorto); // 0
 
  digitalWrite(pinDatos, HIGH);
  delayMicroseconds(pulsoCorto * 2); // 11
  digitalWrite(pinDatos, LOW);
  delayMicroseconds(pulsoCorto); // 0
 
  digitalWrite(pinDatos, HIGH);
  delayMicroseconds(pulsoCorto); // 1
  digitalWrite(pinDatos, LOW);
  delayMicroseconds(pulsoCorto * 2); // 00
 
  digitalWrite(pinDatos, HIGH);
  delayMicroseconds(pulsoCorto * 2); // 11
  digitalWrite(pinDatos, LOW);
  delayMicroseconds(pulsoCorto); // 0
 
  digitalWrite(pinDatos, HIGH);
  delayMicroseconds(pulsoCorto); // 1
  digitalWrite(pinDatos, LOW);
  delayMicroseconds(pulsoCorto * 2); // 00
 
  delay(50); // Paro un momento antes de volver a emitir la secuencia
}
 
#endif // FIN DEL EMISOR 

La parte del receptor no es de lo mejorcito, pero para probar nos sirve. La idea está en utilizar la función pulseIn, que nos devuelve el ancho de un pulso alto o bajo, según indiquemos HIGH o LOW. Nosotros sólo nos fijamos en los valores HIGH (los 1).
Las divisiones que realizamos es para dejar cierto margen, ya que la emisión no es perfecta. En teoría, cuatro 1 deberían tener una duración de 1000ms, pero siempre pueden salir un poquito más cortos o largos al recibir.

Como fin, os dejo con el vídeo de dos Arduinos emitiendo y recibiendo: