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

Version 5

    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), 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 =;
                        char c;
                        for (int i = 0; i < nrocar; i++) {
                            c = (char) buffer.get(i);
                            nmea = nmea.concat(String.valueOf(c));
                        if (nmea.contains("\r\n")) {
                            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(){
    public int read(){


    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("\r\n");
        // Wait for response from Emic-2. It responds to all commands with :
    public void writeCommand(String cad) {
        cad = cad.concat("\r\n");
        // 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!