Global remote control of mains sockets

using Raspberry Pi

          August 2012  (Last updated 31 October 2013)


This short video clip demonstrates turning on and off a desk lamp from over 100 miles away. Visual feedback in the video is achieved by the use of a CCTV IP camera at the same site as the desk lamp. If the video is not playing in your browser you can try this link instead.





Overview and Objective


The objective was to see how easy it would be to use a Raspberry Pi to allow remote access to turn power sockets on or off, in some building somewhere else on the planet. One limitation was that I needed a method of switching mains which was safe and left no chance for exposed lethal voltages. This was nothing to do with protecting electronics, but to do with protecting against injury. One obvious candidate was to somehow harness a remote control power switching unit - which are reasonably cheap and available. I got this from Maplin and decided to work with it.


Method of Switching


The internals of the remote control handset is a matrix of switches which feed into an encoder. The encoder outputs a different pulse train (on its DOut pin) depending on which button is pressed. This feeds into a 433Mhz RF transmitter which sends the pulse train out towards the RF receivers in the mains sockets.


So the idea was to replace the remote control handset with the Raspberry Pi and get that to turn the sockets on and off. There seem to be two methods of achieving this. One was to replace each physical switch on the remote control with a GPIO output, another was to fake the output of the encoder and feed that into the RF transmitter. I didn’t like the former, simply because it required many GPIO pins to be used. There were eight switches in the handset, and each of these was double pole, as the encoder/RF needed to be turned on at the same time that the pulse was generated. I am sure this matrix would have condensed down by multiplexing the outputs, but this did not seem as elegant as faking the encoder and using one pin for the signal, and possibly one pin to turn the RF on. Also, if the truth be told, the latter option just seemed like more fun anyway.


Determining the pulse train patterns for each switch


Images of each waveform were captured and analysed, for example :


The pulse width was measured at 428us

There are two main sub-patterns in use, each is 8 pulses (3.424ms long)


               Button 1 On                                                                    Button 3 Off












0 =


(high low low low   high low low low)



1 =

(high low low low   high high high low)



S =

There is a third pattern, used as a sync marker at the end of a message

(1 high pulse, 31 low)



Message Format


The message contained within the each pulse train consists of the following four parts:


Socket group


four * 8 bit patterns, see below

Socket number


four * 8 bit patterns, see below


1 for on, 0 for off

four * 8 bit patterns, see below



See “S” above


Socket Group, Socket Number

Socket group and socket number are made up of 4 8 bit patterns each, filled with 1's with a 0 to mark the number being represented, as follows


0111 = group or socket 1

1011 = group or socket 2

1101 = group or socket 3

1110 = group or socket 4



So group 3, socket 1 would be

1101 1000


Group 4, socket 2 would be


1110  0100



The command is also made up of 4 8 bit patterns, the first three are 1. The last one is 1 for on, and 0 for off.



To turn Group4 socket 1 off we would send

1110  0111 1110 S


To turn Group3 socket 3 on we would send


1101 1101 1111 S



Simulating the Remote Control Handset


These signals were then implemented in C code (sckctrl.c) such that command line parameters could be passed to the executable specifying a group/button/state. Note that if you hold a button down on the remote control handset is repeats the pulse train until you stop. If there are other 433Mhz transmitters nearby this may be important to ensure the signal reaches the receiver cleanly, so a parameter was included the number of repetitions of the pulse train transmission, to be set. The command line parameters were of the form :


<group> <socket> <state> <number of repetitions>


Mike McCauley’s GPIO library, C library for Broadcom BCM 2835 (thank you Mike) was used to transmit the chosen pulse trains to GPIO pin GPIO11. The waveforms were checked with a scope. However the voltage was obviously 0/3.3v. In order to generate maximum RF power, a 0/12v signal would be needed. 


An update to the C code was needed after versions after 1.9 of the bcm2835 library to ensure a fundamental pulse width of around 428 us because the the way that the timing routines had been implemented changed in this version of the library. The timing in the code assumes that the Raspberry Pi has not been overclocked.


Adding RF


To implement a faked remote control for proof of concept, I added one of these 434MHz RF transmitters to a veroboard circuit. The pulse train was stepped up to 12v via a transistor. It was now possible to turn any of the five sockets I had, on or off by running the code from Putty.



Schematic/Circuit Diagram



Stepping signal up to 12v.


Stepping the pulse train up to 12v from 3.3v was achieved using an npn transistor (Q1), with a collector resistor of 1KR, and a base resistor of 22KR to ensure that with a transistor hfe of 100, and a base/emitter voltage of 0.85v, at least 8ma was available via the collector. The one problem here of course was that this inverted the signal. A simple modification was made to the C code so that it produced an inverted signal at the GPIO pin, giving a correct polarity of 0/12v at the collector once it was inverted again by the transistor.


The code and the circuit also ensure that the RF is only enabled when we want to transmit a pulse train.  This is done from the GPIO via transistor Q2. Again the base resistor value of 22KR ensures that at least 8ma (11ma in fact) can flow through the transmitter to ground.




Constructing a shield


Having achieved a proof of concept, what I wanted to do was to mount the transmitter inside the Raspberry Pi box rather than have it on a trailing lead.  At the time of writing (August 2012) there was one prototyping shield I was aware of for the for the Raspberry Pi, but this seems geared up to RF comms and does not have the density of holes I would like.  The obvious option was to make one from some veroboard and headers I had lying around.



I then constructed the transmitter and added a 6 pin socket read to receive the on/off feedback signals to the software – which is a bit more compact than adding 4* 5v sockets to the board, as was done in the original prototype.



This worked fine, but needed a very slight trim to the power socket to make it a snug fit inside the cardboard Pi case (punnet).


By this time I had realised that feeding back a DC voltage to indicate the state of each socket was really not that practical. What was needed was a full duplex comms system where the receiver could transmit back when it had turned the socket on or off.


This made me consider a more general platform architecture for using for telemetry and control hosted by a Raspberry Pi. This would allow not just digital outputs to turn sockets on or off and other things, but analogue outputs and analogue inputs to be fed between the hosting raspberry pi and multiple intelligent remote terminal units. But that would be for another project.


Output from Circuit


The shield circuit was scoped to check pulse widths and voltage levels. The inverted GPIO output from the (channel 2 in yellow) and the 12v stepped up (channel 1, in green) scoped signals are shown here for a command driving group 4, socket 1, off.  Note that the signals are inversely related.





Driving from a web page


The real usefulness of being able to turn sockets on and off would be to be able to drive it remotely from anywhere globally where there was an internet connection.  One would not normally use a multitasking operating system to generate a 2Khz waveform, so there has to be some reason for this compromise. 

nginx is a web server which is very quick to install and configure on the Raspberry Pi. It was then fairly straight forward to add some html buttons representing on and off for each socket to a web page, and then using some basic JavaScript and PHP, invoke the program written above from the chosen button, passing in the appropriate parameters.  A quick tweak to the port forwarding on my internet router for port 80, and it was now possible to control the sockets from hundreds of miles away.



Socket State Feedback


I thought it was important to be able to display on the web page, whether each socket was turned on or off. It would be easy to contrive things within the web page software to show the socket state based on whether On or Off was the last button pressed. However this seemed pointless, and a proper end to end solution was sought. This was achieved by allocating a text file for each socket, which would either hold a 1 (on) or a 0 (off). The webpage would read these files and show a green led for a 1 and a grey one for a zero. Next, a cheap 5v phone charger was plugged into each socket's power distribution block and this was connected to a GPIO input via a resistor divider (330R/680R) to drop it down to 3.3v. Each of the four socket feedback GPIO inputs was set with its internal resistor set to pull down because when the socket was turned off, we get 0v, and we want a 0 input for that case, not to float to a 1.


The final link in the chain was another C program which was added to /etc/rc.local so that it automatically started on reboot of the raspberry pi. This program simply polled the four inputs, if any state changed, the appropriate text file had its state changed, which would be picked up by the webpage the next time it polled the file, and would then change its HTML LED image accordingly.


Use of Cron

Although the Web user interface has its uses, I have started to make use of cron on the Raspberry Pi, to automate turning sockets (mainly switching lights) on and off.  The crontab I am using looks a bit like this :



# m h  dom mon dow   command

# living room 4:4

  45 18 * * * sudo /webroot/sckctrl 4 4 1 10

  0   2 * * * sudo /webroot/sckctrl 4 4 0 10

# dining room 4:3

  30 22 * * * sudo /webroot/sckctrl 4 3 1 10

  45 23 * * * sudo /webroot/sckctrl 4 3 0 10

  30  1 * * * sudo /webroot/sckctrl 4 3 1 10

  30  2 * * * sudo /webroot/sckctrl 4 3 0 10

# Study 4:2

  30 21 * * * sudo /webroot/sckctrl 4 2 1 10

  00 22 * * * sudo /webroot/sckctrl 4 2 0 10

  30  3 * * * sudo /webroot/sckctrl 4 2 1 10

  35  3 * * * sudo /webroot/sckctrl 4 2 0 10

# kitchen 4:1

  20 22 * * * sudo /webroot/sckctrl 4 1 1 10

  30 22 * * * sudo /webroot/sckctrl 4 1 0 10

  38  1 * * * sudo /webroot/sckctrl 4 1 1 10

  39  1 * * * sudo /webctrl/sckctrl 4 1 0 10

# Bedroom2 3:3

  00 21 * * * sudo /webroot/sckctrl 3 3 1 10

  35  0 * * * sudo /webroot/sckctrl 3 3 0 10

  11  4 * * * sudo /webroot/sckctrl 3 3 1 10

  31  4 * * * sudo /webroot/sckctrl 3 3 0 10


This is obviously just getting cron to run the sckctrl program with the necessary group/socket/state and repetitions (10 seems good) at the chosen time (mm hh).

This is very easy to change (using crontab –e) and it should be possible to automate changing crontabs based on day of week or month of year.  It should also be reasonably straight forward to modify these settings from a web page if necessary.





Other Issues


a)  RF Regulations

Within the UK, the Ofcom UK Interface Requirements 2030 document suggests that there is a 10% duty cycle (per hour) for 433.05- 434.79 MHz devices.  The

original prototype had the transmitter turned on permanently (modulating regardless of whether a signal was being sent over it), and whilst I doubt this ruling has

much significance in my case, it seemed sensible to only turn it on when transmitting. Hence the reason for Q2 in the circuit.


b)  Phone Charger Capacitance

Although everything seemed to work as expected, one wrinkle was that due to the internal capacitor smoothing of the phone charger, it did not drop to 0v for

around 2s after the socket was turned off. This was duly reflected in a delay changing the HTML image from green to grey when turning off the image. This was

improved by adding a 50R resistor (calculated to 52R) of suitable power rating across the output of each supply, but there is probably more work required in this

area to improve the way power state is fed back. OK for a proof of concept though.


c)   Work in Progress

Note that this page is still being added to, and in the meantime please direct any corrections or requests for additional information (e.g. web server configuration details, source code etc.) to the email address at the top of the page, and I will add it as soon as I can.


d)  Downloads

Warning: This project is a prototype, built for fun and proof of concept.

Downloads are therefore made available in the hope that they will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose. All source code is made available under GNU General Public License.

Encoder Waveforms scoped from Remote control

sckctrl.c   -   C Source code to drive transmitter circuit from Raspberry Pi