Introduction: Sensorino Wireless Home Lighting With Arduino

Home automation exists for a while (since the 90's?) and has been quite expensive but with the advent of Arduino and above all cheap sensors, relays, other components from Ebay there's no longer any inherent reason for a maker not to automate their home. There might be no major reason for you to need it either but if you start with just the lighting think about the following:

  • Basic remote control of the lights through the web.

  • Logs of your activity - acccess to statistics and timestamps of when you left, went to sleep, got home from the hackerspace, etc.

  • Quick reassignment of switches to light bulbs.

  • Macros, for example "flip any switch three times to switch all lights off when leaving."

  • Learn what all the wires are for in those messy junction boxes and be able to say "I installed part of that!"

At home I did it using an Arduino library and toolkit that three of my friends and I developed at the Madrid Makespace. We called the project Sensorino. We had some major delays in the project while Arduino was slowly losing its advantages to other boards, but now it's ready for an instructable. I'll document only my particular setup here, more general instructions with all the possible choices are on our github wiki.

It does require some playing around to connect all the things right, some Linux command line fu to install and configure packages (although we keep it as easy as possible), and some soldering. The soldering is basic because I'm not great at it myself. It's by all means a maker oriented project.

If you get into any trouble look for a solution on the project's wiki or ask on the project's mailing list.

Why use Sensorino?

  • It's basically just a selection of the cheapest components from aliexpress.com or Ebay and some software but with Sensorino it's easier to do than if you wanted to start from scratch. It's really cheap, see the parts list below.
  • The server runs on a tiny Linux router, no need for a computer running 24 hours a day.
  • Extensible - you can integrate more sensors later, such as battery powered plant moisture meters, and even some consumer "smart" appliances, for example Bluetooth Low-Energy ones.
  • Unlike in some other systems, the remote Arduinos can execute some of the automation rules (including basic on/off switching with your normal light switches) and not depend on the wireless communication with server should something happen to it...
  • I have it running here for a while and it works. I live together with a rather demanding bunch and they haven't complained yet!

Note that there are some risks when messing with mains voltages and with the power that goes into the things you depend on, such as your fridge, heaters, ovens. SAFETY DISCLAIMERS GO HERE. Don't hurt yourself, others or your important stuff.

I don't have any instructions on making it pretty, I like raw electronics sticking out of places at home (especially with LEDs) and I'm not good at making enclosures for things but I'm sure you can laser-cut a great looking wooden or acrylic case for the elements that didn't fit inside junction boxes.

Parts list

I used the following:

  • Some mains cable (this must be 18 AWG or so), not a lot because mostly we'll be removing or replacing those thick cables, not adding more. Perhaps get a 25 metre roll from a DIY store.
  • A lot of thin signal cable, I used a 50m roll of two-wire telephone cable (0.5mm²) but even thinner would work.
  • $1.50 Arduino Pro Mini clones from aliexpress.com. One for the server (base node) and one for each remote node. I only use one remote node here, but it'll depend on how big your home is. More about this in the next step. Regardless perhaps just get a box of 10 or 20 boards from aliexpress, they are really cheap and will turn out useful for many other projects. Search for "pro mini 5v" (16MHz) on that site (example seller).
  • One or two USB-to-Serial adapters for Arduino from aliexpress.com, this is also in the $2 range (example seller).
  • nRF24L01+ radio modules from aliexpress.com. One for the server (base node) and one for each remote node. Again just get a box of 10, they're in the $0.80 / piece range (example seller).
  • Relays to control the lights. I only use on/off switching at this time, no dimming, so the cheap mechanical relays from aliexpress.com will do (example seller). They make click sounds, so you may want a solid-state relay instead. There's also a good selection of them on aliexpress. You can also find them recycled on taobao and elsewhere, at prices sometimes lower than mechanical.
  • A good number of $1 mini USB chargers from aliexpress, we'll use them as 5V DC power supplies for our remote nodes and for the server (example seller).
  • A TP-Link TL-WR703n wifi router to be our server. This is a tiny 5cm x 5cm box running Linux and starting at $18. Also get a small unpowered USB hub for it (example) since it only has one host port and a small USB memory of any modern size to extend the router's memory.

Note that since the aliexpress.com links go out of date quickly you may need to use the search box to find a replacement. The replacement will probably be better and cheaper since these things advance fast.

Step 1: Plan Out

Before we start we need to decide on a few things, like how many remote nodes we're going to need (i.e. remote arduino boards, the nerve cells of the network) and where they'll be. Here are some things to take into account.

You'll first need to understand a little about the existing installation at your home. If you have a schematic of the installation that could be very useful, but you can also just take note of where junction boxes are in the walls, try to figure out which ones connect to which other boxes by looking inside (tricky...) and then assume that each switch connects to a corresponding light through one such box, perhaps the one that's nearest. It gets a little more complicated with "multiway switching" setups used in corridors, stair wells, etc. What we care about here is how long each cable is.

Each "node" can control multiple switches and lights but these will be physically connected to the node with cables. To save ourselves work we'll want as few individual nodes as possible, subject to a few limitations:

  • Most Arduinos have about 10-15 usable inputs/outputs so we can't connect more than this. In my case the exact limit is 12 free digital pins. My first node uses 11 of them to take input from 7 switches and control 4 lights in 4 different rooms.
  • Cable length. Long cables are problematic because they have electrical resistance and also pick up radio signals (they're antennas). This is a problem mainly for the 5 volt connections between your node and the light switches, less so for the mains voltage connections to the actual lights. Set yourself a conservative limit of 5m or 20ft and try to place the node such that it has access to as many switches and lights within that radius. In my home's case the junction boxes in the corridors were the optimal locations. I'd need 4 nodes to comfortably cover the whole house
  • Perhaps, for starters, don't try to convert all of the lighting at home. Use just one node in a central place. Later, when this works, you can come back and add further nodes.

Step 2: Assemble the Remote Node

Now we'll need to electrically assemble the remote node, i.e. make connections between the 5V power adapter (from a USB charger), the Arduino-compatible brains of the node and the nRF24L01+ radio module so that these elements can talk to each other. We'll also want something to mechanically mount all those elements to. We'll also mount the 220V / 110V relays and connect them to the Arduino board, to be able to control lights.

You'll find similar instructions in Sensorino github wiki page for generic node setup and this one for connecting lights and switches.

My first node has 7 elements each of which is a small PCB so I laser-cut an acrylic base board to server as the mechanical support for it, there are probably much better ways to do that.

Now for the electrical connections:

  • The power supply is a small PCB, it's just a standard USB charger taken out of its case. You can remove the bolts that normally plug into a wall socket and just solder two short cables that will feed the board mains voltage. On the other end of the board you've got a USB female connector. You can rip out the connector and just use the two wires that fed 5V to it. You can use multimeter to find which was ground and which was 5V or infer that from which of them connected to the USB connector's ground pin.
  • These two pins are just what the Arduino and our other peripherals need to come alive. Have a look at the Pro Mini pinout diagram and connect the ground wire to the Arduino's GND pin and the 5V to the Arduino's VCC pin. I used male pin headers on the Arduino and female headers on the cables from the power supply.
  • The radio module is quite complicated to connect because it needs its input voltage lowered to 3.3V and also needs 6 signal pins. I have soldered a female pin header strip on the side of the Arduino that hosts the SPI signals (MOSI, MISO, SCK, SS) and used a male pin strip of the same length to make a connector for the radio module. The connector has the following pinout corresponding to the radio module's pins:
    • MOSI to MOSI.
    • MISO to MISO.
    • SCK to SCK.
    • Arduino SS to CSN.
    • Arduino A1 to CE.
    • Arduino A0 to IRQ.
    • Arduino GND to GND.
    • Arduino VCC connects through three standard N4007 diodes in series to the module's VCC pin. Together the diodes lower the input voltage by about 2V, just right to power the radio module. In my case the connector has a thin, short wire connecting each pin header to the radio module pin. The VCC cable is a little shorter and connects to the first diode's anode, who's cathode in turn is soldered directly to the second diode, that one to the third diode and this one is soldered directly to the module's VCC.
    • Remaining unsued pins on the male connector are left unconnected.
  • On the other edge of the Arduino PCB I have another female header row to be used for inputs and outputs, such as light switches and relays. I have two more header rows of the same length glued to the first one side by side. All the pins in the second row are connected together and to the VCC pin of the Arduino board. The third row is also common and connects to the Arduino's GND. This way each peripheral, sensor, actuator, etc. can use a three pin male header as a connector plugging sideways, giving it both power and a digital pin signal to the Arduino board.
  • Now each relay on the board uses such a three-pin connector. The relay PCB has the following pin names: GND, VCC, IN, COM, GND. The connector uses GND, VCC and IN.

I don't have great manual or soldering skill so my finished board doesn't look very pretty but I'm sure it can be done in an elegant way. For practical matters I tend to secure all of the uncovered metallic parts of pins or cables sticking out with hot glue. This gives it an additional level of ugliness but when gives both minimal electrical protection and mechanical stregth to all of the connectors and if you need to plug and unplug them a few times during development they won't break as easily, and you can even transport them in a backpack or a pocket.

Step 3: Assemble the Base Node

There'll be only one base node, to allow the server (a Linux machine) to communicate with the remote nodes using the same radio modules as they do. The Base is just an Arduino board, a radio module and a Serial-to-USB adapter in my case. The connections between the Arduino and the radio module are the same as in case of remote nodes (previous step). Then I have male pin headers on the power + serial port side of the Pro Mini PCB which plug directly into the female jumper cables that ship with the Serial-to-USB adapters from aliexpress.

Note that the adapter's TXD pin will connect to the Arduino's RXD and the Arduino's TXD to the adapter's RXD. The GND and VCC (5V) pins connect normally. You can also connect the DTS pin if available on the adapter you got.

My server (see next step) and the base node sit inside a wardrobe so I don't feel guilty having no case for them, it's just a bunch of PCBs connected with cables.

Step 4: Upload Sketches to Nodes

Now is a good time to program the Arduino boards in your remote nodes with a basic Sensorino sketch that will drive the lights and switches and do the communications part. It's good to do that before mounting the whole thing in an inaccessible place.

I won't go into full details here as I don't want this to be a software instructable and instead refer to the instructions on this github wiki page.

But it's quite simple. If you have the Arduino IDE installed, just add the Sensorino library to your libraries. Then open the example Sensorino sketch and adjust the number of relay and switch Services (Sensorino term) that are created, by adding and removing lines from the example. Also give the digital pin numbers to use, the Service IDs and the node's ID (numbers of your choice -- just need to be unique). Then upload it to the node using a USB-to-Serial adapter as you'd do with any Arduino.

Unfortunately this requres you to already know which pins you're going to use for the switches and the relays connections. You don't need to know which relay is which, and which switch is which but still need to know which pins you're going to use. Specific assignment is going to be done by sending a radio command later.

There's another way to do it too. This wiki page talks about installing a special bootloader on the Arduino board which will allow uploading a whole new Arduino sketch remotely. It is a little more involved but works well, specially for nodes that are difficult to access. I'm personally relying on this a lot.

We'll also take a moment now to program the Base node -- it's the same story as programming the remote nodes just no customisation to make. You can just take the example sketch and upload as is to your Sensorino base.

Step 5: Wire Up the Lighting

Now comes the interesting part where we mess with the electrical installation of the house. Make sure it is unpowered with the general switch / circuit breaker switched off. Check that lights effectively don't work, but remember that the rest of the cables in the junction boxes are still powered, unless you use the master circuit breaker instead of one specific for lighting.

The diagram shows what the switch+lightbulb circuit in the normal (our old) installation looks like and what it'll be like afterwards. There will effectively be two separate circuits, one for the light fixture and one for the switch, so we'll treat them separately.

You'll want a terminal block strip of some kind to make the wiring easier.

  1. First we need to connect the Sensorino node's power supply to the mains. Find a pair of mains cables that power the house's lighting (i.e. goes through the light-specific circuit breaker) and connect them to a pair of terminals in your terminal block. Connect the thin little cables from your node's power supply (USB charger PCB) to these terminals.
  2. Until now, for each light we had a circuit with basically three cables:
    • From the power terminal to the light-bulb - this cable will stay as is.
    • From the light bulb to the switch. Now this cable might have been quite long and passed through one or more junction boxes. If our node is mounted at one of them, we can cut the cable there and plug it into the relay's terminal. Otherwise you may need to find a new route for that cable to reach your node and it may end up being shorter or longer than previously. If it ends up longer you can use a screw terminal to extend it with another piece of cable.
    • The third cable was from the other terminal of the light switch back to the power source. Now that cable can be removed completely. You just need a very short piece to connect the other terminal of your relay in your node back to the other terminal of the mains source in the junction box.
  3. For each switch we'll now need a single two-wire thin cable to the node, such as the telephone cable I listed in the parts list. You'll need to route it through the conduits yourself. You can use a cable puller device for that or, if you're pulling out an old thick cable that is no longer needed, you can tie its end to the end of your new cable and use that. Depending on how crowded your conduits are both methods may prove difficult but ultimately there's no way around it.

    Strip 2-3 centimetres off of the cable's insulation to expose the two wires and then strip maybe 5mm of each wire's individual insulation. Plug the two wires into the two connectors of your wall switch (you may need a piece of a thicker cable too if the connectors don't produce any friction on wires that thin). On the other end, before connecting them to the Arduino try to secure them mechanically to the node's base or something else so that they're not only held there with the Arduino's electrical connection.

    Again strip a little of the cable's insulation and then some 5mm of each wire's insulation. If they are 0.5mm² telephone wires they should fit right into the female connectors on your Arduino board's side. Plug either one of the cables into the GND connector and the other to the digital input.

Multiway switching

In a normal installation multiway switching (wikipedia) needs a special type of circuit with the switches are in a sort of series connection with each other and the light fixture. With Sensorino we effectively don't care and just connect the lights separately and each switch separately. The Arduino sketch will do the multiway switching.

Step 6: Install the Server

I'm using a small Linux router, the TP-Link TL-WR703n popular with many electronics projects for its size, price and capabilities. You may want to first try running the server on a laptop PC, and old netbook or something else that is well supported and the software setup is effectively trivial. Note that you'll need a Linux flavour of some kind, other operating systems are not supported at this time. Below I'll describe the setup for the TL-WR703n router for completeness.

Here's the Sensorino github wiki page on this topic, I'll only give an outline here as most of this is messing with software.

As for the hardware setup there isn't much to do. We need to plug two USB devices to the router's USB port so we'll use a USB hub because there's only one host port. Plug the hub in and the plug a USB memory of any kind (small pendrive) into one of its ports and the USB-to-Serial adapter of the base node that we assembled earlier, into another port. To avoid radio interference with the router's wifi adapter I recommend using a USB extension cable to put the base a metre or so away. Otherwise I'd have squeezed the whole base inside the router's enclosure which would make the whole thing much cleaner.

We'll need to power the router through its micro-USB port. You can use a USB charger like the ones we disassembled earlier or some other 5V source. Just plug it into a power socket, then plug a USB-to-micro-USB cable into it.

Finally you may want to have this router integrated into your home wifi or wired network. The router has wifi capability and you can make it connect to your home network but you can also connect it with an ethernet cable and use it as a wireless access point in addition to being your home automation hub. For some of the setup instructions below you will need an ethernet connection either way.

Now comes the difficult part: setting up the software on the router which is more involved than doing the same on a real PC because of the type of the minimalistic low-footprint Linux distribution it uses. The router is also much slower, of course. If your WR703n is completely new it ships with TP-Link's specific Linux system in Chinese and on the first use you have to work your way through that Chinese user interface to an option that lets you update/change the Operating System. We want to install the free and opensource OpenWRT linux on it. See full instructions here on Sensorino wiki.

To continue with the remaining steps you'll need an ssh connection to the router, which requires you to connect through an ethernet cable the first time as the wifi connection will be disabled after OpenWRT installlation. See instructions here. Also note the package installation further down requires the router to have an internet connection -- this will again depend on whether you want to use the router's wifi adapter to establish a connection or use it as an access point in which case you'll need an ethernet cable to let the router get online.

Next we need to install OpenWRT extroot to escape the 4MB flash memory limitation of this device. See official docs here or one of the many tutorials.

To run the server we'll need to install a few packages (most of these will be already present on a normal Linux distribution if you're using a PC instead):

# opkg update
# opkg install python git screen # opkg install kmod-usb-serial kmod-usb-serial-cp210x kmod-usb-serial-ftdi kmod-usb-serial-pl2303

Finally we're ready to launch the server. Refer to the complete instructions here on our wiki but here's a quick way to test run it:

# git clone https://github.com/Sensorino/sensorino-smarthome.git
# cd sensorino-smarthome
# ./server.py &
# ./base-connect.py &

Step 7: Test Communication, Interface and Assign Switches

If everything went well you'll now have the server running and at least one node that it can talk to. It should be enough to flip any of your wall switches for the remote node to send the server a message, which should in turn trigger the server to start a discovery process and find the current states of all your switches and relays.

When you load http://routers_addr:8000/ the Sensorino web interface will open and if the server has detected any new nodes there'll be message saying that you can now go into the floorplan editor and lay out your sensor and actuator widgets visually. You can rotate/resize them, draw some walls to make the floorplan less empty, etc. The interface should be rather intuitive.

If that didn't happen, which is entirely possible because Sensorino hasn't received a great deal of testing yet, you'll want to start troubleshooting with checking if communication works at all. In the web interface go the Console tab to see if you're receiving anything when you actuate your switches. You can also check if messages are transmitted okay in the opposite direction by typing something in, such as a command to turn a relay on, and seeing whether that had the expected effect. The following message will tell node under address 10 to switch its relay 5 on (service ID 5), adjust according to your remote node's sketch.

{ "to": 10, "type": "set", "serviceId": 5, "switch": true }

If you see the following error returned:

{"error":"xmitError"}

that will mean that no Acknowledge packet has been received, which could happen if the transmission failed but also when transmission was successful and only the return packets aren't reaching us. It could also mean the "to" address was wrong. Note that transmission and reception can be affected differently by interference and one may have a high packet loss rate even if the other works. Another factor that affects radio transmission a lot is the voltage supplied to the radio module -- below about 3.0V packet drop rate increases quickly. It's good to test the radio communication before mounting the remote nodes in inaccessible places, if possible.

If nothing works, seek help from the sensorino@googlegroups.com mailing list where all things Sensorino can be discussed.

If on the other hand things seem to work you can proceed to configure the switch assignment to you relays so that switches work as they did previously (if that's what you want). The server's web interface for the rule engine isn't finished yet so instead use the Console tab again to send remote nodes a command that will create the rule you need.

This is the suggested pattern. Following is a command to the node's Rule Engine service (service ID 1) to create a new rule at position 0. The condition that triggers this rule is given by the expression: new switch 6 value does not equal previous switch 6 value, in other words when Switch 6 (service ID 6) has been flipped. The action that will be taken is to send service 5 the command to toggle it. Effectively this whole rule means: toggle the light when I toggle the switch.

{ "to": 10, "type": "set", "serviceId": 1, "count": 0, "expression": "data:6:switch:0 != prev:6:switch:0", "message": { "serviceId": 5 } }

Create each new rule at a new position, i.e. increase the "count" value by 1 each time. If you made a mistake you can wipe the whole rule storage clean on the given node with the following command:

{ "from": 10, "type": "set", "serviceId": 1, "count": 0 }

If all of this is too confusing you can refer to the message examples wiki page or to the full message format specification page. Or just shoot an email to the sensorino@googlegroups.com mailing list.