2014年7月23日水曜日

Socket.IOとNode.js、Node-serialport、それにArduinoを加えてスマホから家電のスイッチを制御する(3)

こんにちは。前回までの記事ではNode.js、Socket.IO、Expressを使用してWebアプリケーションの開発方法を学んできました。ここからは、ブラウザを通して実世界とのインタラクションをデザインしていきます。具体的にはサーバPCにArduinoを接続することでさまざまなセンサやアクチュエータを動かしてブラウザでの操作を実世界に作用させていきます。Node.jsでSerial通信を行うためにNode-Serialportというパッケージを用います。今回の記事ではNode-SerialPortのインストールを行い、Arduinoとシリアル通信を行って、

  1. Arduinoからの情報をうけとる。
  2. Arduinoへ命令を出す。
という2つの動作を同時に実現したいと思います。

まずは、Node-SerialPortのインストールです。

これまでにやってきた方法と同じようにnpmを使用してインストールを行います。そのコマンドは、
npm install --save serialport
となっています。

続いては、Arduinoのプログラムを書きます。

ここで書くプログラムは非常に単純なシリアル通信のプログラムとなっています。内容としては、擬似乱数を生成しシリアル通信でindex.jsに送信、index.jsはクライアントとなるindex.htmlに受信した数値を送信し表示します。また、同時にindex.htmlに用意されたButton要素がクリックされたらindex.jsにイベントを送信し、index.jsからシリアル通信を利用してArduinoに命令を送信(今回は'1'を送信)し、命令を受信したArduinoでDigitalPinのHIGHとLOWを切り替えます。こうするとブラウザを経由してLチカ(LEDをチカチカさせること)ができるようになります。今回はLEDをソリッドステート・リレーに置き換えて、AC100V電源のON/OFFを切り替えます。

以下ソース
char incomingByte;
boolean sw = false;

void setup(){
    Serial.begin(57600);
    pinMode(4,OUTPUT);
}

void loop(){
        int rnd = random(1,100);
        delay(500);
        Serial.println(rnd);
        if(Serial.available() > 0){
            incomingByte = Serial.read();
            if(incomingByte == '1'){
                sw = !sw;
                if(sw == true){
                    digitalWrite(4,HIGH);
                }else{
                    digitalWrite(4,LOW);
                }
            }
        }
}
先ほど説明したように擬似乱数を生成してシリアル通信で送信し、命令があったらDigitalPinのHIGH/LOWを切り替えるというシンプルなプログラムになっています。DigitalPinが4番ピンを指定している理由は特にありません。何番でも大丈夫です。Arduinoの4番ピンにLEDのアノード(足が長い方)、GNDにカソードを刺します。電流制限抵抗とかはとりあえず気にしません。

続いてはChatアプリを基にシリアル通信を行うアプリを作製します。

でははじめにソースを示します。

index.js
ar app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var SerialPort = require('serialport').SerialPort;
var serial = new SerialPort('/dev/tty.usbmodemfd121',{
    baudrate:57600
});

app.get('/',function(req,res){
    res.sendfile('index.html');
});

serial.on('open',function(){
    console.log('open');
});

serial.on('data',function(data){
    io.emit('recvmsg',data.toString());
});

io.on('connection',function(socket){
    socket.on('message',function(msg){
        serial.write(msg,function(err,results){
        });
    });
});

http.listen(3000,function(){
    console.log('listen 3000 port');
});
新しく出てきたNode-SerialPortの部分は、
//ここと
var SerialPort = require('serialport').SerialPort;
var serial = new SerialPort('/dev/tty.usbmodemfd121',{
    baudrate:57600
});
//ここの部分です
serial.on('open',function(){
    console.log('open');
});

serial.on('data',function(data){
    io.emit('recvmsg',data.toString());
});

io.on('connection',function(socket){
    socket.on('sendmsg',function(msg){
        serial.write(msg,function(err,results){
        });
    });
});
上のほうではパッケージを使う宣言を行い、serialを作製しています。一番目の'/dev/tty.usbmodemfd121'という部分は、シリアルポートを特定する部分です。Macなのでこういった感じになっていますが、Windowsでは'COM3'などのようになるかもしれません。また、Raspberry Piに移植する際にもこの部分の変更が必要になります。
下の方では、Arduinoからのデータを受信し、index.htmlにrecvmsgというイベント名で文字列データとして送信する部分io.emit('recvmsg',data.toString());と、htmlからsendmsgイベントを受け取り、Arduinoに命令(msg)を送る部分serial.write(msg,function(err,results){});から成っています。とてもシンプルです。

index.html
<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8" />
  <title>arduino control</title>
  <style>
   article, aside, dialog, figure, footer, header,
   hgroup, menu, nav, section { display: block; }
  </style>
 </head>
 <body>
            <h1>hello</h1>
            <button>SW1</button>
            <script src="/socket.io/socket.io.js"></script>
            <script src="http://code.jquery.com/jquery-1.11.1.js"></script>
            <script>
                var socket = io();
                $('button').click(function(){
                    socket.emit('sendmsg','1');
                });
                socket.on('recvmsg',function(data){
                    $('h1').text(data);
                });
            </script>
 </body>
</html>
このHTMLは、h1要素とbutton要素の2つの要素のみで構成されています。先ほどのindex.jsでArduinoから受け取ったデータをrecvmsgイベントを通してh1要素に表示し、button要素がクリックされたら、sendmsgイベントを通してindex.jsに'1'を送信します。この'1'は最終的にindex.jsからArduinoに送信されます。

図に書くと
となります。これで、Arduinoから情報を受信しつつ、Arduinoに命令を送ることができる双方向のWebアプリケーションが完成しました。秋月電子のソリッドステート・リレーと組み合わせた例が以下になります。
この電球は家庭用AC100V電源につながっています。そのため扇風機など他の家電を動かすこともできます。もちろんソリッドステート・リレーだけでなく、サーボモータや赤外線LEDなどなどArduinoで動かせるものはなんでも使うことができますし、ブラウザに表示する情報も温度湿度や照度、果ては空気清浄度までArduinoにつけるセンサやアイデアによっては無限大です。カメラがiPhoneしかない関係上、ブラウザはMacBookのものを使っていますが、もちろんiPhoneから操作することも可能です。

さて、次回の記事ではこのシステムをRapsberry Piに移植し、自動起動化することでよりコンパクトで便利なシステムにまとめていきます。

0 件のコメント:

コメントを投稿