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.

Connections


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.io.*;
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);
         p.waitFor();
      }
      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);
         p.waitFor();
         // 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 {
            temp.readTemperatures();
            Thread.sleep(1000);
         }
         catch(Exception ex) { ex.printStackTrace(); }
      }
   }
}

Compiling & Running the Program

The program is very easy to compile -

javac TwoTmp102.java

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

java -cp . TwoTmp102

End the program using Ctrl-C.

No comments:

Post a Comment