ここから細かい制御が出来るようになる。マオです。
今まではコマンドで個別に部品を制御してたけど、プログラムで制御する事により複雑な事が出来るようになる。
使える言語は様々で推奨はPythonらしい。
ここでは既に開発環境が整っているJavaを使用していく。
GPIOを使うには、Pi4Jというライブラリが必要になる。
もし、RaspberryPiが直接ネットワークに繋がっているなら、インストールは簡単に終わる。
curl -s get.pi4j.com | sudo bash
これをsudoが出来るユーザで実行するだけだ。
JDKなんかはデフォルトで入ってるようなので、問題無いっぽい。
ライブラリは「/opt/pi4j/lib」にインストールされる。
今回の回路は前回のタクタイルスイッチと前々回のフルカラーLEDを使って、スイッチを押すごとに色が変わっていく物を作る。
注意点はコマンドの時とGPIOの番号が違う所だ。
コマンドではGPIO16だった所が、Pi4JではGPIO27となる。
詳細は公式のPin Numbering(Raspberry Pi 2 Model Bはここ)にあるので、確認しよう。
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import com.pi4j.io.gpio.GpioController; import com.pi4j.io.gpio.GpioFactory; import com.pi4j.io.gpio.GpioPinDigitalInput; import com.pi4j.io.gpio.GpioPinDigitalOutput; import com.pi4j.io.gpio.PinPullResistance; import com.pi4j.io.gpio.PinState; import com.pi4j.io.gpio.RaspiPin; import com.pi4j.io.gpio.event.GpioPinDigitalStateChangeEvent; import com.pi4j.io.gpio.event.GpioPinListenerDigital; public class ButtonDeLedTikatika { public static void main(String[] args) { // #1 final GpioController gpio = GpioFactory.getInstance(); // #2 final GpioPinDigitalOutput led_red = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_29, PinState.HIGH); led_red.setShutdownOptions(true); final GpioPinDigitalOutput led_green = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_25, PinState.HIGH); led_green.setShutdownOptions(true); final GpioPinDigitalOutput led_blue = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_28, PinState.HIGH); led_blue.setShutdownOptions(true); // #3 final GpioPinDigitalInput button = gpio.provisionDigitalInputPin(RaspiPin.GPIO_27, PinPullResistance.PULL_UP); button.setShutdownOptions(true); // #4 button.addListener(new GpioPinListenerDigital() { private byte flag; @Override public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent pin_event) { if(pin_event.getState().isLow()) { flag += flag < 7 ? 1 : -flag; led_red.setState((flag & 1) != 0 ? PinState.LOW : PinState.HIGH); led_green.setState((flag & 2) != 0 ? PinState.LOW : PinState.HIGH); led_blue.setState((flag & 4) != 0 ? PinState.LOW : PinState.HIGH); } } }); // #5 BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); try { while(!in.ready()) { Thread.sleep(1000); } in.readLine(); } catch (IOException | InterruptedException e) { e.printStackTrace(); } // #6 gpio.shutdown(); } }
以上が制御するプログラム。
#1でGPIOをなんやかんやするインスタンスを貰う。
なんやかんやするインスタンスを使って、#2でLED部分の設定をしている。
赤をGPIO29、緑をGPIO25、青をGPIO28に繋いである。
二つ目の引数にあるPinState.HIGHはデフォルトの出力状態を指定している。
このLEDは電圧がかかっていると消えるので、実行されると消えた状態になる。
setShutdownOptionsは終了時に関わる設定なので、そっちで説明するので飛ばす。
#3はタクタイルスイッチ部分の設定だ。
GPIO27に接続してあり、二つ目の引数PinPullResistance.PULL_UPはプルアップ抵抗の設定をしている。
#4はタクタイルスイッチの状態が変化された時の処理を登録している。
各色の状態は3ビット(0~7)で記録して、ビットが立っている部分が光る。
スイッチが押されると処理がされ、電圧がLowになるのでif分の中が実行される。
フラグ管理をしているflagに1を加算するか、7から溢れる場合は0に戻している。
setStateでPinState.LOWかPinState.HIGHを指定する事で、電圧を変更する事が出来る。
これによりスイッチを押すたびに、消えた状態からレッド→グリーン→イエロー→ブルー→マゼンタ→シアン→ホワイトとなり、次でまた消える。
#5はエンターキーを押すまで、プログラムを抜けないようにループさせている。
GPIOの制御部分は別スレッドで動く為に、この部分が無いと処理が終了してしまう。
#6の部分でGPIOを開放(コマンドにおけるunexport)したりする。
しかし、#2や#3でやっているsetShutdownOptions(true)を指定していないと開放してくれない。
setShutdownOptionsでは色々と開放後のピンの状態も指定出来たりする。
実行は一般ユーザからクラスファイルが置いてあるディレクトリで以下のコマンドで出来る。
sudo java -cp .:"/opt/pi4j/lib/*" ButtonDeLedTikatika
意外とサクサクとここまで出来てしまった。
基礎は終わったので、ここから難易度がドンドン上がって大変な事になりそうだ・・・(遠い目)
javaagentで遊んでいたら「java.lang.VerifyError」が起こって、ハマっていたんだけど、まあ何か解決した上に原因っぽい物も発見したので書いておく。
簡単な解決方法は起動オプションに「-XX:-UseSplitVerifier」を追加する。
発生する原因は感なのだけど、ビルドターゲットが違うバージョンのクラスファイルにアクセスすると起こるような気がする。
色々検索してみるけど、具体的な原因を出している人が中々見つからないし、これで解決しないって人もいるみたいだねぇ。
中にはライブラリにアクセスして問題が起きるってパターンがあったので、これはうちと同じパターンなのかもしれない。
一応、ビルドターゲットを合わせたら、ぱったりとエラーが出なくなった。
大体の場合はターゲットのバージョンを下げる事になると思うのだが、新バージョンのコードで書いてしまった場合は修正が必要になるから大変かもしれないな・・・。
使いたいなぁ。マオです。
マイナビニュース:大刷新リリース Java 8の新機能
来週リリースですか。
ぶっちゃけ、マイクラのお陰でJava7の機能は全く使うことが無かったんだよねぇ。
8までの新機能を使えば、結構ソースがスッキリしそうな気がする。
インターフェースのデフォルト実装なんかは、使えたら私空へ登っていきそうなレベル。
ラムダ式はそんなんでもないな・・・逆に私は混乱しそうな雰囲気がある。
コレクション系も使えたら天国なんだろうなぁ。
・・・でも、結局JDKのインストールすらしない予感・・・。
一応、こんな可能性があるらしい。マオです。
新UgoCraft使用者で、Ugo objectがガクガクするという方へ。
Javaのバージョンを確認してみて下さい。
古いバージョンだと、ガクガクして動かないという報告がありました。
現在Javaは7でUpdate 17が最新です。
ただ最新版が入っていても、旧版が削除されていなくて、そちらを参照されてMinecraftが起動している場合があります。
Minecraftで、どのバージョンが使われているかを手っ取り早く知る方法は、Minecraftを起動して「設定→情報収集設定」のjava_versionで確認する事が出来ます。
1.7.0_17とあるなら、Java7 Update17で起動している事になります。
もしそれ以外だった場合は、Windowsなら「コントロールパネル→プログラムと機能」で、Java7 Update17以外のJavaが残ってると思われるので、それらを削除します。
他の事でJavaを使っているなら、確認して削除してね。
で、もしMinecraftが起動しないなら、もう一度Javaの最新版をインストールすれば、問題無いはずです。
今度から動作確認しているJavaのバージョンも書いた方が良いのかしら・・・。
Javaはバージョンが上がると、大体速度が良い感じにアップする。
6から7に上げた時の、ループ処理の改善には感動した記憶があるんだよね。
何かしら問題を抱えてる人がいるなら、それもJavaのバージョンも考慮すれば解決するかもしれないね。
破的か! マオです。
色々プログラミングで使うツール類を新調しているのですが、困った事が出てきました。
今後リリースする物を難読化しようと、ProGuardを使っているのですが、こいつの最適化処理が使いづらい。
解析していらない物の削除したり、命令をインライン化して高速化してくれたりするのだが、この機能を使うとヌルポを吐いて止まっちゃうんだよね。
難読化された後の物をトレースしてみるんだけど、何が悪いのか理解出来ない。
文法的には問題無いように見えるんだけどなぁ。
で、この機能を切ればいいんだけど、この機能が有効じゃないと私が欲しい機能が動いてくれないという状態になる。
その機能が、指定した命令のみを削除するという物で、用途としてはデバッグメッセージの削除に使おうと思っている。
何か良い方法が無いかと探っているのだが、今の所代案が全く出てこない。
リリースするたびに、ブランチ作ってメッセージ削除ってのも考えただけで萎えそうだしなぁ。
楽をする方法を色々導入しているけど、それがいつになったら発揮されるのやら・・・。