One thing that really annoyed me about the lights in my room is when I went to bed I would always forget to turn the lights off and have to climb out of bed and turn them off. That sounds like a first world problem, and well it is. But I had a solution in mind. Back a few years ago I would control my lights with one of those cheap remote outlets you would find at places like Home Depot or Lowes around Christmas time. I took the only one I had a long time ago to see what made it tick. Before I ended up frying the remote, I discovered that it was nothing but a RF transmitting remote and receiver. The receiver would get the signal from the remote and flip a relay.

A few years passed by and I preordered my Raspberry Pi in February of 2012. The first thing I knew I wanted to do was home automation. Instead of running a full computer I could run a Raspberry Pi to control everything. Everything I knew about home automation had to deal with X10, but let’s face it X10 isn’t exactly cheap. Oh sure compared to some other solutions out there it’s not too bad, but I wasn’t really willing to dish out $20 per outlet. Not to mention you have to have a controller alongside the computer in order to control everything.

A1HE_1_20120910_43546435

As I was looking for home automation stuff I remembered the cheap remote outlet I had. I looked them up on Google and then ended up finding a pack of five on Amazon for ~$35. I figured if I could interface with this remote somehow by either faking button presses on a very low hardware level, or somehow reverse engineer the RF signal the remote puts out. Unfortunately, I’m not that smart so I chose the former.

The way the remote works is actually really simple. Each button when pressed brings a voltage to a pin on the encoder chip. By wiring the Pi directly to the pins, I was able to fake a button press by setting GPIO pins high. Once I did that all I had to do was write the software.

At first I wrote it using PHP and using MySQL to keep track if a socket was currently on or off. Unfortunately the remote that came with the sockets had only one button per socket so each press would toggle a socket. Over time PHP and MySQL would take too long and it was just getting tedious to toggle my lights. The Pi also only puts out 3.3v on output of a GPIO pin so the range on the remote wasn’t very good. This led to sockets getting out of sync.

However since I was using PHP I built a web interface. This coupled with a Tasker task on Android that would do a POST to the Pi’s web page let me control the lights from my room.

Just today I finally decided to improve on my code and add some features. The first thing I did was add an IR sensor and configure LIRC to do a POST to the web page. This functionality was actually really cool because I can now turn my lights on or off from my Harmony remote or my sonic screwdriver.

https://www.youtube.com/watch?v=YP_TDsSkYiI

Yeah, that’s right I said sonic screwdriver. For those that don’t know, the Sonic Screwdriver is a tool used by the Doctor from the famous British show, Doctor Who. In the show the screwdriver is shown controlling a multitude of things from radios to opening padlocks. It obviously does a lot more than simple day to day tasks, but I really liked this aspect. Recently I found out that a company makes a universal remote shaped like the 11th Doctor’s sonic screwdriver. I think you can see where this is going. I programmed the buttons from a remote into the sonic screwdriver and used those IR command to control the Raspberry Pi. Again, this worked, and worked quite well. However, I still had problems with my convoluted script. Thus I decided to redo my script and I thought how could I make this more stable? What language would I have to use? Obviously the answer was C (and I think it got a couple PHP haters off my back). Sure enough I wrote the program, compiled it, and now my lights turn on and off about four times faster and with much better accuracy and timing. I still kept the web interface, but I did drop the MySQL database stuff because it really just wasn’t necessary.

Below I’ve pasted the code that I used. Feel free to adapt it to your needs. Note that you’ll need the wiringPi library.

    #include <stdio.h>
    #include <wiringPi.h>

    int lights[] = {0,1,2,7,6,5};

    int main (int argc, char **argv)
    {
      printf ("Raspberry Pi Automated Light Control\n") ;

      // Make sure we want to turn off a light
      if (argv[1] == NULL) {
        printf("You didn't type what light you want to toggle! Exiting!\n");
        exit(1);
      }

      // Let's set up wiringPi and some pins

      if (wiringPiSetup() == -1) return 1;

      int i = 0;
      // Set our light pins as output
      for (i = 0; i < sizeof(lights); i++) {
        pinMode(lights[i], OUTPUT);
      }

      // If we want to toggle
      if (strcmp(argv[1], "toggle") == 0) {

        if (argc < 4) {

          printf("Toggling light %s\n", argv[2]);

        } else { // Multiple lights
          // Loop through each argument after toggle
          int j = 0;
          for (j = 0; j < argc - 2; j++) {         // Typecast our argument to an int         int light = (int)(argv[j + 2][0] - '0');         // Check to see if our light exists based on the size of the lights[] array
            if (light > (sizeof(lights) / 4)) {
              printf("Cannot toggle light %d as it does not exist.\n", light);
            } else {
              // Light exists so we can toggle it!
              printf("Toggling light %d\n", light);
              flipLight(lights[light - 1]);
            }
          }
        }

      } else if (strcmp(argv[1], "all") == 0) {
        printf("Toggling all lights!\n");
        int j = 0;
        for (j = 0; j < (sizeof(lights) / 4); j++) {
          flipLight(lights[j]);
        }
      } else {
        printf("Invalid argument! You must choose either \"toggle [pin]\" or \"all\"\n");

      }

      return 0;
    }

    void flipLight(int pin) {
      digitalWrite(pin, 1);
      delay(140);
      digitalWrite(pin, 0);
      delay(60);
    }

Now that I’ve got the code right I think I’ll spend some time improving the hardware. I’ll probably purchase those sockets that have the remote with a separate button for on or off. There’s also a lot of documentation on how these sockets work where people have found versions that let you set what channel the sockets are on. There’s also a library out there for the Pi that lets you take the transceiver from the remote and let the Pi do all the encoding.