July 8, 2013
The Pi Control Script

The Raspberry Pi was built as a cheap, educational computer platform for students. But it’s exposed GPIO pins, linux support and prices comparable to an Arduino, have all contributed to it’s meteoric rise as an ‘internet of things’ style embedded computer. Many projects have used it’s small form factor to control all types of things. For example, the Cloud Lamp project, that I recently built!

In the past, when I’ve wanted to connect a hardware project to the internet, I’ve gone with Arduino and an ethernet shield. The problem with this solution is that the price was high and the available space for software was limited. This is where the Raspberry Pi really shines! But in order for the Raspberry Pi to provide these great benefits, you’ll need your program to be able to communicate. In particular, a web-based API will make it a snap to communicate with. Python is a popular language for using the GPIO pins and so pairing that with the Twisted networking module makes for a powerful program.

First check out what I was able to accomplish using this technique, then, after the video, stay tuned for a simple, pared down and detailed tutorial of the basics. After that I jump into the code that powers the actual lamp!

A simple example and tutorial of the basics of turning a Raspberry Pi into a networked controller

First, let’s consider a simple example of a single bulb lamp connected to a powerswitch tail, which communicates with a Raspberry Pi on GPIO pin 17.

If you wanted to write a python program that would turn the lamp on, then off the code would look like this:

If you’ve programmed for an Arduino before, this code is really straightforward.

  • The first few lines are setup, import will load the Raspberry Pi GPIO library
  • The second sets the pin naming scheme
  • The third tells pin 17 to be an output pin.

Once the setup is taken care of you can turn the pin off or on now, easily. Which in turn turns the lamp off and on!

Now we can control the hardware, but what good is a controller program if it isn’t  listening? Here’s where Twisted comes in, let’s say we wanted to be able to turn the lamp off and on remotely. The code to listen for input over the web looks like this:

After including the twisted modules you’ll recognize the GPIO setup again.

The next chunk is our response class, it will define a standard ‘get’ request that we can use as an API to turn the bulb off and on. ‘lampAPI’ is the class name I chose, name it whatever you like. In the first IF statement, the first term in the condition is the URL variable. So if you want your API call to look like this ( http://127.0.0.1/API?foo=1 ) then you would put ‘foo’ in the quotes instead. Once you’ve confirmed that your variable made it into the request object, you can now check what the variable holds. That’s what the next two IF statements are doing. The variables can contain whatever you like. You could look for a zero or one, yes or no, off or on, etc. Again, you should recognize the GPIO statement from before, that will turn the light off or on, respectively. The return statement should be a string, and whatever it contains is what the client will spit out to the browser!

Lastly, the Twisted object is initialized, and the program enters an infinite loop where we check to see if there’s a new request, forever. Now you can turn your light off and on from anywhere by typing the following URL/commands:

  • http://[ip of rasberry pi]/API?light=on (Turn the light on)
  • http://[ip of rasberry pi]/API?light=off (Turn the light off)

Ok, this is great, but an API is an interface for robots, let’s make one for humans.

The first step is to set up the root object of the twisted object to pass files to the client, which is the primary job of a web-server. This can be done simply by changing:

to

Now, create a directory called ‘lampwww’ in the same directory as your python file. Anything called from the URL of the Pi will be passed along to the browser. The last step here is simply creating an html file with links that will call up our API. In it’s simplest form, it could look like the following (create a file called index.html and put it in the lampwww dir) :

If you browse to the IP of your lamp, you’ll see the heading and the two choices to turn the lamp on or off; Tada! Web-connected lamp.

Getting more sophisticated: showing what I added to get the functionality in my Cloud Lamp project

I crafted this simple example to make an easy to follow tutorial but there’s a whole lot of improvements that could be made. In my Cloud Lamp project for instance, I not only had light bulbs connected, I also had a 60 ‘pixel’ string of ws2801 LED’s. So what could we do with this type of display? How about creating different modes of operation, each with it’s own unique display.

Adding this functionality required a few key changes, first, the end of our example is an infinite loop that looks for changes from the network. We need to change this so that we can do other things besides listening. The statement,

will run the loop, but if we change that to

Now we’re not tied down to only listening for new connections. The end of our program would now be an infinite loop that includes but is not limited to, our listening statement, like this:

Next, how do we animate the LED’s in different modes, which is a continual process, while also listening for new connections. I opted for a simple list of IF’s that choose which animation subroutine to run on every loop iteration. A global ‘mode’ variable will decide which animation to iterate through. Each of the animation sub-routines is contained in a function that can be called on from the main while loop. In my infodisplay mode, I’m showing the state of the house (Whether all the doors are close or not, whether there’s motion in the house), the surf report and the weather report. I accomplished this by using the Beautiful Soup module to scrape a Magic Seaweed widget, Weather Underground’s API for the weather report and MicasaVerde’s json feed, all formatted to output into a serial list of multicolored LED’s.

I'm into the flat look these days :)

I’m into the flat look these days :)

And finally, I wrote a more sophisticated web interface, taking advantage of the ample speed and space available on the Raspberry Pi. Besides a fancier looking interface, the important part is multi-directional feedback powered by Jquery. Talking to the lamp is easy, i just use standard .click’s on the mode buttons and .get’s to call the API that I created. The web interface is also able to dynamically tell which mode it’s in and whether the bulbs are off or on. I do this by creating another API that spits out a Json feed of the state of all the lamp’s functions, like this:

Then, I use Jquery’s cross-domain capable Jsonp functionality to check the status every X number of seconds and update the interface. It’s fairly simple from a code perspective and the result is that even with multiple interfaces open, they will all update depending on the actual state of the Lamp!

Well, now that I’ve talked about most of what makes my Cloud Lamp Project tick, why not dig into all the code yourself? It’s up on Github, feel free to modify, use, scoff at or appreciate all of it! :)

[ml_raw_html]


 

The Cloud Lamp

Dig into all the code for my Lamp project or grab the whole package for your modifying pleasure!

[/ml_raw_html]

What’s next?

In addition to turning the light-bulbs off and on and running the LED’s internally, I’ve also got a mode that allows the LED’s to be controlled externally through a TCP stream. It’s too slow to be very functional right now, however. And still requires some debugging. To try that as well, here’s an example Processing.org script:

I will also be coding and publishing a Mi Casa Verde plugin that will allow you to control the functions of the Lamp and see it’s status through their home control system.

Finally, a few features I plan on adding to the setup are a brightness setting for all Modes and some kind of mechanism for letting modes have individual settings. Like frequency for the strobe lights, or speed of drops for the rain mode.

Let me know if you have any comments or questions down below! :)

π

Hey thanks for reading this far! Maybe you'll be interested in more of my projects? Check out my homepage :)