SenseLamp: a ultra-low cost, WiFi enabled sensor platform

The SenseLamp is an ultra-low cost (less than 30GBP/45US$), WiFi enabled sensor platform that is easy to build, easy to deploy and fully open source. A SenseLamp is a lamp shade that can be remotely controlled and gathers temperature, humidity, light-levels and motion data. It runs Linux and can do some on-board processing before passing the data on to e.g. busfarhn or COSM.

The story

One can write a story from two angles: a historical account or coming from the motivation. Since my motivation is something like “it sounded like a fun thing to do”, I’ll give the historical account.
The purpose of all this is to put a temperature, humidity, light-level and motion sensor in every room. And while we’re at it, throw in a relay to control a light-bulb. This combination allows some nice home-automation to be implemented. Even further: it provides a test-bed for activity recognition and helps to implement the idea of a quantified self. But in the end, it really just sounded like a fun thing to do.

Mark 0

SenseLamp v0.0

SenseLamp v0.0

After I had finished a first version of busfarhn and implemented the central heating control, I wanted to take things to the next level and started working on the SenseLamp. It didn’t take too long to whip up a first prototype: SenseLamp v0.0. It consisted of a TL wr703n, TI Launchpad with an MSP430G2553, a relay module, HC-SR501 PIR sensor and a DHT11 temperature/humidity sensor. All neatly wired up with jumper cables and attached to a lunchbox to which I went to town on with a Dremel. It wasn’t pretty, but got the job done – and it was running for 2 months!

I learned three things from this first prototype:
  1. The Linux CDC ACM drivers are buggy: it seems to be a well known problem that the Launchpads serial interface doesn’t work so well in Linux. The reason for this is a bug in the CDC ACM kernel module (see here, here and here). Despite the patches provided, I was unable to fix the issue on the WR703N resulting a bit of instability. A cronjob to reboot the router every 6 hours served as a usable workaround, but certainly does not fix the issue.
  2. HTTP only goes so far: using a simple HTTP based interface implemented via CGI worked beautifully for the central heating control as the interface was unidirectional. The SenseLamp however, needs to be able to send sensor data as well. So a different protocol/interface is needed.
  3. It will have to look better than this: While the dremeled lunchbox worked fine as a first prototype, I wouldn’t want plastic lumps hanging throughout my flat. So if I was to deploy this on a bigger scale (count > 1), it would have to look better than this.

Mark I

SenseLamp v0.1

SenseLamp v0.1

The next iteration was designed to do away with the flaws of the prototype. To get rid of all those jumper cables and get things neat and tidy, I designed a PCB and sent if of to SeeedStudio Fusion. As much as I favor local production and business – SeeedStudio was simply 10 times cheaper than anything I found in the UK – even with similar lead time. It only took about 2.5 weeks until I got the PCB in the mail, with the cheapest delivery option that is.
The goal for the SenseLamp PCB is to serve as a "shield&quot: for the WR703N router. The shield is powered by the router and directly talks to the routers AR7240 CPU via the serial port exposed via two test-pads (yep, fiddly soldering included). To make the power supply work, the board sports a 3.3V LDO. All sensor protocols required (the single wire protocol of the DHT11/DHT22), GPIO stuff for the PIR sensor and ADC stuff for the LDR are handled by the MSP430G2553 which is also on the PCB. A neat package all in all.
At the same I started playing around with different frame designs. The lamp shade side of things would have to support the boards, mains to 5V power supply (which handily comes with the router), some space for the light bulb and a spot to place the PIR and temperature sensor away from the light-bulb. As I happen to be interested in personal fabrication (sigh) I laser-cut a triangular frame that unfortunately is not really portable across different machines and can certainly not be ordered from services like Ponoko. But then, any other form of shade/lamp holder would do.
I ended up deploying that version in the kitchen and ran it there for a while. It successfully did away with the communication issues that plagued version 0. Also it looked quite a bit better. But it still wasn’t quite there yet:
  • forgot the PIR sensor: the lesson learned here is never design a PCB in a hurry. For some reason I forgot to add the the appropriate pinheaders for the PIR sensor on the PCB. So I had to compensate for that while wiring up the whole thing – it worked, but it was messy. Because like this the PIR sensor can not simply sit on the board, it has to be placed somewhere on the frame. Yet another thing to consider.
  • assembly was still too difficult: which is in part due to the PIR screw-up. Until this version I assumed I could simply tie it all together using some good old zipties. But as it turns out the holes in the relay board, as well as the router board are close to M2 and that’s too small for those standard 50mm zipties. So, I’d have to put in screws. Combine that with my tendency to pack everything too tight (on the frame) and you end up with something that’s very hard to put together.
  • DHT11 sensors are too inaccurate: according to their datasheet, DHT11 sensors have a tolerance of +- 2 Celsius and 1% humidity. That’s quite a lot when one wants to monitor temperatures in the range of 20 +- 3 degrees. So I needed better sensors: the pin-compatible DHT22 to the rescue.

Mark II

SenseLamp v0.2

SenseLamp v0.2

That’s the version that I ended up building four times and putting one up in every room. It uses a new revision of the SenseLamp PCB (taking the PIR sensor into account), has a way cleaner cable structure and sports DHT22 sensors. Let’s see how it’s made in the next section.

How it’s made


Besides the sensors, there are two main hardware components involved: the wr703n router and the SenseLamp board. As the figure shows, the router merely passes through the 5V USB power and provides WiFi – effectively turning a Linux machine into a wifi shield. This is still twice as cheap as buying a dedicated WiFi shield. And as power consumption is not really of concern here, this works just fine.

Power supply

The router as well as the SenseLamp board are powered from a single 5V power supply, which in turn is powered from the power line which would normally light up the lamp. As a result, existing light-switches effectively turn the whole device on and off and not just the light. I’ve taped something over the light switches to prevent accidentally turning of a SenseLamp.
To connect the 5V power supply (which comes with the wr703n), I solder cables to the plugs of the power supply and wire them in parallel to the light bulb.
Sensorboard of SenseLamp v0.2

Sensorboard of SenseLamp v0.2

Sensor board

This little board does most of the heavy lifting: it provides the 3.3V power supply for the MSP320, connects the relay to the MCU and provides a home for all the sensors. There is a programming port as well, which allows in-circuit programming/testing of the firmware using a TI Launchpad as FET. At some point one may ask: why an MSP430 and not something Arduino-ish? I have two reasons: MSP430s require a lower external part count if one wants stable timings (just a resistor and no quartz), and a TI Launchpad is a lot cheaper than an Arduino or an AVR ISP. In short, the MSP430G2553 just delivers more "bang for the buck" than an AVR, let alone an Arduino.


We’re not using much of the WR703N except for its WiFi, serial port and 5V coming from its USB port. The only thing that’s tricky here is soldering wires to the two testpads, as described elsewhere.


The software side of things consists of two parts: the firmware on the MSP430 and some userland program running on the WR703N.
The MSP430 firmware has to deal with all the sensors and serial communication to the "WiFi shield". Thanks to that awesome project called Energia, writing code for the MSP430 is as convenient as it is with an Arduino (but at a fraction of the cost). The firmware can be found in the GitHub repository.

OpenWRT and busfahrn

Having a sensor laden lamp shade hanging around is boring, unless one does something with those sensors. Earlier this year, I wrote busfarhn which is a message bus at the core of my home automation effort. This message bus also sports a GUI module implemented using MetroUI CSS and socket.io.
I’ve written a simple TCP based client that bridges between busfarhn and the SenseLamp firmware. It relays incomming commands and translates the SenseLamp output into busfarhn messages. All of that code can be found in the GitHub repository of busfarhn.


First things first: all SenseLamp material is open source. If not stated otherwise, it is published under the MIT license and can be found on GitHub. Should you be in the process of building one yourself and have questions – I’d be happy to help.
Building a SenseLamp is a straight forward process, involving three main activities:

  1. Gathering all parts and components
  2. Assembling the hardware
  3. Flashing OpenWRT and firmware + installing some userland driver program.

Gathering all parts and components

The part count of a SenseLamp is lower than one might expect. Besides the WR703N router and sensors and microcontroller, only common place parts such as resistors and caps are required. The SenseLamp PCB is single-sided, uses exclusively through-hole components and not too fine traces so that it can be produced at home if necessary. Find a A rudimentary bill of materials can be found here.
I bought most of the components from eBay, RS Components and Farnell. The board was manufactured by SeeedStudio Fusion. It took roughly a month to source all parts – including the custom PCB.

Assembling the hardware

Hardware assembly takes part in three stages:

  1. First, all components have to be soldered to the SenseLamp PCB, some wires to the WR703N router (described above), and some thick enough wires to the 5V power supply coming with the router (it helps to drill a hole in the plugs). Then, a "sandwich" is made by stacking the SenseLamp board on top of the WR703N using M2 screws (I drilled slightly bigger holes in the WR703N) and some spacers, which I 3D printed. Once that tower was assembled, I connected the SenseLamp PCB to a 5V power supply, FTDI 223 3V3 serial cable and TI Launchpad to test the SenseLamp board in isolation and program the firmware.
  2. The frame is assembled (depends on the kind of frame) and the 5V power supply is added. Try and layout the cables in this stage as well. Add the SenseLamp board sandwich in this stage as well.
  3. At last one has to wire it all up. I used luster terminals to wire the 5V parallel to the lamp and ran one lead through the relay, so that the lamp could be controlled from the SenseLamp.
  4. At this point it is a good idea to power it all up and see if everything’s working fine. I used a leftover cable, which I opened on one end and fed the leads into the top luster terminal to simulate it hanging from the ceiling.

Closing remarks

All in all I built four of these puppies and installed them in my livingroom, hallway, kitchen and bedroom. For now I’m simply using the light and motion sensor to automatically turn on the light when its dark. The temperature/humidity data is simply logged away and I glance at it every now and then out of interest. In the future I plan to use them for some light activity recognition and infer my sleep times and similar activities from the data.
Another thing I might do is design different frames as I’m not entirely happy with the current form. The WR703N, as well as the relay module both have LEDs which are constantly on and are slightly annoying – despite their usefulness.

My final remark should be that this was a fun build that took about twice as long as originally anticipated. I spent about two months (spare time) going through the prototypes, implementing the firmware and busfarhn integration. Would I do it again? Anytime.

Central heating control on the cheap

The gas heating system in my flat is pretty rudimentary when it comes to features. Not only is there the absence of a proper billing system (yep, pre-paid gas causes me to wake up in a cold bedroom once or twice a month), but also in terms of heating control. Besides controlling how much water flows through each radior, there are two ways to control the heating centrally: a timer with 30min. resolution and a dial without a scale that sets something like the “heating level”. Now, the timer controls when the boiler is active at all, and that includes warm water. So what I would typically do is set the timer to always on and set the room temperature by controlling the heating dial once a day. With that method I’d still heat during the day, when I’m not at home which is highly suboptimal.
I’m also currently in the process of building a simple home automation system using busfarhn running on a RasperryPi. So it seemed like a natural fit to have some form of automated heating control, integrated into the home automation system. The solution is pretty more or less straight forward:heating control schema
The TP-MR3020 WiFi router gets signals via http, relays them to a serial port where it is received from an MSP430, which in turn bit bangs a signal for a servo motor controlling the central heating dial.

The WiFi part

For the whole thing to integrate with busfarhn, it has to somehow become part of the network – read, WiFi. As power consumption is not one of the primary concerns here (the whole setup is going to be close to a power outlet), I opted for the cheap WiFi solution. Embedded WiFi is still pretty expensive and complex, although the Electric Imp eases the complexity side and hopefully the TI CC300 modules will cut costs in the future. But were not there yet.
Another way to get WiFi for an embedded project is to appropriate existing hardware. A prime example of such appropriation is the TP MR3020 WiFi router (or its smaller brother, TP WR703 for that matter). This inexpensive piece of hardware can run OpenWRT, sports a USB port and is powered using a USB power supply itself.
Getting OpenWRT to run on this little white box is really easy, and described plenty elsewhere. Once the OS is setup, the only thing missing is the HTTP-to-Serial relay part.
First, we need to be able to control serial ports. Unfortunately, OpenWRT does not ship with stty support in its busybox build. Johan von Konnow has figured that out as well and provides a rebuilt busybox. After ungzipping it, I installed it with

mv busybox /bin/busybox.stty && ln -s /bin/busybox.stty /bin/stty

OpenWRT comes with uhttpd by default. uhttpd is a nifty little webserver that supports CGI. So placing a script much like the following one in /www/cgi-bin and one can send commands to the serial port via: http://<ip-of-the-router>/cgi-bin/servo?position=[0-9].

#!/bin/sh -ax

CMD=`echo "$QUERY_STRING" | grep -oE "(^|[?&])position=[0-9]+" | cut -f 2 -d "=" | head -n1`

echo "Content-type: application/json"
echo ""

if [ -z "$CMD" ]; then
    echo "{ 'status': 'error', 'msg': 'missing position' }"
elsif [ ! -f $SP ]
    echo "{ 'status': 'error', 'msg': 'missing servo controller' }"
    [ "$(stty -F $SP-a | grep speed | cut -d ' ' -f 2)" != "9600" ] && stty -F $SP raw speed 9600 -crtscts cs8 -parenb -cstopb

    echo $CMD > $SP
    echo "{ 'status' : 'success', 'msg' : 'done' }"

The business end

Sending commands alone will not turn that knob. To make that happen, one needs a servo motor. A typical RC servos works very well here, as their power requirements tend to be < 250mA so they can be powered straight from the USB bus. Connecting the servo with the actual knob was a bit harder than I anticipated. For one, I'm not allowed to permanently modify the boiler (it's not my property). And then there is that strange dial shape (see video below). So for the actuation part, two things had to be done: writing a bit of code for the MSP430 to control the servo and building a rig to hold everything in place and to connect the servo with the dial its supposed to turn.
Programming an MSP430 Launchpad is really straight forward thanks to an awesome project called Energia (if basic Wiring-style programming suffices and one doesn’t mind the overhead). The code for the MSP430 – which would also run on an Arduino – can be found in the source archive.
Mounting the whole system to the boiler was one the bigger challenges of this project. My first attempt with duckt tape held about 3 hours before it hit the floor. As it turns out, stick-on velcro bought from the local haberdashery does the job quite well. It allows me to easily remove and reposition the contraption from/on the boiler without leaving any permanent damage. And should the day come at which I move out of this place, I’ll hope that acetone will get easy the velcro removal.
Besides mounting the whole thing to the boiler, some form of adapter to fit the servo to the dial had to be created. It took me two attempts get the strange curvature of the dial right, but thanks to my trusty printrbot that was less done in less than two hours time.
Again, the outlines and models can be found in the source archive below.

Let’s see it

So far I’m pretty happy with the outcome. The machine sticks to the boiler and hasn’t come down yet. WiFi interface and servo work reliably. In case you want to build your own system like this, you might find the files uploaded here helpful.
Download the sources here.
Fork me on GitHub