Overview

Combine the power of CloudTurbine with the PocketBeagle single board computer to create a PocketTurbine!

PocketBeagle is a small computer platform released in September 2017, touted as “an ultra-tiny-yet-complete open-source USB-key-fob computer” (https://beagleboard.org/pocket). This system uses the 21mmx21mm Octavo Systems OSD3358 “System-In-Package” processor, which includes a 1GHz ARM Cortex-A8 CPU, 512MB of DDR3 RAM, and two programmable real-time units (e.g. for robotic motor control). The PocketBeagle includes extensive break-out pin headers for access to analog inputs, digital I/O, UART, etc. Available for $25 (https://www.arrow.com/en/products/pocketbeagle/beagleboardorg)!

Project Goals

Setup CloudTurbine

Get CloudTurbine running on the PB.

Progress: 100%

Data acquisition

Acquire data from the onboard analog input channels and save it in CT format. Analog input could be saved as a CSV string and then streamed using UDP to a locally running CTudp.

Progress: 100%

Data sharing

Explore modes of sharing CT data from the PocketTurbine. Ideas include locally hosted data on the PB served via CTweb; UDP data to a remote CT server machine; rely on a third-party file sharing service (e.g. Dropbox or Syncthing) running on the PB to distribute/mirror the data.

Progress: 0%

Sensors and networking

Explore adding peripheral sensor or networking hardware to the PocketBeagle, for example, a microBus Click sensor or Ethernet board (https://github.com/beagleboard/pocketbeagle/wiki/mikroBus%E2%84%A2-Click-Boards). Adding such hardware provides options for data to stream to CT and flexibility in how to access and share the data.

Progress: 0%

DAQ configuration

Add a web page to configure data acquisition, for instance what channels to acquire, the channel names and the data rate. Data could be saved to an XML file which is then read by the DAQ process when it launches.

Progress: 0%

Resources

Developer Updates

Purchase PocketBeagle

September 28, 2017 John Wilson

My PocketBeagle order arrived today!

Purchased from Digi-Key:

Note that Arrow is offering PB for a little less ($23.99) with free overnight shipping!  https://www.arrow.com/en/products/pocketbeagle/beagleboardorg

Setup CT on the PocketBeagle

October 6, 2017 John Wilson

Setup operating system and connect to PB

Followed the instructions at https://beagleboard.org/getting-started.  From what I have seen, PB setup is similar to BeagleBone setup.  In my case I am using a Windows 10 machine in this setup; this is also the machine to which I will be connecting the PB.

  1. Downloaded the latest Beagle image from https://beagleboard.org/latest-images; clicked on the link to download “Debian 9.1 2017-09-21 4GB SD IoT”, which was the Debian image they had listed for PocketBeagle.  As indicated on the “Getting Started” page, “The ‘IoT’ images provide more free disk space if you don’t need to use a graphical user interface (GUI).”  Checked the “sha256sum” provided alongside the image download link against what Cygwin returned using its sha256sum program.
  2. Installed Etcher on my Windows 10 machine (https://etcher.io/); this is used to burn images to SD cards.
  3. Used Etcher to burn the Debian image to my microSD card; when complete, ejected the SD card.
  4. Inserted microSD card into the PB and then connected the USB cable from the PB to the Windows 10 computer; a new drive shows up on the Windows 10 computer.

NOTE: As recommended by the Beagle getting started page (https://beagleboard.org/getting-started), use a high quality USB cable to connect the PB to your computer.  We have found that not every cable works (you’ll be able to tell because the new drive won’t show up on your computer).

Here’s a picture of the flash drive that is automatically mounted:

Double-clicking “START.htm” from this drive brings up the start page in a browser (see image below).  This page includes some useful information, for example about the network adapter that was automatically created on my Windows 10 computer after connecting the PB.  As of the time of this Developer Update (not even a month since the release of the PocketBeagle), some of the information on this page is specific to the BeagleBone, not the PocketBeagle.

In the figure below, notice the web-based services available from the links in the left panel: a web server, a Cloud9 integrated development environment, and a “Node-RED” graphical programming environment.  Beagle has put thought into getting developers (even beginner developers) connect to the PB.  The link for “SSH server” didn’t work in my browser, but as shown further below I can SSH to the PB.

Clicking the “Web server” link (in the upper left corner of this start web page) connects us to the web server running on the PocketBeagle (see image below).  As of the time of this writing with the Debian package we have used, some information on this web page (specifically the hardware documentation) is specific to the BeagleBone, not the PocketBeagle.

When the PB connects to its host machine (Windows 10 in my case), it creates a new Ethernet adapter on the host.  On Windows, the new adapter can be seen by bringing up a command prompt and executing ipconfig.  The IP address associated with the Ethernet adapter for my Windows machine is 192.168.7.1; the corresponding IP address for the PB is 192.168.7.2.  Use Cygwin or PuTTY to connect to the PB via SSH.

Default login information: username: debian, password: temppwd

Change the password after you login!

Here’s an image after SSH’ing to the PB.

Networking setup

Following the instructions at https://www.digikey.com/en/maker/blogs/how-to-connect-a-beaglebone-black-to-the-internet-using-usb/cdf66181b3a5436e9ad730e4ed4cf9ee, I was able to tether the PB to my Windows 10 desktop so PB could access the internet.  Only step that didn’t work was the last one:

echo "nameserver 8.8.8.8" >> /etc/resolv.conf

On the PB, /etc/resolv.conf links to /run/connman/resolv.conf.  The above “echo” command doesn’t work to create this file.  Can use vi to manually create /run/connman/resolv.conf and store “nameserver 8.8.8.8” in it, but the file will be deleted after reboot.  To have this file created every time at boot, I did the following:

  1. Create resolv.conf in my home directory (/home/debian), just containing the single string “nameserver 8.8.8.8” (without quotes)
  2. Create the following script in /etc/init.d called cp_resolv_conf; at boot, this copies /home/debian/resolv.conf to /run/connman (as mentioned above, there is a link from /etc/resolv.conf to /run/connman/resolv.conf).
#!/bin/sh
### BEGIN INIT INFO
# Provides:       cp_resolv_conf
# Default-Start:  2 3 4 5
# Short-Description: As part of tethered networking setup, copy
#                    /home/debian/resolv.conf to /run/connman
### END INIT INFO

DESC="Copy /home/debian/resolv.conf to /run/connman"
case "$1" in
  start)
        cp /home/debian/resolv.conf /run/connman/resolv.conf
        ;;
  *)
        log_success_msg "Usage: $0 {start}" >&2
        exit 1
        ;;
esac

exit 0
  1. Install this startup script: cd to /etc/init.d and execute: sudo systemctl enable cp_resolv_conf

The other command that needs to be run every time after boot is:

sudo /sbin/route add default gw 192.168.7.1

I tried adding this command to the init.d script, but that didn’t work.  Tried adding it to /etc/init.d/networking, but that didn’t work.  Also tried adding the following line to /etc/network/interfaces, but that didn’t work either:

up route add default gw 192.168.7.1 dev usb0

I’m a Linux networking noob, what can I say!  For now I run the above command every time I log in.  I’ve put this command in a script in my home directory.

Once networking is setup, the PB can access the internet.  Here’s an example of executing “ping google.com”:

Repartition the file system on the microSD card

Even though I purchased a 16GB microSD card, the initial Debian file system was only 3.3GB:

To repartition the file system, follow the instruction at: https://elinux.org/Beagleboard:Expanding_File_System_Partition_On_A_microSD

The ONLY step that was a little nerve-wracking was after creating the new partition, fdisk asked:

Partition #1 contains a ext4 signature.

Do you want to remove the signature? [Y]es/[N]o: y

To which I did respond “y” and it worked fine.  Phew!  Image below shows the updated file system after repartitioning:

Install Java

http://beagleboard.org/project/java/

Downloaded installation file for JDK from http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

PocketBeagle is 32-bit, so I need the “Linux ARM 32 Hard Float ABI” 32-bit version; filename was “jdk-8u144-linux-arm32-vfp-hflt.tar.gz”.  After downloading this to my Windows 10 machine, I used SFTP to transfer the file to the PB.

For installation, I followed the instructions at http://www.rpiblog.com/2014/03/installing-oracle-jdk-8-on-raspberry-pi.html which are for the RaspberryPi, but it worked for the PB as well.

Compile CloudTurbine

Git is included in the Debian installation on the PB; use it to download the CloudTurbine source.  For example, to clone the main CloudTurbine repository into a local CloudTurbine directory:

git clone https://github.com/cycronix/cloudturbine.git CloudTurbine

In my case, I have a forked CloudTurbine repository in my own GitHub account; to clone my forked repo into a local directory on the PB I did the following:

git clone https://github.com/jpw-erigo/cloudturbine.git CloudTurbine

It can be helpful to have your GitHub credentials stored on the PB so you aren’t prompted every time you interact with GitHub.  To have your username and password permanently stored in a file called “.git-credentials” in your home directory:

git config --global credential.helper store

NOTE: your username and password are stored as plain text!

To build the CloudTurbine JavaCode projects:

cd CloudTurbine/JavaCode
./gradlew build

It is important that PB have internet access for the build as numerous libraries are downloaded from repositories.

As we saw with the RaspberryPi, the only application that doesn’t compile is CTadmin, due to a missing JavaFX library.  I copied this library from my Windows 10 PC to the PB to solve the issue (see more information at the RPi setup, http://www.cloudturbine.com/app_kit/raspberry-pi-demonstration/).

Data acq: CSV to CT

October 10, 2017 John Wilson

The PocketBeagle (PB) includes support for 8 x 12-bit A/D channels.  A layout of PB’s expansion headers is available in the PB datasheet. The voltage range for analog input channels 0, 1, 2, 3, 4 and 7 is 0-1.8V; the voltage range for analog input channels 5 and 6 is 0-3.3V.

I used the JavaScript “BoneScript” library to read the analog input channels.  You can try the analogRead function right from a browser connected to the PB by going to http://beaglebone.local/bone101/Support/BoneScript/analogRead/.  Do the following:

  1. Connect a wire from pin 18 on the P1 header (1.8V reference) to pin 19 on the P1 header (analog input channel 0, AIN0)
  2. Go to the analogRead page on the PB’s web server
  3. In the first “Example” box, enter ‘P9_39’ as the pin address in the analogRead function (see discussion below why this pin address isn’t ‘P1_19’)
  4. Click the run button on the webpage.  The value returned from analogRead is displayed.  This function returns a scaled value: 0 corresponds to 0V and 1.0 corresponds to 1.8V.  Since 1.8V is connected to AIN0, the return value should be close to 1.0 (see screenshot below).

A trick with analogRead is figuring out the pin address for each analog input channel.  Pin layout is defined in the file /usr/bin/config-pin on the PB.  As of the time of this write-up (Oct 2017), it appears that the Debian distribution I used for my PB uses the  same pin assignments as the BeagleBone Black (BBB).  Thus, AIN0 is defined at ‘P9_39’ in the config-pin file, matching the pin assignment for AIN0 for the BBB (see the BBB “analog inputs” at http://beagleboard.org/Support/bone101/#headers).  Even though PB has 8 analog input channels, it appears we can only access 7 of these channels since an “AIN7” input is not defined in config-pin (this is in keeping with the BBB, which only has 7 analog input channels).

Here are the pin assignments for the PB:

AN0    P9_39
AN1    P9_40
AN2    P9_37
AN3    P9_38
AN4    P9_33
AN5    P9_36
AN6    P9_35
AN7    n/a, not defined in config-pin

For demo purposes, potentiometers were used as voltage dividers to supply variable voltages to channels AN0-AN3 (see picture below).  One potentiometer was used for each analog input channel, as follows: PB’s analog reference pins (1.8V AIN REF+ pin P1_18 and REF- pin P1_17) are connected to the potentiometer’s two end terminals; the potentiometer’s “wiper” terminal is connected to one of the analog input pins.  As seen below, we soldered dual male 0.1″ pitch headers along both sides of the PB.  A ribbon cable was used to connect one set of headers (the set which includes the analog inputs) to a breakout board we had on hand (Winford’s 2×20 0.1″ breakout).  Since the ribbon cable we are using is 2×20 and the PB male headers are 2×18, the extra 4 pin sockets in the ribbon cable simply hang off the end with no pin connections; no big deal, we simply won’t connect anything to pins 37-40 on the breakout board.

Using the cloud9 service on the PB, I coded the following example to acquire data from 4 analog input channels, scale the returned values to voltage, create a CSV string (including a milliseconds since epoch timestamp) and send the CSV string to local UDP port 5555.  The source code was saved to file /var/lib/cloud9/analogin_to_udp.js.

#!/usr/bin/env node
const bs = require('bonescript');
const dgram = require('dgram');

const ain0_inputPin = "P9_39";
const ain1_inputPin = "P9_40";
const ain2_inputPin = "P9_37";
const ain3_inputPin = "P9_38";

var loopCtr = 0;
var ledOutput = bs.HIGH;

// Initialize the LED
bs.pinMode('USR3', bs.OUTPUT);
bs.digitalWrite('USR3', ledOutput);

// Initialize UDP client
const PORT = 5555;
const HOST = '127.0.0.1';
const udpClient = dgram.createSocket('udp4');

loop();

function loop() {
    var milliseconds = (new Date).getTime();
    var ain0 = bs.analogRead(ain0_inputPin);
    ain0 = ain0 * 1.8; // Scale for 1.8 volts
    var ain1 = bs.analogRead(ain1_inputPin);
    ain1 = ain1 * 1.8; // Scale for 1.8 volts
    var ain2 = bs.analogRead(ain2_inputPin);
    ain2 = ain2 * 1.8; // Scale for 1.8 volts
    var ain3 = bs.analogRead(ain3_inputPin);
    ain3 = ain3 * 1.8; // Scale for 1.8 volts
    
    // Create and send out the CSV string
    var udpStr = milliseconds.toString() + ',' + ain0.toFixed(3) + ',' + ain1.toFixed(3) + ',' +
                   ain2.toFixed(3) + ',' + ain3.toFixed(3) + '\n';
    var buf = Buffer.from(udpStr);
    udpClient.send(buf, 0, buf.length, PORT, HOST, function(err, bytes) {
        if (err) {
            // udpClient.close();
            console.log('Error sending UDP:');
            console.log(err);
        }
    });
    
    // Every fifth iteration, print the CSV string and toggle LED
    ++loopCtr;
    if (loopCtr == 5) {
        loopCtr = 0;
        // Print output
        console.log(udpStr);
        // Toggle the LED
        if (ledOutput == bs.HIGH) {
            ledOutput = bs.LOW;
        } else {
            ledOutput = bs.HIGH;
        }
        bs.digitalWrite('USR3', ledOutput);
    }
    
    setTimeout(loop, 200);
}

To run this program, I SSH to the PB and execute the following:

cd /var/lib/cloud9
node analogin_to_udp.js

This program can also be automatically run at boot-up by putting it in cloud9’s “autorun” folder at /var/lib/cloud9/autorun.

The screenshot below shows the program running; approximately once per second, the CSV string is printed to the console.  The timestamp shown in the first field is milliseconds since epoch.

CTudp was used to capture the UDP packets and save the data as individual channels in CT format.  CTudp startup command:

java -jar CTudp.jar -csplit time,ain0,ain1,ain2,ain3 -p 5555 -s CTdata/PocketBeagle

The screenshot below shows CTudp flushing ZIP files to disk at approximately one second intervals:

CTweb was run on the PB to serve this data:

I accessed the CT data on my Windows 10 host computer by going to 192.168.7.2:8000 in a browser, as shown below.  To illustrate some variation in the data, I adjusted each of the 4 potentiometers in succession.

Internet tethering problem - SOLVED

October 16, 2017 John Wilson

At some point the tethered internet connection from my PocketBeagle (PB) to the Windows 10 desktop machine stopped working.  (As noted in the Developer Update on October 6, tethered networking was setup using the instructions at https://www.digikey.com/en/maker/blogs/how-to-connect-a-beaglebone-black-to-the-internet-using-usb/cdf66181b3a5436e9ad730e4ed4cf9ee.)  I could still ping the Windows 10 machine PB was connected to (“ping 192.168.7.1”) but could not, for example, ping Google using “ping google.com” – instead of the normal ping response I got a message such as:

ping: google.com: Temporary failure in name resolution

Since I could ping the Windows 10 machine but could not ping Google, it makes sense that the issue was with the tethering setup on the Windows 10 machine, not with the networking setup on the PB.

The problem turned out to be the networking setup in the “remote NDIS” Ethernet device.  As shown in the figure below, the IP address for this connection was somehow reset to 192.168.137.1.  After changing this back to 192.168.7.1 everything worked fine!

Cleaned up DAQ demo

October 17, 2017 John Wilson

I cleaned up the data acq demo accessory board using some supplies from Adafruit:

A list of the Adafruit items we used:

  • Adafruit Perma-Proto Half-sized Breadboard (https://www.adafruit.com/product/1609); great boards for prototyping small projects
  • 2×20 IDC Breakout Helper (http://www.adafruit.com/product/2270); this ingenious connector sits in the middle of the Perma-Proto board with one set of 10 legs connecting to one side of the board and the other set of 10 legs connecting to the other side; this was a very convenient way to breakout a 2×20 header
  • 2×20 ribbon cable (https://www.adafruit.com/product/1988); this was shorter (less bulky) than the ribbon cable I previously used

 

Scripts to launch data acq

October 17, 2017 John Wilson

I wrote scripts to launch all the applications needed for this data acq demo on the PocketBeagle.  On my PocketBeagle, these scripts are located in /home/debian/CloudTurbine/RunPocketTurbine, which is the same folder where CloudTurbine data is written.  The main script in this folder, “startPT”, is shown below.  Note that there are 2 environment variables created near the top of the script, testdir and ctdev, which define the test home directory and the directory where CloudTurbine jar files are stored, respectively.

#!/bin/bash

#
# Note that we run the sub-scripts with an initial '.', as in:
# . ./_startDAQ
# This runs the script in the current shell environment. That way,
# the sub-scripts will have the definition of $testdir and $ctdev.
# See the following URL for more info:
# https://stackoverflow.com/questions/1464253/global-environment-variables-in-a-shell-script
#

# Define environment variables
# testDir = test home directory; this is where the CT data will be written
# ctdev = folder containing CT jar files
export testdir=/home/debian/CloudTurbine/RunPocketTurbine
export ctdev=/home/debian/CloudTurbine/CloudTurbine/JavaCode/Distribute

# Make sure tethered networking is started
sudo /sbin/route add default gw 192.168.7.1

cd $testdir
# create the CTdata directory if it doesn't exist
mkdir -p ./CTdata
# remove existing data
rm -R ./CTdata/*
# start CTweb
. ./_startCTweb
sleep 5
# start data acquisition
cd $testdir
. ./_startDAQ
# start CTudp
cd $testdir
. ./_startCTudp

Note that this main script launches a series of sub-scripts:

  • _startCTweb: launch CTweb, used to remotely view the data in a browser
  • _startDAQ: launch data acquisition; this samples the data, writes it to a CSV string and sends the string off to a specific port via UDP
  • _startCTudp: captures the CSV string, parses it into individual channels and writes the data out in CT format

Each of these scripts are displayed below.  First, _startCTweb:

#!/bin/bash
cd $testdir
java -jar $ctdev/CTweb.jar &
echo $! > ./pid_CTweb.file

Second, _startDAQ:

cd /var/lib/cloud9
node analogin_to_udp.js &
echo $! > $testdir/pid_node.file

Third, _startCTudp:

#!/bin/bash
cd $testdir
java -jar $ctdev/CTudp.jar -bps 120 -csplit time,ain0,ain1,ain2,ain3 -p 5555 -s CTdata/PocketTurbine &
echo $! > ./pid_CTudp.file

Each script stores the process ID from the launched application in a file in the test folder.  These files/process IDs are used by another script, killPT, to terminate all of the programs:

#!/bin/bash
testdir="/home/debian/CloudTurbine/RunPocketTurbine"

if [ -f "$testdir/pid_node.file" ]
then
 kill $(cat $testdir/pid_node.file)
 rm $testdir/pid_node.file
fi

if [ -f "$testdir/pid_CTudp.file" ]
then
 kill $(cat $testdir/pid_CTudp.file)
 rm $testdir/pid_CTudp.file
fi

if [ -f "$testdir/pid_CTweb.file" ]
then
 kill $(cat $testdir/pid_CTweb.file)
 rm $testdir/pid_CTweb.file
fi

 

Run procedure

March 5, 2018 John Wilson

Reminder: as described above, the way the PocketBeagle is currently setup, here’s what I do to start the PocketTurbine demo:

  1. plug the PB via USB into the Windows 10 machine
  2. on the PB, cd to the home directory and run “start_tethered_networking.sh”
  3. cd /home/debian/CloudTurbine/RunPocketTurbine  and run “startPT” script

I’m having a problem running tethered networking on the PB for some reason.  This causes a problem when I run CTweb server because it can’t access the CTweb/WebScan files from the remote AWS server.  Need to sort this out…

Team Members

Avatar

John Wilson