Integration with JeeNodes

JeeNodes are RF enabled AVR328P boards using the same development tools as the Arduino. We love the JeeLabs weblog, jcw inspires us.

As JeeNodes are RF based, they make a great way to RF enable a variety of functions. Importantly, the JeeNodes support reliable bi-directional RF comms, so we can both send commands to the JeeNode and receive information from it.

Block diagram of how the JeeNodes are integrated into the HAH livebox

You will need a minimum of TWO nodes, one is tethered to the LIVEBOX via a USB attach cable and acts as the RF/Serial gateway (HAHcentral). The others will be scattered about your environment acting as remote nodes.

From a code architectural point of view the following layers constitute the JeeNode pluggable system. This framework allows a user to write and build their own nodes minimising the effort required. For example the IR node to code, build and assemble from start to finish was 1hr worth of work.

Each of these layers is written in Lua and the source can be found on your HAH in /usr/share/lua/5.1/xap.

A brief summary of what each layer is responsible for: The xAP layer handles encoding/decoding xAP, fetching values from a packet, creation of timers and multiplexing Filter callbacks. BSC (Basic Status and Control) is a layer that manages endpoints conforming to this specification. JeeNode layer provides support infrastructure for the creation of xAP endpoints, RF bitstream packet decoding, TTL (time-to-live) management and a higher level of abstraction over the BSC framework simplifying the Node implementations. The Node classes implement logic to create endpoints and handle the incoming xAP serial packet from the HAH tethered unit and incoming xAP directed communication for a JeeNode that can receive data.

Each JeeNode class can be plugged in multiple times to the applet, each instance of the class will correspond with a piece of physical hardware, a JeeNode, that has a unique ID. For example you might have multiple room nodes around your house all reporting temperature and light readings, so you would plug in multiple RoomNode classes each with a unique ID and endpoint designator.

In a nutshell

  • Install RF12Demo on one JeeNode. Attach to the HAH via its USB serial cable. This is the BASE UNIT
  • Each JeeNode must have a unique Node ID this is set in the JeeNode EEPROM using RF12Demo
  • Download RoomNode2 or OutputNode from the HAH SVN - flash remote JeeNodes
  • Copy the plugboard sample jeenodeApplet.lua into /etc/plugboard directory and configure
  • Enable xap_serial on the HAH
  • Restart the HAH plugboard

Up to 32 NODES can be present in a single JeeNode group. You may have a mixture of node types.

The Hardware

There is only one place that you can get a JeeNode - from jeelabs.com (or for US based folks).

We have developed a clone variant (lower quality PCB but with some features to ease Airwick integration), and that is available from our Shop

The completed kit without port pin female connectors.

HAHnode

The port pinouts are as follows:

  • P - Battery +Ve
  • D - Digital I/O
  • G - Gnd
  • + - Regulated voltage (3.3V)
  • A - Analogue input
  • I - interrupt line

The HAHnode design is a variant of the JeeNode design. The BASE Kit contains…

  • HAHnode PCB
  • ATMega328P chip (pre-programmed)
  • RFM12B - RF Transceiver module
  • Voltage regulator IC
  • 16MHz ceramic resonator
  • Miniature Electrolytic capacitor
  • 4off Miniature Ceramic capacitors
  • One resistor
  • IC Socket for the ATMega328P
  • Antenna wire for the 868MHz RFM12B RF Transceiver (once fitted, trim to 82mm in length)
  • 1×6 Male pin header (for our attach/programming cable)

Firmware images are available from : http://code.google.com/p/livebox-hah/downloads/list

The first thing to do is to connect the PCB to your HAH. To do this you will need the attach/program cable

This image shows the correct way to fit the attach/programming cable. The green wire on the cable is nearest to capacitor 'C1'. progcable.jpg

Next, check that you don't have any processes running that might use a port on the HAH which we will use for setting up the Node PCB. From the HAH UI, on the 'Automation/Assists' tab, ensure that every service is set to 'disabled'. Then reboot the HAH.

The popular AVR device programmer, AVRDUDE, is built-in to the HAH firmware since build 284. We will use AVRDUDE to program the AVR chips whilst they are fitted to the HAHnode PCB that is connected via USB to the HAH.

The hex file images for the code that we want to flash onto the AVR chip are held online in the project code repository at googlecode. We use 'curl' to retrieve the hex file images that will be flashed onto the AVR Mega328P-PU device on the HAHnode PCB.

# cd /root
# curl -o roomnode2.hex http://livebox-hah.googlecode.com/files/roomNode2.cpp.hex
# curl -o HAHcentral.hex http://livebox-hah.googlecode.com/files/HAHCentral.hex
# curl -o HAHcentral_nocfg.hex http://livebox-hah.googlecode.com/files/HAHCentral_nocfg.cpp.hex

If you purchased a HAHnode kit from the Shop, the AVR chip is pre-flashed with RFdemo, so you can proceed straight to the configuration of your chips

To flash your HAHnodes run following commands:

stty -F /dev/ttyUSB0 hupcl
avrdude -v -c arduino -p m328p -P /dev/ttyUSB0 -b 57600 -Uflash:w:HAHcentral.hex

Once you have flashed this configuration sketch you can configure your Node.

Each Node must be configured to be in the same GROUP and running the same frequency, and each must have a unique ID. The HAHCENTRAL and RFDEMO sketches allow you to adjust these settings (but the roomNode sketch and HAHcentral_nocfg sketch do not). The means that preparing a Node is a two step process. You first load a sketch that supports configuration. Then, once configured, you load the HAHcentral_nocfg or roomNode sketch for normal operational use.

To configure the AVR, use microcom to connect to the HAHnode. The connection speed is 57600 baud.

microcom -s 57600 /dev/ttyUSB0

Hit the return key a couple of times. You should see the following menu of commands.

    Available commands:
      <nn> i     - set node ID (standard node ids are 1..26)
      <n> b      - set MHz band (4 = 433, 8 = 868, 9 = 915)
      <nnn> g    - set network group (RFM12 only allows 212, 0 = any)
      ...,<nn> a - send data packet to node <nn>, with ack
      ...,<nn> s - send data packet to node <nn>, no ack
      <n> q      - set quiet mode (1 = don't report bad packets)

For the baseNode you would want the following configuration. node Id = 1. For the RFM12Bs that we supply, the frequency = 868MHz. The network group must be set = 212.

[HAHCentral.1] D i1 g212 @ 868 MHz 

Once configured, be sure to reflash the baseNode with the code that disallows accidental re-configuration.

stty -F /dev/ttyUSB0 hupcl
avrdude -v -c arduino -p m328p -P /dev/ttyUSB0 -b 57600 -Uflash:w:HAHcentral_nocfg.cpp.hex

For a roomNode - first flash the HAHcentral sketch. Just so you can configure the settings - then assign it a unique ID. In this case it's NODE 2, of the same group and frequency as we assigned above.

[HAHCentral.1] D i2 g212 @ 868 MHz 

Then, with the configuration done, flash the final roomNode firmware.

stty -F /dev/ttyUSB0 hupcl
avrdude -v -c arduino -p m328p -P /dev/ttyUSB0 -b 57600 -Uflash:w:roomnode2.hex

Unlike the baseNode, the roomNodes do not transmit anything on the serial port. So there is no point in soldering up that 6way molex connector & plugging a roomNode into the HAH (this is why this part is not supplied with a roomNode kit). They only transmit via RF. Amongst other things, this saves precious battery power. Just use your baseNode hardware to program all the AVR chips (and, to avoid confusion, label the chips as you go!).

For anybody who is flashing their own Mega328P parts 'from scratch', here are the required fusebit settings (if you purchase from the HAH shop, these are already setup on the devices that are on sale).

and the ATMEGA328P EEPROM content should look something like this (depending on your exact configuration) …

Configuring the jeenodeApplet.lua

There is only one file that you need to modify to expose a HAHnode as a xAP BSC endpoint. This file is held on the HAH in the plugboard directory /etc/plugboard. As it's very small its entire source code has been reproduced here

Use the sample already supplied in your HAH as a starting point

# cp /etc_ro_fs/plugboard/samples/jeenodeApplet.lua /etc/plugboard

--[[
    JeeNode to xAP Endpoint mapping
--]]
 
--_DEBUG=1
module(...,package.seeall)
 
monitor = require("xap.jeenode").monitor
RoomNode = require("xap.roomnode").RoomNode
OutputNode = require("xap.outputnode").OutputNode
 
info={
   version="2.0", description="HAHNode"
}
 
local jeemon={
      port="/dev/ttyUSB0",
      baud=57600,
      stop=1,
      databits=8,
      parity="none",
      flow="none"
}
 
-- Keyed by NODE ID
local nodes = {
   [3] = RoomNode{instance = "jeenode:3", endpoints={temp=1,lobat=1}, ttl=900},
   [4] = OutputNode{instance = "jeenode:bedroom",endpoints={p1="light",p2="heater",p3="amp",p4=0}},
}
 
function init()
   monitor(jeemon, nodes)
end

There are two configuration sections that you'll need to modify: jeemon and nodes.

jeemon - describes how we are going to communicate with the JeeNode that is attached to the HAH via its USB port, in the configuration section the only value that you'll need to adjust will be the port. Depending on what other USB serial devices you have attached to your HAH this port will move around. Use “dmesg” to see where your JeeNode is located, and verify this using “microcom -s 57600 /dev/ttyUSBxx” (replacing 'xx' with the number of your USB port).

These settings are used internally to send a message to xap-serial to initialise the port.

By default the target used for xap-serial will be dbzoo.livebox.serial if however you are running an INSTANCE livebox and you want to use the xap-serial message from that box then you need to additionally supply a target=

In this example we have assumed you have set the hostname to livebox2.

local jeemon={
      target="dbzoo.livebox2.serial",
      port="/dev/ttyUSB0",
      baud=57600,
      stop=1,
      databits=8,
      parity="none",
      flow="none"
}

nodes - this is where you configure the layout of your specific installation of HAHNode.

-- [ID] = NodeType 
[2] = RoomNode{instance="jeenode:attic", endpoints={temp=1}}

Each JeeNode must have a UNIQUE ID this is configured using RF12Demo like so. This would set the JeeNode as NODE ID 2.

2i

Depending on the SKETCH you have loaded on the JeeNode you must align this with the Node type so that it correctly interprets the data received. Failure to do this will results in STRANGE readings.

Each Node has a different set of initialisation parameters but each will start with its TARGET name.

You can choose whatever naming scheme you want but it must be of the form

vendor.device.instance:location

Enable xap-serial

Don't forget to enable the xap-serial service and the plugboard engine, of course.

If you connect your baseNode to the HAH via a USB Hub, it is advisable to have a separate power supply for the Hub. We have had a reported instance of intermittent operation with an unpowered hub.

Example configuration

If a Node defines multiple endpoints these will be appended to this base SOURCE description. For example if the roomNode was configured like this

[ID] = RoomNode{instance="jeenode:attic", endpoints={lobat=1,temp=1,light=1}}

We would get the endpoints

dbzoo.livebox.jeenode:attic.lobat
dbzoo.livebox.jeenode:attic.temp
dbzoo.livebox.jeenode:attic.light

See nanode_gateway for advanced integration concepts.

A node may have multiple endpoints and not all of them might be needed. For example, the roomnode has: temperature, movement, lo-battery, humidity and light endpoints. Depending upon the hardware configuration you might not have a humidity or movement sensor attached.

How do we specify that we only want: temp, lobat, light? Like this:

[ID] = RoomNode
    { instance= "jeenode:bedroom1",
      endpoints = {temp=1,lobat=1,light=1,humi=0,moved=0} }
    }

Each key=value pair in the endpoint definition table indicates whether this endpoint is needed or not. 1 if it's needed, 0 if it's not. If we don't specify the endpoint in the configuration it's equivalent to setting it to 0.

This code is functional equivalent to that above

[ID] = RoomNode
    { instance = "jeenode:bedroom1",
      endpoints = {temp=1,lobat=1,light=1} }
    }

This would create the following

  • dbzoo.livebox.jeenode:bedroom1.temp
  • dbzoo.livebox.jeenode:bedroom1.lobat
  • dbzoo.livebox.jeenode:bedroom1.light

This syntax also allows us to rename the endpoints. Any other value but 1 is taken to be a new NAME for the endpoint.

[ID] = RoomNode
    { instance = "jeenode:bedroom1",
      endpoints = {temp="temperature",lobat=1,light=1} }
    }

This would create the following

  • dbzoo.livebox.jeenode:bedroom1.temperature
  • dbzoo.livebox.jeenode:bedroom1.lobat
  • dbzoo.livebox.jeenode:bedroom1.light

As we use RF to transmit signals it's possible that we may lose connectivity due to dead batteries or just bad placing. What we need is the ability to time-out an endpoint's value if data is not seen. This is accomplished by using the ttl (time-to-live) attribute and specifying a number of seconds that can elapse without seeing the JeeNode report in, before we consider it non-responsive.

When a node expires its state, and its values, get set to '?' this means that the node has not reported in within its TTL setting. A expiring node will generate a xAPBSC.event for EACH endpoint it has then every 2 minutes you'll get a xAPBSC.info until the node comes back online. In the example below we have 3 endpoints (temp, lobat, and light) so we would expect an expiry event for each.

You must set a value for the ttl that is HIGHER than the reporting periodicity of your node otherwise your data will constantly expire.

For example: Here we specify that 5 mins can elapse.

[ID] = RoomNode
    { instance="jeenode:bedroom1",
      endpoints = {temp="temperature",lobat=1,light=1},
      ttl=300 }
    }

The mininum TTL is defined by how often the SKETCH that you uploaded is configured to report.

roomNode2.pde

#define MEASURE_PERIOD  300 // how often to measure, in tenths of seconds
#define RETRY_PERIOD    10  // how soon to retry if ACK didn't come in
#define RETRY_LIMIT     5   // maximum number of times to retry
#define ACK_TIME        10  // number of milliseconds to wait for an ack
#define REPORT_EVERY    5   // report every N measurement cycles
#define SMOOTH          3   // smoothing factor used for running averages

This set of #defines configure this stuff. Measure every 30 seconds, report every 5 cycles = 150 seconds (this is your base minimum TTL).

So 120 is too small… 180 is fine - Personally I would make the TTL at least 2x the reporting cycle, this way you can miss ONE event and it won't time out as the 2nd one will reset things. So I would use a TTL of 300 seconds.

Nodule I/O pins

This shows the pin/port allocation for the HANnode/jeenode configurations above

RFM12B at the bottom and FTDI connector at the top

Nodule ideas

  1. Remote LCD head and a PCB with the IDC connector that allows the existing LCD from the HAH to be removed and placed into this remote head unit. All messages to the INTERNAL LCD could now be displayed remotely!
    Larger LCD panels for heads up displays.
  2. Using the I2C expansion board to allow multiple inputs/outputs.
  3. Controlling a Stepper motor linked to a remote rotator this would make an interesting demo, not sure of the practical purpose of it.
  4. GAS monitoring by counting the pulses. Each pulse is 1cu of gas used. Reporting consumption every 2min and then resetting the internal counter.
  5. Extended range nodes via use of external antenna. See the pics of the setup that HAH user Dean has put in place.