Saturday, July 12, 2014

Sample Java Code to Read Temperature from an TMP102 via I2C & Save Data to a MySQL Database Table

The Java code below reads current temperature data from the TMP102 temperature sensor using the i2cget command line utility to read the TMP102's registers.  The reading is taken every second and the result is saved to a MySQL database table.  The table contains a column for the date and time and a column for the temperature in degrees Fahrenheit.  The code below should work with Java 6, 7, or 8.  You will need to have the complete JDK installed to compile the code.

Prerequisites


The i2cget command line utility is part of the I2C Tools package.  You can install this package on the Raspberry Pi using the following apt-get command:

apt-get install i2c-tools

To install MySQL, use the following command and follow the prompts:

apt-get install mysql-server

The following command installs the Java database (JDBC) driver that allows your code to access the database:

apt-get install java-mysqldb


Database Structure


CREATE TABLE tmp102 (
  date_time        datetime NOT NULL,
  temp_f            double,
  PRIMARY KEY (date_time)
);

Java Code

import java.io.*;
import java.util.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.PreparedStatement;

public class Tmp102 {
    // i2cget command to read raw data as a word (16-bit value)
// from TMP102 sensor.  -y tells command to run 
    // without confirmation from user.
    // I2C address for TMP102 by default is 0x48.
    // Command is passed a separate String, unlike loadPinMapCmd
    // that has to be passed as an array of Strings.
    String runI2CGetCmd = "i2cget -y 1 0x48 0 w";

    Connection conn = null;
    PreparedStatement stmt = null;
    // Change gpsdb to name of your DB. Also change
    // DB user name & password
    String url = "jdbc:mysql://localhost/temperature?" +
        "user=YourDBUser&password=YourDBPassword";

    String insertSQL = "INSERT INTO tmp102(date_time, temp_f) " +
        "VALUES (now(), ?)";

    public Tmp102() {
        // Constructor sets up DB connection
        try {
            Class.forName("com.mysql.jdbc.Driver").newInstance();
            conn = DriverManager.getConnection(url);
        }
        catch(Exception ex) { ex.printStackTrace(); }
    }

    // Read temperatures from both sensors & print it out to terminal
    public void readTemperature() {
        short tempData = 0;
        double temp = 0.00;
        tempData = runI2CGet(runI2CGetCmd);
        tempData = reverseBytes(tempData);
        temp = convertToDegreesF(tempData);
        try {
            stmt = conn.prepareStatement(insertSQL);
            stmt.setDouble(1, temp);
            stmt.execute();
            System.out.printf("%.3f\n", temp);
        }
        catch(Exception ex) { ex.printStackTrace(); }
    }

    // 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;
    }

    private void closeDBConn() {
        try {
            stmt.close();
            conn.close();
        } catch(Exception exc){ exc.printStackTrace(); }
    }

    public static void main(String[] args) {
        Tmp102 temp = new Tmp102();
        try {
            while(true) {
                temp.readTemperature();
                Thread.sleep(1000);
            }
        }
        catch(Exception ex) { ex.printStackTrace(); }
        finally { temp.closeDBConn(); }
    }
}

Compiling & Running the Program

javac -cp /opt/mysql-connector-java-5.1.31/mysql-connector-java-5.1.31-bin.jar Tmp102.java

Adjust the -cp path for the MySQL-Connector .jar file to match your installation, if needed.

The following command runs the program.  The temperature readings are printed to the terminal, while the current timestamp and temperature are saved in the database. 

java -cp .:/opt/mysql-connector-java-5.1.31/mysql-connector-java-5.1.31-bin.jar Tmp102

Again, adjust the -cp path to match the location of your MySQL-Connector .jar file.

Stop the program by pressing Ctrl-C.


No comments:

Post a Comment