miércoles, 31 de julio de 2013

Enchufes radiocontrolados (parte 2)

NOTA: Este blog se ha trasladado a trasteandoarduino.com.
 
Hace ya un tiempo que tenía pendiente profundizar en el tema de los enchufes radiocontrolados, y ahí va. 

Para hacer las pruebas he usado una pequeña placa con una pareja de módulos de recepción y emisión RF en la banda de 433Mhz que es la que usan los enchufes que os mostré anteriormente. Se pueden conseguir directamente en Ebay por menos de un euro la pareja si los compráis directamente a China

En la foto siguiente veis que están montados los dos módulos, a la derecha el de recepción, con el pin de datos conectado al pin 2 de Arduino, y a la izquierda el de emisión con el pin de datos conectado al pin 7 de Arduino. El resto son las conexiones a Vcc y Gnd, excepto el cable naranja que hace las funciones de antena en la parte de emisión.

Esquema del montaje para pruebas

La librería que he usado en los ejemplos es la de Randy Simons, RemoteSwitch, que os podéis descargar desde aquí. Antes de poder usarla tendréis que cambiar las referencias a WProgram.h por Arduino.h en los ficheros RemoteReceiver.h y RemoteSwitch.h.

Vamos entrando en materia. ¿Cómo podemos saber los códigos que envía nuestro mando al pulsar uno de los botones? Pues dentro de la librería viene un ejemplo, show_received_code.pde que algo retocado y en castellano queda de la siguiente forma:

 #include <RemoteReceiver.h>  
   
 /*  
 * Este programa lee los codigos recibidos por el modulo de RF  
 * y los muestra por pantalla.  
 * El pin de datos del receptor va al pin 2 de Arduino  
 * (este codigo esta basado en el original de Randy Simons show_received_code.pde)  
 */  
   
   
 void setup()  
 {  
  Serial.begin(9600);  
   
  // Indicamos que cuando se active la interrupcion 0 (pin 2 de Arduino) se llame a la  
  //funcion de callback "mostrarCodigo" al recibir 3 veces el mismo codigo (que es lo  
  //mismo que pulsar una tecla en el mando por un instante)  
  //                   interrupcion  
  //                   |  repeticiones  
  //                   |  |  funcion callback  
  //                   |  |  |  
  RemoteReceiver::init(0, 3, mostrarCodigo);  
 }  
   
 void loop()  
 {  
  // no se hace nada, ya que cada vez que se reciba un codigo se ejecutara la funcion  
  //mostrarCodigo  
 }  
   
   
 void mostrarCodigo(unsigned long receivedCode, unsigned int period)  
 {  
  //Note: interrupts are disabled. You can re-enable them if needed.  
   
  Serial.print("Codigo: ");  
  Serial.print(receivedCode);  
  Serial.print(", periodo: ");  
  Serial.print(period);  
  Serial.println("us.");  
 }


Al ejecutarlo nos da una salida como la siguiente:

Codigo: 334554, periodo: 150us.
Codigo: 334554, periodo: 153us.
Codigo: 334554, periodo: 152us.
Codigo: 334550, periodo: 150us.
Codigo: 334606, periodo: 153us.
Codigo: 334554, periodo: 150us.
Codigo: 334606, periodo: 152us.
Codigo: 334550, periodo: 150us.
Codigo: 334550, periodo: 153us.
Codigo: 334550, periodo: 150us.
Codigo: 334550, periodo: 152us.
Codigo: 334550, periodo: 152us.
Codigo: 334606, periodo: 152us.
Codigo: 334550, periodo: 150us.
Codigo: 334550, periodo: 153us.
Codigo: 334550, periodo: 150us.
Codigo: 334550, periodo: 152us.

Donde podemos ver que el código 334554 corresponde a 'D On' y 334550 a 'D Off'. El código 334606 es un código erróneo, que nos devuelve la librería debido seguramente a interferencias (o no...). El periodo de la señal es de 150 microsegundos (este dato nos sera útil a la hora de enviar los códigos en el siguiente ejemplo).


NOTA: Como habréis visto, aunque en la placa esté conectado el módulo de envío por RF, en este ejemplo no se ha usado para nada. Está montado, más que nada, por comodidad, y por no tener que estar montando y desmontando los módulos cuando cambio de ejemplo.


El siguiente paso natural es sustituir nuestro mando por un Arduino. Imaginemos que queremos hacer que cuando con nuestro mando enviemos una señal D On, nuestro Arduino lo detecte y envíe una señal E On. No tiene mucho sentido pero puede servirnos de punto de partida para otras implementaciones mas complejas (en el ejemplo vemos como se puede recibir y enviar con el mismo programa).

Configuramos el enchufe como 10100 00001 (Aparato E) para que podamos comprobar que al pulsar el botón D ON el Arduino envía el código E ON y se activa el enchufe.
Configuración 10100 aparato E.


Cargamos el siguiente código en nuestro Arduino y lo probamos:

#include <RemoteReceiver.h>
#include <RemoteTransmitter.h>

// Codigo de Casa: 10100
// Aparato A: XXXXX10000
// Aparato B: XXXXX01000
// Aparato C: XXXXX00100
// Aparato D: XXXXX00010
// Aparato E: XXXXX00001

unsigned long A_on  = 333150;
unsigned long A_off = 333146;
unsigned long B_on  = 334122;
unsigned long B_off = 334118;
unsigned long C_on  = 334446;
unsigned long C_off = 334442;
unsigned long D_on  = 334554;
unsigned long D_off = 334550;
unsigned long E_on  = 334590;
unsigned long E_off = 334586;

int period=150;
const int pinEMISOR=7;

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

  RemoteReceiver::init(0, 3, procesaCodigoRecibido);
}

// --------------------------------------------------------------------
// Procesamiento de los codigos recibidos
// --------------------------------------------------------------------
void procesaCodigoRecibido(unsigned long receivedCode, unsigned int period) 
{
  // Leemos el codigo recibido y ejecutamos la accion que corresponda

  Serial.print("Codigo: ");
  Serial.print(receivedCode);
  Serial.print(", periodo: ");
  Serial.print(period);
  Serial.println("us.");

  // Si recibimos un D-ON, enviamos un E-ON
  if(receivedCode==D_on)
  {
     Serial.println("Recibido D_ON");
     cli();
     sei();
     delay(2*period);
     Serial.println("Enviado E_ON");
     RemoteTransmitter::sendCode(pinEMISOR,E_on,period,3);
  }

  delay(350);
}


void loop()
{
   //el codigo se ejecuta cuando se activa la interrupcion
}


Y a partir de ahí ya podeis adaptar el código para hacer lo que querais.

Bueno, un último apunte: existe una versión más moderna de la librería aquí, que soluciona algún problema como el de tener que activar y desactivar manualmente las interrupciones (cli/sei) para que se pueda usar la recepción y el envío simultáneamente en el mismo programa.

Espero que os sirva, y si tenéis alguna pregunta, será bienvenida.

PUEDE COMENTAR ESTA ENTRADA AQUÍ