Sunday, June 28, 2015

RFID for Intel Edison

The following example shows how to connect an ID-20LA RFID reader (125 kHz) to an Intel Edison and read RFID tags. This example reads RFID cards using a relatively simple program written in C. To keep things simple, the program just reads the card and prints the number to the terminal window.  Using a Sparkfun RFID USB Reader board makes connecting the RFID reader very easy (using the serial hookup on the board instead of the USB connection).  On the Edison side, the connection is via the UART1 pins provided by the Sparkfun GPIO block for Edison (included in the starter pack for Edison).


Note that the UART1 pins on the GPIO block connect to the Linux serial port device /dev/ttyMFD1. (See this post for information on the Edison's serial ports.)

RFID Reader Board Edison GPIO Block(UART1)
GND               GND
TXR               GP131/TX
TX                GP130/RX
VCC               3.3v

C Code

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

/* Edison's UART1 connects to /dev/ttyMFD1 */
#define SERIAL_DEV "/dev/ttyMFD1"

/* baudrasettings are defined in <asm/termbits.h>, which is
   included by <termios.h>. Change as needed, keep B 
#define BAUDRATE B9600

/* POSIX compliant source */
#define _POSIX_SOURCE 1

// Function declarations
void configPins();
int openSerial(const char *);
void handleSIGINT(int);

/* Declare variable for original serial port settings here
   so it can be accessed from handleSIGINT function 
struct termios savedTio;

/* Make descripter for serial connection global so
   handleSIGINT() can access it to restore original serial
   settings when program ends. 
int serialHandle;

// Set loop that reads serial port to run indefinitely
int run = 1; 

int main() {
   int fd, c, res;
   char buf[255];

   printf("\nScan a tag to see its ID number. Press ctrl-c to quit.\n\n");

   // Program runs until user presses ctrl-c
   signal(SIGINT, handleSIGINT);
   serialHandle = openSerial(SERIAL_DEV);

   /* Loop continuously to handle serial input */
   while (run) {     
      /*  read blocks program execution until a line terminating character is
          input, even if more than 255 chars are input. If the number
          of characters read is smaller than the number of chars available,
          subsequent reads will return the remaining chars. res will be set
          to the actual number of characters actually read. 
      res = read(serialHandle, buf, 255);
      /* set end of string, so we can printf */
      buf[res] = 0;
      printf("%s", buf, res);

// Configure & open serial port.
int openSerial(const char *serial) {
   struct termios tio;
   /* Open device for reading and writing and not as controlling tty
      because we don't want to get killed if linenoise sends CTRL-C. */
   int fd = open(serial, O_RDWR | O_NOCTTY );
   if (fd < 0) { 
      printf("\nError opening %s.\n", serial); 
   /* save current serial port settings to global var so they can be 
      restored when the program ends (see handleSIGINT). . 
   tcgetattr(fd, &savedTio);
   /* clear struct for new port settings */
   memset(&tio, 0, sizeof(tio));

   /* CRTSCTS : output hardware flow control
      CS8     : 8n1 (8bit,no parity,1 stopbit)
      CLOCAL  : local connection, no modem contol
      CREAD   : enable receiving characters 
   tio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;

   /* IGNPAR  : ignore bytes with parity errors
      otherwise make device raw (no other input processing) 
   tio.c_iflag = IGNPAR;

   /*  Raw output  */
   tio.c_oflag = 0;

   /* ICANON  : enable canonical input disable all echo functionality, and 
      don't send signals to calling program 
   tio.c_lflag = ICANON;
   /* now clean serial line & activate settings for the port */
   tcflush(fd, TCIFLUSH);
   tcsetattr(fd,TCSANOW, &tio);
   return fd;

// Function to clean up & end program when user presses ctrl-C
void handleSIGINT(int signum) {
   char *gpio[] = {"4", "40", "41"};
   char path[30];
   tcsetattr(serialHandle, TCSANOW, &savedTio);
   printf("\nProgram ending...\n");
   // Export ports for sysfs access
   int fd = open("/sys/class/gpio/unexport", O_WRONLY);
   int c;
   for(c = 0; c < 3; c++) {
      write(fd, gpio[c], strlen(gpio[c]));

Saturday, June 27, 2015

Installing Nano on an Intel Edison

I've started experimenting with an Intel Edison and the Sparkfun Starter Pack for Intel Edison.  Things have gotten off to a good start, but I missed the nano editor.  I couldn't install nano using opkg, but the following code will download the source code (using wget), compile it, and install it.

wget && tar xvf nano-2.4.1.tar.gz && cd nano-2.4.1 && ./configure && make && make install

As of June 2015, nano 2.4.1 is the latest version. Update the numbers in the line above for other versions. You can see what's available by browsing

I've been able to get C code working that reads from an I2C sensor. I'll post about that shortly.

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)