Monday, September 30, 2013

Java Program to Read GPS Data from a Sparkfun Copernicus II GPS & Store it in a MySQL Database on a Raspberry Pi

The following is a very minimal example of how to read GPS data from a Sparkfun Copernicus II GPS board and save the readings to a MySQL database table on the Raspberry.

Prerequisites


  1. 09/25/2013 version of Raspbian Linux (includes Java 7)
  2. Make sure the serial port is available as described in "Freeing UART on the Pi." 
  3. Install the Java RXTX library:  sudo apt-get install librxtx-java
  4. Create soft link to comm port:  sudo ln -s /dev/ttyAMA0 /dev/ttyS80 The RXTX library can't find /dev/ttyAMA0.  You will need to re-create this symbolic link whenever you reboot the Raspberry Pi. 
  5. Install MySQL on the Raspberry Pi: apt-get install mysql-server-5.5 
  6. Get the platform-independent version of the MySQL Connector/J JDBC driver. Place the  mysql-connector-java-5.1.26-bin.jar (ver. number may vary) in the /usr/share/java/ directory. 
  7. The database table (gps) consists of two DOUBLE columns: n_lat, w_long, and a DATETIME column (that is also the primary key). 

Connections


Copernicus II Raspberry Pi
VCC           3.3V 
GND           GND 
TX-B          GPIO15
RX-B          GPIO14

Java Code


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

public class gps {
    static Connection conn = null;
    static PreparedStatement stmt = null;
    // Change gpsdb to name of your DB. Also change
    // DB user name & password
    static String url = "jdbc:mysql://localhost/gpsdb?" +
                "user=bberkland&password=Test1234";
    static String insertSQL = "INSERT INTO gps(n_lat, w_long, date_time) " +
        "VALUES (?, ?, now())";
    static String port = "/dev/ttyS80";
    static InputStream inStream;
    static OutputStream outStream;
    static String gpsData = "";

    public static void main(String[] args) {
        try {
            Class.forName("com.mysql.jdbc.Driver").newInstance();
            conn = DriverManager.getConnection(url);
            CommPortIdentifier portId = CommPortIdentifier.getPortIdentifier(port);
            SerialPort serialPort = (SerialPort) portId.open("GPS", 5000);
            // Change serial port speed as needed
            serialPort.setSerialPortParams(115200, SerialPort.DATABITS_8,
                SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
            serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
            inStream = serialPort.getInputStream();
            outStream = serialPort.getOutputStream();
            // Send NMEA command to set Copernicus II to 
            // output $GPGLL message every second.
            String nmeaString = "$PTNLSNM,0002,01*55\r\n";
            byte[] nmeaCmd = nmeaString.getBytes();
            String gpsData = "";
            outStream.write(nmeaCmd, 0, nmeaCmd.length);
            while(true) {
                if(inStream.available() > 0) {
                    int b = inStream.read();
                    if(b != 13) {
                        gpsData += (char)b;
                    }
                    else {
                        System.out.println(gpsData);
                        String[] datum = gpsData.split(",");
                        gpsData = "";
                        if(datum.length < 8 || datum[1] == null) {
                                continue;
                        }
                        stmt = conn.prepareStatement(insertSQL);
                        stmt.setDouble(1, Double.parseDouble(datum[1]));
                        stmt.setDouble(2, Double.parseDouble(datum[3]));
                        stmt.execute();
                    }
                }
            }
        } catch (Exception ex) {
                ex.printStackTrace();
        } finally {
            try {
                stmt.close();
                conn.close();
            } catch (Exception exc){
                exc.printStackTrace();
            }
        }
    }
}

Compiling & Running the Code


javac -cp /usr/share/java/RXTXcomm.jar:/usr/share/java/mysql-connector-java-5.1.26-bin.jar gps.java

java -Djava.library.path=/usr/lib/jni/ -cp /usr/share/java/RXTXcomm.jar:/usr/share/java/mysql-connector-java-5.1.26-bin.jar:. gps



5 comments:

  1. Hi, first of all i wanted to thank you for this post, because this has really helped me. Now i want to know if you could help me with an issue i have, when i am running this program i get this error:
    RXTX Warning: Removing stale lock file. /var/lock/LCK..ttyS80
    and nothing more.
    Thanks.

    ReplyDelete
    Replies
    1. Hi Jack -

      If you try running the Java program as root, do you have the same problem?

      Delete
    2. Hi Jack -

      I am sometimes able to reproduce the warning about the deletion of the lock file, but the code still runs just fine and produces the expected output. I wonder if maybe I'm looking in the wrong place for the problem. Maybe your GPS unit's baud rate doesn't match the rate you're setting for the serial port. If the baud rater is wrong, I can reproduce the problem of no output after the warning message. There is no output because the baud rate is wrong. Try changing the baud rate in the code or hook your GPS up to Trimble Studio and see what its current baud rate is. If you don't have it already, you can find Trimble Studio for the Copernicus II at http://www.trimble.com/embeddedsystems/copernicus2_support.asp?Nav=Collection-71144.

      --Brad

      Delete
  2. Hi Brad this is not working for me :D
    I have done some tests, first the code runs until "if(inStream.available() > 0)" looks like if the data is not avaliable.
    Second, i have tried all baud rates and neighter of them works.
    Third, i have tried the same code in the laptop without the raspberry pi and it works perfectly.
    I don't know what else to do.
    Thanks!

    ReplyDelete