Thursday, October 31, 2013

Beaglebone Black Image Setup for 'The App'

Below is the procedure that I follow to create an Operating System mage on which my app runs.   This assumes we are starting with a distribution image that has been flashed to the internal drive of the BBB, dd'ed off that image having booted from the external SD drive, and then having used the img copy to create a new bootable SD card.  I know, there is probably an easier way to accomplish creating a new bootable image from a distribution file!

In any case then we do the following:



First make sure that the system date and time is accurate: 
ntpdate -b -s -u pool.ntp.org



Then update the package indexes for both the OS and for NPM:
opkg update
npm update 



Now install all the OS level stuff that we will be needing:
opkg install python-compiler
opkg install python-misc
opkg install python-multiprocessing
opkg install xdotool
opkg install gettext



The version of git on the BBB needs to be updated so download the tarball with the code and then do the following:
tar -xvf git-1.8.?.tar.gz
cd git-1.8.?
./configure --without-python
make
make install



There is a problem with npm such that it will incorrectly fail thinking that it does not have the right version of Python installed.   Fix this via the below edits:
nano /usr/lib/node_modules/npm/node_modules/node-gyp/lib/configure.js 
Change:
if (semver.gte(version, '2.5.0') && semver.lt(version, '3.0.0')) {
getNodeDir()
                    } else {
               failPythonVersion(version)
                    } 
To:
getNodeDir()



Now all the npm packages that we need can be installed:  
npm install -g node-gyp
npm install -g i2c
npm install -g socket.io
npm install -g descriptive-statistics
npm install -g exec-sync
npm install -g zipstream  
npm install -g line-by-line
npm install -g serialport2



Following sections, for RTC, are obsoleted by getting the date and time via the Arduino.  At this point, assuming we are wired for our I2C devices, we can set up our Real Time Clock.    This is, of course, assuming that when you run the first of the below commands you see something at address 0x68!   If there is, test it by doing the rest of the commands (get current network time, create the RTC device, write the time to the RTC, pull it off the RTC):
i2cdetect -y -r 1

ntpdate -b -s -u pool.ntp.org
echo ds3231 0x68 >/sys/bus/i2c/devices/i2c-1/new_device
hwclock -f -w /dev/rtc  
hwclock -f -s /dev/rtc


If all is well above (note that you need to check the device [/dev/rtc?] that was created to ensure you have the right name), create the following file “rtc” in “/etc/init.d”:
#! /bin/sh
# /etc/init.d/rtc

### BEGIN INIT INFO
# Provides:          Time sync
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Updates time from rtc
### END INIT INFO

# If you want a command to always run, put it here

# Carry out specific functions when asked to by the system
case "$1" in
  start)
    echo "Starting time sync"
    echo ds3231 0x68 >/sys/bus/i2c/devices/i2c-1/new_device
    hwclock -f /dev/rtc -s
    ;;
  *)
    echo "Usage: /etc/init.d/rtc {start}"
    exit 1
    ;;
esac

exit 0



Make the above created file executable:
chmod +x rtc



And have it run automatically:
update-rc.d rtc defaults




Now make sure the board time is set, then load it to the RTC:

ntpdate -b -s -u pool.ntp.org
hwclock -f -w /dev/rtc  


Now we can create our source directories for the application.   First create a directory named "AppNameHere", cd into it, and execute the following command:
git clone https://github.com/ThamesWill/AppNameHere.git dev

Fix for possible authentication issues:
http://derekmolloy.ie/fixing-git-and-curl-certificates-problem-on-beaglebone-blac/

Once this has completed (note that you will need an id on github) you should execute the following script from the download:
dev/install



The above should have created all the other directories and startup files that will be needed.   At this point you should be able to execute the command line configuration tool:
./config



If everything is working you will see a list of default parameters.
One last change is to point the cloud9 environment at the source code we just downloaded. Do this by editting the following file replacing the "/etc/lib/cloud9" entries with the path to the dev directory created above.
nano /lib/systemd/system/cloud9.service 



You will now need to either reboot or tell systemctl about your changes and then restart cloud9:
systemctl --system daemon-reload
systemctl restart cloud9
nano /lib/systemd/system/cloud9.service 



Finally, make sure that you have updated the hosts file to match your server name for The App configuration

DONE!

Wednesday, October 30, 2013

Implementing an I2c Workaround

The i2c library that I am using (kelly/node-i2c) works great...but...after some period of observations it causes node.js to fail with a segmentation fault.   I am not sure this is a problem with the base library or with how I am using it with the Analog Digital Converter that I am using.   I suspect that it is the latter but I don't have the technical skills to diagnose the problem.  Given the former I decided to implement a workaround as described below.

wireServer = require('child_process').fork('wireServer.js', 
   [global.config.i2cDevice, global.config.i2cAddress, global.config.i2cCommand]);
wireServerPid = wireServer.pid; 
utilities.trace(false, "test - wireServer started as PID " + wireServerPid);
Since failures generally only occurred after a period of time I decided to create a background process that could be started for the period of observation and then killed until the next period is started.  


eventEmitter.on('startObserve', function(message){
    wireServer.send({"message":"init", 
        "i2cDevice":global.config.i2cDevice,
        "i2cAddress":global.config.i2cAddress,
        "i2cCommand":global.config.i2cCommand});
    // Each message will be a voltage reading that we then pass to the below routine
    wireServer.on('message', function (message) {
        observe(message.voltageIn);
    });
});
I am using an event to start the observation period by sending a message to the wireServer process started above.   The message tells the server where to look for the I2c device.  Once this is done I setup a handler for readings coming back from the server.



execSync('kill ' + wireServerPid);
utilities.trace(false, "test - Current wireServer running as PID " + wireServerPid + " killed")
Once the I2c interface is started node will no longer respond to messages sent to the background process!   This means I have no way of asking it to die gracefully.  That being missing I use a little less graceful approach and kill it at the O/S level.

eventEmitter.emit('startObserve', '');
Finally we launch the observation perio.

The background process that the above launches, and then communicates with, is shown below:


// Load the library we need to get voltage measurements using i2c
var i2c = require('i2c');       
var i2cDevice = "/dev/i2c-" + process.argv[2];
var i2cAddress = process.argv[3];
var i2cCommand = Number(process.argv[4]);
// Convert the i2c address from character to hex
i2cAddress = parseInt("0x" + i2cAddress);
var wire = new i2c(i2cAddress, {device: i2cDevice, debug: false}); 
var seq = 0;

wire.on('data', function(data) {
    observe(data.data);
});

// Look for an init message from test to start our observations
process.on('message', function (message) {    
    wire.stream(i2cCommand, 4, 3);
});

// Take a voltage reading and send it on to test
function observe(buffer) {
    var voltageIn = 0;
    voltageIn = (buffer[0] << 8) + buffer[1];
    // Did we get a negative value?  If so make it a zero.
    if (voltageIn > 2048) {
        voltageIn = 0;
    }
    else {
        voltageIn = voltageIn / 2048;
    }
    if (seq == 5000 || seq === 0) {
        console.log(datetimeStamp() + " - wireServer - active");
        seq = 1;
    }
    process.send({seq:seq++, voltageIn: voltageIn });    
}

Integrating a Joystick via I2c with a GPIO Detected Button - Software

The code used to integrate with the Joystick hardware described by the previous post is shown below.   Note that the entire working demo is avalable on GitHub.
  1. Bring in the "i2c" ibrary (Kelly / Node-I2C) used to interface with I2C devices such as our Analog Digital Converter (ADC).  I have configured the device to be on address 0x6A and I know that it is /dev/i2c-1 from using i2cdetect
  2. Bring in the "onoff" library (fivdi / onnoff) that we will use to detect the pressing of the select button on the Joystick.  Note that bonescript on the BeagleBone Black would accomplish this with an interupt but since I am doing my demo on an Raspberry Pi I pulled in the onoff library.
  3. Bring in the "events" library (node events) that I use to poll for I2c and Select Button states.
  4. React to an event requesting a read of the Y axis.  Use the I2c library to read 4 bytes in response to the command "0xB0" which is a request to read 12 bits of data from channel 2.
  5. React to an event requesting a read of the X axis.  Use the I2c library to read 4 bytes in response to the command "0xD0" which is a request to read 12 bits of data from channel 3.
  6. The observe routine translates the buffer returned from the I2c library into a usable voltage reading and stashes it in one of our two axis variables
  7. The "startObserve" event triggers a repeating event that will do our actuall polling for the Joystick state.  It launches an interval event every 25 ms that toggles between the X and Y axis getting an update for each every 50 ms.   The current state of the axis's are sent to the client every cycle.   The state of the joystick select button is also checked every iteration and if it is depressed a snapshot is sent to the client for the current X and Y axis positions.
  8. Once all the event handlers have been registered we kick things off by emitting startObserve!
(1) var i2c = require('i2c');
var address = 0x6A;
var wire = new i2c(address, {device: '/dev/i2c-1', debug: false});
(2) var Gpio = require('onoff').Gpio,
    button = new Gpio(4, 'in', 'both');
button.debounceTimeout = 1000;
(3) var events = require('events');
var eventEmitter = new events.EventEmitter();
(4) eventEmitter.on('measureY', function(message){
    wire.readBytes(0xB0, 4, function(err, res) {
        observe("Y", res);
    });
});
(5) eventEmitter.on('measureY', function(message){
    wire.readBytes(0xD0, 4, function(err, res) {
        observe("Y", res);
    });
});
(6) function observe(xy, buffer) {
    var voltageIn = (buffer[0] << 8) + buffer[1];
    if (voltageIn > 2048) {
        voltageIn = 0;
    }
    else {
        voltageIn = voltageIn / 2048 * 5 * 22.6;
    }
    if (xy == "X") {
        voltageInX = voltageIn
    }
    else {
        voltageInY = voltageIn
    }
}
(7)
eventEmitter.on('startObserve', function(message){
    var toggle = "X";
    intervalId = setInterval(function() {
        if (toggle == "X") {
            eventEmitter.emit('measureX', '');
            toggle = "Y";
        }
        else {
            eventEmitter.emit('measureY', '');
            toggle = "X";
        }
        plot();
        if (button.readSync() == 1) {
            console.log("Sent " + voltageInX + " - " + voltageInY);
            socket.emit('buttonPressed', { dp1: voltageInX, dp2: voltageInY });
            buttonPressed = false;
        }
    }, 25);
(8) eventEmitter.emit('startObserve', '');

Integrating a Joystick via I2c with a GPIO Detected Button - Hardware

The images below illustrate the wiring for a joystick that I purchased from eBay.   Here are notes corresponding to the diagram:
  1. The circuit board for the Joystick has the button wired from ground so the signal would go from high to low.   I wanted a rising signal so broke the default connection (as shown by the picture) and wired the button to the 5v supply.
  2. The output from the button is connected to a pull down resistor...
  3. ...and since the output 5v I route it through a voltage divider to make it safe for the Raspberry Pi.
  4. Each axis of the Joystick delivers a voltage that indicates the position of the controller.   These outputs are connected to the Analog Digital Convertor (ADC) using channels 2 and 3.
  5. The output from the ADC is connected to the Raspberry Pi using the SLC and SDA connections.
I will talk to the software side of the above in another post.

Friday, October 11, 2013

Using Socket.IO on Node.Js with RGaph to Animate a Report

“The App” demo uses Socket.IO for easy real-time communications between the server process running under Node.js and the client process running JavaScript in the browser as described by the example on this page.
  1. Initialization of the client and server libraries and opening of a connection on port 7300.
  2. Server sends maxSustained to the client as this is needed while the data points are being received.  The payload of this message also includes the type of graph we are preparing (best second or all of second).
  3. Client sends “ready” to the server to ack the maxSustained message.   The server has a socket.on for the ready message.
  4. On receipt of the “ready” message the server starts sending the data for the graph.  On the client the each “graph” message is received and its payload of data points added to an array.
  5. Once all the data points have been dispatched to the client the server sends a “done” message with some additional data in the payload to be used on the web page being presented.   On receipt of this message the client presents the graph.
Sample code for my demo application can be found on GitHub.

Thursday, October 10, 2013

Node.Js, Socket.IO, Physical Interface, Screen Recording

Here is a screen capture of the demo application that I have been, and will be, discussing.  It's a simple example but demonstrates a fair amount of functionality behind the scenes.
  • The "ADC Test Session" demonstrates the app reading voltage levels from an ADC via I2c and displaying a graph of both the realtime data and of a high water mark achieved over a second. 
  • The "Joystick Test Session" demonstrates the app reading voltages from a joystick via the same ADC as above and detecting a button push via a GPIO.
Some of the things that I will be discussing include the following:
  1. Node.Js Async Processing Example
  2. Node.Js Web Page Processing (Using 'html' Library)
  3. Using Socket.IO to animate a client side graph
  4. Integrating a Realtime Clock and an ADC via I2c
  5. Integrating a Joystick via I2c with a GPIO detected button
Sample code for my demo application can be found on GitHub.

Wednesday, October 9, 2013

Node.Js Web Page Processing (Using 'html' Library)

Node.Js supports a number of libraries to facilitate handling of web interactions.   One of the most primitive is 'html' with 'connect' and 'express' further up the food chain.   When I started my project I looked for examples of express being used for a reasonably traditional web application and did not find one.   What I found was one that gave me a foundation for putting together an application based on the somewhat primitive functions provided by 'html'.


I am actually ok with that as it has given me a lot of control.   I have implented the
“The App” with two modules “main” and “form” that integrate with the Node.js to provide a web server as described by the example on this page. 

  1. "The App” is launched at startup with main running and a “/” is fired on behalf of the LCD display.
  2. “main”  is monitoring the http port and sees the “/”. It invokes form.send to put the main.html form out to the client.
  3. When the user presses the “Start” button main sees it and invokes form.receive to handle the page.  The call to form.receive is made with a callback given that reveiving a form is asynchronous.
  4. form.receive does inspects the return from the client to see if the button pressed on the received page is asking for a new page (versus some other action).
  5. In this case the button press indicates that we need to start a test so the appropriate html file is sent to the client using form.send and the callback is completed after populating global.context with the name of the page sent and with the button pressed on the client.
  6. Main then receives that callback, sees that we want to start a test, loads the test module, and calls test.execute.
  7. test.execute starts running and does a setInterval to begin collecting our observations.
  8. setInterval fires as often as it can calling test.observe to do our data collection
What is not shown on this page is the library backbone.js.  This library consolidates related processing from main and form into one place for readability.   The async processing shown here still applies.


Sample code for this demo can be found on GitHub.

Monday, October 7, 2013

Node.Js Async Processing Example


  • The BeagleBone Black supports a number of development environments native to other linux platforms.  My original thought was to use Python but a closer look at Node.Js and Javascript convinced me to go in that direction.
  • Node.js is a platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.
  • Using Javascript on both the server and client will make development more consistent and will allow access to a realm of addons for graphing and other functions. 
  • The “event-driven, non-blocking I/O model” mentioned of Node.Js does pose a bit of a challenge in terms of the structure of programs written for the node environment.
  • The below diagram presents an example of how this works.
  • Code written in this manner allows the node engine to focus on processing tasks that need attention rather than on those waiting for slower operations completing.
  • It can lead to a plate of call back spaghetti  ... and has not been the easiest environment in which I have ever worked!
  1. Function that sends the specified file of html to the client.
  2. Asynchronous read of the file initiated here with two arguments – the file name to read and the function to call when the read has been completed.
  3. Inline definition of the function mentioned above – the call back function named as such because it is called back when the read finishes.
  4. (and 5.) In this example the message “sendForm ended” will appear on the console BEFORE the message “Form xxx Sent"
Sample code for my demo application can be found on GitHub.

Tuesday, October 1, 2013

Wiring the BBB for "The App"

Wiring the BBB for my application was pretty straight forward though the software side of the data collection proved to be a little less so.   

 

Integrating the Real Time Clock (RTC)

  • The BeagleBone Black, like other single board computers, does not have an onboard clock with battery backup to preserve current date and time.  
  • Theory of the case being that if the application needs one the date and time can be gotten from:
    • The network via NTP, or
    • An optional battery backed Real Time Clock.
  • Since ‘The App’ is not a network attached device the latter alternative has been implemented.
  • Luckily the BBB does come with the necessary hooks to easily integrate an RTC (assuming it is one of a list that is supported).
  • The RTC is connected using I2C and powered from the BBB as shown in the previous diagram.
  • Once it is connected the time on the BBB is set using NTP while it is connected to the network – ‘ntpdate -b -s -u pool.ntp.org’
  • Once the BBB is running the correct time it can be downloaded to the RTC – ‘hwclock -f /dev/rtc1 –w’
  • From that point the BBB can get the time from the RTC rather than the network – ‘hwclock -f /dev/rtc1 –s’
  • It is not essential that the BBB support a real time clock for operation of ‘The App’, however, doing so will allow files to be date and time stamped.

Integrating the Analog Digital Convertor (ADC)

  • The BBB has an onboard ADC, however, the entire ADC is allocated to the LCD cape!
  • Given this I have integrated an off board ADC, one that was designed for the Raspberry Pi, but that works with anything that communicates via I2C.
  • Wiring is shown by the preceding diagram and consists of five lines, two power, two for I2C, and a single line from our input source.
  • One of the disadvantages with the onboard ADC was it’s operating range for input (-1.8 to +1.8v).  The Pi ADC operates from 0-5v which better suits our requirement.
  • The bulk of the work of talking to an I2C device is done by a library installed via NPM – ‘npm install i2c’.  This library is available as part of Bonescript which ships with the BBB or as an install from npm per the above (which is what I am using since I don't have a need for the rest of Bonescript.
  • The code to access the ADC is shown below with some comments.
Initialize the interface library
var i2c = require('i2c');
Setup the address and command for the ADC.  The command translates to 12 bit resolution, gain of 1, in continuous mode
var address = 0x6A; var command = 0x90;
Use the library loaded above to instantiate a new wire (I2C) interface
var wire = new i2c(address,

    {device: '/dev/i2c-1', debug: false});
Setup an interval to capture observations.   5ms is as fast as we can go
intervalId = setInterval(function() {

    observeCallback();

}, 5);
Here is the callback for the above interval.  This function actually calls on the I2C interface to get four bytes of data from the ADC
function observeCallback() {

    wire.readBytes(command, 4, function(err, res) {

        observe(res);

    });

}
Within the observe function the two bytes of data that actually contain our reading are bit shifted into a measurement
function observe(buffer) {

    var voltageIn = (buffer[0] << 8) + buffer[1];

    voltageIn = (voltageIn / 2048) * 5.0;

There is a huge caveat on the above code.  Namely that when embedded within my application it will, at some point, cause a Segmentation Fault.  In a later post I will describe my solution to this rather fatal problem!