Sunday, December 15, 2013

Reading Multiple 1-Wire Temperature Sensors Using Java on a Raspberry Pi

This example shows how a Java program can read temperature data from multiple DS18B20 1-wire temperature sensors.  This program prints the device number and temperature from each device in a continuous loop.  It works with Java 7 or Java 8.

Before running the program below, be sure to run the following commands to load the needed kernel modules -

sudo modprobe w1-gpio
sudo modprobe w1-therm


Connections


Looking at the flat side of the DS18B20's plastic head, connect the left pin to ground, the right pin to 3V3, and the center pin to GPIO4.  A 4.7k Ohm pull-up resistor is required on the connection of the first sensor's center pin to GPIO4.  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 Raspberry Pi).


Java Code



import java.io.*;
import java.util.*;

public class w1 {
  //This directory created by 1-wire kernel modules
  static String w1DirPath = "/sys/bus/w1/devices";

  public static void main(String[] argv) throws Exception {
    File dir = new File(w1DirPath);
    File[] files = dir.listFiles(new DirectoryFileFilter());
    if (files != null) {
      while(true) {
        for(File file: files) {
          System.out.print(file.getName() + ": ");
  // Device data in w1_slave file
          String filePath = w1DirPath + "/" + file.getName() + "/w1_slave";
          File f = new File(filePath);
          try(BufferedReader 
              br = new BufferedReader(new FileReader(f))) {
            String output;
            while((output = br.readLine()) != null) {
              int idx = output.indexOf("t=");
              if(idx > -1) {
                // Temp data (multiplied by 1000) in 5 chars after t=
                float tempC = Float.parseFloat(
                    output.substring(output.indexOf("t=") + 2));
                // Divide by 1000 to get degrees Celsius
tempC /= 1000;
System.out.print(String.format("%.3f ", tempC));
float tempF = tempC * 9 / 5 + 32;
System.out.println(String.format("%.3f", tempF));
              }
            }
          }
          catch(Exception ex) {
            System.out.println(ex.getMessage());
          }
        }
      }
   } 
}

// This FileFilter selects subdirs with name beginning with 28-
// Kernel module gives each 1-wire temp sensor name starting with 28-
class DirectoryFileFilter implements FileFilter
{
   public boolean accept(File file) {
     String dirName = file.getName();
     String startOfName = dirName.substring(0, 3);
     return (file.isDirectory() && startOfName.equals("28-"));
   }
}  


Friday, December 6, 2013

C Program to Read Temperature from a 1-Wire Temperature Sensor Connected to a Raspberry Pi

The following example shows how to read the temperature from a single DS18B20 1-wire temperature sensor connected to a Raspberry Pi using code written in C.  The program reads and prints the temperature to the console until the user ends the program with a ctrl-c.  (It should be possible to read from multiple sensors chained together, but this example just uses one for simplicity).

I found this post by Matt Hawkins at Raspberry Pi Spy very helpful.

For multiple DS18B20s, see this post.

This code relies on two kernel modules that must be loaded by the following commands before the code is run:

sudo modprobe w1-gpio
sudo modprobe w1-therm

These modules make it possible to access the 1-wire sensor via the Linux file system.

Connections


Looking at the flat side of DS18B20, connect it to the Raspberry Pi as follows.

DS18B20 Pin   Raspberry Pi (Rev. B)
Left          GND
Center        GPIO4 (w/ 4.7k pull-up resistor)
Right         3V3

C Code


#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
     
int main (void) {
DIR *dir;
struct dirent *dirent;
char dev[16];      // Dev ID
char devPath[128]; // Path to device
char buf[256];     // Data from device
char tmpData[6];   // Temp C * 1000 reported by device 
char path[] = "/sys/bus/w1/devices"; 
ssize_t numRead;

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) { 
strcpy(dev, dirent->d_name);
printf("\nDevice: %s\n", dev);
}
(void) closedir (dir);
        }
else
{
perror ("Couldn't open the w1 devices directory");
return 1;
}

        // Assemble path to OneWire device
sprintf(devPath, "%s/%s/w1_slave", path, dev);
// Read temp continuously
// Opening the device's file triggers new reading
while(1) {
int fd = open(devPath, O_RDONLY);
if(fd == -1)
{
perror ("Couldn't open the w1 device.");
return 1;
}
while((numRead = read(fd, buf, 256)) > 0) 
{
strncpy(tmpData, strstr(buf, "t=") + 2, 5);
float tempC = strtof(tmpData, NULL);
printf("Device: %s  - ", dev);
printf("Temp: %.3f C  ", tempC / 1000);
printf("%.3f F\n\n", (tempC / 1000) * 9 / 5 + 32);
}
close(fd);
}
        /* return 0; --never called due to loop */
}

Compiling & Running 


Assuming the code is saved in a file called w1.c, run the following tom compile - 

gcc -Wall -std=gnu99 w1.c -o w1

Run the code by typing ./w1.  Press ctrl-c to end the program.

Monday, November 25, 2013

C Code to Read RFID Data from an Innovations ID-20LA Using the SparkfunRFID USB Reader Board

This example shows a C program that reads RFID data from an Innovations 20-LA reader using the Sparkfun RFID USB reader board.  This RFID reader board makes it easy to connect the Innovations 20-LA to the Raspberry Pi using a USB cable.

This code is based on sample serial port code by Gary Frerking that I found at the Linux Documentation Project.

This very basic program reads an RFID card and prints the card's unique number to the terminal window.  The program runs continuously until interrupted by the user (ctrl-c).

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>

#define BAUDRATE B9600
#define MODEMDEVICE "/dev/ttyUSB0"
#define TRUE 1

main()
{
        int fd, c, res;
        struct termios newtio;
        char buf[13];
        fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
        if (fd < 0) { perror(MODEMDEVICE); exit(-1); }
        bzero(&newtio, sizeof(newtio)); /* clear struct for new port settings */
        /* BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
           CRTSCTS : output hardware flow control (only used if the cable has
                     all necessary lines. See sect. 7 of Serial-HOWTO)
           CS8     : 8n1 (8bit,no parity,1 stopbit)
           CLOCAL  : local connection, no modem contol
           CREAD   : enable receiving characters */
        newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
        /* IGNPAR  : ignore bytes with parity errors
                     otherwise make device raw (no other input processing) */
        newtio.c_iflag = IGNPAR;

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

        /* ICANON  : enable canonical input
                     disable all echo functionality, and don't send signals to calling
                     program */
        newtio.c_lflag = ICANON;
        /* now clean the modem line and activate the settings for the port */
        tcflush(fd, TCIFLUSH);
        tcsetattr(fd,TCSANOW,&newtio);
        while (TRUE) { /* loop continuously */
                res = read(fd, buf, 13);
                buf[res] = 0;
                printf("%s", buf, res);
        }
}

C Program to Read Copernicus II GPS Data via Serial on a Raspberry Pi

I've already posted a couple examples of using Java to read GPS data from a Copernicus II GPS module connected to a Raspberry Pi ("Sample Java Code to Read GPS Data from a Sparkfun Copernicus II DIP Module on a Raspberry Pi" & "Java Program to Read GPS Data from a Sparkfun Copernicus II GPS & Store it in a MySQL Database on a Raspberry Pi").

The following example is written in C.  It shows how to send an NMEA command over the serial port to the GPS module to configure the output and then reads the GPS data from the module and prints it to the terminal window. The program runs until the user presses ctrl-c.

This code is based on sample serial port code by Gary Frerking that I found at the Linux Documentation Project.  I also posted a version of this code for Beaglebone Black on my Brad's µC Blog.

For more information about the commands to configure the Copernicus II, see Appendix C of the Copernicus II manual.  Each command must include a 2-digit checksum after the asterisk.  See this page for an online tool to calculate the checksum.


If you need a way to test your GPS module or adjust its settings, you may find Trimble GPS Studio helpful. You can download a free copy for Windows here.

Connections


Copernicus II Raspberry Pi
VCC           3.3V 
GND           GND 
TX-B          GPIO15 (RXD) (P1-10)
RX-B          GPIO14 (TXD) (P1-08)


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>

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

/* change this definition for the correct port */
#define MODEMDEVICE "/dev/ttyAMA0" 

#define _POSIX_SOURCE 1 /* POSIX compliant source */

#define FALSE 0
#define TRUE 1

main()
{
    int fd, c, res;
    struct termios oldtio, newtio;
    char buf[255]; 
    /* Open modem device for reading and writing and not as controlling tty
       because we don't want to get killed if linenoise sends CTRL-C. */
    fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
    if (fd < 0) { perror(MODEMDEVICE); exit(-1); }

    bzero(&newtio, sizeof(newtio)); /* clear struct for new port settings */

    /* BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
       CRTSCTS : output hardware flow control (only used if the cable has
                 all necessary lines. See sect. 7 of Serial-HOWTO)
       CS8     : 8n1 (8bit,no parity,1 stopbit)
       CLOCAL  : local connection, no modem contol
       CREAD   : enable receiving characters */
    newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;

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

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

    /* ICANON  : enable canonical input
       disable all echo functionality, and don't send signals to calling program */
    newtio.c_lflag = ICANON;
    /* now clean the modem line and activate the settings for the port */
    tcflush(fd, TCIFLUSH);
    tcsetattr(fd,TCSANOW,&newtio);
    // NMEA command to ouput all sentences
    // Note that this code & format values in manual are hexadecimal
    write(fd, "$PTNLSNM,273F,01*27\r\n", 21);
    /* terminal settings done, now handle input*/
    while (TRUE) {     /* loop continuously */
        /*  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(fd, buf, 255);
        buf[res] = 0;             /* set end of string, so we can printf */
        printf("%s", buf, res);
    }
}


Compiling & Running the Code


Compiling the code at the command line is very easy.   Assuming that the source code is saved in a file called gps.c -

gcc gps.c -o gps

And the following will run the new program until the user presses control-c -

./gps

Tuesday, October 8, 2013

Reading from an I2C Device with Java & JNA on a Raspberry Pi

Here is a brief example of using Java Native Access (JNA) with a simple C shared library to access an I2C device (TMP102 temperature sensor) on a Raspberry Pi.

The 09/25/2013 release of Raspbian Linux has Java 7 already installed.  The version of Java in this release supports "hard float," so it works better with JNA than "soft float." This is important in this example because the C code that accesses the TMP102 returns a float (which doesn't work on "soft float" versions of Java, such as the one found at present on the Beaglebone Black).

To use JNA, you need jna.jar and jna-platform.jar from Git Hub and put them in the /usr/share/java directory.

C Code for Shared Library


The code for the shared library consists of two files: tmp102.h and tmp102.c.

The tmp102.h file is only one line -

extern float getTempC();

Here is the tmp102.c file -

#include <stdio.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include "tmp102.h"

float getTempC() {
        int devHandle;
        int readBytes;
        char b[2];
        // initialize buffer
        b[0] = 0x00;
        int devI2CAddr = 0x48;
        // open device on /dev/i2c-1
        if ((devHandle = open("/dev/i2c-1", O_RDWR)) < 0) {
                printf("Error: Couldn't open device! %d\n", devHandle);
                return 1;
        }
        // connect as i2c slave
        if (ioctl(devHandle, I2C_SLAVE, devI2CAddr) < 0) {
                printf("Error: Couldn't find device on address!\n");
                return 1;
        }
        // begin transmission and request acknowledgement
        readBytes = write(devHandle, b, 1);
        if (readBytes != 1)
        {
                printf("Error: No ACK-Bit, couldn't establish connection!");
        }
        else
        {
                // read response
                readBytes = read(devHandle, b, 2);
                if (readBytes != 2)
                {
                        printf("Error: Received no data!");
                }
                else
                {
                        float t = (((b[0] << 8) | b[1]) >> 4) * 0.0625;
                        return t;
                }
        }
        // close connection and return
        close(devHandle);
        return 1;
}

 Run the following command to compile this code as an .so file.

gcc tmp102.c -o tmp102.so -shared

Place the resulting .so file (tmp102.so) to the same directory as the JNA JAR files.

Java Code


Two Java files are required, an interface (Tmp102Library.java) and the Java code that uses the interface to call the method via JNA (tmp102.java).

Here is the code for the interface -

 import com.sun.jna.Library;
import com.sun.jna.Native;

public interface Tmp102Library extends Library {
   Tmp102Library INSTANCE = (Tmp102Library) Native.loadLibrary("tmp102.so",
        Tmp102Library.class);
   float getTempC();
}

Here is the Java program itself - 

import com.sun.jna.Library;

public class tmp102 {
    public static void main(String[] args) {
        System.setProperty("jna.library.path","/usr/share/java");
        try {
            float temp = Tmp102Library.INSTANCE.getTempC();
            System.out.println("Temp: " + Float.toString(temp));
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

}

Run these commands to compile the Java -

javac -cp /usr/share/java/jna-4.0.0.jar:/usr/share/java/jna-platform-4.0.0.jar:. tmp102.java


javac -cp /usr/share/java/jna-4.0.0.jar:/usr/share/java/jna-platform-4.0.0.jar Tmp102Library.java

Then use the following to run the program -

java -cp /usr/share/java/jna-4.0.0.jar:/usr/share/java/jna-platform-4.0.0.jar:. tmp102



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



Saturday, September 28, 2013

Sample Java Code to Read GPS Data from a Sparkfun Copernicus II DIP Module on a Raspberry Pi

The 09/25/2013 version of Raspbian Linux includes Java 7.  This example provides very basic Java code that reads GPS data via a serial port and prints the results to the console. My intention is not to provide an example of good object-oriented programming or thorough coverage of the RXTX library.  This post is about a minimum example of Java serial communication on the Raspberry Pi.

I found this post by Johannes Eickhold very helpful.

I used nano in a terminal window on the Raspberry Pi to edit the code.

Prerequisites


  1. As noted above, this example assumes you have the 09/25/2013 (or later) version of Raspbian.  
  2. Make sure the serial port is available as described in "Freeing UART on the Pi." 
  3. Install the Java RXTX library:  apt-get install librxtx-java 
  4. Create soft link to comm port:  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. 


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.*;

public class gps {
    private static InputStream inStream;
    public static void main(String[] args) {
        try {
            CommPortIdentifier portId = CommPortIdentifier.getPortIdentifier("/dev/ttyS80");
            SerialPort serialPort = (SerialPort) portId.open("GPS application", 5000);
            // Change baud rate if not 115200
            serialPort.setSerialPortParams(115200, SerialPort.DATABITS_8, 
                 SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
            serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
            inStream = serialPort.getInputStream();
            String reading ="";
            while(true) {
                if(inStream.available() > 0) {
                    int b = inStream.read();
                    System.out.print((char)b);
                }
            }
        } catch (Exception ex) {
                ex.printStackTrace();
        }
    }
}

Compiling & Running


When compiling, be sure to include the RXTX JAR file in the classpath.   

javac -cp /usr/share/java/RXTXcomm.jar gps.java

When you run the program, you will need to include the RXTX JAR file in the classpath and also tell the Java runtime where to find the .so library files for RXTX:

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

(The command above assume your current working directory contains the gps.class file.)  

Tuesday, July 9, 2013

Logging GPS Data to a MySQL Database Using the Adafruit Ultimate GPS Breakout

The Adafruit Ultimate GPS Breakout (ver. 3) works nicely with the Raspberry Pi.  This quick example shows how to log GPS data from this GPS module to a MySQL database table.

Connections


Adafruit GPS Raspberry Pi
VIN          3V3 (P1-01)
GND          Ground (P1-06)
RX           GPIO 14 (TXD) (P1-08)
TX           GPIO 15 (RXD) (P1-10)

The RXD and TXD pins on the Pi connect to the Linux serial device ttyAMA0. By default, though, this device is used for console output. Follow the 3 steps on the Adafruit Learning System page, "Freeing UART on the Pi."


Software


In addition to installing MySQL on the Raspberry Pi, you will need to have the python-serial and python-mysqldb packages installed (using apt-get).

The structure of the gps database table is very simple. Here is the output from MySQL's describe gps -

+-----------+----------+------+-----+---------+-------+
| Field     | Type     | Null | Key | Default | Extra |
+-----------+----------+------+-----+---------+-------+
| n_lat     | float    | NO   |     | NULL    |       |
| w_long    | float    | NO   |     | NULL    |       |
| date_time | datetime | NO   | PRI | NULL    |       |
+-----------+----------+------+-----+---------+-------+


Python Code


import serial
import time
import datetime
import os
import sys
import MySQLdb as mdb

try:
    serial = serial.Serial("/dev/ttyAMA0", baudrate=9600)
    time.sleep(1)
    con = mdb.connect('localhost', 'YourDBUser', 'YourDBPasswd', 'YourDB');
    cur = con.cursor()

except:
    print "Error opening serial port."
    sys.exit(1)

resp = ""

try:
    while True:
        while (serial.inWaiting() > 0):
            resp += serial.read()
            if "\r\n" in resp:
                if "$GPRMC" in resp:
                    data = resp.split(',')
                        if data[2] == 'A':
                            dom = data[9][0:2]
                            month = data[9][2:4]
                            year = int(data[9][4:6]) + 2000
                            date = "%d-%s-%s" % (year, month, dom)
                            hour = data[1][0:2]
                            min = data[1][2:4]
                            sec = data[1][4:6]
                            t = "%s:%s:%s" % (hour, min, sec)
                            dateTime = "%s %s" % (date, t)
                            north = data[3]
                            west = data[5]
                            sql = "insert into gps(n_lat, w_long, date_time) values(%s, %s, %s)" % (north, west, t)
                            print sql
                            cur.execute(sql)
                            print "Rows inserted: %s" % cur.rowcount
                            con.commit()
                            time.sleep(0.5)
                            resp = ""
except:
    print sys.exc_info()[0]

finally:
    if con:
        con.close()
    serial.close()

Saturday, May 25, 2013

RFID via USB for the Raspberry Pi Using the Innovations ID-20LA & Sparkfun RFID USB Board

The Innovations ID-20LA is a 125 kHz RFID tag reader that works with input voltages from 2.8 to 5 volts. The Sparkfun RFID USB Reader (Board) provides a socket for the ID-20LA (with its 2mm pin spacing) a mini-USB (B) connector, and broken out pins for a serial connection.

Using the mini-USB connection, it is very easy to connect it to the Raspberry Pi.  The Linux distribution that comes installed on the Raspberry Pi includes the FTDI-SIO driver/kernel module, so no additional drivers are needed. When connected to the RPi, the RFID reader is mapped to the serial device /dev/ttyUSB0.

For a Python script to read from a serial device, you do need to install the Python Serial package (apt-get install python-serial).

Python Code


import serial
serial = serial.Serial("/dev/ttyUSB0", baudrate=9600)

code = ''

while True:
        data = serial.read()
        if data == '\r':
                print(code)
                code = ''
        else:
                code = code + data

Note (11/12/2013):  You will need to free up the serial port on the Pi.  For help doing this, see the Adafruit tutorial at http://learn.adafruit.com/adafruit-nfc-rfid-on-raspberry-pi/freeing-uart-on-the-pi.

Saturday, May 18, 2013

TCS34725 RGB Color Sensor & the Raspberry Pi

The TCS34725 RGB color sensor board from Adafruit works with the Raspberry Pi using an I2C connection. You can find the datasheet here.

The Python example below reports the clear, red, green, and blue light levels for a given sample (printing them to the console).

Connections


TCS34725  RPi
SDA       P3 GPIO 0 (SDA)
SCL       P5 GPIO 1 (SCL)
3V3       P1 3V3
GND       P9



Python Code


import smbus
import time
bus = smbus.SMBus(1)
# I2C address 0x29
# Register 0x12 has device ver. 
# Register addresses must be OR'ed with 0x80
bus.write_byte(0x29,0x80|0x12)
ver = bus.read_byte(0x29)
# version # should be 0x44
if ver == 0x44:
print "Device found\n"
bus.write_byte(0x29, 0x80|0x00) # 0x00 = ENABLE register
bus.write_byte(0x29, 0x01|0x02) # 0x01 = Power on, 0x02 RGB sensors enabled
bus.write_byte(0x29, 0x80|0x14) # Reading results start register 14, LSB then MSB
while True:
data = bus.read_i2c_block_data(0x29, 0)
clear = clear = data[1] << 8 | data[0]
red = data[3] << 8 | data[2]
green = data[5] << 8 | data[4]
blue = data[7] << 8 | data[6]
crgb = "C: %s, R: %s, G: %s, B: %s\n" % (clear, red, green, blue)
print crgb
time.sleep(1)
else: 
print "Device not found\n"


To keep this example simple, I have left the timing/power consumption for the analog to digital converters on the sensor board and sensor gain at their default values. For more information about these (and other settings) see the datasheet.

Saturday, April 13, 2013

Serial (UART) Communication between a Netduino Plus 2 & a Raspberry Pi

This code is part of a small experiment to work out how to send data between a Raspberry Pi and a Netduino Plus 2 via a serial (UART) connection. See this posting on one of my Arduino/Netduino blog for more information (including notes on how the two devices are wired together).

This code waits for a '@', '$', or '#' sent as a 1-byte "command" from the Netduion. The Raspberry Pi then responds with the requested information. The end of the response is marked with a linefeed (0x0A) character.


Python Code


import serial
import datetime

ser = serial.Serial("/dev/ttyAMA0", baudrate=115200)
while True:
        # Read 1-byte command from Netduino
        c = ser.read()
        # @ = get full date & time
        if c == '@':
                now = datetime.datetime.now()
                ser.write(str(now))
                ser.write('\x0A')
        # $ = get date
        elif c == '$':
                today = datetime.date.today()
                ser.write(str(today))
                ser.write('\x0A')
        # # = get time of day
        elif c == '#':
                now = datetime.datetime.now()
                time = "%02d:%02d:%02d" % (now.hour, now.minute, now.second)
                ser.write(time)
                ser.write('\x0A')

Saturday, April 6, 2013

Text to Speech with a EMIC2 & a Raspberry Pi

The EMIC2 text to speech module does not require any special libraries and it communicates with the controller using a serial connection, so it is not difficult to get it working with a Raspberry Pi. Below is an example that uses Python to send messages to the EMIC2.  

The EMIC2 is a 5V device, so a logic level converter is required on the serial connection to and from the Raspberry Pi.

For audio output, I have used a cheap thin speaker from Sparkfun, but you can also use the headphone jack on the module.

The RXD and TXD pins on the Pi connect to the Linux serial device ttyAMA0. By default, though, this device is used for console output. Follow the 3 steps on the Adafruit Learning System page, "Freeing UART on the Pi."

Connections


EMIC2  Logic Level Converter  Raspberry Pi
GND    HV GND     ----->      GND
5V     HV HV      ----->      5V
SOUT   HV RXI     LV RXO      RXD
SIN    HV TXO     LV TXI      TXD
                  LV LV       3V3
                  LV GND      GND

Connect SP- & SP+ to the speaker.

    

Python Code


The following demonstration code counts out load. Depending on your actual output, ou may need to experiment with the time.sleep() calls to get the values right.

import serial
import time

serial = serial.Serial("/dev/ttyAMA0", baudrate=9600)
serial.open()
serial.write("\n")
time.sleep(1)
serial.write("V15\n") # Adjust volume
c = 0
while True:
        serial.write("\n")
        time.sleep(0.75)
        data = serial.read()
        if data == ':':
                buffer = "S%d" % (c)
                c = c + 1
                serial.write(buffer)
                time.sleep(0.5)
        else:
                time.sleep(0.5)

serial.close()

For documentation on the various EMIC2 commands, see the manual.
      




Wednesday, April 3, 2013

Reading Time & Date from a Chronodot Using Python with a Raspberry Pi

Here is a quick example of how to read the time and date from a Chronodot using the Python SMBus module (for I2C communication).

Connections


Chronodot   Raspberry Pi
GND         GND
VCC         3V3
SCL         SCL0
SDA         SDA0

The Raspberry Pi has built-in pull-up resistors on the SCL and SDA lines, so external pull-up resistors are not needed.

Code



import smbus
import time
import time
bus = smbus.SMBus(1)
address = 0x68
data = bus.read_i2c_block_data(address, 0)
ss = (data[0]/16*10) + (data[0]%16)
mm = (data[1]/16*10) + (data[1]%16)
hr = (data[2]/16*10) + (data[2]%16)
day = (data[3]/16*10) + (data[3]%16)
date = (data[4]/16*10) + (data[4]%16)
month = (data[5]/16*10) + (data[5]%16)
year = (data[6]/16*10) + (data[6]%16)
buffer = "%02d:%02d:%02d %02d/%02d/%02d" % (hr, mm, ss, month, day, year)
print buffer