HAH and the Arduino

arduino316.jpg The Arduino board is a low cost, off the shelf, micro-controller that is readily available. These make great external devices that can be controlled and connected to the HAH system.

Arduino boards come in three interfacing flavours: Board types

  • Arduino Serial
  • Arduino USB
  • Arduino Ethernet (with a shield)

All can be interfaced with the HAH unit. Depending on your existing knowledge of things like FTP/the vi editor/unix style operating systems/the Lua scripting language, it might take you a little time to read up on these topics. However, the examples and support library code have been designed to help you along.

Once a USB Arduino is connected it will be presented as a /dev/ttyUSBx or /dev/ttyACMx device to the HAH system. At this point it can be interfaced to the xAP bus via the xap serial adapter software.

/var/log/messages
usbserial.c: FTDI 8U232AM converter detected
usbserial.c: FTDI 8U232AM converter now attached to ttyUSB0 (or usb/tts/0 for devfs)
ttyACM0: USB ACM device

Programming the Arduino from the HAH

Arduino: Duemilanove

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

Arduino: UNO

# stty -F /dev/ttyACM0 hupcl
#  avrdude -v -c arduino -p m328p -P /dev/ttyACM0 -b 115200 -Uflash:w:FILE.hex

All the examples are managed in the projects Google code repository. I recommend installing a SVN client, then you can checkout the samples like this.

  • Install Tortoise SVN client.
  • Create a work folder for example. “C:\Users\brett\Documents\Arduino”
  • Inside this “Arduino” directory, Right click to get the “SVN Checkout…” context menu option.
  • Complete the dialogue as follows.

If you're not a project maintainer you should use HTTP for a read-only copy.

http://livebox-hah.googlecode.com/svn/trunk/userapps/arduino

See a list of files checked out onto your computer:

Don't move any of the libraries from their checkout location. YES, YES every other Arduino site talks about shifting them into the Libraries folder of the IDE, but seriously you don't need to anymore! In fact if you don't they correctly appears as “Contributed Library” under the “import library…” IDE menu option. Also it makes upgrading your IDE so much easier if you don't pollute it.

Tested with v18 of the IDE

Ethernet xAP Arduino Library

To aid writing xAP compliant applications for the Arduino, an xAP processing library has been written. This allows Arduino to be connected to your LAN and will transmit xAP messages without any HAH involvement. See http://wiki.london.hackspace.org.uk/view/Project:Ethernet_Arduino

These are the classes exposed by the library. Grab the source and browse to see the inner working.

This is a base class that provide the ability to parse an xAP message and extract information from it. It also provides a helper function to assist with performing activities on a regular basis.

class XapClass
{
class XapClass
{
 public:
  XapClass(void);
  XapClass(char *source, char *uid);
  char *getValue(char *section, char *key);    // Get the contents of a parsed xAP message by section/key.
  int getState(char *section, char *key);   // Get a BSC state value
  int isValue(char *section, char *key, char *value);   // does section/key have value ?
  int getType(void);               // The (TYPE) of the xAP message
  int parseMsg(byte *buf, int size);  // Parse a raw XAP message; exposed for Ethernet shield users.
  int after(long);                    // Useful for managing TIMED events such as heartbeats and info
  void dumpParsedMsg();
  void heartbeat(void);
  virtual void sendHeartbeat() {};
 
  const char *SOURCE;
  const char *UID;
}

after

The after function allows you to easily setup recurring events. Example of how this would be used to do something every 2 mins.

const int infoBeat = 120000; // 120 seconds (120,000ms)
long infoTimeout = smillis()+infoBeat;
XapClass xap();
 
…
if(xap.after(infoTimeout)) {do something.
  infoTimeout = smillis()+infoBeat;  // Reset the timer
}

ethernet_shield_2.jpg

This class makes it easy to interface an arduino with the nuelectronics ethershield and manage Transmission and Receiving xAP messages. The nuelectronics ethershield uses the ENC28J60 chip, however I found their library overly complicated, to that end an Ethernet library has also been supplied. This is a modified version of ethercard from the jeenode project extended to handle UDP broadcast and UDP packets > 220 bytes.

class XapEther : public XapClass {
 public:
  XapEther();
  XapEther(byte *mac, byte *ip);
  XapEther(char *source, char *uid, byte *mac, byte *ip);
 
  void setBuffer(byte *buf, word len);
  void process(word len, void (*callback)());
  void sendHeartbeat(void);

Examples

These code samples are checked into the SVN code repository:

Using the BSC library and the xap serial daemon we can construct a BSC compliant endpoint that will control a LED attached to an Arduino.

Step 1. Compile this sketch and flash it to your Arduino This SKETCH accepts the commands “LED ON” and “LED OFF” to control a LED connected to PIN 13 of your Arduino

#define LEDPIN 13
 
const int inBufferLen = 255;
uint8_t inPtr = 0;
char inBuffer[inBufferLen+1];
 
void doCommand() {
  if(strcmp("led on", inBuffer) == 0) {
    digitalWrite(LEDPIN, HIGH);
  } 
  else if(strcmp("led off", inBuffer) == 0) {
    digitalWrite(LEDPIN, LOW);
  }
}
 
void readSerial() {
  int inByte = Serial.read();
  if(inByte == '\r') { // CR to LF
    inByte = '\n';
  }
  switch(inByte) {
  case '\n':
    if(inPtr > 0) { 
      doCommand(); 
    }
    inPtr = 0;
    break;
  default:
    if(inPtr < inBufferLen) {
      inBuffer[inPtr] = inByte;
      inPtr++;
      inBuffer[inPtr] = '\0';
    }
  }
}
 
void setup() 
{ 
  Serial.begin(9600); 
} 
 
void loop()
{
  while(Serial.available()) {
    readSerial();
  }
}

Step 2. Plug your Arduino into your HAH. Identify the correct USB serial port and adjust the sample below.

# dmesg
usbserial.c: FTDI 8U232AM converter detected
usbserial.c: FTDI 8U232AM converter now attached to ttyUSB0 (or usb/tts/0 for devfs)

In this case we are using /dev/ttyUSB0

Step 3. Now we will create a Lua plugboard applet and a BSC endpoint so this LED can be easily controlled. This will take care of converting the xAPBSC.cmd message into a xap-serial message for us, along with providing xAPBSC.query capabilities, and regular xAPBSC.info reporting about the status of our LED.

Like all Plugboard scripts, this must be placed in the /etc/plugboard directory on the HAH. The vi editor is included in the HAH Busybox operating system build, so you can create/edit the script directly from a Telnet session onto the HAH (default username/password is root/admin). Remember that your script filename must end in 'Applet.lua' (case sensitive). Also check that you have enabled the plugboard scripting engine and the serial schema services via the HAH web UI (Automation/Assists tab).

--[[
    Arduino to xAP Endpoint mapping
--]]
module(...,package.seeall)
require("xap")
require("xap.bsc")
 
info={
   version="1.0", description="Arduino control"
}
port="/dev/ttyUSB0"
 
function cmd(endpoint)
   xap.sendShort(string.format([[
xap-header
{
class=Serial.Comms
target=dbzoo.livebox.serial
}
Serial.Send
{
port=%s
data=led %s\n
}]], port, endpoint.state))
end
 
function init()
   local serialSetup = [[
xap-header
{
class=Serial.Comms
target=dbzoo.livebox.serial
}
Serial.Setup
{
      port=%s
      baud=9600
      stop=1
      databits=8
      parity=none
      flow=none
}]]
   xap.sendShort(string.format(serialSetup, port))
 
   bsc.Endpoint{ source="dbzoo.livebox.arduino:led",
                 direction=bsc.OUTPUT,
                 type=bsc.BINARY,
                 cmdCB=cmd
              }
end

Step 4. Restart the plugboard daemon to make sure the new Applet is loaded. One easy way to do this is to reboot the HAH.

Step 5. Send a BSC control message to our endpoint and turn the LED on/off. An easy way to send BSC control messages and to view the new LED endpoint itself is to use xFx Viewer.

With xFx Viewer you can't send a new message directly. You need to open any arbitrary message, edit it and then press 'send'.

xap-header
{
v=12
hop=1
uid=FF00D800
class=xAPBSC.cmd
target=dbzoo.livebox.arduino:led
source=dbzoo.acme.test
}
output.state.1
{
id=*
state=on
}

Arduino links