In part one I gave you a little background as to why you might be interested in home control – and some information on the RF24 and RF24 libraries. If you’ve not read the earlier article – I suggest going there first.
Putting some meat on the bones
With my background in home control I’m looking for low cost and simplicity – but don’t take that to mean simplistic. I want powerful control over a range of devices, inputs and outputs. The important thing is cost and reliability – it has to cost very little – and sit there and just WORK once set up.
The design explained below is based on the notion of a controller and a bunch of slaves - in each case just a simple ATMEL 328-based board put together using the Arduino IDE (1.1 as it happens).
So let’s take the “slave” units first. Starting at the beginning, they need inputs and outputs. In my version those inputs will include temperature and humidity (don’t worry that’s one cheap single-wire device from China) and an analog input (thanks to the Arduino 328 chip) which could be used for example with a cheap light sensor. They’ll have some digital outputs (including a relay) and 3 analog (PWM) outputs.
So how do they communicate?
“In the beginning”, each slave broadcasts a message – every few seconds to say “I’m here” until it is contacted. The delay is fixed but SLIGHTLY different for each one – merely incorporating the ID number into the delay – just to make sure you don’t get a boatload of units trying to sign on at the same time. This constant sign-on ONLY happens until they make contact with the master or if they LOSE contact with the master.
The master maintains a list of slaves it should be contacting regularly. Once slaves get confirmation that they’ve sent something (i.e. some information is sent back to them from the master – they STOP sending this regular heartbeat – instead they reply immediately and once only, every time unit 0 talks to them. So unit 0 sends a package (outputs) – the units program their pins respectively, read their inputs and send the package back. If they hear nothing back for a few seconds – they go back to their constant sending without waiting to hear anything.
And now to the master. The master initialises by clearing out a table of working units…. and sits in a loop looking at that empty table while checking inputs.
If a communication comes in from any unit, the table is updated with that unit and it’s data. From now on the loop sends data to that unit and any others constantly in a loop. If that communication fails, a flag is set to say that unit is not responding (the OK flag – merely the top bit in the address field)..
As more units sign on – the table fills – and the master loop talks to each one in turn.
After each of these communications before going to the next item in the loop – the software checks for incoming data – if it gets a package it either ADDS this unit to the table or updates the table – resetting the OK flag high even if it was high already.
And that’s about it for communications.
In the slaves you may have all units active or some may merely be acting as bridges (device 2 for example) to get through a thick wall or extend range generally. An INPUT pin on these units, if pulled LOW, tells the unit not to check inputs, set outputs or process the rules – and not to communicate at all but simply to call that network function so that it may pass information back and forth. With current consumption of radio+chip of less than 20ma, one could consider making this solar powered even. The easy way however is a simply USB plug-in-the-wall adaptor – these are cheap and efficient (sub-£2 from China) and should not stress the electricity bill.
So that’s nice – a fully functional, massively expandable totally brain-dead home control system capable of reading temperature, humidity, analog inputs, digital inputs and setting digital and PWM outputs all from a simple table stored in memory in device zero – but with no brain to do ANYTHING useful.
Talk for miles?
Incidentally all of the above WORKS – I have unit 0 and unit 022 sitting in front of me – not talking to each other but talking via unit 02 which is on the other side of a very thick wall… so immediately I’m looking at open air range of maybe 80+80 metres. I could be looking at 80+80+80+80 or more. If you want to get REALLY large range – I’m prepared to guess that if you stuck 2 units into the LNB holder of a typical satellite dish and pointed them at each other you could get DRAMATICALLY more range (again think perhaps of solar power+battery here if you live in the country). Not tried it yet and you’d have to fiddle a bit but that’s what LED indicators are for!
Brain Dead Home Control
I woke up in the early hours over the weekend and I guess my history of home control (see, there’s a reason I put the history up there) is coming into play here as I have a plan.
So – device 0 has this table – ID numbers, input status, output status, analog values…
and we might have lots of these – remember the top bit (16 bit number) of that node address will be set if the device is THERE and ACTIVE – if there is anything there other than a zero you would assume that the device is either sleeping (I’ve not thoroughly thought that out yet) or just on the edge of range – so basically if the value is not zero you’d use this info.
The data being passed back and forth is even simpler…
So how do we take this basic info and give it a brain.
SD memory seemed to be the simple answer…a series of questions and answers that loop and together make the system DO something. I had a vision of a little slot in the master unit that accepted SD memory and you’d simply program something up on your PC and populate the SD. But then after a few coffees I remembered that I’ve a small library for handling 24C65 chips – a tiny 8-pin, widely available flash memory chip that is cheap and easy to use. The current plan is to put instructions in here from any PC via something like comma-delimited serial of even simply XML – the format isn’t important – it’s how to create the content and get it sent over that’s important – but that comes later.
Simple… it can’t be THAT simple can it? Well yes – read on… I hit on the idea of a simple sequence of numbers to control the thing – based on 5 bytes at a time.
Bear with me – this will become obvious.
In order to actually DO something you need to have rules – ie conditions and actions.
I came up with the format you see above – rule (8 bits), device address (16 bits), a value (8 bits) and the next command (8 bits) – this is incredibly easy for a simple processor to handle.
So the rules may or may not be conditions or actions and may or may not use the device address and value.
So for example given that each unit has a couple of inputs.. some suitable conditions might be…
If input 1 on device 022 is high
If input 1 on device 022 is not high
For the sake of it I’ve given these one-bye conditions a name… IF_IN_1 and IF_NIN-1 – but you could call them any thing you like – they need the device address only – they ignore the value…
If you’re checking temperature you might use the value..
IF_TEMP_GT (i.e. if temperature reading on a device is greater than)… oh, how can you store temperature in one byte? Easy – assuming you’re only interested in a practical temperature range and only to the nearest 0.5 degrees C, it’s easy to fit that into a byte and saves messing with floating points etc.
You might expect the INSTRUCTION at the end to be “THEN” – and you’d be right most of the time but I’ve implemented AND and OR ……
AND is also implemented in the ACTIONS….. turn on output 2 on device 022 AND turn off output 1 on device 023…
After actions are done the instruction END finished off that rule nicely and a rule starting with ENDRULES finishes the table.
Here’s an example – for now I have this stuff stored in memory – adding the 24C65 comes last.
What you see above is a simple set of rules…each complete rule taking up maybe 10 bytes, talking to device 18 (022) in this case and bearing in mind we’re looking at an 8KBytes chip – you could put a LOT of rules in there and there is no reason to make such an arbitrary limit.
You can imagine needing a range of commands to cover all the inputs…oh and some general purpose flags – (use the device address as a flag address but given we’re talking Arduino we’d not be talking thousands of flags – maybe a few dozen). Perhaps a few automatically-decrementing counters… I plan all of that.
With the ability to check inputs and flags and then set outputs and flags the power of such a simple, cheap system is down to your imagination… I’ve also added time and date commands and a random function …I did think that I’d have to make device address more than 16 bits to handle time – but then you’d really not need time as such more like day of week, hour of day, month etc.. i.e. if month > October OR month < March do something with the heating… etc.…
So many things you could do but for now I have implemented this lot.
So what are the catches.. right now I could do with someone to cooperate on this – there does not seem to be any development going on with RF24NETWORK– the comms is giving me grief – my coding should allow constant communications yet every now and then at high speed, communications stops for a second or so and I have no idea why – it’s reliable – it always comes back but it is failing – and the requirement to constantly poll is getting to be a show-stopper. In the network software as it stands, using RF24NETWORK can stop if a unit acting as a relay fails – all the units after that will fail – 328-based boards can be made INCREDIBLY reliable but it would be nice to have a better networking layer if that is possible. Having a better understanding of RF24NETWORK library would be good as would figuring out how to get a public function out of it to indicate when it is relaying information (to put on a LED to help with range checking). What is REALLY needed is to get RF24NETWORK running reliably under interrupts – one guy did start it but there were concerns over the code – and try as I might I cannot contact him or see any related development on the web. Also while I envisage using something simple like a spreadsheet to create more complex rules it might be nice if someone could look at that angle with a view to a better way.
However, as you can see, I’m off to a flying start, the rule example you see above is working right now on my desk reliably aside from network reliability. If anyone has any experience in using interrupts with RF24Network I would be more than happy to hear from them.
Update May 17th 2013 – it has come to my attention that a gentleman by the name of G Copeland has a fork of the RF24 library which he claims is more reliably while retaining compatibility. In all of this time I have not been able to get the code to work reliably – the radio just does not seem to run smoothly – with caps of up to a second in transmission… So I’ve replaced the original RF24 library with this one… I’m experimenting with it right now – it worked without any issues – but I’m still not seeing completely smooth transmission. With devices 0, 02 and 022 I’m getting results back (022 can’t work without 02 being on as 0 can’t address it directly) and there are still gaps of no transmission – but I’ll keep working on this and update this blog – meanwhile if anyone has any ideas do feel free to contact me at firstname.lastname@example.org
Update June 23rd 2013 – I’ve not taken the rule system further – however this article has now been superseded by a more practical development which is currently near fruition – a slightly different route however I think you’ll agree when you see it – something that is easily put into practice – I encourage you to follow this later article on home control over the Internet… I have the RF24 Network working reliably now along with Ethernet control. Worth a read.