On January 27th, this site will be read-only as we migrate to Oracle Forums for an improved community experience. You will not be able to initiate activity until January 30th, when you will be able to use this site as normal.

    Forum Stats

  • 3,889,553 Users
  • 2,269,759 Discussions


Java ME 8 + Raspberry Pi + Sensors = IoT World (Part 3)

Yolande Poirier-Oracle
Yolande Poirier-Oracle Member Posts: 97 Silver Badge
edited Oct 6, 2015 6:21PM in Java ME Embedded

by Jose Cruz

Learn how to connect sensors to the Raspberry Pi and control them with Java.

Part 1 of this series explained how to connect electronic sensors to the Raspberry Pi Model B using general-purpose input/output (GPIO) interfaces. Part 2 focused on using inter-integrated circuit bus (I2C) interfaces to connect sensors.

This article focuses on using universal asynchronous receiver/transmitter (UART) interfaces to connect new modules that do the following:

In addition, because we won't have all UART interfaces you need, this article describes how to convert an I2C interface to UART using the SparkFun I2C/SPI-to-UART breakout board (SC16IS750). We'll also use a little mono audio amplifier, the SparkFun module TPA2005D1.

Note: The complete example code for this NetBeans IDE 8.0.2 project can be downloaded from the attached zip file at the bottom of this article.

Enabling UART on the Raspberry Pi

UART is a serial port that consists of two signals—a transmit signal (TxD) and a receive signal (RxD)—made available on pin 8 (BCM or GPIO 14) and pin 10 (BCM or GPIO 15), respectively, on the GPIO header. You can view the Raspberry pinout here.

Remember that all GPIO pins operate at 0 and 3.3 V logic levels, not the common RS-232 serial port level of +/- 12 V. If you wish to connect a UART device, you need a board or adapter to convert the higher signal levels to the lower GPIO signal levels. For example, you can use a MAX3232CPE transceiver and some capacitors. See this tutorial.

By default, the Raspberry Pi uses its built-in UART interface as the serial console. To have control of it, we need to run a few commands to release it.

First, back up the /boot/cmdline.txt file by running the following command:

$ sudo cp /boot/cmdline.txt /boot/cmdline_backup.txt

Then, enter the following command from the command line to edit the file.

$ sudo nano /boot/cmdline.txt

Change the following line in the file, from this:

dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 
console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

to this:

dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 
elevator=deadline rootwait

Next, enter the following command from the command line to edit the /etc/inittab file:

$ sudo nano /etc/inittab

Then change the following line in the file from this:

#Spawn a getty on Raspberry Pi serial line
T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100

to this (to comment out the second line):

#Spawn a getty on Raspberry Pi serial line
#T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100

As the last step, reboot the Raspberry Pi.


Circuits We Will Create

Based on the block diagram shown in Figure 1 and the components shown Figure 2, we create the circuits shown in Figure 3.


Figure 1. Block diagram of the circuits we will create


Figure 2. Components we will use


Figure 3. Schematic of the circuits we will create


Connecting the GPS Receiver Engine Board

The EM-406a is a compact, high-performance, low power consumption GPS engine board. It uses the SiRF Star III LP Single GPS chipset, which can track up to 20 satellites at a time, and has the following features:

  • Very high sensitivity (tracking sensitivity: -159 dBm)
  • Extremely fast TTFF (Time To First Fix) at low signal levels
  • Support for the NMEA 0183 data protocol
  • Built-in SuperCap to maintain system data for rapid satellite acquisition
  • Built-in patch antenna
  • Foliage lock for weak signal tracking
  • All-in-view 20-channel parallel processing
  • Snap lock 100ms reacquisition time

Let's now connect the device to the Raspberry Pi's GND, GPS Tx to UART RxD, GPS Rx to UART TxD, and VCC 5v pins, as shown in Figure 3, and create a Java ME 8 class called GPSEM406ADevice to control the GPS device. See Listing 1.

public class GPSEM406ADevice {

    private UARTConfig config=null; //UART config parameters object
    private UART uart = null;       //UART object
    private static String nmea = ""; //NMEA protocol data read from UART event listener
    private String time = null; //Time from GPS
    private final String longitude[] ={null, null};     //Longitude read from GPS
    private final String latitude[] = {null, null};     //Latitude read from GPS
    private final String altitude[] = {null, null};     //Altitude read from GPS

Listing 1. Creating the GPSEM406ADevice class

Next, create a class constructor that initializes and activates UART using the DeviceManager API and the UARTConfig class (see Listing 2) to establish the following conditions for serial communication and activate the input data listener to receive status from the GPS device.

  • Controller Number: DeviceConfig.DEFAULT
  • Channel Number: DeviceConfig.DEFAULT
  • Baud Rate: 4800
  • Data Bits: DATABITS_8
  • Parity: PARITY_NONE
  • Stop Bits: STOPBITS_1
  • Flow control: FLOWCONTROL_NONE

public GPSEM406ADevice() throws IOException {
        //Config UART
        config = new UARTConfig(DeviceConfig.DEFAULT, DeviceConfig.DEFAULT, 4800,
        //Create UART object
        uart = (UART) DeviceManager.open(UART.class, config);
        // Initialize GPS to talk NMEA protocol
        //Create read data listener to UART 
        uart.setEventListener(UARTEvent.INPUT_DATA_AVAILABLE, new MyUARTListener());

Listing 2. Establishing the initial conditions for the GPS device and UART

The GPS_Switch_Mode_To_NMEA method (see Listing 3) initializes the GPS device to talk the NMEA protocol by using several byte commands (see explanation here) that establishes this type of text protocol.

private static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i + 1), 16));
        return data;
private void GPS_Switch_Mode_To_NMEA() {
        byte[] data = hexStringToByteArray("A0A20018810201010001010105010101000100010001000100012580013AB0B3");
        ByteBuffer buffer = ByteBuffer.allocateDirect(data.length);
            Logger.getGlobal().log(Level.FINE, "GPS Config Ok...");

Listing 3. Method to initialize the GPS device to talk the NMEA protocol

Then create the following format and get methods (see Listing 4):

  • formatTime: Format read time
  • formatLat: Format read latitude
  • formatLong: Format read longitude
  • formatAlt: Format read altitude
  • getTime: Read time
  • getLatitude: Read latitude
  • getLongitude: Read longitude
  • getAltitude: Read altitude

private String formatTime(String time) {
   return (time != null) ? time.substring(0, 2) + ":" + time.substring(2, 4) + ":" + 
time.substring(4, 6) : "";

private String formatLat(String[] pos) {
   return ((pos[0] != null) && (pos[1] != null)) ? pos[0].substring(0, 2) + 
"* " + pos[0].substring(2, 4) + "' " + pos[0].substring(5, 9) + "\" " + pos[1] : "";

private String formatLong(String[] pos) {
   return ((pos[0] != null) && (pos[1] != null)) ? pos[0].substring(0, 3) + 
"* " + pos[0].substring(3, 5) + "' " + pos[0].substring(6, 10) + "\" " + pos[1] : "";

private String formatAlt(String[] alt) {
   return ((alt[0] != null) && (alt[1] != null)) ? alt[0] + " " + alt[1] : "";

public String getTime() {
   return formatTime(time);

public String getLongitude() {
   return formatLong(longitude);

public String getLatitude() {
   return formatLat(latitude);

public String getAltitude() {
   return formatAlt(altitude);

Listing 4. Format and get methods

To read all UART data, we need to create a listener class called MyUARTListener that implements UARTEventListener with a synchronized method eventDispatched (see Listing 5).

class MyUARTListener implements UARTEventListener {
        public synchronized void eventDispatched(UARTEvent event) {
            if (event.getID() == INPUT_DATA_AVAILABLE) {
                ByteBuffer buffer = ByteBuffer.allocateDirect(10);
                try {
                    int nrocar = uart.read(buffer);
                    char c;

                    for (int i = 0; i < nrocar; i++) {
                        c = (char) buffer.get(i);
                        nmea = nmea.concat(String.valueOf(c));

                    if (nmea.contains("")) {
                        if (nmea.contains("$GPGGA")) {
                        nmea = "";
                } catch (IOException ex) {
                    Logger.getGlobal().log(Level.WARNING, ex.getMessage());

Listing 5. Listener class MyUARTListener

When data is available, we parse it with the processNMEA method (see Listing 6). We use this method to read all the GPS data into a special String that begins with the $GPGGA tag.

private void processNMEA(String message) {
    try {
        StringTokenizer tokens = new StringTokenizer(message, ",");
        // pull off the first token and check if it is the message we want
        //$GPGGA,130612.255,,,,,0,00,,,M,0.0,M,,00 (no info)
        //$GPGGA,161229.487,3723.2475,N,12158.3416,W,1,07,1.0,9.0,M,,,,0000*18 (with info)

        tokens.nextToken(); // $GPGGA position
        // Next token is the time
        time = tokens.nextToken();
        latitude[0] = tokens.nextToken();
        latitude[1] = tokens.nextToken();
        if ((latitude[0].equals("0")) || (latitude[1].equals("00"))) {
            Logger.getGlobal().log(Level.FINE, "Time: " + formatTime(time) + " - No GPS satellite link...");
        } else {
            longitude[0] = tokens.nextToken();
            longitude[1] = tokens.nextToken();
            // Skip the next three tokens
            tokens.nextToken(); // Position indicator
            tokens.nextToken(); // Satellites used
            tokens.nextToken(); // Horizontal Dilution of precision
            altitude[0] = tokens.nextToken();
            altitude[1] = tokens.nextToken();
            Logger.getGlobal().log(Level.FINE, "Time: " + getTime() + "\n"
                + " Latitude: " + getLatitude() + " Longitude: " + getLongitude() + "\n"
                + " Altitude: " + getAltitude() + "\n");
    } catch (Exception ex) {

Listing 6. Parser method processNMEA

Finally, free all resources by closing the UART object (see Listing 7).

public void close() {
   uart.setEventListener(UARTEvent.INPUT_DATA_AVAILABLE, null);

Listing 7. Closing the UART object and freeing the listener

Let's now create the Test MIDlet class called TestGPSEM406A to receive the time, latitude, longitude, and altitude from satellites, as shown in Listing 8.

public class TestGPSEM406A extends MIDlet {

    private LoggingHandler loggerHandler = LoggingHandler.getInstance();
    private GPSEM406ADevice gps;

    public void startApp() {
        try {
            gps = new GPSEM406ADevice();

        } catch (IOException ex) {
    public void destroyApp(boolean unconditional) {

Listing 8. Test MIDlet for the EM-406a GPS device

Converting I2C Interface to UART by Connecting the I2C/SPI-to-UART Breakout Board

This is a breakout board for the SC16IS750, which is a handy chip used to convert I2C or SPI serial signals to a single-channel, high-performance UART interface.  The input pins of the SC16IS750 are 5.5 V–tolerant, so this board should work with both 3.3 V and 5 V controllers. The following are some of its general features:

  • Single full-duplex UART interface
  • Selectable I2C-bus or SPI interface
  • 64-byte first-in, first-out (FIFO) transmitter and receiver
  • Full compatibility with industrial standard 16C450 and equivalent
  • Baud rates up to 5 Mb/sec in 16x clock mode
  • Auto hardware flow control using RTS/CTS
  • Auto software flow control with programmable Xon/Xoff characters
  • Single or double Xon/Xoff characters
  • Receive and transmit FIFO levels
  • Programmable special character detection
  • Line break generation and detection
  • Software reset

This chip has the following registers (addresses are shown in hexadecimal):

When LCR bit 7 = 0:

  • 00h: XHR (Receive/transmit holding register)
  • 02h: FCR (FIFO control register)
  • 03h: LCR (line control register)
  • 04h: MCR (Modem control register)
  • 05h: LSR (line status register)
  • 06h: MSR (modem status register)
  • 08h: XLVL (transmit FIFO level register)
  • 09h: RXLVL (receive FIFO level register)

When LCR bit 7 = 1:

  • 00h: DLL
  • 01h: DLH (division register)

To support these registers, create an enumeration called SC16IS750, as shown in Listing 9.

public enum SC16IS750 {

    public int cmd;

    private SC16IS750(int cmd) {
        //SC16IS740 expects a R/W bit first, 
        //followed by the 4 bit register address of the byte.
        //So shift the bits left by three bits:
        this.cmd = cmd << 3;

Listing 9. Enumeration that defines all SC16IS750 registers

Let's now connect the SC16IS750 breakout board to the Raspberry Pi's 3.3 V, SCL, SDA, and GND pins, as shown in Figure 3, and create a Java ME 8 class called SC16IS750Device with its constructor using the control address to initialize the converter registers, as shown in Listing 10.

public class SC16IS750Device extends I2CRpi {

    private static final int SC16IS750_write = 0x48;

    public SC16IS750Device() throws IOException {

Listing 10. SC16IS750Device class with its constructor establishing the control address

Then create the following operation methods (see Listing 11):

  • configUARTregs: Configure all registers to establish I2C-to-UART conversion
  • write: Write a String to buffer data
  • bytesToRead: Bytes at buffer to be read
  • read: Read all bytes at buffer

private void configUARTregs() {
     //Line Control Register: Enable Writing DLH & DLL
     //& set no Parity, 1 stop bit, and 8 bit word length
     SC16IS750.LCR.write(device, (byte) 0b10000011);

     //Division registers DLL & DLH
     // Write '96' to get 9600 baud rate
     // Assumes you have the version with the ~14MHz crystal
     // (16x9600 = 153600 = 14.7456Mhz/96)
     SC16IS750.DLL.write(device, (byte) 96);
     SC16IS750.DLH.write(device, (byte) 00);
     //Line Control Register: Disable Writing DLH & DLL
     //Same setup 
     SC16IS750.LCR.write(device, (byte) 0b00000011);

     //Modem Control Register
     //Normal Operating Mode
     SC16IS750.MCR.write(device, (byte) 0b00000000);

     //FIFO Control Register: Enable the FIFO and no other features
     SC16IS750.FCR.write(device, (byte) 0b00000111);

public void write(String cad) {
     ByteBuffer buffer = ByteBuffer.allocateDirect(cad.length());
     try {
         device.write(SC16IS750.XHR.cmd, 1, buffer);
     } catch (IOException ex) {

public int bytesToRead(){
    return SC16IS750.RXLVL.read(device);
public int read(){
    return SC16IS750.XHR.read(device);

Listing 11. Operation methods

Connecting the Text-to-Speech Module to the I2C/SPI-to-UART Breakout Board

The Emic 2 text-to-speech module is a multilanguage voice synthesizer that converts a stream of digital text into natural sounding speech. Its simple command-based interface makes it easy to integrate into any embedded system.

Here are some of its general features.

  • High-quality speech synthesis for English and Spanish languages
  • Nine predefined voice styles comprising male, female, and child
  • Dynamic control of speech and voice characteristics, including pitch, speaking rate, and word emphasis
  • Industry-standard DECtalk text-to-speech synthesizer engine (5.0.E1)
  • Communication: Asynchronous 9600 b/sec serial (8N1)
  • On-board audio power amplifier and 1/8-inch (3.5 mm) audio jack

Let's now connect the Emic 2 module's GND, SOUT, and SIN pins to the SC16IS750 breakout board's GND, RX, and TX pins, respectively, and connect its 5 V pin to the Raspberry Pi's 5 V pin, as shown in Figure 3. Then, create a Java ME 8 class called  EMIC2Device with its constructor that creates an SC16IS750 object using class SC16IS750Device, as shown in Listing 12.

public class EMICI2CDevice {

    private SC16IS750Device sc;

    // Define all messages for Emic
    private final String[] emic2Msgs = {
        "Emic 2 Ok.", //0
        "Hello my friends.", //1
        "I am testing I2C to UART converter.", //2
        "See you later.", //3
        "Bye.", //4
        "Hola como estan.", //5
        "Ahora hablo Espanol.", //6
        "Adios amigos."//7    

    public EMICI2CDevice() throws IOException {
        //I2C Emic interface using SC16IS750
        sc = new SC16IS750Device();

Listing 12. EMIC2Device class with its constructor creating an SC16IS750 object

Create the following operation methods (see Listing 13):

  • msg: Write a predefined message
  • getMsg: Get a predefined message
  • write: Write a String
  • writeCommand: Send a command
  • waitResponse: Wait for Emic 2 response characters
  • close: Close UART communication

public void msg(int msgnum) {
    Logger.getGlobal().log(Level.FINE, emic2Msgs[msgnum]);

public String getMsg(int num) {
        return emic2Msgs[num];

public void write(String cad) {
    cad = "S " + cad.concat("");
    // Wait for response from Emic-2. It responds to all commands with :

public void writeCommand(String cad) {
    cad = cad.concat("");
    // Wait for response from Emic-2. 

private void waitResponse(int nrobytes) {
    int work = 0;
    //wait two chars :\n
    while (work != nrobytes) {
        work = sc.bytesToRead();
    for (; 0 < work; work--) {

public void close() {

Listing 13. Operation methods

We can connect an headphone to the onboard 1/8-inch (3.5 mm) audio jack, but if we want to use a little speaker, the SparkFun mono audio amplifier module TPA2005D1 is recommended, as shown in Figure 3, with an additional 10K volume control potentiometer. We must connect SP- and SP+ from the Emic 2 to IN- and IN+ on the amplifier module's connector.

Let's now create the test MIDlet class called TestEMIC2 to hear the Emic 2 speak predefined messages in English and Spanish, as shown in Listing 14.

public class TestEMIC2 extends MIDlet {

    public void startApp() {
            EMICI2CDevice sc = new EMICI2CDevice();

            sc.writeCommand("L0"); //Set English
            sc.write("End of English Test.");
            sc.writeCommand("L1"); //Set Spanish
            sc.write("Fin de la prueba en Espanol.");


Listing 14. Test MIDlet for Emic 2

Performing Some Additional Configuration

Before running our TestEM406A MIDlet using NetBeans IDE 8.0.2, it is important to establish the appropriate API permissions. To do this, in the IDE, select project JavaMEDemos, and then right-click and select Properties to show the Project Properties window.  Select Application Descriptor, and then select the API Permissions tab. Include the following permission, as shown in Figure 4:

jdk.dio.uart.UARTPermission *:* , open


Figure 4. Establishing API permissions


The Raspberry Pi has a UART port that can be used for serial communication with some devices such as the EM-406a GPS device, but remember that it is very important to check voltage levels, because this port works at 3.3 V, not at the classic serial level of +/- 12 V.

By default, the UART port is used by the serial console and it must be released before you can manipulate it.

If you need to connect additional serial devices, you can use SC16IS750 modules that convert the I2C or SPI protocols to UART. You can use up to fifteen modules with distinct I2C addresses, and you can manipulate up to fifteen serial devices.

In the next article in this series, we will examine other types of sensors using other types of interfaces, such as serial peripheral interface bus (SPI).

See Also

About the Author

Jose Cruz (@joseacruzp) is a software engineer who has been working with Java since 1998. He is a lead developer of Java, Java ME, and Java EE at Ferreteria EPA C.A. in Venezuela. From an early age, his hobby has been electronics. This has led him to combine computing with electronics and develop projects where Java and embedded devices such as Arduino and Raspberry Pi are used.

Join the Conversation

Join the Java community conversation on Facebook, Twitter, and the Oracle Java Blog!