みなさんあのね

エクセルいじりがお仕事のインフラ系SEのメモ

ArduinoとRaspberry Piで作るスマート家電(寝返り扇風機)(2)




前回の続き記事です。Raspberry PIでWEBサーバを構築して、ソケット通信を試してみましょう。しれっと途中でXBeeの設定なんかも挟んでいますが、気にしないでください。

OSのインストール

1. 自分の作業用PCの環境に合った「SD Formatter」をダウンロードする。
2. 「SD Formatter」でOSをインストールするSDカードをフォーマットする。
3. こちら からOSのインストールツール「NOOBS」をダウンロードする。圧縮ファイルになっているので予め解凍しておく。
4. 解凍してできたファイルをすべて選択し、SDカードにコピーする。
5. Raspberry Pi に挿し込む。
6. HDMIケーブル(対向には電源オン状態のディスプレイを接続)、LANケーブル、USBキーボード、を Raspberry Pi に接続してから、microUSB電源ケーブル(対向には2AのUSBアダプタを接続)を接続する。(Raspberry Pi には電源ボタンが存在しないので、電源ケーブルうを接続した瞬間に電源がオンになります。)
7. インストールメニュー画面が表示されたら、Raspbianを選択し、インストールを開始する。
8. キーボードとタイムゾーンの設定
[Configure keyboard]>[Generic 105-key(Intl) PC]>[Other]>[Japanese]>[Japanese]>[The default for the keyboard layout]>[No compose key]>[No]
[change_timezone]>[Asia][Tokyo]

初期設定

  • rootユーザのパスワードを設定し、スイッチする
pi@raspberrypi ~ $ sudo passwd root
新しいUNIXパスワードを入力してください:
新しいUNIX パスワードを再入力してください:
passwd: パスワードは正しく更新されました
pi@raspberrypi ~ $ su -
パスワード:
root@raspberrypi:~# 


  • ネットワークの設定

 自分の環境ではデフォルト設定のDHCPを使用しています。一応、設定ファイルの中身を記載しておきます。

root@raspberrypi:~# cat /etc/network/interfaces 
auto lo

iface lo inet loopback
allow-hotplug eth0
iface eth0 inet dhcp

allow-hotplug wlan0
# iface wlan0 inet manual
iface wlan0 inet dhcp 
# wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet d


  • アップデート
root@raspberrypi:~# apt-get update


  • vimのインストール

 Raspbianには初期でvimがインストールされています。しかし、これの実体は最低限の機能のみを持ったvim-tinyであり、今一つ使い勝手が良くありません。なので、普通のvimをインストールしましょう。

root@raspberrypi:~# apt-get install vim


  • 作業用PCからSSHログイン

特に不要な作業ですが、慣れ親しんだ環境で作業したい場合や、ログを編集しながら作業をしたい場合にこの手順を実施してください。ifconfigを実行し、表示されたinetアドレスに作業用PCにインストールしたTera Term(macならターミナル)などからSSHしましょう。

root@raspberrypi:~# ifconfig
eth0      Link encap:イーサネット  ハードウェアアドレス *********
          inetアドレス:192.168.64.42 ブロードキャスト:192.168.64.255  マスク:255.255.255.0


Node.jsの設定

  • Node.jsのインストール
root@raspberrypi:~# git clone https://github.com/creationix/nvm.git ~/.nvm
root@raspberrypi:~# source ~/.nvm/nvm.sh
root@raspberrypi:~# nvm install v0.10.4
root@raspberrypi:~# node -v
v0.10.4  
root@raspberrypi:~# npm -v
1.2.18
root@raspberrypi:~# nvm alias default 0.10.4
default -> 0.10.4 (-> v0.10.4)
root@raspberrypi:~# echo 'source ~/.nvm/nvm.sh' >> .bashrc 


  • 作業用ディレクトリの作成
root@raspberrypi:~# mkdir -p /var/node/negasen
root@raspberrypi:~# cd /var/node/negasen


  • socket.ioのインストール

 Node.js⇔他デバイス間でのソケット通信を可能にするライブラリです。

root@raspberrypi:/var/node/negasen# npm install -g socket.io


  • node-serialportのインストール

 Node.jsでシリアルポートを制御できるようにしたライブラリです。

root@raspberrypi:/var/node/negasen# npm install serialport


XBee連携

  • 初期設定

 下記サイトにて、準備していた2個のXBeeモジュールがお互いを認識し、通信が行えるように初期設定をする。※WindowsのPCが必要になります。
 XBeeをはじめてみよう(ZB編)

WEBアプリ作成

  • Node.jsのメイン処理部分を「app.js」というファイル名で作成
root@raspberrypi:/var/node/negasen# vi app.js
root@raspberrypi:/var/node/negasen# cat app.js
var http = require("http");
var socketIO = require("socket.io");
var fs = require("fs");

// クライアントからアクセスが会った場合に表示させるページを指定
var server = http.createServer(function (req, res) {
	res.writeHead(200, {"Content-Type":"text/html"});
	var output = fs.readFileSync("./negasen.html", "utf-8");
	res.end(output);
});
server.listen(11337);

// シリアルポートの設定
var serialport = require('serialport');
var SerialPort = serialport.SerialPort;
var sp = new SerialPort('/dev/ttyUSB0', {
	parser: serialport.parsers.readline('\r\n')
});

var io = socketIO.listen(server);

// 接続中の処理
io.sockets.on("connection", function (socket) {
	console.log("connected");

	// スマホからWebSocketのパケットが来た時の処理
 	socket.on('value', function(data) {
                console.log(data);
		// 書き込みデータをつくって
  		var xbeewrite = ["ON", Math.pow(2,data.value)-1];
  		// XBeeに送信
  		sp.write(xbeewrite);
	});

	// 取得させて加速度をブロードキャストしてブラウザに表示させる
	socket.on("accel", function(accel) {
	socket.broadcast.emit("accel", accel);
	});

});


  • WEBアプリの表示部分を「negasen.html」というファイル名で作成

 ソケット通信関連のコードは下記記事を参考にしています。
 [node] socket.IOとHTML5 Canvasを用いた手書きチャットアプリを作ってみた

root@raspberrypi:/var/node/negasen# vi negasen.html
root@raspberrypi:/var/node/negasen# cat negasen.html
<html>
<head>
  <meta charset="utf-8">
  <title>Negaeri Senpuuki</title>
</head>
<body>
  <!-- Header -->
  <h1 class="title">Negaeri Senpuuki</h1>

  <!-- Main -->
  <script src="/socket.io/socket.io.js"></script>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
  <script type="text/javascript">
    window.addEventListener("load", function () {

      // サーバーサイドのsocket.IOに接続する
      // 接続出来たら、サーバー側のコンソールにconnected!と表示させる
      var socket = io.connect("/");

      var $id = function(id)
      {
        return document.getElementById(id);
      }

      window.addEventListener('devicemotion', function(e){

        // 重力加速度(3軸)
        var gravity = e.accelerationIncludingGravity;
        $id("gravity").innerHTML = gravity.x + ', ' + gravity.y + ', ' + gravity.z;
        // 加速度(3軸)
        var accele = e.acceleration;
        $id("accele").innerHTML = accele.x + ', ' + accele.y + ', ' + accele.z;
        // 回転加速度
        var rotation = e.rotationRate;
        $id("rotation").innerHTML = rotation.alpha + ', ' + rotation.beta + ', ' + rotation.gamma;

        socket.emit("accel", {gravity:gravity, accele:accele, rotation:rotation});

        // 寝返りを打った場合(加速度センサーで取得した値gしきい値を超えた場合)のみArduinoに通信を行う
        // 評価に使用する加速度やしきい値は調整の必要があるかも
        if (gravity.x >= 2 || gravity.y <= -2) {
            socket.emit("value", "P1");
        }

      });

      socket.on("accel", function (accel) {

        // 重力加速度(3軸)
        var gravity = accel.gravity;
        $id("gravity").innerHTML = gravity.x + ', ' + gravity.y + ', ' + gravity.z;
        // 加速度(3軸)
        var accele = accel.accele;
        $id("accele").innerHTML = accele.x + ', ' + accele.y + ', ' + accele.z;
        // 回転加速度
        var rotation = accel.rotation;
        $id("rotation").innerHTML = rotation.alpha + ', ' + rotation.beta + ', ' + rotation.gamma;

      });

    }, false);         

  </script>

重力加速度(3軸)<br>
  <div id="gravity"></div>
加速度(3軸)<br>
  <div id="accele"></div>
回転加速度<br>
  <div id="rotation"></div>

</body>
</html>


  • 実行

 下記コマンドを実行して、Wi-Fiルータに接続済みのスマホからWEBサーバに接続(http://192.168.64.42:11337)してみましょう。ソケット通信の確認用にPCのブラウザからもWEBサーバにアクセスしておくといいかもしれません。
IPアドレス部分は自分が構築したサーバのものに置き換えてください。

root@raspberrypi:/var/node/negasen# node app.js
   info  - socket.io started



うまく動けばの↓のような動作をします。iPad miniで試してみたのですが、加速度センサーがついてるデバイスなら何でもOKみたいです。





ちなみに、Raspberry Pi はこんな感じで衣装棚の上で動いてます。コンパクトでいいですねえ。
f:id:si871137:20130720224409j:plain


次回はいよいよ、Arduinoをいじってサーボモータを動かします。