Node.jsのAdvent Calendar 12日目です。
巷でIoTとか流行ってるので大学でちょっと電子工作(Arduino)をした時についでにRaspberryPiを買ってから早2ヶ月
Raspbianを入れてから放置したままだったので
これを機会にRasPiでGPIOやっていきたいと思います!
Q. 何故 Node.jsでやるのか?
A. JavaScriptが好きだからです!!
けど、構文そのものはすきではな開発効率のためCoffeeScriptを普段から使っているのでCoffeeScriptで書いていきます。
使うもの (環境)
- 秋葉原で衝動買いしたRaspberryPi B+ - Raspbian GNU/Linux 7 (wheezy)
- Amazonで買ったB+用のケーブルとブレッドボード
- Arduinoと一緒に買ったLEDなどなど
- Ethernetケーブルとアダプター(大学やカフェとかでも使えるように)
Node.jsのインストール
バージョン管理にはnodebrewを使います。
nodebrewのインストール
$ curl -L git.io/nodebrew | perl - setup
nodebrewからnodeのインストール
インストール方法は二通りあり
- ソースコードをダウンロードしてコンパイル
- バイナリをダウンロードして設置
一番手っ取り早いの後者のバイナリをダウンロードするタイプなんですが
新しいバージョンのだとRaspberryPi用のバイナリがなかったりします。
$ nodebrew install-binary v0.11.14
v0.11.14 is not found
Can not fetched: http://nodejs.org/dist/v0.11.14/node-v0.11.14-linux-arm-pi.tar.gz
今回、自分がbinary installで動くのを確認したのはv0.10.28
なので
バイナリインストールする場合は以下のコマンドでインストールします。
$ nodebrew install-binary v0.10.28
RaspberryPiのGPIOを操作する方法
プログラムからRaspberryPiのGPIOの操作方法は二通り
メモリに直接書き込む
か/sys/class/gpio
をシェルから操作することでGPIOをON/OFFできます。
とりあえずシェルを使ってNode.js抜きで操作してみたいと思います。
回路は発光ダイオードを直接繋いだだけのシンプルなものでやってみます。
(写真ですみません。回路図の画像を作れるWebサービスないかな...)
// GPIO24 を使うためのコマンド
$ echo 24 > /sys/class/gpio/export
// IN/OUTの設定 出力する場合はout
$ echo out > /sys/class/gpio/gpio24/direction
// 信号のON/OFFの切り替え ONは1 OFFは0
$ echo 1 > /sys/class/gpio/gpio24/value
// OFFにする
$ echo 0 > /sys/class/gpio/gpio24/value
// unexport
$ echo 24 > /sys/class/gpio/unexport
出力するだけならシンプルですね。
ちなみにメモリを直接操作する方法は Node.jsでどうやればいいのかよくわからないので今回は保留 (/dev/mem をあれやこれやするようですがまだよくわからないのでまた今度)
Node.jsからGPIOを操作する
/sys/class/gpio をNode.jsから操作する方法で行こうとお思います。
さっきの操作をNode.jsでやるにはFileSystemを使えばOKです。
fs = require 'fs'
path = require 'path'
dir = '/sys/class/gpio/'
pin = 24
# export
fs.writeFileSync path.join(dir, 'export'), pin
gpio24 = path.join dir, 'gpio' + pin
# directionの設定
fs.writeFileSync path.join(gpio24, 'direction'), 'out'
# 値の書き込み
fs.writeFileSync path.join(gpio24, 'value'), 1
# 3秒後に終了
setTimeout ->
fs.writeFileSync path.join(gpio24, 'value'), 0
fs.writeFileSync path.join(dir, 'unexport'), pin
, 3000
わかりやすくするため同期メソッドを使いましたが
JavaScript的には非同期がいいと思うのでasyncやPromiseなんかを使うといいと思います。
Lチカ
プログラミングの最初の一歩がHello World
なら
電子工作の最初の一歩はLチカです。
Lチカとは「LEDチカチカ」の略です。
既に冒頭でやってしまってますがライブラリを使った もう少しちゃんとしたLチカをやりたいと思います。
ライブラリは覚えたての知識であるPromiseを活用したいのでPromise使ったライブラリないかなぁと思って探したんですが
なかったので作ったnode-pi-gpioを使いたいと思います。
回路は上の写真と同じです。
GPIO = require 'node-pi-gpio'
pin = 24
time = 500
_loop = (gpio, val)->
gpio.value val
setTimeout _loop, time, gpio, (unless val then 1 else 0)
GPIO.open pin, 'out'
.then (gpio)->
process.on 'SIGINT', ->
gpio.value 0
gpio.close()
.then ->
process.exit()
_loop(gpio, 1)
return
.catch (err)->
console.log 'err', err.stack
実行するとLEDが0.5秒ごとにON/OFFが切り替わると思います。
終了するには Ctrl+c
を入力して終了させます。
ボタンの入力を受け付ける
今度はボタンを使って入力を受けてみたいと思います。
ちなみにfs.watchでは変更をキャッチできないようです。orz
回路は先程のLチカのやつに追加してます。
ボタンを橋渡しのようにつけてGRAND側に抵抗(10k)、ボタンと抵抗の間に線を繋ぎます。
繋ぐ先はGPIO25になってます。
GPIO = require 'node-pi-gpio'
Promise = require('es6-promise').Promise
led_pin = 24
button_pin = 25
Promise.all [GPIO.open(led_pin, 'out'), GPIO.open(button_pin, 'in')]
.then (res)->
console.log 'open'
[led, button] = res
process.on 'SIGINT', ->
led.value 0
Promise.all [led.close(), button.close()]
.then ->
process.exit()
button.on 'change', (val)->
console.log 'change', val
led.value val
.catch (err)->
console.log 'err', err.stack
ボタンを押すとLEDが光るサンプルです。
Lチカとボタンのソースコードはgithubのexampleに入っています。
npmのスクリプトも設定しているので
npm installした後に
$ npm run example:l_chika
$ npm run example:button
で、すぐに実行できます。
まとめ
ネタかぶりを防ぐためにRaspberryPiを使おうとしたけど、参考文献少ないしライブラリも少ないしfs.watchは使えないし
自分でライブラリ書いてるしで想像より大変でした。
赤外線とかもうちょっとセンサー使ったあれこれも紹介したかったんですが長くなりそう(*1)なのでここではHelloWorld的なところまでにしておきます。
*1 文量ではなく作業量 orz
追記:
どうもrpio
Node.js Advent Calendar 2014 明日は@Wmrfreewさんが担当です!