Wednesday, July 16, 2014

C# (Mono) Program to Read an TMP102 Temperature Sensor on a pcDuino 2

Mono is an open source implementation of Microsoft's .NET framework.  It is actually very easy to install Mono on the pcDuino 2 and get up and running with a fairly simple C# program that uses the i2cget utility to read the TMP102 temperature registers, convert it to Celsius and Fahrenheit, and print the results to the console.

For this example, I am using the TMP102 on a breakout board from Sparkfun.

Installing Mono on the pcDuino 2

To install Mono, simply run the following apt-get command as root:

apt-get install mono-complete

It will take a few minutes to download and install, but it isn't any more complicated than that.

You can confirm that your Mono installation is working by checking the version using the mono command:

mono --version

The results should look something like this -

root@ubuntu:~# mono --version
Mono JIT compiler version (Debian
Copyright (C) 2002-2011 Novell, Inc, Xamarin, Inc and Contributors.
TLS:           __thread
SIGSEGV:       normal
Notifications: epoll
Architecture:  armel,vfp
Disabled:      none
Misc:          softdebug 
LLVM:          supported, not enabled.
GC:            Included Boehm (with typed GC and Parallel Mark)

The pcDuino Web site also has information on installing smaller Mono configurations.

Installing I2C-Tools

This example uses i2cget to access the TMP102.  This program is part of the i2c-tools package.  You can install it (if you don't have already installed) by running this command as root:

apt-get install i2c-tools

C# Code

Use your favorite text editor to save this code to a file called Tmp102.cs

using System;
using System.Diagnostics;
using System.Threading;

public class Tmp102
    private string i2cgetExe = "/usr/sbin/i2cget";
    private string i2cgetCmdArgs = "-y 2 0x48 0 w";
    private string hexString = "";
    private Process p;

    public Tmp102()
        p = new Process();

    public double tempC
        get { return readRawTempData() * 0.0625; }
    public double tempF
        get { return this.tempC * 1.8 + 32; }

    private int readRawTempData()
         // Don't raise event when process exits
         p.EnableRaisingEvents = false;
         // We're using an executable not document, so UseShellExecute false
         p.StartInfo.UseShellExecute = false;
         // Redirect StandardError
         p.StartInfo.RedirectStandardError = true;
         // Redirect StandardOutput so we can capture it
         p.StartInfo.RedirectStandardOutput = true;
         // i2cgetExe has full path to executable
         // Need full path because UseShellExecute is false
         p.StartInfo.FileName = i2cgetExe;
         // Pass arguments as a single string
         p.StartInfo.Arguments = i2cgetCmdArgs;
         // Now run i2cget & wait for it to finish
         // Data returned in format 0xa017
         // Last 2 digits are actually most significant byte (MSB)
         // 2 digits right after 0x are really least significant byte (LSB)
         string data = p.StandardOutput.ReadToEnd();
         // Get LSB & parse as integer
         hexString = data.Substring(2, 2);
         // Redirect StandardOutput so we can capture it
         p.StartInfo.RedirectStandardOutput = true;
         // i2cgetExe has full path to executable
         // Need full path because UseShellExecute is false

         p.StartInfo.FileName = i2cgetExe;
         // Pass arguments as a single string
         p.StartInfo.Arguments = i2cgetCmdArgs;
         // Now run i2cget & wait for it to finish
         // Data returned in format 0xa017
         // Last 2 digits are actually most significant byte (MSB)
         // 2 digits right after 0x are really least significant byte (LSB)
         string data = p.StandardOutput.ReadToEnd();
         // Get LSB & parse as integer
         hexString = data.Substring(2, 2);
     int lsb = Int32.Parse(hexString,
     // Get MSB & parse as integer
     hexString = data.Substring(4, 2);
     int msb = Int32.Parse(hexString,
     // Shift bits as indicated in TMP102 docs & return
     return (((msb << 8) | lsb) >> 4);

    public static void Main()
         Tmp102 t = new Tmp102();
            // Print temp in degrees C and F to console
            Console.WriteLine("{0} C  {1} F", t.tempC , t.tempF);

Compiling & Running the Code

To compile the code, run this command:

gmcs Tmp102.cs

This will produce a Tmp102.exe file that you can then run using mono.

mono Tmp102.exe

The program will print the current temperature until you press Ctrl-C to stop it. 

Tuesday, July 1, 2014

Java Program to Read 2 TMP102 Temperature Sensors with the Same Address Connected to Separate Buses on a Beaglebone Black

I made a post on June 28th, "Using 2 I2C Buses on the Beaglebone Black," that shows how to use the two I2C buses available on the Beaglebone Black to read from 2 TMP102 sensors with the same I2C device address.  The post below offers a fairly simple Java 7/8 example that does the same thing.  As noted in my previous post, it is certainly possible to change the address of the TMP102, but the new version of the TMP102 from Sparkfun has a solder jumper that has to be removed before you can change the address.  This example might be useful when working with other sensors that don't allow you to change the device's I2C addresses.

I have tested the code below with Java 8 on the Beaglebone Black (rev. C) running Debian Linux.  It should also run on Java 7.

This example assumes that you are working at the command line in a terminal window or via an SSH connection.

By default, there is only 1 I2C bus accessible via the P9 pins on the Beaglebone Black.  You need to load the BB-I2C1 pin map overlay.  The sample program below handles this for you.

Last year, I posted an example of Java code that read the temperature from a TMP102 using JNA and a simple C program.  The code below uses Java's Runtime class to run the i2cget utility in order to reduce complexity.


TMP102 #1 Beaglebone Black
VCC       3.3V
GND       GND
SDA       P9 20
SCL       P9 19
ADD0      (Not connected)

TMP102 #2 Beaglebone Black
VCC       3.3V
GND       GND
SDA       P9 18
SCL       P9 17
ADD0      (Not connected)

Java Code  

import java.util.Scanner;

public class TwoTmp102 {
   // Linux shell command that loads pin map overlay with both I2C
   // buses connected to I/O pins on the Beaglebon Black.
   // Shell echo command must be passed as array of Strings.
   private static String[] loadPinMapCmd = { "bash", "-c",
      "echo BB-I2C1 > /sys/devices/bone_capemgr.9/slots" };

   // 2 i2cget commands to read raw data as a word (16-bit value)
   // from both TMP102 sensors.  -y tells command to run 
   // without confirmation from user.
   // I2C address for TMP102 by default is 0x48.
   // Each command is passed a separate String, unlike loadPinMapCmd
   // that has to be passed as an array of Strings.
   private String[] runI2CGetCmd = {"i2cget -y 1 0x48 0 w",
      "i2cget -y 2 0x48 0 w"};

   public TwoTmp102() {
      try {
         Process p = Runtime.getRuntime().exec(loadPinMapCmd);
      catch(Exception ex) { ex.printStackTrace(); }

   // Read temperatures from both sensors & print it out to terminal
   public void readTemperatures() {
      short temp1Data, temp2Data = 0;
      double temp1, temp2 = 0.00;
      temp1Data = runI2CGet(runI2CGetCmd[0]);
      temp2Data = runI2CGet(runI2CGetCmd[1]);
      temp1Data = reverseBytes(temp1Data);
      temp2Data = reverseBytes(temp2Data);
      temp1 = convertToDegreesF(temp1Data);
      temp2 = convertToDegreesF(temp2Data);
      System.out.printf("%.3f  %.3f\n", temp1, temp2);

   // Need to reverse bytes in value returned by i2cget command
   private short reverseBytes(short tempData) {
      int b1 = (byte)  tempData & 0xFF;
      int b2 = (byte) (tempData >> 8) & 0xFF;
      return (short) (b1 << 8 | b2);

   // Convert raw temperature data to degrees Fahrenheit
   private double convertToDegreesF(short tempData) {
      return (tempData >> 4) * 0.0625 * 1.8 + 32;

   private short runI2CGet(String cmd) {
      String line;
      short data = 0;
      try {
         Process p = Runtime.getRuntime().exec(cmd);
         // Use Scanner to read results from i2cget command
         Scanner scan = new Scanner(
            new InputStreamReader(p.getInputStream()));
         // Shell command returns hex number as string like 0x6017.
         // Need to use substring to skip over 0x for parsing.
         // Using Short.parseShort() sometimes throws NumberFormatExceptions.
         if(scan.hasNext()) {
            data = (short) Integer.parseInt((scan.nextLine())
               .substring(2), 16);
      catch(Exception ex) { ex.printStackTrace(); }
      return data;

   public static void main(String[] args) {
      TwoTmp102 temp = new TwoTmp102();
      while(true) {
         try {
         catch(Exception ex) { ex.printStackTrace(); }

Compiling & Running the Program

The program is very easy to compile -


To run the program (assuming that it is in the current working directory) -

java -cp . TwoTmp102

End the program using Ctrl-C.

Saturday, June 28, 2014

Using 2 I2C Buses on the Beaglebone Black

The Beaglebone Black (rev. B or C) has two I2C buses that are accessible by user programs.  This post shows how you can use two I2C devices with the same device address, with each one on a separate bus.  The new version of the Sparkfun TMP102 temperature sensor can be configured to use different I2C device addresses, but this requires removing a solder jumper, so I have used two of them for this example.

In order to use both I2C buses, you need to load a device mapping overlay file, /lib/firmware/BB-I2C1-00A0.dtbo.  This is accomplished via the shell echo command in the code below.

The code below reads the temperature from two TMP102s and prints the reading from each (converted to degrees Fahrenheit) to the terminal window.

In looking into this, I found "BeagleBone Black I2C References" by Joshua Datko very helpful.

The Python code below requires the SMBus library.  The following apt-get command (run as root) will install this library.

apt-get install python-smbus


TMP102 #1  Beaglebone Black
VCC        D9 3
GND        D9 1
SDA        D9 20  (/dev/i2c-1 bus 1)
SCL        D9 19  (/dev/i2c-1 bus 1)
ADD0       (Not connected)

TMP102 #2 Beaglebone Black
VCC       D9 3
GND       D9 1
SDA       D9 18   (/dev/i2c-2 bus 2)
SCL       D9 17   (/dev/i2c-2 bus 2)
ADD0      (Not connected)

Python Code

# -*- coding: utf-8 -*-
# Need to declare encoding in line above in order to use degree sign
import os
import smbus
import time

# Path to slots on Beaglebone Black rev. C
slots = "/sys/devices/bone_capemgr.9/slots"
os.system("echo BB-I2C1 > %s" % slots)

bus1 = smbus.SMBus(1) # pins D9 19, 20, /dev/i2c-1
bus2 = smbus.SMBus(2) # pins D9 17, 18, /dev/i2c-2

tmp102_addr = 0x48

   data = bus1.read_i2c_block_data(tmp102_addr, 0)
   msb = data[0]
   lsb = data[1]
   t1 = (((msb << 8) | lsb) >> 4) * 0.0625
   data = bus2.read_i2c_block_data(tmp102_addr, 0)
   msb = data[0]
   lsb = data[1]
   t2 =  (((msb << 8) | lsb) >> 4) * 0.0625
   print "t1: %.3f°  t2: %.3f°" % (t1 * 9/5 + 32,
      t2 * 9/5 + 32)

Sunday, June 22, 2014

Java 8 Program to Record GPS Data to a JavaDB Database on the Beaglebone Black

I posted yesterday about how to install the Java 8 JDK on the Beaglebone Black.  The Java JDK includes the JavaDB database (previously known as Derby).  This example shows how to read GPS data over a serial connection and record the data to JavaDB database table.  I have developed and tested this code on the Beaglebone Black Rev. C running Debian.  This example assumes that you are working at the Beaglebone Black's command line (using a monitor, keyboard, and mouse connected to the Beaglebone or via SSH).

While JavaDB is included with the JDK, a couple steps are needed to configure it.  I am using JavaDB in network server mode so that it can be accessed simultaneously from programs running in separate JVMs.

I am using the Copernicus II DIP GPS module from Sparkfun.

Configuring JavaDB

Add the following exports to your .bashrc to set the environment variables for JavaDB.  You should already have JAVA_HOME set after installing Java 8.

export PATH=$PATH:$DERBY_HOME/bin 

Also run the export statements at the command line or log out and back in to add these values to the environment.

Edit the /usr/jdk1.8.0/jre/lib/security/java.policy file to allow the server to accept connections by adding the following line before the closing brace of the grant section.

permission "localhost:1527", "listen";

Start the JavaDB server with the following command -

$JAVA_HOME/db/bin/startNetworkServer &

Creating the Database Table

This example uses a simple database table called gps_readings in a database named gpsdb.  Run ij to create the table.  At the ij> prompt, run the following command to create the database:

connect 'jdbc:derby://localhost:1527/gpsdb;create=true';

After the DB has been created, you can connect in future using the same connect statement or you can drop the ;create=true to cut down on typing.

Here is what I ran at the ij command prompt to create the gps_readings table:

ij> create table gps_readings (
> utc_time_date timestamp not null,
> lat varchar(15) not null,
> long varchar(15) not null,
> constraint pk_gps_readings_utc_time_date primary key(utc_time_date)
> );

Connecting the Copernicus II GPS Module

GPS Module  Beaglebone Black
VCC         P9 3
GND         P9 1
TX-B        P9 26
RX-B        P9 24

The Java Code

import java.util.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.time.LocalDate;
import java.time.ZoneId;

public class Gps {
    private static String port = "/dev/ttyS80";
    private InputStream inStream;
    private OutputStream outStream;
    // NMEA command to set Copernicus II to output $GPGLL every second.
    private static String nmeaString = "$PTNLSNM,0002,01*55\r\n"; 

    private Connection connect = null;
    private Statement statement = null;
    private static String driverClass = "org.apache.derby.jdbc.ClientDriver";
    private String jdbcURL = "";
    private static String sql = "INSERT INTO GPS_READINGS(UTC_TIME_DATE, LAT, LONG) VALUES(?,?,?)";

    // Constructor takes JDBC URL for JavaDB server as argument
    public Gps(String url) { jdbcURL = url; }

    public void recordGPS() {
        try {
            // echo & its args have to be called using an array of Strings,
            // just using a single String (as with ln command below) does 
            // not work.
            String[] configPinsCmd = { "bash", "-c", 
                "echo BB-UART1>/sys/devices/bone_capemgr.9/slots" };
            Process p = Runtime.getRuntime().exec(configPinsCmd);
            // RXTXComm library uses /dev/ttyS80, so symbolic link needed
            String lnPortCmd = "ln -s /dev/ttyO1 /dev/ttyS80";
            p = Runtime.getRuntime().exec(lnPortCmd);
            CommPortIdentifier portId = CommPortIdentifier.getPortIdentifier(port);
            SerialPort serialPort = (SerialPort)"GPS", 5000);
            // Change serial port speed as needed
            serialPort.setSerialPortParams(19200, SerialPort.DATABITS_8,
                SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
            inStream = serialPort.getInputStream();
            outStream = serialPort.getOutputStream();
            byte[] nmeaCmd = nmeaString.getBytes();
            String gpsData = "";
            outStream.write(nmeaCmd, 0, nmeaCmd.length);
            connect = DriverManager.getConnection(jdbcURL);
            PreparedStatement statement = connect.prepareStatement(sql);
            while(true) {
                if(inStream.available() > 0) {
                int b =;
                    if(b != 13) {
                        gpsData += (char)b;
                    else {
                        gpsData = gpsData.trim();
                        String[] datum = gpsData.split(",");
                        gpsData = "";
                        // Check for valid $GPGLL NMEA sentence
                        if(datum.length < 8 || !("$GPGLL").equals(datum[0]) || datum[1] == null || 
                               !("A").equals(datum[6])) {
                        else {
                            LocalDate todayUTC ="UTC"));
                            String t = datum[5].substring(0,2) + '.';
                            t += datum[5].substring(2,4) + '.';
                            t += datum[5].substring(4,6);
                            statement.setString(1, todayUTC.toString() + '-' + t);
                            statement.setString(2, datum[1] + ' ' + datum[2]);
                            statement.setString(3, datum[3] + ' ' + datum[4]);    
        catch (Exception ex) {
        finally {
            try {
            catch(Exception exc) {

    public static void main(String[] args) {
        Gps copernicus = new Gps("jdbc:derby://localhost:1527/gpsdb");

Compiling the Code

The Ubuntu distribution that came installed on my Beaglebone Black Rev. C included the Java RXTXComm library.  If you need to get it, you can run the following apt-get command to install it.

apt-get install librxtx-java

Use the following javac command to compile the code -

javac -cp /usr/share/java/RXTXcomm.jar:/usr/jdk1.8.0/db/lib/derby.jar

Running the Program at the Command Line

With the JavaDB network server running, use the following command to run the program -

java -Djava.library.path=/usr/lib/jni/ -cp /usr/share/java/RXTXcomm.jar:/usr/jdk1.8.0/db/lib/derbyclient.jar:. Gps

While the program is running, you will see the GPS GLL sentences printed out to the console.  The readings are parsed and saved to the DB table.  You can use ij to connect to the database and run a query against the table to see the entries.  Using JavaDB in network server mode allows you to query the DB table while the program is running. 

Note that the command to run the program needs the java.library.path parameter set to the location of the native library (.so file) for RXTXComm.  Be sure to include the derbyclient.jar (not derby.jar) file in the classpath (-cp).

Saturday, June 21, 2014

Installing Java 8 (JDK 8) on the Beaglebone Black

I just got my new Beaglebone Black Rev. C with 4GB of onboard storage, so I wanted to try installing the Java 8 JDK.  The process is very quick and easy.

The first step is to download the installation package from the Oracle JDK 8 for ARM Downloads page. Remember to select the radio button indicating your acceptance of the license agreement and look for the product  Linux ARM v6/v7 Hard Float ABI (file name jdk-8-linux-arm-vfp-hflt.tar.gz).

If you haven't downloaded the file directly to the Beaglebone, use scp to copy the file to the Beaglebone.

Use the following commands to unzip and untar the archive:

gunzip jdk-8-linux-arm-vfp-hflt.tar.gz
tar xfv jdk-8-linux-arm-vfp-hflt.tar

I put the JDK file tree under the /usr directory (mv jdk1.8.0 /usr/).  If you put it somewhere else, adjust the paths below accordingly.

I added the following lines to my .bashrc file to adjust the path and define JAVA_HOME in the environment:

export JAVA_HOME=/usr/jdk1.8.0
export PATH=$PATH:$JAVA_HOME/bin

Confirm that all is working by running the following command to get the current Java version:

java -version

The result should look like this -

java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
Java HotSpot(TM) Client VM (build 25.0-b70, mixed mode)

Friday, June 20, 2014

GPS for the Beaglebone Black: Sparkfun Copernicus II DIP Module - Improved & Tested with Beaglebone Black Rev. C

I published some sample code last October that showed a simple Python script that read NMEA GPS data from the Copernicus II via a serial port.  The code below is a slightly improved version that I have tested with the Beaglebone Black Rev. C (the new model with 4GB NAND) that comes with Debian installed.  This example uses the UART1 overlay included in the /lib/firmware directory.  This code also adds a couple formatting functions for the output.  The output is displayed in the terminal window.

This example assumes that you are working at the command line (via SSH or via an attached monitor, keyboard, and mouse).  This code is in Python and is not intended to run as Bonescript.


GPS Module  Beaglebone Black
VCC         P9 3
GND         P9 1
TX-B        P9 26
RX-B        P9 24


# -*- coding: utf-8 -*-
# Need to declare encoding in line above in order to use degree sign

import serial
import time
import datetime
import re
import os
from decimal import Decimal

# Use overlay file BB-UART1-00A0.dtbo from /lib/firmware
os.system("echo BB-UART1 > /sys/devices/bone_capemgr.9/slots")

# Adjust the connection speed as needed. 
# You can use Triimble Studio on your PC to detect/set speed
# if you can't figure it out. 
# BB-UART1 maps UART1 to /dev/ttyO1 (note capital letter O, 
# not zero)
serial = serial.Serial("/dev/ttyO1", baudrate=19200)

# Send NMEA config cmd to output only $GPRMC message every second
nmeaCmd = "$PTNLSNM,0100,01*56\r\n"

resp = ""

# format UTC time as hh:mm:ss
def formatTime(utc):

        return "%s:%s:%s" % (utc[0:2], utc[2:4], utc[4:6])

# format date as mm/dd/yyyy
def formatDate(date):
        return "%s/%s/20%s" % (date[2:4], date[0:2], date[4:6])

# format latitude as deg°min'sec"
def formatLat(lat):
        deg = lat[0:2]
        min = lat[2:4]
        sec = 60 * Decimal(lat[4:9])
        return "%s°%s'%0.3f\"" % (deg, min, sec)

def formatLong(long):
        deg = long[0:3]
        # If 1st digit in degrees is 0, replace with space
        if deg[0] == '0':
                deg = ' ' + deg[1:]
        min = long[3:5]
        sec = 60 * Decimal(long[5:12])
        return "%s°%s'%0.3f\"" % (deg, min, sec)

while True:
        while (serial.inWaiting() > 0):
                resp +=
                if "\r\n" in resp:
                        if "$GPRMC" in resp:
                                data = resp.split(',')
                                info = "UTC: %s  Date: %s  N Lat: %s  W Long: %s" % (
                                        formatTime(data[1]), formatDate(data[9]),
                                        formatLat(data[3]), formatLong(data[5]))
                                print info
                        resp = ""

Tuesday, June 3, 2014

C Program to Read Multiple DS18B20 1-Wire Temperature Sensors on a Beaglebone Black

Here is a fairly simple C program that reads from multiple DS18B20 One-Wire temperature sensors and prints the results (device ID and temperature for each) to the terminal.  This example uses a linked list to keep track of the attached sensors rather than fixed arrays.

For help getting started with One-Wire on the Beaglebone Black (including loading the pin configuration), see this post at Hipster Circuits.  This configuration is required before continuing.


Looking at the flat side of the DS18B20's plastic head, connect the left pin to ground on the Beaglebone Black (P9-1), the right pin to 3V3 (P9-3), and the center pin to P9-22.  A 4.7k Ohm pull-up resistor is required on the connection of the first sensor's center pin to P9-22.  If using multiple sensors, each needs to be connected to the voltage and ground; parasitic power mode does not seem to be supported.  The center (data) pins need to be connected together (with the pull-up on the connection to the BB Black).

C Code

#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
// struct to hold ds18b20 data for linked list
struct ds18b20 {
char devPath[128];
char devID[16];
char tempData[6];
struct ds18b20 *next;

// Find connected 1-wire devices. 1-wire driver creates entries for each device 
// in /sys/bus/w1/devices on Beaglebone Black.  Create linked list.
int8_t findDevices(struct ds18b20 *d) {
DIR *dir;
        struct dirent *dirent;  
struct ds18b20 *newDev;
        char path[] = "/sys/bus/w1/devices";
        int8_t i = 0;
        dir = opendir(path);
        if (dir != NULL)
                while ((dirent = readdir(dir))) {
                        // 1-wire devices are links beginning with 28-
                        if (dirent->d_type == DT_LNK &&
                                        strstr(dirent->d_name, "28-") != NULL) {
newDev = malloc( sizeof(struct ds18b20) );
                                strcpy(newDev->devID, dirent->d_name);
                                // Assemble path to OneWire device
                                sprintf(newDev->devPath, "%s/%s/w1_slave", path, newDev->devID);
newDev->next = 0;
d->next = newDev;
d = d->next;
(void) closedir(dir);
                perror ("Couldn't open the w1 devices directory");
                return 1;
return i;

int8_t readTemp(struct ds18b20 *d) {
while(d->next != NULL){
d = d->next;
int fd = open(d->devPath, O_RDONLY);
if(fd == -1)
        perror ("Couldn't open the w1 device.");
                return 1;
char buf[256];
ssize_t numRead;
        while((numRead = read(fd, buf, 256)) > 0) {
                strncpy(d->tempData, strstr(buf, "t=") + 2, 5);
                float tempC = strtof(d->tempData, NULL);
                printf("Device: %s  - ", d->devID);
                printf("Temp: %.3f C  ", tempC / 1000);
                printf("%.3f F\n\n", (tempC / 1000) * 9 / 5 + 32);
return 0;

int main (void) {
struct ds18b20 *rootNode;
struct ds18b20 *devNode;
// Load pin configuration. Ignore error if already loaded
system("echo BB-W1 > /sys/devices/bone_capemgr.9/slots 2>/dev/null");
while(1) {
rootNode = malloc( sizeof(struct ds18b20) );
devNode = rootNode;
int8_t devCnt = findDevices(devNode);
printf("\nFound %d devices\n\n", devCnt);
// Free linked list memory
while(rootNode) {
// Start with current value of root node
devNode = rootNode;
// Save address of next devNode to rootNode before deleting current devNode
rootNode = devNode->next;
// Free current devNode.
// Now free rootNode
return 0;

Compiling & Running the Code

Assuming you have the code above saved in a file called w1m.c, run the following command at the Beaglebone Black's command line to compile it and produce an executable called w1m

 gcc -Wall -o w1m w1m.c

The code should compile without warnings or errors.  You can then run ./w1m to see the output.  The program reports the number of sensors found and then lists the ID and temperature reading for each one.  If you add a sensor to the circuit, it should be detected in about a minute.  If you remove a sensor or two, they will be dropped from the list after a couple minutes, but will show a false temperature near freezing until the driver removes the entry for the disconnected sensor(s).

Press Ctrl-C to stop execution.

Monday, June 2, 2014

Installing the Java 8 Embedded JRE on the pcDuino 2

Download the Java 8 embedded JRE from  I usually download files to my desktop computer and then use SCP to copy the files to my pcDuino, though you can, of course, download directly to the pcDuino if you have a screen, keyboard, and mouse set up.

1. Check the "Accept" box in the section OTN LICENSE AGREEMENT

2. Scroll down to the section ORACLE JAVA SE EMBEDDED VERSION 8.  For the pcDuino, download "ARMv7 Linux - VFP, HardFP ABI, Little Endian." The name on the download link is ejdk-8-fcs-b132-linux-arm-vfp-hflt-03_mar_2014.tar.gz.

3. Use gunzip and tar to extract the installation files.

4. Set the JAVA_HOME environment variable to point to the JRE in the directory tree just extracted.  In my case, this is what I used.  Change the path to match where you extracted the files on your pcDuino.

    export JAVA_HOME=/media/BBerkland2/ejdk1.8.0/linux_arm_vfp_hflt/jre/

 5.  Now run the script.  I used the following command to install all aspects of the JRE.  See this document for configuration options.  Again, update that path to to match your circumstances.  The destination directory for installation (--dest) should not already exist.  

  /media/BBerkland2/ejdk1.8.0/bin/ --dest /media/BBerkland2/Java8/

The installation process may take 10 - 15 minutes, and there isn't any indication of progress.  Just let it run.  When you see the command prompt, the installation is complete.

Update your .bashrc file to update your path and permanently export the JAVA_HOME environment variable.  

You can quickly confirm that all is well by running java -version. 

Note that there is no Java 8 compiler (javac) for the pcDuino, so you will need to do development work on another machine.