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

  • 54
    いいね
  • 3
    コメント
この記事は最終更新日から1年以上が経過しています。

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抜きで操作してみたいと思います。

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

IMG_20141212_033412.jpg

(写真ですみません。回路図の画像を作れる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を使いたいと思います。

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

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

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

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

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

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の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さんが担当です!

この投稿は Node.js Advent Calendar 201412日目の記事です。