Remote controlled power sockets for home automation etc

I’ve had these remote controlled sockets lying around for a while. They can be controlled via a radio-based remote. They often use 434MHz and OOK modulation (on-off-shift keying, which basically is turning the radio signal on and off based on a digital signal). This is a very simple protocol and frequency to reverse-engineer. This one is called NEXA, but I think there are quite a few versions with different brand names using the same RF protocol.

First take a receiver module such as this one. Connect it to power and ground, place an 8 cm wire to the antenna and connect the signal to a digital signal oscilloscope. If you don’t have one, you should get one. There are some sub-100 USD ones that work very well. I use Open Logic Sniffer, which is a great tool. Below is a picture showing a sample collected data. This is not the one from my NEXA remote controlled power socket. I didn’t save that one.

Connect it to the PC and you can see digital waveforms, timing etc on the PC. Use the remote that came with the socket to send a signal and read it using the receiver-module and the logic-sniffer. Press a button, and record the waveform. Note the timings etc. Zoom in to see the details. Try to see the timings + recognize specific repeating wave-forms. If you don’t have a logic-sniffer, you can also write a program to capture the timings of the signal using a simple MSP430-program. Then you have a DSO priced at $4.30 🙂 . Here is a picture of the Receiver-module.

Then use a transmitter module such as this one to send the same signal. Here’s a picture:

Use an MSP430 Launchpad or an Arduino as your microcontroller-board. Connect GND to ground, VCC to your Launchpad 3.5V and ANT to an 8 mm cable. Connect DATA to P1.0 and write a program to replicate the signal you captured using the DSO. I have one example that works with the above NEXA remote controlled socket in Inventortown on this link. You can take it from Inventortown and use it in your ‘local’ compiler if you prefer. This code is just for MSP430 Launchpad.

You can probably use the same mechanism to replicate many garage door openers also. I’ve used this code and the mentioned devices from Farnell to remote control devices in my house. The good thing about doing this is that you don’t have to worry about playing with higher voltages. The external, certified power socket takes care of all the dangerous voltages, and you just control it remotely. Very safe and nice. Source code is also below the line here.

/*
	Author: Lars Kristian Roland
	License: GPL
	Website: http://lars.roland.bz/ and www.inventortown.com
	This is code to control a NEXA remote controlled power switch, using
	an 433 RF TX board connected at P1.0
*/

#include
#define interrupt(x) void __attribute__((interrupt (x)))

void on1();
void off1();
void on2();
void off2();
void on3();
void off3();

void delay(unsigned int us);
void long_delay();
void pulse(int pulses);
void betweenPulse();

volatile unsigned char pressed;

#define ONE pulse(1)
#define TWO pulse(2)
#define THREE pulse(3)

#define BUTTON BIT3

int main(void)
{
  WDTCTL = WDTPW + WDTHOLD; // disable watchdog

  P1REN |= BUTTON;               // Enable Pull up resistor
  P1OUT |= BUTTON;               // Enable pull up resistor
  P1IES  |= BUTTON;               // Int on falling edge
  P1IFG &= ~(BUTTON);           // Clr flags
  P1IE |= BUTTON;                // Activate interrupt enables

  P1DIR |= BIT0;
  P1OUT &= ~BIT0;

  pressed = 0;

  _BIS_SR(GIE);

  while (1)
  {
      	_BIS_SR(LPM0_bits + GIE);
	on1();on1();on1();on1();
	long_delay();
	on2();on2();on2();on2();
	long_delay();
	on3();on3();on3();on3();
	long_delay();
	off1();off1();off1();off1();
	long_delay();
	off2();off2();off2();off2();
	long_delay();
	off3();off3();off3();off3();
	//long_delay();
  }
}

void preamble()
{
      delay(4000);
      ONE;
      delay(600);
      TWO;
      TWO;
      TWO;
      TWO;
      TWO;
      ONE;
      TWO;
      THREE;
      ONE;
      TWO;
      TWO;
      TWO;
      TWO;
      TWO;
      TWO;
      THREE;
      TWO;
      TWO;
      ONE;
      TWO;
      TWO;
      THREE;
      ONE;
      TWO;
      TWO;
      THREE;
      TWO;
}

void on1()
{
      delay(4000);
      preamble();
      ONE;
      THREE;
      TWO;
      TWO;
      TWO;
      ONE;
}

void off1()
{
      delay(4000);
      preamble();
      TWO;
      TWO;
      TWO;
      TWO;
      TWO;
      ONE;
}

void on2()
{
      delay(4000);
      preamble();
      ONE;
      THREE;
      TWO;
      TWO;
      ONE;
      TWO;
}

void off2()
{
      delay(4000);
      preamble();
      TWO;
      TWO;
      TWO;
      TWO;
      ONE;
      TWO;
}

void on3()
{
      delay(4000);
      preamble();
      ONE;
      THREE;
      TWO;
      ONE;
      THREE;
      ONE;
}

void off3()
{
      delay(4000);
      preamble();
      TWO;
      TWO;
      TWO;
      ONE;
      THREE;
      ONE;
}

void pulse(int pulses)
{
    for (int i = 0; i < pulses; i++)
    {
	P1OUT |= BIT0;
	delay(120);
	P1OUT &= ~BIT0;
	delay(120);
    }
    delay(510);
}

void betweenPulse()
{
	P1OUT &= ~BIT0;
	delay(1050);
}

// Delay function. # of CPU cycles delayed is similar to "cycles". Specifically,
// it's ((cycles-15) % 6) + 15.  Not exact, but gives a sense of the real-time
// delay.  Also, if MCLK ~1MHz, "cycles" is similar to # of useconds delayed.

void long_delay()
{
    for (int i = 0; i < 100;i++) {     	delay(1000);     } } void delay(unsigned int cycles) {   while(cycles>15)                          // 15 cycles consumed by overhead
    cycles = cycles - 6;                    // 6 cycles consumed each iteration
}

// The ISR assumes the interrupt came from a pressed button
interrupt(PORT1_VECTOR) PORT1_ISR()
{
  // If Switch was pressed
  if(P1IFG & BUTTON)
  {
  	//P1OUT |= BIT0;
  	LPM0_EXIT;
  	_NOP();
  	P1IFG &= ~BUTTON;
  }
}

Leave a Reply

Your email address will not be published. Required fields are marked *