【Node.jsでIoT】Lチカをやってみる【Raspberry Pi 2】

# はじめに
ずっと興味を持ちつつなかなか手を出さずにいたIoTへの挑戦をしていこうかなと思います。
その過程を全部メモとして残そうかなということでこの記事を書いています。
とりあえず初めての挑戦なので今日はIoT的「Hello world」であるLチカ(LED電球をチカチカさせること)をやっていきたいと思います。

僕はフロントエンドエンジニアなので大好きなJavaScriptを使って操作したいなと思ってるので今回はRaspberry Pi(以下ラズパイ)をNode.jsを使って動かしていきます。
ラズパイを選んだ理由はドキュメントや記事の豊富さです。未熟な僕でもいけそうな気がしちゃうのがいいところ。

最終的に核搭載二足歩行型戦車メタルギアをNode.jsで動かすところまでこのIoTシリーズを続けていきたいと思っています！


# 用意したもの
- [本体＆ケース　超小型パソコン　Raspberry Pi 2 Model B　ＲＳ正規品 (Clear)](http://www.amazon.co.jp/%E6%9C%AC%E4%BD%93%EF%BC%86%E3%82%B1%E3%83%BC%E3%82%B9-%E8%B6%85%E5%B0%8F%E5%9E%8B%E3%83%91%E3%82%BD%E3%82%B3%E3%83%B3-Raspberry-Pi-Model-%EF%BC%B2%EF%BC%B3%E6%AD%A3%E8%A6%8F%E5%93%81-Clear/dp/B00T9L5M1S)
- [BUFFALO 無線LAN子機 コンパクトモデル 11n技術・11g/b対応 WLI-UC-GNM](http://www.amazon.co.jp/gp/product/B003NSAMW2/ref=oh_aui_detailpage_o02_s00?ie=UTF8&psc=1)
- [ＴＯＳＨＩＢＡ　マイクロＳＤカード（ｍｉｃｒｏＳＤＨＣ）　１６ＧＢ　４０ＭＢ／ｓ](http://akizukidenshi.com/catalog/g/gS-09054/)
- [ブレッドボード　ＢＢ－８０１](http://akizukidenshi.com/catalog/g/gP-05294/)
- [ブレッドボード・ジャンパーワイヤ（オス－メス）　１５ｃｍ（青）](http://akizukidenshi.com/catalog/g/gP-03473/)
- [高輝度５ｍｍ青色ＬＥＤ　５ｃｄ６０度　ＯＳＵＢ５１６１Ａ－ＰＱ（１０個入）](http://akizukidenshi.com/catalog/g/gI-01322/)
- 有線マウス
- 有線キーボード
- モニター
- HDMIケーブル
- microUSBケーブル

※リンク付きのものは今回購入したものです。

# やってみる

## Raspberry Piセットアップ

とりあえずラズパイは埃かぶるとショートしてやばいという話を聞いたのでケース付きのものを買いました。

![raspi.jpg](https://qiita-image-store.s3.amazonaws.com/0/70780/05e6de35-6791-1fd8-4db5-f408cdd12362.jpeg)

あ、そもそもラズパイとはなんなのかって部分からよくわからない自分がいたのでとりあえずそこから調べてみました。

[Raspberry Pi - ウィキペディア](https://ja.wikipedia.org/wiki/Raspberry_Pi)
> Raspberry Pi（ラズベリー パイ）は、ARMプロセッサを搭載したシングルボードコンピュータ。

うんうん、なるほどね、コンピュータってことね、おっけー。
色んな人が作ったラズパイの制作物をブログで見たりするとなんでも簡単に作れちゃうんだなーという印象。webアプリとかしか作れないフロントエンドエンジニア(自称)の僕でも形のあるものが作れちゃうってんだから良い世の中になったものですね。

ということでまずはOSを入れなければならないですね。
ラズパイに使えるOSはいくつかあるようなのですが、Raspbian(ラズビアン)というのが推奨されてるようなのでそれを入れてみます。RaspbianはイメージファイルでインストールするパターンとNOOBSというものを使ってインストールするパターンと2つあって、僕は初心者なので初心者向けのNOOBSを使ってインストールしてみることにしました。
まずは以下のサイトからNOOBSをダウンロードします。
ちなみに僕は自分の端末はmacを使っています。

[Download NOOBS for Raspberry Pi](https://www.raspberrypi.org/downloads/noobs/)

![screen1.jpg](https://qiita-image-store.s3.amazonaws.com/0/70780/f71df663-0476-e369-c381-1a680d6d555d.jpeg)


zipだと時間かかっちゃってやばいので[BitTorrent](http://www.bittorrent.com/)使うのをおすすめします。
まあBitTorrentでも僕の場合めっちゃ時間かかったのですが…

ダウンロードができたらRaspbianをmicroSDに入れる為の準備をします。
ラズパイはmicroSDがハードディスクとなるようですね。
ラズパイを動かすのに最低4G必要なのですが今回は16Gを使っています。あ、あとmicroSDはclass10のものを使った方が良いっぽいです。

まずはmicroSDをなんかしらの変換機通してmacに差し込みます。
そしたらフォーマットします。
macの場合は、ディスクユーティリティを起動＞フォーマット「MS-DOS（FAT）」を選択し「消去...」をクリックでフォーマットが完了します。

フォーマットが完了したらダウンロードしたNOOBSを解凍してできたフォルダの中にある全てのファイルをmicroSDの一番上の階層にコピーします。


ここまできたら準備おっけーなのでラズパイを起動します。
手順としてはまずは以下をラズパイに接続します。

- microSDカード
- USBマウス
- USBキーボード
- HDMIに繋いだモニター

全て接続したら最後にmicroUSB端子で電源に接続すると自動でラズパイが起動します。
その後は以下のように操作します。

1. Raspbianにチェックを入れます。
2. Language : English（US）, Keyboard : jpを選択します
3. 「Install」ボタンを押してYesを選択
4. インストールが始まるので待機(これも結構かかります)
5. 「OS（es） Installed Successfully」が表示されたらOKを押すとラズパイが起動してデスクトップが表示されます

起動後いくつかのコマンドをラズパイ上で叩きます。
左上のあたりにあるディスプレイのアイコンをクリックするとターミナルが開きます。

まずはOSを最新にします。(もしかしたら必要ないかも)

```bash:ラズパイターミナル
$ sudo aptitude update
$ sudo aptitude -y upgrade
```

そして初期で入ってるviが意味わかんないのでvimを入れます。

```bash:ラズパイターミナル
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install vim
```

ここまでやったら無線LAN接続がしたいのでWi-FiアダプターをUSBに差し込みます。
そして右上のLANのボタンを押して自分の家の回線に接続します。
うまく回線が表示されなかった場合はアダプターを挿したまま一度シャットダウンしてもう一度起動するといいかもしれません。

インターネットに接続できたらこれ以降は無線で自動接続してくれます。


次にSSH接続のためにIPアドレスを調べます。以下のコマンドを叩いて、`inet addr:`の右に書いてあるものがIPアドレスです。

```bash:ラズパイターミナル
$ ifconfig
```

僕の場合は`192.168.1.36`でした。
(ここらへんはDHCPで自動でIP割り振る設定になってないとだめかも)
IPアドレスがわかったので自分の端末からSSH接続することができます。

```bash:OSXターミナル
$ ssh pi@192.168.1.36
```

コマンドを叩くとパスワードをきかれます。
SSH初期値のIDが`pi`、パスワードが`raspberry`です。

SSH接続が成功したら自分の端末からラズパイを操作することができるようになります。
ここまででセットアップが終わりました。ラズパイを直接触ることはなくなるのでHDMIもマウスもキーボードもラズパイから外しちゃって大丈夫です。すっきり。


## Node.jsのインストール

まだNode.jsに触ることはないのですがとりあえず先にインストールしときましょう。
Node.jsはバージョンアップが激しいのでnvmでバージョン管理できるようにします。

[creationix/nvm](https://github.com/creationix/nvm)

nvmをgitでcloneします。
(SSHでラズパイに接続状態です)

```bash:OSXターミナル
pi@raspberrypi:~ $ git clone git://github.com/creationix/nvm.git ~/.nvm
```

cloneしたらnvmを使えるようにするためにパスを通します。

```bash:OSXターミナル
pi@raspberrypi:~ $ source ~/.nvm/nvm.sh
```

ちなみにこれはnvm使うときに毎回叩かなきゃいけないので.bash_profileに記述しておくと毎回打つ手間が省けます。
パスが通ったらnvmコマンドが使えるのでまずはインストールできるNodeのバージョンを確認します。

```bash:OSXターミナル
pi@raspberrypi:~ $ nvm ls-remote
```

Nodeのバージョンのリストが出たので僕は現時点の最新のv5.3.0をインストールします。

```bash:OSXターミナル
pi@raspberrypi:~ $ nvm install v5.3.0
```

インストールができたらNodeのバージョンを確認します。
インストールしたバージョンが表示されたらおっけーです。

```bash:OSXターミナル
pi@raspberrypi:~ $ node -v
v5.3.0
```

ついでにNodeのデフォルトのバージョンを今回インストールしたものにしておきます。

```bash:OSXターミナル
pi@raspberrypi:~ $ nvm alias default v5.3.0
```

これでNodeの準備は完了です。

## 必要な道具を用意

で、ここからがIoT初心者の僕にとっての最大の課題ですね。
回路とか全然よくわからないので。
なんだかGPIOっていう言葉がよく出てくるので調べてみました。

[GPIO - ウィキペディア](https://ja.wikipedia.org/wiki/GPIO)
> GPIOはGeneral Purpose Input/Output（汎用入出力）の略語である。
マイクロプロセッサ、マイクロコントローラ、インタフェースデバイスは、外界と接続するための一つまたは複数のGPIOインタフェースを持っている。
入力として動作した場合は電気回路のほかの部分からのデジタル信号を読み取り、出力として動作した場合は他デバイスの制御や信号の通知を行う。
しばしばGPIOはピンのグループ（典型的には8ピン）であるGPIOポートで扱われることがある。通常は個別のGPIOピンごとに入力または出力に個別に設定することが出来るが、GPIOポートはグループごとの入出力設定となる。

とにかくGPIOが入出力のインターフェースということか。
ここに色々ぶっさしてラズパイと他のデバイスを繋ぐということですね。

ぶっさして繋ぐっていうとすごく簡単そうなんですけど、このラズパイ2にはぶっさすことのできる針が40本もあってそれぞれが役割を持っているので適当にぶっさせばいいわけではないようです。
それぞれのピンの役割の説明として以下の画像が出回ってたので使わせてもらうことにした。

![GPIO_Pi2.png](https://qiita-image-store.s3.amazonaws.com/0/70780/e0e62dbb-53ad-e086-d1b5-82086c2ce0f9.png)

これだけ見ても正直意味わかんないので進めつつ使うピンの役割を覚えていきたいと思います。
まあわからないなりに少しでもわかった部分を説明すると、今日覚えるべきものとしては5種類あって、常に3.3v供給している1と17、常に5v供給している2と4、Groundと呼ばれるものが6と9と14と20と15と30と34と39、あとなんかよくわからんが使うことのできないのが27と28、あとは残りのやつって感じです。
(適当ですいません。次回知識として知っとかなきゃいけない部分全て調べてまとめようかなと思います)

とりあえずGroundってのはちゃんと知っとかなきゃだ。

[GND（接地） - Wikipedia](https://ja.wikipedia.org/wiki/%E6%8E%A5%E5%9C%B0)
> 接地（せっち）とは、電気機器の筐体・電線路の中性点・電子機器の基準電位配線などを電気伝導体で基準電位点に接続すること、またその基準電位点そのものを指す。本来は基準として大地を使用するため、この名称となっているが、基準として大地を使わない場合にも拡張して使用されている。アース（英: earth）、グランド（グラウンド）（英: ground）とも呼ばれる。

アースだそう。なんとなくわかったような。わからないような。
とりあえずマイナス極側をGroundに接続すればいいということは調べてわかった。


そしてこのGPIOからジャンパーワイヤというものを通して今回はLEDに接続するのですが、ジャンパーワイヤから直接LEDに接続するわけではなく、そこからブレッドボードというものを経由します。

[ブレッドボード - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%96%E3%83%AC%E3%83%83%E3%83%89%E3%83%9C%E3%83%BC%E3%83%89)
> ブレッドボードとは、電子回路の試作・実験用の基板（土台）のことである。試作、実験、評価などに用いる。
ブレッドボードの中でも、特にはんだ付けが不要なタイプ（各種電子部品やジャンパ線を差し込むだけで電子回路を組むことの出来る、はんだ付けが不要な基板）を指す場合は、英語では「solderless breadboard ソルダーレス・ブレッドボード」と言うが、日本語で（アマチュアの電子工作愛好家が）「ブレッドボート」と言う時は、しばしばこのsolderless breadboadを指している。

はんだ付けせずとも電子回路を組むことができるってことで初心者にとても優しい素晴らしいアイテムですね。
で、ブレッドボードにジャンパーワイヤさしてLEDもさしてLEDをピカってさせるみたいです。

![FullSizeRender.jpg](https://qiita-image-store.s3.amazonaws.com/0/70780/3d19d98c-b7d0-d8ec-7899-dee6b1e67552.jpeg)

上下にプラスとマイナスのエリアがあって、内側にa〜jのアルファベットの書かれたエリアがあります。
プラスとマイナスのエリアは赤い線と青い線で図示したように横に繋がっています。
アルファベットのエリアはオレンジの線で図示したように縦で繋がっています。しかしeとfの部分は繋がってないです。
プラスとマイナスの部分は電源を供給するときに使うようなので今回は必要ないパターンですね。
電気の流れがわかれば挿す場所は大体わかりそうですね。

とりあえず今回使うものを並べてみました。

![FullSizeRender-2.jpg](https://qiita-image-store.s3.amazonaws.com/0/70780/30fb4551-8b72-a8c2-d9ee-0e809ca4df4a.jpeg)

ちなみにLEDは足が短い方と長い方とがあって、長い方がプラスで短い方がマイナスになります。
ジャンパーワイヤはオス・メスがあるので買うときは気をつけた方がいいです。
メスをGPIOに挿してオスをブレッドボードに挿す感じですね。

あとは本当はLED使うときは抵抗っていうものもないといけないようなのですが今回は勉強不足で買わなかったので無しで進めます。それはまじでだめって場合は怒ってください…。


## とりあえず光らせてみる

先ほどGPIOには常に電気を供給しているピンがあるということがわかったのでとりあえずぶっさして光るかどうか確認したいと思います。
回路図はこんな感じです。

![Untitled-Sketch_ブレッドボード.jpg](https://qiita-image-store.s3.amazonaws.com/0/70780/a55adecc-935c-bfb5-501a-07ba81853e4f.jpeg)


1番ピンと繋がっているのがLEDのプラス側でLEDのマイナス側を通って6番のGRDにいくって流れですね。
実際やってみると


![FullSizeRender.jpg](https://qiita-image-store.s3.amazonaws.com/0/70780/b6079212-6ea7-b8b9-0b90-ea0930c7010f.jpeg)

おおお光った！
ただ電球が光っただけなのになんかすごく嬉しいw

ただこれだと特になんの操作もしていないのでとりあえずコマンド叩いて光らせて消してってできるようにします。

今度はこちらで操作できるピンにさします。
先ほど1番ピンに挿してたものを3番ピンの「GPIO2」にうつします。3番ピンだけど2です。ややこしい。上記の回路図で言うとGPIOの一番左下に挿してたものを一つ右に移し替えただけです。
これ以降はずっとこの形で進めていきます。

これでLEDは消えると思ったのですがなぜか微弱に光ってます。よくわからん…。
ただまあとりあえずコマンドで操作してみます。

```bash:OSXターミナル
pi@raspberrypi:~ $ sudo su // 管理者権限で実行
pi@raspberrypi:~ $ echo 2 > /sys/class/gpio/export // GPIO2を指定します
pi@raspberrypi:~ $ echo out > /sys/class/gpio/gpio2/direction // 出力に設定します
pi@raspberrypi:~ $ echo 1 > /sys/class/gpio/gpio2/value // 光る
pi@raspberrypi:~ $ echo 0 > /sys/class/gpio/gpio2/value // 消える
pi@raspberrypi:~ $ echo 2 > /sys/class/gpio/unexport // 終了します
```

ファイルに書き込みがしたいので1行目で管理者権限にしています。
2行目でGPIO2を使うということを指定します。指定したパスに2を書き込んでるようです。
3行目で指定したピンを入力に使うのか出力に使うのかを設定します。今回は出力なのでアウトです。
valueを1か0にすることで光ってるかどうかを指定するので、4行目で光って5行目で消えます。
最後、6行目でGPIO2の指定を終了します。

うーん、僕の操作で光ったり消えたりするのが感動ですね、たまらんですね。
LED光らせてるだけでなんでこんなに楽しいんだ。
出力設定にしたところで光が消えて、1と0の操作で良い感じに動いたのですが最後終了させたらまた微弱に光ってました。GPIO2にも常に微弱に電気が流れてるって感じなんですかね。
今回はとりあえずあまり深く考えずに次に進みます。


## Node.jsでLチカする

ここまでくるのに時間かかりましたが今回の目的であるNode.jsでLEDを動かしたいと思います。
すでにNode.jsはインストールしてあるのであとはJSファイルを作るだけですね。

ソースはこんな感じにしてみました。

```js:led.js
var fs = require('fs');

var dir = '/sys/class/gpio';
var gpio2 = dir + '/gpio2';

var count = 0;

fs.writeFileSync(dir + '/export', 2); // 2ピン
fs.writeFileSync(gpio2 + '/direction', 'out'); // 出力に設定

function flash() {
  count++;
  fs.writeFileSync(gpio2 + '/value', count % 2);

  if (count <= 20) {
    setTimeout(flash, 500);
  } else {
    fs.writeFileSync(dir + '/unexport', 2); // 処理の終了
  }
}

flash();
```

20回チカチカしたら繰り返し処理が終わる感じです。
先ほどはshellで直接書き込むことでLEDを操作しましたが、Nodeを使う場合は`fs`モジュールを使うことでその処理を実行します。
繰り返し処理の中で1と0を交互に書き込むことで点滅させています。処理自体は簡単なのであっさりできましたね。

`$ sudo node led.js`でこのJSファイルを実行します。

```bash:OSXターミナル
pi@raspberrypi:~ $ sudo node led.js
fs.js:706
    return binding.writeBuffer(fd, buffer, offset, length, position);
                   ^

Error: EBUSY: resource busy or locked, write
    at Error (native)
    at Object.fs.writeSync (fs.js:706:20)
    at Object.fs.writeFileSync (fs.js:1234:24)
    at Object.<anonymous> (/home/pi/led.js:8:4)
    at Module._compile (module.js:398:26)
    at Object.Module._extensions..js (module.js:405:10)
    at Module.load (module.js:344:32)
    at Function.Module._load (module.js:301:12)
    at Function.Module.runMain (module.js:430:10)
    at startup (node.js:141:18)
```

あれ、なんか怒られた。
ここで僕ははまって大分苦労してました。

EBUSYってのはリソースが使用中のときに起こるエラーのようで、shellでLEDつけたり消したりしてたときに最後に`echo 2 > /sys/class/gpio/unexport`をせずに終わってたのでnodeで触ることができなかったみたいです。
なのでちゃんとshellでの処理を終わらせたあとにもう一度実行したらいけました。

[![Lチカ](http://img.youtube.com/vi/04UUkteCinM/0.jpg)](http://www.youtube.com/watch?v=04UUkteCinM)


Qiitaに動画載せるのむずい…。
スマホで撮った動画をGIFにして色々頑張って圧縮してそれでも全然重くてやっと載せれるかなくらいになるまで頑張ったのに投稿したら結局動かなくてYoutubeにしたけどYoutubeだとこのページ上でみられないんですね、Qiitaむずい。
まあとにかくチカチカの感動が伝わったら嬉しいな！


今回はとりあえずここまでで終わりにします。
Nodeで動かすっていうくらいだからsocket通信でブラウザ上から操作できるとこまでやってようやく「Lチカ」って感じもするのだけれどあまりにも長くなりそうなのでここらへんで切ります。
また次の機会にそこらへんは書こうと思います。

とりあえず普段webサイトやwebアプリしか作ってないエンジニアが形のあるものに触れられるってのはものすごく胸踊る体験だなあと思いました。今後もどんどんIoTやっていきたいと思う。
ではでは。


# 参考サイト
- [公式サイト](https://www.raspberrypi.org/)
- [ウィキペディア](https://ja.wikipedia.org/wiki/Raspberry_Pi)
- [Raspberry PiのOSをインストールしてみた（NOOBS篇）](http://raspi.seesaa.net/article/414754789.html)
- [Raspberry Piの初期設定](http://www.cenav.org/raspi2a/)
- [第9回「ラズベリーパイで電子工作！Lチカ…の前にLピカ！」](http://deviceplus.jp/hobby/raspberrypi_entry_009/)
- [node.jsを使ってWebからエアコンを遠隔操作できるようにしてみた](http://qiita.com/suzumi/items/43d0f68bfa0b1b34942d)