0

Raspberry PiのGPIOを使う

Raspberry Piの基板上のIC(BC2835)から出ているGPIOを使ってみた。
とりあえず3Vを出してLEDを光らせたり、スイッチをつないでon/offを検出したりした。
がんばればPWMやI2Cもできる。

回路

まずGPIOをオスメスのジャンパワイヤでブレッドボードに引き出す。
23,24番とGNDを引き出してLEDをつないだ。
18番とVCCの間にタクトスイッチを入れて、100Ωのプルダウン抵抗もつけた。

ピン配置は
RPi Low-level peripherals – eLinux.org
に書いてある。


デバイスファイルからGPIOを操作

Raspbianの場合、/sys/class/gpio/以下のデバイスファイルに標準入力するとGPIOが使える。
sudo su
echo 24 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio24/direction
echo 1 > /sys/class/gpio/gpio24/value ## LED点灯
echo 0 > /sys/class/gpio/gpio24/value ## LED消灯
rootじゃないと書き込めないのだが、sudoでpipeの右辺にroot権限を持たせる方法がよくわからなかったので事前にsudo suした。


pi_piper gemを使う

WiringPiが先存在してて有名なようだが、試したら動かなかった(エラーも出ない)のでpi_piperを使う。
WiringPiはC拡張だが、pi_piperはFFIとEventMachineを使ってGPIOを使っている。
・・・のだけど、ソースを読んだ感じたぶんFFIを使っているのはBC2835のI2C機能などを使う部分だけで、単純なdigital read/writeの操作はデバイスファイルごしにFile.openでやっている。
入力ピン状態変化イベントが遅く感じるのも、eventmachine使ってるのにThreadやsleep使ったりしているせいだと思う。ちょっと手を入れるとすごく速くなりそうなのであとでやる。


インストール
sudo gem install pi_piper
ネイティブコードをコンパイルするので少し時間がかかる。


pi_piperでLEDの点滅

GPIO 23,24番を1秒ごとに点灯消灯した。
非常にオブジェクト指向で良いと思う。

blink.rb
require 'pi_piper'

pin_a = PiPiper::Pin.new :pin => 24, :direction => :out
pin_b = PiPiper::Pin.new :pin => 23, :direction => :out

loop do
pin_a.on
pin_b.off
sleep 1
pin_a.off
pin_b.on
sleep 1
end
これも実行にはroot権限が必要
sudo ruby blink.rb


pi_piperでスイッチの押下判定

18番スイッチのon/off変化をイベントで取得した。
require 'pi_piper'

PiPiper.watch :pin => 18 do
puts "#{last_value} -> #{value}"
end

PiPiper.wait

ボタンを押したり離したりする毎にprintされる。

0

Arduino – UART、LED、AD変換を試した

昨日届いたArduino(右)

受け取って1時間で速攻で動作チェックした。

Wiring & Arduino

左はWiring。

Wiringは結構使った事がある。proce55ingの様に手軽に電子工作を「スケッチ」できる、難しいC言語とかを書かなくても簡単に赤外線やサーボの制御ができたりするツール。最近、avr-libcなどのよりローレベルなライブラリを読み込む事ができるようになって面白い。

ただし、16bitタイマ2つと8bitタイマ1つがWiringに占有されているので、タイマ処理(スレッドの様なもの)が使えない。また、外部入力やUSART受信など全ての割り込みが使えないので、1つのloop()メソッドの中で全てを処理しなければならなくなる。例えば、delay()で停止中にセンサからの入力があっても受け取ることができないのが弱点。ただ、そういう時はCPUを増やす(Wiring/Arudinoを2つ使う)という技でどうにかなる。

s.h.log: WiringでできることWiringタグ

Arduinoは、Wiringをベースに、マイコンや部品を人間の手で実装できる物に変えたもので、これも同じくスケッチツール。(部品が大きくてはんだづけしやすく、安い物を使っている)

性能も、できる事も全く同じで、ただしArduinoの方がピンが少ない(つまり制御できるLEDとかが少ない、まあマルチプレクサとかで工夫すればどうにでもなるが)

今学期SAをやってるインタラクションデザインの教材でもあるので、とりあえずよく使う機能を試してみた。

Read more

2

AVR – MEGA8の外部入力割り込み

90S2313での外部入力割り込みに続いて、ATMEGA8でも外部入力割り込み SIG_INTERRUPT0, SIG_INTERRUPT1 を使った。

DSC00816.jpg

INT0、INT1への割り込みをSIG_INTERRUPT0、SIG_INTERRUPT1でそれぞれ受け取り、立ち上がりエッジ/立ち下がりエッジで2つのLEDを点灯/消灯させる。→ソースコード(AVR-GCC)動画(3MB)

90S2313は立ち上がり/立ち下がりのどちらかしか検出できなかったのでプログラムでなんとかしていたが、mega8は論理変換を検出(つまり両エッジ)できるので全然簡単になっている。というかそれ以外全部同じだったので一発で動いた。

データシートの翻訳版より

MCUCR(MCU制御レジスタ)の割り込み発生条件制御ビット表

■やり方

INT0を設定する関数を作った。

/* INT0設定 */
void interrupt0_init(void){
cbi(DDRD,PD2); // INT0入力設定
sbi(GICR,INT0); // INT0割り込み許可
sbi(GIFR,INT0); // INT0割り込み要求フラグON
/* 両エッジ検出 */
sbi(MCUCR,ISC00);
cbi(MCUCR,ISC01);
/* 立ち上がりエッジ検出
sbi(MCUCR,ISC01);
sbi(MCUCR,ISC00);
*/
/* 立ち下がりエッジ検出
sbi(MCUCR,ISC01);
cbi(MCUCR,ISC00);
*/
}

main()で呼び出して、すぐsei();して有効にしておく。

そして割り込み部分。

/* INT0 外部割り込み */
SIGNAL(SIG_INTERRUPT0){
if(bit_is_set(PIND,PD2)){ // 立ち上がりの時
LED1_SET(); // LED1点灯
}
else{ // 立ち下がりの時
LED1_CLR(); // LED1消灯
}
}

INT1の方も全く同様に書いてある。