Thursday, August 18, 2016

Intel Edison Digital IO as Output with Java

Arduino IDE is very simple and fast development tools to create application based on Arduino in Intel Edison. Anyway, I was wondering if we can use java language to build application in Intel Edison rather than Arduino IDE, because when I start the Edison it already have openjdk.

Before we start, lets take a look at "Intel Edison Kit for Arduino Hardware Guide" we will find Arduino pin table as seen below. These table explain which GPIO address in linux substitute to Arduino Uno GPIO pin. There are two SoC pin modes you can configure: 0 as GPIO and 1 as specific pin usage.

As an example we set digital IO pin 13 as output, because Intel Edison Arduino Kit already have Led connected to pin 13 the same as Arduino Uno.
If, we look at the table above there is a note before we configure digital IO we need to set pin 214 (TRI_STATE_ALL) to low, after complete we have to set pin 214 to high again. Here are the step by step:
  1. Set pin 214 to low
  2. export pin 261, 229 and 40
  3. Set pin 261 as output enabled (high)
  4. Set pin 229 to high for pullup enable or low to disable
  5. Set mode 0 for pin 40 as digital IO
  6. Set pin 214 to high
  7. To set GPIO 13 high, set pin 40 value to high
  8. To set GPIO 13 low, set pin 40 value to low  

How do we configure it in linux? Now, connect and logon to your Intel Edison remotely with SSH tools (putty). At prompt type:
echo low > /sys/class/gpio/gpio214/direction
# prepare io pin to be use
echo –n “261” > /sys/class/gpio/export
echo –n “229” > /sys/class/gpio/export
echo –n “40” > /sys/class/gpio/export
echo high > /sys/class/gpio/gpio261/direction
echo high > /sys/class/gpio/gpio229/direction
echo mode0 > /sys/kernel/debug/gpio_debug/gpio40/current_pinmux
echo high > /sys/class/gpio/gpio214/direction
# set output value for gpio pin 13 to high
echo high > /sys/class/gpio/gpio40/direction
# set output value for gpio pin 13 to low
echo low > /sys/class/gpio/gpio40/direction

Don’t forget, when you’ve done using gpio just remove configuration by unexport all used pin as an example to remove pin 40:
echo –n “40” > /sys/class/gpio/unexport

If we not remove, when we start the same pin and export it, it will show warning message “Device or resource busy”. But, you can still using it. By default pin 214 already export when we start Intel Edison, so you don’t need to export it.

Now, how do we run it from java? If you look at those script you’ll find 4 function; export, unexport, direction/write and mode. In here we describe it as

1. GPIO configuration constants
// const declaration for using GPIO
final static String _GPIO_EXPORT = "/sys/class/gpio/export"; // prepare pin export
final static String _GPIO_UNEXPORT = "/sys/class/gpio/unexport"; // prepare remove pin
final static String _GPIO_IO_VALUE = "/sys/class/gpio/gpio"; // prepare io pin value/direction
final static String _GPIO_MODE = "/sys/kernel/debug/gpio_debug/gpio"; // prepare pin mode

2. Function for export GPIO pin
// this function is use for export io pin
// example: echo –n “40” > /sys/class/gpio/export
private static void gpio_export(int iopin) {
        try {
            OutputStream ioExport = new FileOutputStream(_GPIO_EXPORT);
            OutputStreamWriter ioExportWrite = new OutputStreamWriter(ioExport);
            ioExportWrite.write(Integer.toString(iopin));
            ioExportWrite.close();
        }
        catch (Exception ex) {
            System.out.println("GPIO Export Error: " + ex.toString());
        }  
    }

3. Function for write value to GPIO pin (direction)
    private static void gpio_write(int iopin, int value) {
        try {
            OutputStream ioDirection = new FileOutputStream(_GPIO_IO_VALUE + Integer.toString(iopin) + "/direction");
            OutputStreamWriter ioDirectionWrite = new OutputStreamWriter(ioDirection);
            if (value == 0) {
                ioDirectionWrite.write("low"); // set output to high state
            }
            else {
                ioDirectionWrite.write("high"); // set output to low state
            }
            ioDirectionWrite.close();
        }
        catch (Exception ex) {
            System.out.println("GPIO Direction Error: " + ex.toString());
        }  
    }

4. Function for set GPIO pin mode
    private static void gpio_digital(int iopin) {
        try {
            OutputStream ioMode = new FileOutputStream(_GPIO_MODE + Integer.toString(iopin) + "/current_pinmux");
            OutputStreamWriter ioModeWrite = new OutputStreamWriter(ioMode);
            ioModeWrite.write("mode0");
            ioModeWrite.close();
        }
        catch (Exception ex) {
            System.out.println("GPIO Mode Error: " + ex.toString());
        }  
    }

You have at least 3 function for running digital IO pin as output. For unexport the GPIO from linux you just use the same function as gpio_export except you need to use _GPIO_UNEXPORT const. Here are the complete example for configure GPIO pin 13 (just create gpiotest project from you Netbeans):

package gpiotest;
import java.io.*;
public class Gpiotest {
   
    final static String _GPIO_EXPORT = "/sys/class/gpio/export";
    final static String _GPIO_UNEXPORT = "/sys/class/gpio/unexport";
    final static String _GPIO_IO_VALUE = "/sys/class/gpio/gpio";
    final static String _GPIO_MODE = "/sys/kernel/debug/gpio_debug/gpio";
    final static int _SHIELD_PIN13 = 40;
   
    public static void main(String[] args) {
        // TODO code application logic here
        int iOutValue = 0;

        try {
            gpio_write(214, 0);
            // set IO Pin 13 as output
            gpio_export(261);
            gpio_export(229);
            gpio_export(_SHIELD_PIN13);
            gpio_write(261, 1); // output
            gpio_write(229, 1); // pull up enable
            gpio_digital(_SHIELD_PIN13);
           
            gpio_write(214, 1);
       
            while (true) {
                if (iOutValue == 0) {
                    gpio_write(_SHIELD_PIN13, iOutValue);
                    iOutValue = 1;
                }
                else {
                    gpio_write(_SHIELD_PIN13, iOutValue);
                    iOutValue = 0;
                }
               
                Thread.sleep(1000);
            }
        }
        catch (Exception ex) {
            System.out.println("Main App Error: " + ex.toString());
        }
       
    }
   
    private static void gpio_export(int iopin) {
        try {
            OutputStream ioExport = new FileOutputStream(_GPIO_EXPORT);
            OutputStreamWriter ioExportWrite = new OutputStreamWriter(ioExport);
            ioExportWrite.write(Integer.toString(iopin));
            ioExportWrite.close();
        }
        catch (Exception ex) {
            System.out.println("GPIO Export Error: " + ex.toString());
        }  
    }

    private static void gpio_write(int iopin, int value) {
        try {
            OutputStream ioDirection = new FileOutputStream(_GPIO_IO_VALUE + Integer.toString(iopin) + "/direction");
            OutputStreamWriter ioDirectionWrite = new OutputStreamWriter(ioDirection);
            if (value == 0) {
                ioDirectionWrite.write("low");
            }
            else {
                ioDirectionWrite.write("high");
            }
            ioDirectionWrite.close();
        }
        catch (Exception ex) {
            System.out.println("GPIO Direction Error: " + ex.toString());
        }  
    }

    private static void gpio_digital(int iopin) {
        try {
            OutputStream ioMode = new FileOutputStream(_GPIO_MODE + Integer.toString(iopin) + "/current_pinmux");
            OutputStreamWriter ioModeWrite = new OutputStreamWriter(ioMode);
            ioModeWrite.write("mode0");
            ioModeWrite.close();
        }
        catch (Exception ex) {
            System.out.println("GPIO Mode Error: " + ex.toString());
        }  
    }
}

If you having problem to run and code java remotely to your Intel Edison, you may look at my “Intel Edison with Netbeans” tutorial. 

No comments:

Post a Comment