BeagleBone BlackからArduinoをJohnny-FiveとFirmataで操作する

先日[Raspberry Pi(Model B)とArduino](http://qiita.com/masato/items/1cd1f479a0349e9e25d3)をUSBシリアル接続して使っていました。USBケーブルをぶちっと抜いて電源を落としてしまったらSDカードが壊れてました。Raspbianは起動してもファイルシステムがRead-Onlyになってしまいます。マイコンはUSBケーブルを抜いて電源をぶちっと落とすので、Linuxの小型コンピューターでもついやってしまいます。Read-Onlyの修復方法をいくつか試しても直らないので結局SDカードにRaspbianを焼き直しました。[Stopping SD Card Corruption on Raspberry Pi’s Raspbian](http://www.ideaheap.com/2013/07/stopping-sd-card-corruption-on-a-raspberry-pi/)などを読んで最適な方法を見つけたいと思います。作業に困るのでJohnny-Five環境をBeagleBone Blackでも構築します。BeagleBone Blackの方がもうちょっと雑に扱えます。


## ホストマシン

Firmataプロトコルを使うホストマシンをRaspberry PiからBeagleBone Blackに変更しました。ディスプレイとキーボードを使う作業マシンは同様にChromebookを使います。Arduinoとの接続はUSBシリアル変換ケーブルはBBBをケースに入れてしまいピンを刺せないので、USBテザリングをしてSSH接続します。

### Chromebook

BBBにSSH接続するコマンドをスクリプトにまとめました。

``` bash:~/Downloads/bbb-setup.sh
#!/bin/bash
sudo sh -c 'echo 1 >> /proc/sys/net/ipv4/ip_forward'
sudo iptables -t nat -A POSTROUTING -o mlan0 -j MASQUERADE
sudo iptables -A FORWARD -i mlan0 -o eth0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o mlan0 -j ACCEPT
ssh ubuntu@192.168.7.2
```

croshからshellを起動します。

`cntl-alt-t`を押してcroshを起動してからshellを実行します。

``` bash
crosh> shell
```

作成したスクリプトを使いChromebookからBBBにSSH接続します。

``` bash
$ bash ~/Downloads/bbb-setup.sh
```

![bbb-arduino.jpg](https://qiita-image-store.s3.amazonaws.com/0/43745/5dc1c778-e4c0-fdcd-e2ec-a2b7c5221def.jpeg)


### BeagleBone Black

BBBには[Ubuntu 14.04.1](https://rcn-ee.net/rootfs/2015-01-06/microsd/bone-ubuntu-14.04.1-console-armhf-2015-01-06-2gb.img.xz)をインストールしています。

``` bash
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="14.04.1 LTS, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 14.04.1 LTS"
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
```

以前どういう状態でBBBを終了していたか忘れてしまいました。一通りBBBの環境を確認してまわります。時間あわせとタイムゾーンの設定をします。

``` bash
$ sudo ntpdate -b -s -u pool.ntp.org
$ sudo ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
```

ルーティングテーブルを表示します。

``` bash
$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.7.1     0.0.0.0         UG    0      0        0 usb0
192.168.7.0     0.0.0.0         255.255.255.252 U     0      0        0 usb0
```

デフォルトゲートウェイがなかったら設定します。

``` bash
$ sudo route add default gw 192.168.7.1
```

usb0のIPアドレスはstaticにします。

``` bash:/etc/network/interfaces
...
auto usb0
iface usb0 inet static
    address 192.168.7.2
    netmask 255.255.255.252
    network 192.168.7.0
    gateway 192.168.7.1
```

resolv.confにGoogle DNSを使います。

```bash:/etc/resolv.conf 
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 8.8.8.8
nameserver 8.8.4.4
```

DNSが未設定の場合は`/etc/resolv.conf`は直接編集せず`resolvconf`コマンドを使います。

``` bash
$ sudo vi /etc/resolvconf/resolv.conf.d/base
nameserver 8.8.8.8
nameserver 8.8.4.4
$ sudo resolvconf -u
```

BBBからChromebookのUSBテザリングを経由して、名前解決とインターネットに接続できました。

``` bash
$ ping -c 1 www.yahoo.co.jp
PING www.g.yahoo.co.jp (183.79.197.250) 56(84) bytes of data.
64 bytes from 183.79.197.250: icmp_seq=1 ttl=50 time=26.3 ms

--- www.g.yahoo.co.jp ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 26.348/26.348/26.348/0.000 ms
```

## Johnny-Fiveの環境構築

### Node.js

以前はapt-getでNode.jsをインストールしていました。パッケージを削除して最新版に入れ直します。

``` bash
$ sudo apt-get update
$ apt-cache show nodejs
$ sudo apt-get remove --purge nodejs
```

[node-arm](http://node-arm.herokuapp.com/)から最新版をインストールします。

``` bash
$ wget http://node-arm.herokuapp.com/node_latest_armhf.deb
$ sudo dpkg -i node_latest_armhf.deb
```

一度ログアウトしてバージョンを表示します。

``` bash
$ node -v
v0.12.0
$ npm -v
2.5.1
```


### Gort

ArduinoのFirmataファームウェアは最新にしたばかりですが、BBBにも[Gort](http://gort.io/)から[AVRDUDE](http://www.nongnu.org/avrdude/)をインストールしておきます。

``` bash
$ wget https://s3.amazonaws.com/gort-io/0.3.0/gort_0.3.0_linux_arm.tar.gz
$ tar zxvf gort_0.3.0_linux_arm.tar.gz 
gort_0.3.0_linux_arm/gort
gort_0.3.0_linux_arm/README.md
gort_0.3.0_linux_arm/LICENSE
$ sudo cp gort_0.3.0_linux_arm/gort /usr/local/bin
$ gort --version
gort version 0.3.0
```

BBBにUSBケーブルで接続したArduinoのデバイスファイルを表示します。

``` bash
$ gort scan serial
1 serial port(s) found.

1. [/dev/ttyACM0] - [usb-Arduino__www.arduino.cc__0043_55431313338351E0F111-if00]
  USB device:  Bus 001 Device 002: ID 2341:0043 Arduino SA Uno R3 (CDC ACM)
```

ubuntuユーザーはすでにdialoutグループに入っているので、`/dev/ttyACM0`デバイスファイルの書き込み権限を持っています。

``` bash
$ ls -l /dev/ttyACM0
crw-rw---- 1 root dialout 166, 0 Mar 24 12:27 /dev/ttyACM0
$ groups
ubuntu adm kmem dialout cdrom floppy audio dip video plugdev users netdev i2c xenomai weston-launch systemd-journal spi admin
```

BBBにAVRDUDEをインストールします。動作確認のためArduinoのFirmataファームウェアも更新します。

``` bash
$ gort arduino install
$ gort arduino upload firmata /dev/ttyACM0
```

### Lチカ

いつものようにJohnny-FiveのLチカサンプルを動かしてみます。

``` bash
$ mkdir -p ~/node_apps/johnny-five-start
$ cd !$
```

package.jsonにJohnny-Fiveのパッケージを指定します。

```json:~/node_apps/johnny-five-start/package.json
{
  "name": "johnny-five-start",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
    "johnny-five": "0.8.49"
  },
  "scripts": {"start": "node app.js"}
}
```

app.jsは1秒間隔でLチカするサンプルです。

```js:~/node_apps/johnny-five-start/app.js
var five = require("johnny-five");
var board = new five.Board();
board.on("ready", function() {
  var led = new five.Led(13);
  led.blink(1000);
});
```

npmでパッケージをインストールしてサンプルアプリを実行します。Lチカが開始したのを確認できたら、Ctrl-Cを2回押してプログラムを終了します。

``` bash
$ npm install
$ npm start

> johnny-five-start@0.0.1 start /home/ubuntu/node_apps/johnny-five-start
> node app.js

1427170202861 Device(s) /dev/ttyACM0 
1427170202977 Connected /dev/ttyACM0 
1427170206552 Repl Initialized 
>> 
```