Friday, March 17, 2017

A basic 900mhz network (client/server)

Hardware: Adafruit Feather 32u4 Radio (RFM69HCW), Raspberry Pi 3 Model B

I've been building a wireless/wired sensor setup which I thought I should document as a pretty handy basic design for almost any basic wireless project.

Essentially this is taking some of the Adafruit Feather 32u4 900mhz (915/868mhz actually) boards and associated radios to connect to various sensors, buttons, etc. and bring all of that back home to a server that eventually processes everything.  I could have done a very similar design with one of the Moteino boards.



Basic Design

From a design perspective, I went in the direction of keeping things "simple" and "flexible" vs. cheap.  But to be honest, cheap is a very relative term when you're working on these kinds of projects.  If you're already starting with Raspberry Pi's and Arduino-style boards then sometimes you should just accept that you've gone cheap enough.  For example, I had tried some of the Banana Pi boards and such, but you quickly run into software issues, lack of support, etc. When you try to go download the OS for the board from the vendor and Chrome starts warning you that it might contain malware it is time to back away slowly (or rapidly in my case) and rethink your direction.

While some people might feel that time doesn't have value, in my case it most definitely does.  I can't cost-justify spending a month fighting with configurations to attempt to get devices to communicate when I can bring most of it online in a day or two simply by sticking to standard components.  If I find I have time later, then maybe I'll go bang my head on the wall for month to save $5/unit.  Just not today.

Basic design

I originally laid out a series of the Arduino/radio boards and programmed them to all send their data to a single receiver.  The receiver of course was just another of the same boards except programmed to listen 24/7 vs. send on events.  I then connected that unit up to a Raspberry Pi 3 model B via a USB/serial port which made it very easy to of course just read events coming from the radio.  Then reformatted/resent those radio events on to a webservice for processing.  Essentially it looked like the above diagram or you could break it out like:

Arduino -> 900mhz radio -> 900mhz radio -> Arduino -> USB/serial -> RPi -> HTTP -> Webservice

From my perspective, this is probably a very standard configuration for getting your information into a standardized method.

Could I have used some form of Arduino w/ a network connector as the receiver?  Absolutely.  I didn't primarily due to restricting my flexibility.  For example, what if my webservice tomorrow wants HTTPS?  Can the Arduino handle that?  What if I want to break up the programming and use some off-the-shelf utilities via Linux/Python to handle some of the cleanup on the radio transmissions vs. using the more restrictive Arduino C libraries?  

In my mind, this allowed me to standardize on a design that was flexible enough to pretty much handle any request someone wanted to make.  But this chunked things up enough that if I had to swap out hardware it would be a pretty standard swap without increasing complexity for the basic design.  For example, let's say you want to move this whole configuration to Europe.  Well, just switch out all of the Arduino/radio hardware to boards that support 433mhz and leave the remaining items "as-is".  Same for longer-range radios.

Could I have broken out the radio chipsets and connected those to a more general-purpose Arduino configuration?  Sure.  But then you start getting into the benefits of a complete board design for the purposes of battery life and supportability.  Again, I took the "my time has value" road and implemented what (today) feels like a reasonable compromise on price/quality.

Every design is a compromise, but this is a pretty simple method to allow you to focus on the actual problem you're solving instead of focusing on hardware.  These small Feather boards are low power enough for most things and the radio is strong enough for most things and the RPi is flexible enough for most things, etc.  Individual components might change, but overall this works fairly well as a bridge between the world of packet radio and standard TCP/IP protocols.

General Caveats

This design assumes sporadic radio transmissions from nodes vs. continuous.  

Using serial as a communications method for connecting things may seem a little backward to people.  Sure it's slow by comparison to other protocols, but it pretty much works as it has worked for decades.  So unless you're communicating with hundreds of nodes every millisecond or two, then it is plenty fast for pretty much as many nodes as you can manage.

This design assumes a single receiver

In my own deployment I'm actually using multiple receivers.  The problem is that the webservice I am connecting to in my own use case (for some reason I cannot fathom) only expects communications from a single IP address (I mean...no...I'll rant about that for the rest of this post if I don't just stop now...).  So I actually drop multiple receivers (Arduino/Pi combo on the right) out and have them all fwd the transmissions via a sockets connection (see my other article) to the "real" receiver which then transmits the data ultimately to the webservice.

Multiple Receiver Failover

If you care about reach and connectivity then you start considering designs that include multiple receivers.  In some aspects this is easy.  In fact, you could actually configure a receiver to accept packets from all transmitters (e.g. promiscuous mode).  I didn't find good documentation on that, but I also felt it might bring some risks of event duplication into my own design.  So while I could have started tagging each of my transmissions also with an incrementing ID, I went simpler and did a multi-receiver build that was designed around the clients scrolling through a list of them.  

The design wound up looking similar to the original one above.

A simple failover style design

What it all came down to was just programming each client (far left) to have a list of possible receivers and to scroll through that list and attempt to get an ACK back from them.  If it was successful then it started with that receiver going fwd, if not, then it moved on through the list until it found one or the list ran out.

It definitely would save a bit more battery on the clients if I just had enabled "promiscuous mode" on the receivers.  Considering that you're talking about doing a couple of less than 1 second attempts to communicate, I just decided that was yet again:  good enough.



No comments:

Post a Comment