Node.jsでRaspberryPiのGPIOを良しなにする方法

Node.jsのAdvent Calendar 12日目です。

巷でIoTとか流行ってるので大学でちょっと電子工作(Arduino)をした時についでにRaspberryPiを買ってから早２ヶ月

Raspbianを入れてから放置したままだったので

これを機会にRasPiでGPIOやっていきたいと思います！

# Q. 何故 Node.jsでやるのか？
<font class="itemsShowHeaderTitle_title" color="red">A. JavaScriptが好きだからです！!</font>

けど、~~構文そのものはすきではな~~**開発効率のため**CoffeeScriptを普段から使っているのでCoffeeScriptで書いていきます。

# 使うもの　(環境)
- 秋葉原で衝動買いしたRaspberryPi B+ - Raspbian GNU/Linux 7 (wheezy)
- Amazonで買ったB+用のケーブルとブレッドボード
- Arduinoと一緒に買ったLEDなどなど
- Ethernetケーブルとアダプター（大学やカフェとかでも使えるように）

# Node.jsのインストール

バージョン管理にはnodebrewを使います。

## nodebrewのインストール

```bash
$ curl -L git.io/nodebrew | perl - setup
```

## nodebrewからnodeのインストール

インストール方法は二通りあり

- ソースコードをダウンロードしてコンパイル
- バイナリをダウンロードして設置

一番手っ取り早いの後者のバイナリをダウンロードするタイプなんですが

新しいバージョンのだとRaspberryPi用のバイナリがなかったりします。

```bash:バイナリがない場合
$ 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`なので

バイナリインストールする場合は以下のコマンドでインストールします。

```bash
$ nodebrew install-binary v0.10.28
```

# RaspberryPiのGPIOを操作する方法

プログラムからRaspberryPiのGPIOの操作方法は二通り
`メモリに直接書き込む`か`/sys/class/gpio`をシェルから操作することでGPIOをON/OFFできます。

とりあえずシェルを使ってNode.js抜きで操作してみたいと思います。

回路は発光ダイオードを直接繋いだだけのシンプルなものでやってみます。

![IMG_20141212_033412.jpg](https://qiita-image-store.s3.amazonaws.com/0/15818/12f3ee71-97fc-a3dd-cec5-47f2f487938d.jpeg)


(写真ですみません。回路図の画像を作れるWebサービスないかな...)

```bash
// 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です。

```coffeescript

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](https://www.npmjs.com/package/node-pi-gpio)を使いたいと思います。

回路は上の写真と同じです。

```coffeescript:l_chika.coffee

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

![IMG_20141212_022913_2.jpg](https://qiita-image-store.s3.amazonaws.com/0/15818/80f73c20-dcba-452d-4afd-330e728e837c.jpeg)

回路は先程のLチカのやつに追加してます。

ボタンを橋渡しのようにつけてGRAND側に抵抗(10k)、ボタンと抵抗の間に線を繋ぎます。

繋ぐ先はGPIO25になってます。

```coffeescript:button.coffee


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](https://github.com/k2wanko/node-pi-gpio)のexampleに入っています。

npmのスクリプトも設定しているので

npm installした後に

```bash
$ npm run example:l_chika
$ npm run example:button
```

で、すぐに実行できます。

# まとめ

ネタかぶりを防ぐためにRaspberryPiを使おうとしたけど、参考文献少ないしライブラリも少ないしfs.watchは使えないし
自分でライブラリ書いてるしで想像より大変でした。

赤外線とかもうちょっとセンサー使ったあれこれも紹介したかったんですが長くなりそう(*1)なのでここではHelloWorld的なところまでにしておきます。

*1 文量ではなく作業量 orz

追記:
どうも[rpio](https://github.com/jperkin/node-rpio)

[Node.js Advent Calendar 2014](http://qiita.com/advent-calendar/2014/nodejs) 明日は[@Wmrfreew](http://qiita.com/Wmrfreew)さんが担当です！