読者です 読者をやめる 読者になる 読者になる

hollywis's diary (はりうすブログ)

はりうすの活動日記です

IoT的にJohnny-fiveでLED制御する!

こんにちは、のすけです。

かなり間が空いてしましました。

今回は、お手軽にIoTをやろうということで、wifiモジュールを利用せずに Johnny-fiveを利用してLEDの制御をやってみようと思います。

https://github.com/rwaldron/johnny-five/raw/master/assets/sgier-johnny-five.png

GitHub - rwaldron/johnny-five: JavaScript Robotics and IoT programming framework, developed at Bocoup.

よくJohnny-fiveを利用してArduinoを制御する記事などは見かけるのですがネット越しで制御する例は まだ少ないようですので、ここでご紹介したいと思います。

記事中で利用しているArduinoArduino R3になります。

Johnny-fiveをインストール

Johnny-fiveはオープンソースのFirmataというプロトコルを利用したIoTプログラミングフレームワークです。

Johnny-fiveを利用すればArduinoなどのハードウェアの制御を行えるだけでなく、node.jsの機能を利用してインターネット接続し様々なことができるようになります。

なお、今までのようにArduinoIDEはほとんど利用しません。

Arduino言語もFirmataの部分のみしか使いません。

全てJavascriptで記述しますのでJavascript用のテキストエディタを利用して記述しましょう。

MacならSublimeText2WebStorm,Vim

WindowsならさくらエディタTerapad,VisualStudio

などが良いでしょう。

プロジェクトフォルダの作成

次のコマンドを打って、プロジェクトフォルダを作成します。 Macならターミナルを起動し、Windowsならコマンドプロンプトを起動して以下のコマンドを叩いてください。

mkdir NodeProjects
cd NodeProjects
mkdir johnny-test001
cd johnny-test001

node.jsのインストール

http://mdlab.jp/project/node_js/images/node01.png

PCにnode.jsをインストールする必要があります。 しかし、すでに入っている場合もありますので次のコマンドを叩いて確認しましょう。

$ node -v
v5.0.0
$ npm -v
3.3.9

nodeが入っていればバージョンが表示されます。入っていなければ「そんなコマンドはない!」みたいなことを言われると思います。 同じくnpmも確認しましょう。

もし入っていなければ以下のサイトからダンロードしてインストールしましょう。 Node.js nodeには様々なバージョンがありますが、最新の5系のStableを入れておけば良いでしょう。 インストールが完了したら、先ほどのnode -vなどを叩いてnodeコマンドが使えるようになっていることを確認してください。

node.jsについての説明

node.jsはJavascript(ジャバスクリプト)でできたサーバになります。

Javascriptは主にHTMLなどと一緒に利用するイメージですが、その言語を利用してサーバを立てられてしまうのが node.jsです。

通常のサーバに比べて次のような点があると思っています。

  • 簡単にサーバが立てられる

  • 非同期処理が楽

  • 軽量

  • Javascriptで記述できるので、クライアントサイドも、サーバサイドも同じようにコードが書ける。

よくわからんぞ!!という方は、とりあえずスルーでOKです。

jhonny-fiveモジュールをnode.jsにインストール

実はjhonny-fiveはnode.jsのモジュールの一種です。

そのため、node.jsの関連モジュールを管理するコマンドnpmで簡単に入れることができます。

次の1行を実行してください。モジュールが大きいため多少ダウンロードに時間がかかります。

npm install johnny-five

さぁこれで準備は完了しました。 次はコードを書いていきましょう!

まずはnodeからArduinoの接続テスト

f:id:hollywis:20160325185857j:plain photo by fliker 紅色死神

ArduinoにFirmataプログラムを書き込む

ArduinoIDEから次のスケッチを選択して ファイル > スケッチの例 > Firmata > StandardFirmata

を選択して、Arduinoに書き込みます。

以上で終了です。ArduinoIDEの出番も、Arduino言語もこれでおしまいです。

f:id:hollywis:20160325192110p:plain

jonny-fiveを利用した接続テストプログラムを書く

先ほど作成したjohnny-test001というフォルダの下に次のファイル名でjsファイルを作成してください。 led-blink.js

中身は次のように記述します。

var five = require("johnny-five");
var board = new five.Board();

board.on("ready", function() {

  var led = new five.Led(13);

  // "blink" the led in 500ms on-off phase periods
  led.blink(500);
});

そして、PCとArduinoを接続した後に次のコマンドを実行します

node led-blink.js

ArduinoのLEDが点滅すれば成功です。

f:id:hollywis:20160325172825j:plain

これだけでも楽しいのですが、これはIoTではないです。

ただnodeを利用してArduinoを制御しただけですので、永遠点滅してしまいますし、止める方法もありません。

ネットからの指示だしして制御してこそIoTですよね!

nodeのサーバ機能を実装してIoTする

f:id:hollywis:20160325185411j:plain photo by flickr[PROFumi Yamazaki]

実はここから若干難しくなります。nodeでサーバ機能を作らなくてはいけないためです。

だた、node.jsは他のサーバサイドプログラムと比較してもかなり少量のコードで動きます。

server.jsの作成

先ほど作成したjohnny-test001というフォルダの下に次のファイル名で新しくjsファイルを作成してください。

server.js

そして中には次の内容を記述しましょう。

var http = require('http');
var querystring = require('querystring');
var util = require('util');
var fs = require('fs');
var form = fs.readFileSync('./public/form.html');

var five = require('johnny-five');
var board = new five.Board();

cmd_ledon = 'echo "LED ON!!"';
cmd_ledoff = 'echo "LED OFF!!"';

var led;

board.on('ready', function() {
    led = new five.Led(13);
});

http.createServer(function (req, res){
    if(req.method === 'GET'){
        res.writeHead(200,{'Content-Type': 'text/html'});
        res.end(form);
    }
    if(req.method==='POST'){
        var postData = '';
        req.setEncoding('utf8');
        req.on('data',function (chunk){
            // per request
            postData += chunk;
        }).on('end',function(){
            // response data
            var respose_data = '';

            // end request
            if(!postData){
                res.end();
                return;
            } // if postData is empty.
            var postDataObject = querystring.parse(postData);
            console.log('user posted following data:' + postData);
            console.log(postDataObject.userinput1);
            respose_data += 'your poted data is:\n' + util.inspect(postDataObject)+'\n';

            if(postDataObject.userinput1 == '1'){
                led.on();
                respose_data += 'LED ON !!';
                respose_data += '<style type="text/css">.ledon{background-color: #34A7C1;}</style>';
            } // if userinput1で1がPOSTされたならledon
            if(postDataObject.userinput1 == '0'){
                led.off();
                respose_data += 'LED OFF !!';
                respose_data += '<style type="text/css">.ledoff{background-color: #34A7C1;}</style>';
            } // if userinput1で0がPOSTされたならledoff

            res.writeHead(200,{'Content-Type': 'text/html'});
            res.end(form + respose_data,"utf8");
        });
    }
}).listen(8000);

実はこれは、別連載の「node.jsをやってみる」のサーバサイドコードとjhonny-fiveの記述を合体しただけです。 hollywis.hatenablog.com

前半の5行が利用するweb系のモジュールの記載。

var http = require('http');
var querystring = require('querystring');
var util = require('util');
var fs = require('fs');
var form = fs.readFileSync('./public/form.html');

次の2行がJohnny-fiveの記載です。

var five = require('johnny-five');
var board = new five.Board();
board.on('ready', function() {
    led = new five.Led(13);
});

この部分で13番PINをjhonny-fiveと関連付けて、グローバル変数であるledに入れています。

そしてhttp.createServerでサーバ機能を作り、POSTリクエストが来た時に次の部分でled.on()led.off()でLEDを付けたり消したりします。

           if(postDataObject.userinput1 == '1'){
                led.on();
                respose_data += 'LED ON !!';
                respose_data += '<style type="text/css">.ledon{background-color: #34A7C1;}</style>';
            } // if userinput1で1がPOSTされたならledon
            if(postDataObject.userinput1 == '0'){
                led.off();
                respose_data += 'LED OFF !!';
                respose_data += '<style type="text/css">.ledoff{background-color: #34A7C1;}</style>';
            } // if userinput1で0がPOSTされたならledoff

なお、付けたり消したりはuserinput1という変数の値で判断しています。

制御するためのHTMLの作成

HTMLファイルを作成しますので、格納するフォルダpublicを作ってからform.htmlファイルを作成します。 フォルダを作るには次のコマンドを実行してください。

 mkdir public

その下にform.htmlファイルを作ります。

ファイル構成はこんな形になっているはずです。 f:id:hollywis:20160325182856p:plain

form.htmlには次のように記述してください。

<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<form name="form" method="post">
    <button class="ledon" style="width: 150px;height: 150px;" onclick="document.form.userinput1.value = 1">ON</button>
    <button class="ledoff" style="width: 150px;height: 150px;" onclick="document.form.userinput1.value = 0">OFF</button>
    <input type="hidden" name="userinput1"><br><br>
</form>

ボタンledonをクリックしたらhiddenのuserinput1の値に1をセットして送信

ボタンledoffをクリックしたらhiddenのuserinput1の値に0をセットして送信しています。

なお、これは先ほどのコードにvar form = fs.readFileSync('./public/form.html');という部分に関連しています。

PCで実行!

次のコマンドを実行してサーバを起動です。 node server.js

起動できたら、ブラウザでlocalhost:8000にアクセスしてください

f:id:hollywis:20160325183216p:plain

このようにボタンが表示されるはずです。

ONボタンを押すとLEDが点灯し、OFFボタンを押すとLEDが消灯するかと思います。

スマホから実行!

IoTらしくスマホから実行してみましょう。

まず、PCとスマホは同じWifiに接続します。

そしてPCで次のコマンドを叩いてPCのIPアドレスを確認しましょう。

Macならifconfig

Windowsならipconfig

f:id:hollywis:20160325184111j:plain

次に、スマホのブラウザで

xxx.xxx.xxx.xxx:8000と入力します。xxxは確認したIPアドレスです。

f:id:hollywis:20160325184515p:plain

f:id:hollywis:20160325184539p:plain

OKボタンを押すと

f:id:hollywis:20160325184554p:plain

このように命令が実行され,ArduinoのLEDが点灯します。

f:id:hollywis:20160325172825j:plain

OFFボタンを押すとLEDが消灯します。

f:id:hollywis:20160325184701j:plain

まとめ

オープンソースIoTフレームワークJohnny-fiveを利用して、インターネット接続機能が無いArduino R3でIoTしてみました。

PCからだけでなく、同じネットワーク内のスマホからでも簡単に制御できることがわかりました。

本当にインターネット越しに制御するには固定IPを取得するなどして、中継サーバ(ルータなど)が必要ですが 家庭内利用でしたらこの構成でも良いのでは無いかと思います。

最近はスティックPCなども出ていますので、スティックPCとArduinoを接続してしまえば簡単にIoTプラットフォームが 作れてしまうのではないでしょうか。有用そうなのでスティックPC連携は今度試してみたいと思います。