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Í

15 comentarios:

  1. Hola, me viene al pelo el tutorial tengo los mismos enchufes que tu y hay que ver la de pilas que consume el mando jejejeje
    Podrías poner el esquema para poder montarlo, es que no se aprecia donde se conecta los cables, mil gracias por el Tutorial y felicidades por la web

    ResponderEliminar
  2. Hola ante todo felicidades por el articulo es lo que buscaba, tengo una duda respecto al codigo, por que cuando recibes D-on envias un E-on?? se supone que corresponde a otro enchufe el E-on no??? no entiendo bien el funcionamiento, me podrias explicar un poco?
    gracias y continua asi tus tutoriales son una fuente de inspiración

    ResponderEliminar
    Respuestas
    1. Exactamente, imagínate que tienes 15 enchufes radiocontrolados y los quieres controlar con un solo mando: podrías hacer que cuando recibas un D ON y luego un A OFF, por ejemplo (o cualquiera secuencia de pulsaciones), se activara uno de los enchufes o varios, que no tienen por que coincidir con el del código que realmente ha enviado el mando...
      Incluso podrías hacer que al pulsar un D_ON en el mando, se envíe un E_ON, y a los 10 segundos un E_OFF y tendrías una emulación de un enchufe temporizado...

      Por cierto, a ver si esta tarde tengo un hueco y hago el esquema que me pedía el comentario anterior con Fritzing para que quede mas claro todo...

      Gracias por el comentario :)

      Eliminar
    2. Acuerdate del esquema por favor :) que te espero como agua de mayo jejejejee, tengo todos los trastos listos para la operación :)
      graciass

      Eliminar
  3. Mil gracias, espero tu esquema y muchísimas gracias por contestar, ya te contaré como me queda el proyecto cuando lo termine :)

    ResponderEliminar
    Respuestas
    1. Acabo de publicar los esquemas como una nueva entrada en el blog, espero que te sean de ayuda :),

      un saludo!!

      Eliminar
    2. graciasss si lo he vistooo ahora si me voy a poner a montarlo a ver si me resulta bien la jugada k el mando consume demasiadas pilas jejejej

      Eliminar
    3. hola acabo de comprar todo lo necesario :) pero tengo un problema, cuando intento cargar el emisor me da error en la siguiente linea
      RemoteReceiver::init(0, 3, mostrarCodigo);
      es la unica descomentada de la explicación, me puedes decir como hacerlo bien?? es que no se como cargar bien el programa soy novato en arduino
      gracias y felicidades por el blog

      Eliminar
    4. ¿Cual es exactamente el error que te da? ¿Has copiado los archivos de la libreria en la carpeta de librerias de arduino?

      Eliminar
    5. vale creo que va a ser eso, en la propia carpeta que descargue cree ahi el fichero pensando que lo cojeria de ahi.
      Entonces no es asi no?

      Eliminar
    6. Perdona ya he resuelto ese problema, efectivamente no tenia la libreria metida dentro, ya puedo capturar los codigos pulsado con el mando, ahora tengo el siguiente problema es a la hora de mandar cuando compilo me lanza lo siguiente:

      RemoteSwitch\RemoteReceiver.cpp.o: In function `RemoteReceiver::enable()':
      tambien he bajado en newremoteswich por que es el que tenia el transmitter.h que en el primer enlace no esta...
      igual tiene que ver.
      gracias y disculpa de nuevo

      Eliminar
    7. Hola Jose Maria, que tal perdona que te moleste pero has podido averiguar el error que me da a que es debido? es que por mucho que lo miro no encuentro donde he metido la pata...
      mil gracias

      Eliminar
    8. Acabo de verlo, creo que el problema está en que los ejemplos los desarrollé con INO en lugar del entorno IDE Arduino y las librerías las pilla de un lugar distinto: en mi instalación con INO está usando la version 2.2.1 de RemoteSwitch. Prueba con la versión nueva y me cuentas.

      Eliminar
    9. Si parece ser que pueda ser eso, yo he hecho otro codigo basandome en el tuyo y pillando de todos sitios que he podido ver y al final me funciona con el ide con el siguiente codigo:
      #include

      #include

      #define OUTLET_A_ON 265353

      #define OUTLET_A_OFF 265349

      #define OUTLET_B_ON 266325

      #define OUTLET_B_OFF 266321

      #define OUTLET_C_ON 266757

      #define OUTLET_C_OFF 266753

      #define OUTLET_D_ON 266757

      #define OUTLET_D_OFF 266753

      #define OUTLET_E_ON 266793

      #define OUTLET_E_OFF 266789

      #define PERIOD 150;


      #define RF_TX_PIN 4


      void setup() {

      Serial.begin(9600);

      }



      void loop() {
      unsigned char comando=0;
      if(Serial.available()){
      comando=Serial.read();

      if (comando=='a') transmit(OUTLET_A_ON);
      //Serial.println("Sending on");
      else if (comando=='b') transmit(OUTLET_A_OFF);
      else if (comando=='c') transmit(OUTLET_B_ON);
      else if (comando=='d') transmit(OUTLET_B_OFF);
      else if (comando=='e') transmit(OUTLET_C_ON);
      else if (comando=='f') transmit(OUTLET_C_OFF);
      else if (comando=='g') transmit(OUTLET_D_ON);
      else if (comando=='h') transmit(OUTLET_D_OFF);
      else if (comando=='i') transmit(OUTLET_E_ON);
      else if (comando=='j') transmit(OUTLET_E_OFF);
      delay(100);
      }
      }



      void transmit(unsigned long rcode){

      unsigned long code = rcode;

      unsigned long period = PERIOD;

      code |= (unsigned long)period << 23;

      code |= 3L << 20;

      RemoteSwitch::sendTelegram(code, RF_TX_PIN); // RF transmitter pin

      }
      ahora ya seria perfecto quitar de enmedio arduino y que pueda emitir señales directamente desde la raspberry....
      por cierto me puedes indicar como puedo conectarme desde la raspberry al arduino por serial para al menos enviarle las señales por consola??
      mil gracias

      Eliminar
    10. Yo utilizo el picocom, que es lo que usa INO para comunicarse por serie a través del USB, con picocom /dev/ttyUSB0 (o lo que sea) te conectas y para salir pulsas Control A X (creo recordar, las tres juntas y cierra la conexión).

      Por cierto, ¿a que distancia tienes el emisor del receptor para que te funcione correctamente? Yo no conseguí que funcionará de forma fiable a mas de tres metros (sin antena)...

      Eliminar

Nota: solo los miembros de este blog pueden publicar comentarios.