Raspberry Pi4j

      在〈Raspberry Pi4j〉中尚無留言

Java控制GPIO

在樹莓派板子上使用Java控制樹莓派的GPIO, 需借助第三方SDK : Pi4j. Pi4j是使用wiringpi封裝而成, 不僅可操控GPIO, 還可以使用I2C及SPI協定來與硬体設備進行溝通

在樹莓派板子上運行的應用程式, 若要使用GPIO與各種零件互動, 就需要特別的函數庫. 通常是由C語言撰寫. 樹莓派的GPIO函數庫為 “WiringPi”, 由英格蘭的Gordon Hendersonm開發, 採用GNU LGPLv3授權. WiringPi的網站為http://wiringpi.com/

若要使用Java控制GPIO, 需透過JNI與C語言WiringPi函數庫互動. 樹莓派使用Pi4J SDK. Pi4J是目前最常用的Java GPIO類別庫, 由Robert Savage與Chris Walzl共同開發. 官方網站是http://pi4j.com/

Pi4J在2015/04/18發表1.0正式版本. 請注意, 1.0及1.1版本無法使用在Pi 2 及Pi 3型號的板子. 因為這二個型號使用 BCM2835以上的SOC, 1.0及1.1版本不認得這顆SOC. 目前最新的版本為1.2版, 此版才認得BCM2835以上的SOC.

Pi4J主要的功能與特性如下

Java App透過Pi4J提供的類別, 調用WiringPi函數庫與GPIO互動
設定GPIO針腳的控制方向(輸入或輸出)
控制與讀取GPIO針腳的狀態
監聽GPIO針腳狀態的改變
支援I²C與SPI通訊協定

Pi4J SDK與WiringPi 函數庫的架構圖如下

pi4j

安裝Jdk

sudo apt-get install openjdk-8-jdk

在Ubuntu中執行上述指令時, 會自動安裝openjdk-8-jre. 目前(2018/12/16)只有openjdk-8, 使用 8.0的版本即可, 不需要用到jdk 9.

另外, 請不要再用Oracle的版本了, Oracle的jdk11並沒有jre,  所以無法執行netbeans9

安裝netbeans 9.0

到如下網站下載 incubating-netbeans-java-9.0-bin.zip
https://netbeans.apache.org/download/nb90/nb90.html

解開 : unzip incubating-netbeans-java-9.0-bin.zip
執行 : gksu ~/netbeans/bin/netbeans (使用su啟動netbeans, 才能執行撰寫的程式)

安裝Pi4j

網路上大都說明安裝Pi4J 1.1版本, 此版會產生如下的錯誤(原因如上說明), 所以請不要跟著操作.

Unable to determine hardware version. I see: Hardware   : BCM2835,
 - expecting BCM2708 or BCM2709.
If this is a genuine Raspberry Pi then please report this
to projects@drogon.net. If this is not a Raspberry Pi then you
are on your own as wiringPi is designed to support the
Raspberry Pi ONLY.

正確安裝方式, 請先到如下網站下載1.2的版本
http://pi4j.com/download.html

pi4j-1.2-SNAPSHOT.deb 可直接安裝, 適用於文字模式下編譯執行

 pi4j-1.2-SNAPSHOT.zip 解開後, jar  置於 lib目錄之下, 適用於netbeans下使用

netbeans設定

開啟netbeans, 新增一個專案, 然後於專案的Libraries按右鍵/Add Library

再按Create, 名稱改為Pi4j-Core. ClassPath選 pi4j-core.jar, Source選 pi4j-core-sources.jar, Javadoc選pi4j-core-javadoc.jar, 然後按ok

最後記得要選Pi4j-core, 再按Add Library

程式範例

package led1;
import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;

public class Led1 {
    public static void main(String[] args) {
        System.out.println(" GPIO Control Example ... started.");

        // create gpio controller
        final GpioController gpio = GpioFactory.getInstance();

        // provision gpio pin #01 as an output pin and turn on
        GpioPinDigitalOutput pin0 = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_00, "MyLED0", PinState.HIGH);
        GpioPinDigitalOutput pin1 = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_01, "MyLED1", PinState.HIGH);
        GpioPinDigitalOutput pin2 = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_02, "MyLED2", PinState.HIGH);

        // set shutdown state for this pin
        pin0.setShutdownOptions(true, PinState.LOW);
        pin1.setShutdownOptions(true, PinState.LOW);
        pin2.setShutdownOptions(true, PinState.LOW);

        System.out.println("--> GPIO state should be: ON");

        pin0.low();
        pin1.low();
        pin2.low();
        System.out.println("--> GPIO state should be: OFF");

        new Thread(() -> {
            boolean on = false;
            for (int i = 0; i < 200; i++) { 
                on = !on; 
                // toggle the current state of gpio pin #01 (should turn on) 
                pin0.toggle(); 
                System.out.printf("pin0 GPIO state : %s\n", on); 
                int time = (int) (Math.random() * 1000) + 100; 
                try { Thread.sleep(time); } catch (InterruptedException e) {} 
            }
        }).start(); 
        new Thread(() -> {
            boolean on = false;
            for (int i = 0; i < 200; i++) { 
                on = !on; 
                // toggle the current state of gpio pin #01 (should turn on) 
                pin1.toggle(); 
                System.out.printf("pin1 GPIO state : %s\n", on); 
                int time = (int) (Math.random() * 1000) + 100; 
                try { Thread.sleep(time); } catch (InterruptedException e) {} 
            }
        }).start(); 
        new Thread(() -> {
            boolean on = false;
            for (int i = 0; i < 200; i++) { 
                on = !on; 
                // toggle the current state of gpio pin #01 (should turn on) 
                pin2.toggle(); 
                System.out.printf("pin 2 GPIO state : %s\n", on); 
                int time = (int) (Math.random() * 1000) + 100; 
                try { Thread.sleep(time); } catch (InterruptedException e) {} 
            }
        }).start(); 
        // toggle the current state of gpio pin #01 (should turn off) 
        //n.toggle(); //stem.out.println("--> GPIO state should be: OFF");
        //read.sleep(5000);
        // turn on gpio pin #01 for 1 second and then off
        //System.out.println("--> GPIO state should be: ON for only 1 second");
        //pin2.pulse(1000, true); // set second argument to 'true' use a blocking call
        // stop all GPIO activity/threads by shutting down the GPIO controller
        // (this method will forcefully shutdown all GPIO monitoring threads and scheduled tasks)
        //gpio.shutdown();
        //System.out.println("Exiting ControlGpioExample");
    }
}

使用vim編譯程式

使用下列指令將剛下載的deb檔進行安裝
sudo dpkg -i pi4j-1.2-SNAPSHOT.deb

安裝後,  官方文檔放在 /opt/pi4j/examples裏. 所以可以把如下幾個檔copy 到家目錄

cd
mkdir raspberry
cp raspberry
cp /opt/pi4j/examples/ControlGpioExample.java .
cp /opt/pi4j/run .
cp /opt/pi4j/build .

編譯及執行

sudo ./build
sudo ./run ControlGpioExample

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *