ruby で Lチカさせるのやってみたかった。
Intel Edison の GPIO
Edison に Breakout Board を装着すると色々な I/O が引き出せるようになります。
GPIO はプログラムで ON/OFF を制御することができるのでソフトウェアで外部に接続した何かを動かすには基本となります。
Breakout Board のマニュアルを見ながらそこにテスト用のコードをハンダ付けしていきます。
今回は GND, GPIOx2, I2Cの2本を選択しました。
J19-3 --- GND
J20-7 --- GPIO15
J18-2 --- GPIO165
J18-6 --- I2C_1 SCL
J17-8 --- I2C_1 SDA
ここで注意すべき点があります。
Edison で使っているのは高密度な SoC でホビー用の一般的なマイコンと異なりますので、通常のマイコン電子工作とは違って GPIO の電圧が 5V や 3.3V ではありません。Edison のポート電圧は 1.8V となっています。
また電流のドライブ能力も 3mA しかありませんので、この信号で LED を点灯させることはおろかシンク電流としての能力も期待できず LED を直接繋げるのは御法度です。
GPIO sysfs の基本
Linux のユーザーランドから GPIO を操作する手法としてはグローバルな GPIO sysfs を用いる方法が一般的なようです。Intel のネイティブポートドライバーがあるのかどうか良くわかりません。
GPIO sysfs では GPIO デバイスが /sys/class/gpio/ の中に見えます。
この /sys/class/gpio/ にマウントされたデバイスにファイルシステムとしてアクセスすることで、GPIO の制御ができるようになります。
ポートを GPIO として利用する
/sys/class/gpio/ の中を覗いてもまだ gpio15 と gpio165 がいないかもしれません。
まずはポートを GPIO として使用する宣言が必要です。
使用したいポート番号をテキストで /sys/class/gpio/export に書き込みます。
echo '165' > /sys/class/gpio/export
echo '15' > /sys/class/gpio/export
これで gpio15 と gpio165 が現れます。
ポートの方向を指定する
GPIO には in と out の二種類があります。
out は CPU からの制御で ON/OFF をピンに出力します。
in はポートにかかっている ON/OFF (を表す電圧)を CPU に読み込みます。
out では LED を光らせたりするのに対し、in ではスイッチが押されたかどうかの検知に使われます。
このポート方向の指定は gpio フォルダ内の direction で指定します。
echo 'out' > /sys/class/gpio/gpio15/direction
echo 'out' > /sys/class/gpio/gpio165/direction
今回は LED を光らすことが目的なので out しか使いません。
ポートを ON/OFF する
以上で準備が完了しています。あとは、gpio の value に値を書き込んで制御を行ってください。
echo '1' > /sys/class/gpio/gpio15/value
echo '0' > /sys/class/gpio/gpio165/value
1を設定するとGPIOポートの電圧が 1.8V になることが計測でわかります。
まずはテスター等で確認してください。
LEDを光らせたい
次はお待ちかねの LEDチカチカです。
トランジスタドライバ
Edison の SoC から主力される GPIO は 電圧 1.8V、電流 3mA と微弱なモノです、これで LED を点灯させるわけにはいきませんのでトランジスタで電流電圧増幅をしてやる必要があります。
最初はGPIOの代わりに 5V を与えて光ることを確認してください。
次に GPIO に繋いだあと、GPIO sysfs をコマンドラインから制御して LED を ON/OFF できることを確認してください。
成功したらほとんど完成です。おめでとうございます。
ruby でLEDチカチカ
ねんがんの るびーで Lちか が できたぞ
def gpio_out(port)
number = port.to_s
if !File.exist?("/sys/class/gpio/gpio#{number}") then
open("/sys/class/gpio/export", "w") do |fp|
fp << number
end
end
open("/sys/class/gpio/gpio#{number}/direction", "w") do |fp|
fp << 'out'
end
end
def led(port, sw)
code = "0"
if sw == true then
code = '1'
end
open("/sys/class/gpio/gpio#{port}/value", "w") do |fp|
fp << code
end
end
# ---- main
gpio_out(15)
gpio_out(165)
t = Thread.new do
while(1) do
led("15", true)
sleep(0.5)
led("15", false)
sleep(0.5)
end
end
Thread.new do
while(1) do
led("165", true)
sleep(0.8)
led("165", false)
sleep(0.8)
end
end
t.join