Per some previous posts (starting here) I have pulled some functionality from a project that I am working on into a little demo application - Node.Js Physical Interface Demo.
Over the past days I have refined the framework that I am using for my web server. I have chosen to use a fairly primitive approach to providing web service as I have based my application on the http module. This gives me very atomic control though with some added complexity.
In order to attack that complexity I have refined my own framework for http service. There are to scripts that are purely server...server.js which talks to the port and form.js which handles page and form interaces asynchronously. Two additional scripts provide an interface between server and form, serverExits and formExits. As the name implies there are a number of exits embedded in Server and Form that allow a application to customize some key handling aspects.
Everything else is pure application. To add a web page you create a script that includes application logic AND to handlers...serverHandler and formHandler. serverHandler executes the asynchronous recieve of a form which is then processed by formHandler. A matching html file is created in the html directory, with some meta tags that allow substitutions of variables, and Bob is Your Uncle.
I will write more about this later. Remember that my target is an embedded application with its head being a small LCD touchscreen.....
Evolution of a Blog
This blog has evolved as I have as a maker. It starts at the beginning of my journey where I began to re-tread my tires in the useful lore of micro electronics and the open-source software that can drive them. While building solutions around micro-electronics are still an occasional topic my more recent focus has been on the 3D Printing side of making.
Thursday, November 7, 2013
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:
Then update the package indexes for both the OS and for NPM:
Now install all the OS level stuff that we will be needing:
The version of git on the BBB needs to be updated so download the tarball with the code and then do the following:
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:
Now all the npm packages that we need can be installed:
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):
ntpdate -b -s -u pool.ntp.org
echo ds3231 0x68 >/sys/bus/i2c/devices/i2c-1/new_device
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”:
And have it run automatically:
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:
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:
If everything is working you will see a list of default parameters.
DONE!
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
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
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:
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:
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:
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
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.
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.
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.
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.
Finally we launch the observation perio.
The background process that the above launches, and then communicates with, is shown 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);
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); }); });
execSync('kill ' + wireServerPid); utilities.trace(false, "test - Current wireServer running as PID " + wireServerPid + " killed")
eventEmitter.emit('startObserve', '');
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.
- 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
- 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.
- Bring in the "events" library (node events) that I use to poll for I2c and Select Button states.
- 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.
- 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.
- 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
- 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.
- 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 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.
- The output from the button is connected to a pull down resistor...
- ...and since the output 5v I route it through a voltage divider to make it safe for the Raspberry Pi.
- 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.
- The output from the ADC is connected to the Raspberry Pi using the SLC and SDA connections.
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.
- Initialization of the client and server libraries and opening of a connection on port 7300.
- 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).
- Client sends “ready” to the server to ack the maxSustained message. The server has a socket.on for the ready message.
- 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.
- 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.
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:
- Node.Js Async Processing Example
- Node.Js Web Page Processing (Using 'html' Library)
- Using Socket.IO to animate a client side graph
- Integrating a Realtime Clock and an ADC via I2c
- Integrating a Joystick via I2c with a GPIO detected button
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
Sample code for this demo can be found on GitHub.
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.
- "The App” is launched at startup with main running and a “/” is fired on behalf of the LCD display.
- “main” is monitoring the http port and sees the “/”. It invokes form.send to put the main.html form out to the client.
- 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.
- 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).
- 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.
- Main then receives that callback, sees that we want to start a test, loads the test module, and calls test.execute.
- test.execute starts running and does a setInterval to begin collecting our observations.
- setInterval fires as often as it can calling test.observe to do our data collection.
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!
- Function that sends the specified file of html to the client.
- 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.
- Inline definition of the function mentioned above – the call back function named as such because it is called back when the read finishes.
- (and 5.) In this example the message “sendForm ended” will appear on the console BEFORE the message “Form xxx Sent"
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.
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!
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!
Saturday, September 21, 2013
Raspberry Pi vs BeagleBone Black - Expanding on a Review
Some time after I had evaluated the Raspberry Pi versus the BeagleBone Black I came across a really well done comparison of the two platforms by Michael Leonard. It was originally posted on his blog here and then later it was re-posted to Make here. There is nothing in the review that would have changed my recommendation, and there is little with which I disagree, but the following are points where my learnings over the past months augment Michael's review.
I had unboxed three Raspberry Pi's (RPi's) before I got my first BeagleBone Black (BBB). My first impression of the BBB was to be impressed by how much more professional it looks than the RPi. Obviously this is a reflection of it being the latest in a family of devices. I still like the look and feel of it better than the RPi which has a much more "hobbyist" look in my opinion. I would give unboxing to the BeagleBone Black. This is the only scoring difference that I would make in Michael's evaluation.
This certainly does not change the BBB being a clear winner here as you would need an external ADC for the RPi in any case.
In any case, forum tools aside, I hope that the dynamism of the BBB user community will improve over time as the BBB sells more units but for now it is, as Michael's review states, clearly a win for the Raspberry Pi.
You can fry any electronic device, and I am proof to this statement, but one of the strengths of the Arduino is it's ability to resist ham-fisted users like myself.
The Raspberry Pi is clearly more sensitive than the Arduino but I managed to fry one of them. It turns out that it was a model that did not include the poly-fuses that newer boards now support. On a later attempt to smoke another, newer RPi, the poly-fuse did it's thing and some hours later, when things cooled down, the RPi came back to life!
The BeagleBone Black, in my hands anyway, has been expensive. Two of them have been into the Beagle Hospital and I am now a little gun shy. I would strongly recommend that a high degree of caution be taken when working with a BBB connected to the external world. Never connect and disconnect hardware with the power on (should probably go without saying)! Never have the gear to which you are interfacing with powered on before the BBB (came as a little bit of a surprise)!
I am not a hardware guy, but, I can't help but wonder why the RPi would seemingly put poly-fuses to good use but they are not appropriate for the BBB (according to someone associated with the device)? [Yes, I know, you can not protect against all forms of ham-fisted'ness but maybe against some would be nice.]
On the other hand, I have the code that I have written for the BeagleBone Black running pretty much seamlessly on the Raspberry Pi so if I needed to make a change I can do so. This is a great testament to the open-source world within which both boards reside. Cool eh?
Unboxing
I had unboxed three Raspberry Pi's (RPi's) before I got my first BeagleBone Black (BBB). My first impression of the BBB was to be impressed by how much more professional it looks than the RPi. Obviously this is a reflection of it being the latest in a family of devices. I still like the look and feel of it better than the RPi which has a much more "hobbyist" look in my opinion. I would give unboxing to the BeagleBone Black. This is the only scoring difference that I would make in Michael's evaluation.
Ease of Setup
I strongly agree with Michael on the ease of initial setup with the BeagleBone Black but would caveat as follows. There are probably a lot of applications that will never need to boot from the removable micro-SD card but I have one of them and this created some minor complexities similar to what one encounters with the RPi. The ability to connect the BBB to a host computer using the included USB cable is a very nice feature and one that I am planning to use when the BBB is embedded in it's final home where it will not regularily be network attached.Connections
Another caveat here could be important to someone wanting to use the BBB to talk to things via the built-in Analog Digital Convertor or AIN as called on the BBB:- First, and most importantly, if your application is going to use an LCD cape you will not have physical access to the AIN pins, and, it won't matter as the LCD cape monopolizes the ADC chip so even if you had physical access to it...the AIN will still not work for you.
- Second, and this is minor compared to the above, the AIN being based on 1.7 volts is a pain in the butt! Sure you can easily do a voltage divider to get your source, which is probably 5v, down to what the BBB needs, but it is a pain. I have also read, but not verified myself, that the accuracy of the onboard AIN can be impacted by noise on the board.
This certainly does not change the BBB being a clear winner here as you would need an external ADC for the RPi in any case.
Graphical Showdown
I don't disagree with anything that Michael states here but I would give the BBB some points for the availability of three LCD capes of varying sizes at price points well below what I have found to be available for the RPi. They integrate extremely easily, work well, and look great. Yes, I know, credit for this is given in the expandability section. Just sayin'Expandability
I agree with the scoring on this area but not for the availability of the Arduino add on board (though I do think it is pretty cool). I think the chances of needing an Arduino, if you have a BBB, are less than if you have an RPi but if you do need one to take advantage of a shield, there are lots of ways to connect said Arduino. I would give the edge to the RPi simply because of the wide variety of accessories that have entered, or are entering, the market given the popularity of the RPi. I think that some of the expansion boards for the BBB might be a little nicer, and in the case of the LCD, cheaper, than for the RPi but the size of the RPi ecosystem gives them an edge.Community
The other areas where I agreed with Michael did not get a comment...but this one deserves a shout-out. The community for the BeagleBone Black has been helpful but there just does not seem to be many folks out there. On the other hand the RPi community is out there in droves and seem particularly happy to help with problems posted on their message boards. I also greatly prefer the RPi forum which is based on phpbb rather than the Google Groups approach used by the BBB.In any case, forum tools aside, I hope that the dynamism of the BBB user community will improve over time as the BBB sells more units but for now it is, as Michael's review states, clearly a win for the Raspberry Pi.
Fragility
This is not something that Michael talked to but that I needed to add based on my experiences. I will freely admit that this could be "just me".You can fry any electronic device, and I am proof to this statement, but one of the strengths of the Arduino is it's ability to resist ham-fisted users like myself.
The Raspberry Pi is clearly more sensitive than the Arduino but I managed to fry one of them. It turns out that it was a model that did not include the poly-fuses that newer boards now support. On a later attempt to smoke another, newer RPi, the poly-fuse did it's thing and some hours later, when things cooled down, the RPi came back to life!
The BeagleBone Black, in my hands anyway, has been expensive. Two of them have been into the Beagle Hospital and I am now a little gun shy. I would strongly recommend that a high degree of caution be taken when working with a BBB connected to the external world. Never connect and disconnect hardware with the power on (should probably go without saying)! Never have the gear to which you are interfacing with powered on before the BBB (came as a little bit of a surprise)!
I am not a hardware guy, but, I can't help but wonder why the RPi would seemingly put poly-fuses to good use but they are not appropriate for the BBB (according to someone associated with the device)? [Yes, I know, you can not protect against all forms of ham-fisted'ness but maybe against some would be nice.]
Conclusion
Interestingly, my original evaluation of the two boards leaned towards the BBB largely because of the lack of an ADC on the Raspberry Pi. Learning that the ADC is not accessible when the LCD Cape is on the BBB defrayed that advantage but the quality of the LCD, and the integrated nature of the board and the LCD, have become the reason to continue my path to production on the BBB.On the other hand, I have the code that I have written for the BeagleBone Black running pretty much seamlessly on the Raspberry Pi so if I needed to make a change I can do so. This is a great testament to the open-source world within which both boards reside. Cool eh?
Monday, September 2, 2013
Minimum Setup for a GitHub Software Repository
Previous projects have had me using subversion with SmartSvn as a GUI. I had a server setup on my home network but wanted an external server but never got around to setting one up. For this project I decided to go with GitHub. It is, after all, the home of much open source software, is easy to use, is free for public repositories (and cheap for private ones), and has both graphical and command line utilities for the client.
Once you have setup your repository on GitHub the following commands will add your project to the new repository:
Then to update your repository you do the following
There are a lot of other features of both the local client and the remote repositories but the above are a minimum that I use to manage 'The App'.
Once you have setup your repository on GitHub the following commands will add your project to the new repository:
- touch README.me git init
- git add README.md
- git commit -m "First commit"
- git remote add origin https://github.com/ThamesWill/Physical-Interface-Demo
- git push -u origin master
Then to update your repository you do the following
- git add *.*
- git commit -m 'Initial adds'
- git push -u origin master
There are a lot of other features of both the local client and the remote repositories but the above are a minimum that I use to manage 'The App'.
Sunday, September 1, 2013
Back with a (Big) New Project
There has been a period of silence over the past months as I had been given the opportunity to apply some of my new technical skills in the Computing Physical Interface space. In particular a friend offered me the opportunity to build an instrument based on a single board computer with a physical interface to a piece of laboratory equipment. No, there is not much danger of me making money here, and I have been interested enough in it to invest in a number of new pieces of kit, but this pro-bono project has 'def peaked my interest.
Over the coming weeks and months I will attempt to look back on the past several months to document some of my learnings. I am going to backdate these posts to approximate when I actually might have gained the knowledge!
Over the coming weeks and months I will attempt to look back on the past several months to document some of my learnings. I am going to backdate these posts to approximate when I actually might have gained the knowledge!
Wednesday, August 14, 2013
Prototype Hardware - BeagleBone Black and Raspberry Pi
Here are pictures of the hardware for the prototype of "The App" that I am building. As you can see the BeagleBone Black is sporting an LCD while the Raspberry Pi is not. On the other hand, the Raspberry Pi is decked out with a little joystick which the BeagleBone Black is missing.
The components that are shared by both computers are the:
The LCD display on the BeagleBone Black is the 3.5 inch cape (LCD3) from Circuitco. It presents the Beaglebone Black's console in 320 by 240 pixels of resolution. 'The App' is presented by Chromium running in full screen kiosk mode and looks very sharp.
The 5v power supply from the Raspberry Pi is used for the simulated instrument while an external power supply is used in the case of the BeagleBone Black as it delivers a more stable voltage.
Finally, the Raspberry Pi has a joystick attached as a possible option for user input. It is attached to the ADC with two outputs delivering a voltage from -2.5 to +2.5 representing each of the two axis. In addition there is a line to a GPIO pin, attached to a pull down resistor, to register a click.
The components that are shared by both computers are the:
- Real Time Clock (RTC)
- Analog Digital Converter (ADC)
- Variable Resistor
The LCD display on the BeagleBone Black is the 3.5 inch cape (LCD3) from Circuitco. It presents the Beaglebone Black's console in 320 by 240 pixels of resolution. 'The App' is presented by Chromium running in full screen kiosk mode and looks very sharp.
Finally, the Raspberry Pi has a joystick attached as a possible option for user input. It is attached to the ADC with two outputs delivering a voltage from -2.5 to +2.5 representing each of the two axis. In addition there is a line to a GPIO pin, attached to a pull down resistor, to register a click.
Monday, August 12, 2013
Using the uSD on BeagleBone Black as Aux Storage
I followed some instructions, that I have since lost track of, to enable the use of the uSD card on the BBB for auxilary storage when booting from the internal eMMC. The below are my version of what was needed:
Format the drive
Add a partition and make it of type FAT, name it and size it however you want
After it has been formatted and partitioned mount the FAT 32 partition you just made
Create the document "uEnv.txt" in the root of the partition and add the following lines to it:
mmcdev=1
bootpart=1:2
mmcroot=/dev/mmcblk1p2 ro
optargs=quiet
This should do it.
This should do it.
Monday, June 24, 2013
Chromium Full Screen
My application is intended to be completely embedded in a laboratory apparatus presenting a captive user interface on the LCD Cape which is running as the console to the device. The BBB provides a choice of several browsers but I have chosen Chromium as the front-end for my application.
Here is the command line argument that starts Chromium with it pointed to my application running under Node.js. The two command line switches ensure that Chromium is started in full screen mode without any of the browser elements such as an address bar, and, that we don't get any extraneous messages (the exports are needed for that purpose) when pages are loaded from my application:
export GOOGLE_API_KEY=AIzaSyCcjKzcifha1m8P4RVxytpVsx3wNDIEHsY
export GOOGLE_DEFAULT_CLIENT_ID=985919302268.apps.googleusercontent.com
export GOOGLE_DEFAULT_CLIENT_SECRET=vQKKl73QQk8_dgEF44vNTHmJ
google-chrome --kiosk --incognito localhost:7000 &
The above is run from .profile with the user automatically logging in when the 'X' session starts on the console. I also start my application under Node.js at the same time.
Here is the command line argument that starts Chromium with it pointed to my application running under Node.js. The two command line switches ensure that Chromium is started in full screen mode without any of the browser elements such as an address bar, and, that we don't get any extraneous messages (the exports are needed for that purpose) when pages are loaded from my application:
export GOOGLE_API_KEY=AIzaSyCcjKzcifha1m8P4RVxytpVsx3wNDIEHsY
export GOOGLE_DEFAULT_CLIENT_ID=985919302268.apps.googleusercontent.com
export GOOGLE_DEFAULT_CLIENT_SECRET=vQKKl73QQk8_dgEF44vNTHmJ
google-chrome --kiosk --incognito localhost:7000 &
The above is run from .profile with the user automatically logging in when the 'X' session starts on the console. I also start my application under Node.js at the same time.
Friday, June 21, 2013
Software Development on the BeagleBone Black
My original thought was to develop on the BeagleBone Black using Python as I had done on the Raspberry Pi. Once I started to explore the BBB I was both intrigued and worried by the idea of using Node.Js and JavaScript instead.
Intrigued because I really liked the idea of building an application with the front-end presented via a browser. Also intrigued because of Node's reputation for performance. A little worried because I just have not thought of JavaScript as anything more than a client-side scripting language. Also a little worried because the foundation of Node.js lies in it's asynchronous, non-blocking, architecture.
Once I got started slinging some code I did come to the conclusion that I was right about the good things and was overly worried about the bad. This said, the async nature of the Node.js model does give me headaches. Below is a narrative that presents some of the key processing flow for the app that I am developing:
What I have built seems to work well but I am sure that I could have done it better!
Intrigued because I really liked the idea of building an application with the front-end presented via a browser. Also intrigued because of Node's reputation for performance. A little worried because I just have not thought of JavaScript as anything more than a client-side scripting language. Also a little worried because the foundation of Node.js lies in it's asynchronous, non-blocking, architecture.
Once I got started slinging some code I did come to the conclusion that I was right about the good things and was overly worried about the bad. This said, the async nature of the Node.js model does give me headaches. Below is a narrative that presents some of the key processing flow for the app that I am developing:
“The App” modules “main”
and “form” integrate with the Node.js to provide a web
server as described by the example on this page. This is somewhat different than most development
environments where handling of the web interface is more abstracted from the application code!
- “The App” is launched at startup with main running and a “/” is fired from the browser running on the LCD display as console.
- “main” is monitoring the http port and sees the “/”. It invokes form.send to put the main.html form out to the client.
- 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 receiving a form is asynchronous.
- 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).
- 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.
- Main then receives that callback, sees that we want to start a test, loads the test module, and calls test.execute.
- test.execute starts running and does a setInterval to begin collecting our observations.
- setInterval fires as often as it can calling test.observe to do our data collection.
What I have built seems to work well but I am sure that I could have done it better!
Subscribe to:
Posts (Atom)