Arduino Sensor Plugin - Build your own wireless sensors!

Use the following link to learn how to build your own sensors for less than $10.


I’m working on a new plugin for home built Arduino sensors that transmits data to Vera using the nRF24L01 radio chip. Initially I will only send data one-way (to Vera) but there is really nothing stopping two-way communication (or even building mesh networks of sensors like z-wave).

I would like to design it to keep the changes to a minimum in the ReceiverSketch (running on the Arduino attached to Vera) and Vera plugin if possible.

For this to work it would be nice if the sensors could present them self to the ArduinoSensorPlugin with all information needed to create them automatically in Vera (like Device/implementation descriptor files etc).

The sensors could the only has two types of messages:
Presentation Data: Always sent when they are powered up. Contains all info needed to create the device in Vera including a unique Id to identify and transmit data to sensor (pipe-id).
Sensor Data: Sent when sensor data is changed.

The VeraReceiver sketch will only relay messages coming on the radio bus to the usb-serial interface which is read by the ArduinoSensorPlugin in Vera.

So… the question is… Is it best to keep the different sensor in child devices of the ArduinoSensorPlugin… or is it better to real devices? As stated above… I would lite to keep changes to a minimum in the VeraReceiverPlugin and move all logic (specific implementation details) to the “child” plugins. This way someone can create a new Arduino sketch for a new sensor and upload the corresponding device files for it in vera.

Please help me brainstorm here. :wink:

My initial thought would be to keep all Vera-specific service/device/JSON implementation within your distributed plugin, because your radio-accessed nodes are really very far removed from those implementation details. Instead, develop a spec for communicating metadata and data between your devices and to the plugin, and have the plugin you distribute translate that spec into Vera-specific glue code as the sensors are discovered and managed. I see the value in what you are proposing – to have everything load up dynamically without ever needing plugin changes, but I think the reality is that this architecture calls for its own internal interface spec, while the plugin’s sole job is to expose those devices in the Vera-specific way.

The analogy with Z-Wave is apt – the Z-Wave nodes have their own protocol, but Vera translates it all into the single, unified Lua-UPnP interface.

watou

Hmm…
Yes, I would normally agree with you. But in practice the sensors would only hint the plugin which devicetype(s) to create (and relay data by setting variables or some some other way).

Is it even possible to have separate implementation files for child devices?
Is it possible to create non-child devices (totally disconnected from the ArduinoPlugin)?

So. The sensor could for example send data like this:

;;var1=data1;var2=data2;…\n

where
radioid = pipe adress for the radio in the sensor.
subid = the sensor could have a few sub-sensors. These are being specified by this id
var1 = variable data to be transferred from sensor.

The sensors also would need to send some discover-me message when started (of perhaps when issued from Vera plugin).

These messages could contain something like this (one for each device the sensor want to report data on):
;;device_file=D_XXXX1.xml;var1=data1;…\n

This would make it easy for the Vera plugin to create the device if sensor not already exist on vera. And start relaying data to the device when these messages arrives.

I’m thinking the approach I used in the Nest and Ecobee thermostat plugins might fit your purposes well, where every polling cycle the plugin interrogates its web service for all the devices it knows, and the plugin will add or remove child devices based on that discovery (which then triggers a Luup restart). That way, no manual discovery step is needed, as long as the Arduino device that the plugin is dialoguing with is maintaining a current set of known sensors.

So you would have an “Arduino” device object – the manager object – and all sensor device objects would be created or destroyed as they appear or disappear from the set of sensors that the Arduino is aware of. The one “I_Arduino.xml” (or whatever you call it) implementation file would contain all the glue code and service implementations to translate how the Arduino reports its devices and what they know/can do, into the Lua-UPnP format required by Vera.

As I learned writing the Nest plugin, the Vera only has a single hierarchy of parent/child devices (not multiple levels), with the thought behind it being a manager/slaves model. So any nesting of sensors within sensors or the like really doesn’t have an analogy in Vera. Complex interrelations between managed objects, like you might have in JMX or CIM, don’t exist in Vera.

I know this misses the mark on having a completely self-describing and fully dynamic way of bringing new sensors online, but I think there would be so many other obstacles to pulling this off that you might be better off writing your spec (transmitted in JSON or some other easy format), and then having the plugin just focus on the glue logic.

watou

Most of my sensors will be sleeping most of the time to save battery (and I will turn off the radio). So I cannot contact them (poll).
Isn’t it better to let Vera keep the list of known devices (which will be the child devices). If a new sensor pops up it will present itself (fist message sent when started) which will create a new child device (and Luup restart).
Don’t really see the point of storing a list of devices in the receiving/inteface Arduino aswell (this will keep receiver sketch as simple as possible).

Ok… will do some tests to see how “thick” the glue must be :slight_smile:

[quote=“watou, post:4, topic:176573”]As I learned writing the Nest plugin, the Vera only has a single hierarchy of parent/child devices (not multiple levels), with the thought behind it being a manager/slaves model. So any nesting of sensors within sensors or the like really doesn’t have an analogy in Vera. Complex interrelations between managed objects, like you might have in JMX or CIM, don’t exist in Vera.
I know this misses the mark on having a completely self-describing and fully dynamic way of bringing new sensors online, but I think there would be so many other obstacles to pulling this off that you might be better off writing your spec (transmitted in JSON or some other easy format), and then having the plugin just focus on the glue logic.[/quote]

Ok, so a flat structure below receiver plugin then… Will use the altid to keep track of sub-child devices.

Thanks for your help and feedback.

Anyone else is also free to join in the discsussion.


Code says more that 1000 words. This is an example sketch for a Temperature Sensor

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <RF24_config.h>
#include <Wire.h>  // Comes with Arduino IDE
#include <DallasTemperature.h>
#include <OneWire.h>
#include <stdio.h>


/* Update radio id to something unique in your sensor network */
#define RADIO_ID 0xABCDABCD00LL
#define ONE_WIRE_BUS 2

/* This must correspond to the VeraReceivers radio id */
#define RECEIVER_ID 0xABCDABCD71LL

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
RF24 radio(9,10);
const uint64_t pipe = RECEIVER_ID;
const int max_payload_size = 512;

char payload[max_payload_size+1]; // +1 to allow room for a terminating NULL char
char floatBuffer[20]; 


void setup()  
{
  
  Serial.begin(9600);  // Used to type in characters

  sensors.begin();

  // Start up the sensor library
  radio.begin();
  radio.enableDynamicPayloads();
  radio.setRetries(15,15);
  radio.openWritingPipe(pipe);
  radio.printDetails();  
  sendPresentationData(RADIO_ID, 1, "urn:schemas-micasaverde-com:device:TemperatureSensor:1", "D_TemperatureSensor1.xml");
}




void loop()  
{  
  sensors.requestTemperatures(); // Fetch temperature from Dallas
  float temperature = sensors.getTempCByIndex(0);
  sendData(RADIO_ID, 1, "CurrentTemperature", dtostrf(temperature,2,1,floatBuffer));
  delay(10000);
}


/*
  This following functions should probably be moved to a library shared among sensors
*/
void sendData(uint64_t rId, int childId, char *variable, char *value) {
  uint32_t rIdHi = rId >> 32;
  uint32_t rIdLo = rId;  
  sprintf(payload, "%lu%lu;%d;%s=%s\n\0",rIdHi, rIdLo, childId, variable, value);
  Serial.print(payload);
  bool ok = radio.write( payload, strlen(payload));
  if (ok)
    Serial.print("send ok\n\r");
  else
    Serial.print("send failed\n\r");
}

void sendPresentationData(uint64_t rId, int childId, char *deviceType, char *deviceFile) {
  uint32_t rIdHi = rId >> 32;
  uint32_t rIdLo = rId;  
  sprintf(payload, "%lu%lu;%d;device_type=%s;device_file=%s\n\0",rIdHi, rIdLo, childId, deviceType, deviceFile);
  Serial.print(payload);
  bool ok = radio.write( payload, strlen(payload));
  if (ok)
    Serial.print("send ok\n\r");
  else
    Serial.print("send failed\n\r");
}

And this is the basic VeraReceiver sketch

/*
  Copyright (C) 2013 Henrik Ekblad <henrik.ekblad@gmail.com>
   
  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  version 2 as published by the Free Software Foundation.
   
  DESCRIPTION
  The VeraReciever is quite dumb. Only sends out the data received from sensors
  on the serial bus (which will be picket upp by Vera and processed).
  So the logic is placed in Vera plugn and the sensors.

  MESSAGE FORMAT
  The mesages sent by sensors has the following format. The data is a regualar ascii string (no binary data).
  End message with newline character "\n". 
  
  RadioId;Subid;Var1=Data1;Var2=Data2;...\n

  Id = Unique if of sensor (uint64_t) - Same as pipe if sensor is awake and listening for commands
  Subid = If several senosrs ir reporting information from this device. This id is unque per sensor.
  Var1 = Data1, Var2 = Data2, ... Sensor data. Can be different for each type of sensor. Must be in sync with Vera plugin.  

  Maximum message length of is currently 512 bytes.
*/


#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <RF24_config.h>
#include <Wire.h>  // Comes with Arduino IDE


#define RECEIVER_ID 0xABCDABCD71LL
#define BAUD_RATE 38400

RF24 radio(9,10);
const uint64_t pipe = RECEIVER_ID;
const int max_payload_size = 512;
char payload[max_payload_size+1]; // +1 to allow room for a terminating NULL char


void setup()  
{

  Serial.begin(BAUD_RATE);  // Baudrate to vera
  
  radio.begin();
  radio.enableDynamicPayloads();
  radio.setRetries(15,15);
  radio.openReadingPipe(1,pipe);
  radio.startListening();  
  Serial.print("0;0;OK=Arduino receiver startup complete!\n"); 
}



void loop()  
{  
    if ( radio.available() )
    {
      // Dump the payloads until we've gotten everything
      uint8_t len;
      bool done = false;
      while (!done)
      {
        // Fetch the payload, and see if this was the last one.
	len = radio.getDynamicPayloadSize();
        if (len<max_payload_size) {
    	  done = radio.read( payload, len );
  	  // Put a zero at the end to terminate string
	  payload[len] = 0;
  	  // Spew it
          Serial.print(payload); 
        } else {
          Serial.print("0;0;ERROR=Receive error. Too large payload\n"); 
          done=true;
        }
      }
    }
}

Released first version now.

Heavy beta warning!

http://code.mios.com/trac/mios_arduino-sensor/

For the physical connection between the Vera and the Arduino, you’re just using the USB cable that communicates a serial stream, correct? Does it matter which Arduino model you’re using? Does it work with the Arduino UNO? I seem to recall that some Arduino models had an FTDI chip while others did not. I was curious what would work with the Vera 3.

Hi hifs,

You’re right. As stated on the wiki you should only use Arduino Nano for the physically connected Arduino. Uno uses ACM (or something) chipset…

I have been working on a similar idea for a while now. I decided to go with Teensy, an Arduino compatible device and XBees. I have a Raspberry Pi as a Ethernet to XBee gateway. This allows my Vera Lite to do simple communicate with my Teensys via TCP/IP and let the Raspberry handle the hard stuff.

My first device is an LED strip to light up my stairway. The Teensy which is at the bottom of the stairs, has a motion detector and ambient light sensor and controls the LED brightness via PWM and a mosfet to handle the power for the LEDS. At the top of the stairs I have a Z-Wave motion detector.

The Raspberry and Vera work together to handle lighting based on motion and time of day.

In the works is a soil moisture and temperature sensor for my garden.

Anyway, my point is I am letting the Raspberry handle of a lot of the work using PERL as my programming language, which is just easier for me, as apposed to LUA on the Vera Lite.

-Chris

@ChrisK
Cool.

My idea was to create the cheapest possible wireless sensors and minimize the Vera plugin development. You could possibly reuse the arduino library I developed on your Teensy sensor if you use the same transceiver.

hi, is it possible to send data to sensor from vera OR to request data from vera to sensor?
Cool project )

That bit is not quite ready yet… but sure it is possible. I will create a relay sketch when the stuff hardware arrives. It will accept commands from vera side (on/off) and ack that the command has reached the relay.

Note that the sensors that receives data probably cannot be battery driven as they will consume too much power when radio is always on.

Could the Nano attached to the Vera use a store-and-forward approach for packets destined for currently sleeping sensor nodes?

@watou
Yes that would probably preferable. I don’t think the Vera can have this logic in the plugin part. I’m a bit worried about having too large buffers with unsent data hanging around in the “attached nano” (hereafter called ArduinoGateway) though.

Maybe the ArduinoGateway could timeout messages after 2-3 minutes back to vera plugin.

And when a sleeping node wakes up it could probably poll the ArduinoGateway for new commands.

[quote=“hek, post:15, topic:176573”]@watou
Yes that would probably preferable. I don’t think the Vera can have this logic in the plugin part. I’m a bit worried about having too large buffers with unsent data hanging around in the “attached nano” (hereafter called ArduinoGateway) though.

Maybe the ArduinoGateway could timeout messages after 2-3 minutes back to vera plugin.

And when a sleeping node wakes up it could probably poll the ArduinoGateway for new commands.[/quote]

You could use a fixed buffer of outstanding commands in the ArduinoGateway, and when it’s full the next command pushed on the queue would discard the oldest one pushed and NAK the sender of that command. Otherwise it would ACK the sender once it’s been delivered to the sensor node. Since there would be no backing storage of this command queue, command senders should not expect to receive ACKs or NAKs in case of reboots, power outages, etc.

Yup. will probably implement it like that. I already have a “queue” for incoming messages partly received (if they consist of more than one 32 byte fragment).

sound interesting.
Why don’t u use sleep mode in arduino with INT signal from NRF24 to wake-up for sensor?

@mitekdg
So true. Much better.

Is it possible to get interrupts on more than one digital pin? Maybe an attached sensor also needs to trigger?

Now i’m working on my project “arduino ethernet-NRF24 gateway”.

Low-Power Wireless Sensor Node | maniacbug - here the info about power cons. and “battery driven feat.” (INT and sleep mode)
RF24Network for Wireless Sensor Networking | maniacbug - about NRF24 network