Arduino

Arduinoで事業部長を監視しCiao!

カテゴリ
ブックマーク数
このエントリーを含むはてなブックマーク はてなブックマーク - Arduinoで事業部長を監視しCiao!
このエントリーをはてなブックマークに追加
こんにちは、最近はモバイル向け新規サービスの開発を担当している栗原です。
今回のTechブログではMAKE系の話をご紹介したいと思います。

フィジカルコンピューティングとは

皆さんは『フィジカルコンピューティング』という言葉を御存知でしょうか。フィジカルコンピューティングとは、既存のパーソナル・コンピュータのグラフィカル・ユーザー・インターフェイス(ウインドウ,マウス,アイコンなど)を超えて、私たちの生活環境によりそった身体的なコンピュータのあり方を模索する研究の動向のことを言い(出典:はてなキーワード)、最近ではそれらの研究や実験を簡単に実現するための便利なハードウェアがいくつも存在します。

代表的なハードウェアとしては、ArduinoGainerFunnelなどがあります。これらは単純な入出力を供えた拡張可能な基板となっており、適当な電子部品をつなげることにより様々なことを実現できます。

今回は、この中でもArduinoという物を使ってみようと思います(ちなみに「アルドゥイーノ」と読むらしいです)。Arduinoは先に上げた3つのハードウェアの中でも最も人気のあるもので、今、巷で密かな人気が出ており、以前mixiさんの開発者ブログなどにも紹介されていました。

なにを作るか

さて、Arduinoを使ってなにを作ろうかと考えていて、ふと社内のある問題が思い浮かびました。それはある事業部長が忙しいが故になかなか席にいないため、話がしたくても運がよくないとなかなか会えないという問題です。

以前、弊社櫛井のブログのエントリ『ライブドアに行ってきた!』でもご紹介したように、事業部長のポーズ入り写真ボードで確認をしていました。 しかし毎回自分で上げ下げをしないといけなかったり、そもそも席が遠かったり階が違うと確認できないという問題があり、だんだん使われなくなってしまいました。

今回はこのような問題をArduinoとちょっとしたプログラムで解決したいと思います。

作る(MAKE!)

用意するのは、下記になります。
  • Arduino本体 1個 3200円
    説明不要ですね。Arduinoの本体になります。
  • Arduino用イーサネットシールド 1個 4200円
    Arduinoにイーサネットをつなぐためのシールドになります。シールドとは拡張キットみたいなものです。
  • NaPiOn(赤外線センサー) 1個 1600円
    この回路のメインとなります。NationalのNaPiOnという超小型赤外線センサーのAMN11112という型番のものです。
  • ブレッドボード 1個 200円程
    半田などを使わなくても結線することができるフィジカルコンピューティングにはかかせないボードです。このボードにワイヤー(線)を差すだけで回路を作ります。
  • ブレッドボード用ワイヤー 複数本 100円程
    ブレッドボードの穴に差しやすいワイヤーです。
  • 抵抗 1個 雀の涙
    中学校の頃の授業で見たことがある方もいるでしょう。普通の抵抗です。
これらを下記のように配線します。
この図はFritzingというArduinoなどの回路を作成するためのソフトウェアで作成しました。
circuit

簡単に回路図を説明すると、赤外線センサーNaPiOn(画面上部の灰色の電球のようなもの)の電圧入力端子(Vdd)にはArduinoから+5Vの電源をつなぎ、グランド(GND)はArduinoのGND(0V)につなぎます。そしてセンサーで判定した結果が出力される端子(OUT)は、デジタルピンの3番につなぐとともに途中から10Ωの抵抗を経由してGNDに落しています。 実際に配線した様子は下記のようになっています。左に白いポッチのようなものが見えると思いますが、こちらが赤外線センサーのNaPiOnになります。

arduino

次にこの回路を動かすためのスケッチを描きます(なおArduinoの世界では、Arduinoを動かすためのブログラムをスケッチと呼びます)。スケッチは基本的にはProcessingという言語で書きます(Rubyにradというプロジェクトがあり、Rubyでも書くことができます)。

スケッチの基本的な流れはsetup()を実行した後にloop()を実行しつづけます。このスケッチでは、setup()でネットワークの初期化を行なったあと、loop()で赤外線センサーからの値を取得して後述するPerlプログラムが動いているサーバに接続して、その値を渡します。
#include <Ethernet.h>
#include "Dhcp.h"

const int readPin = 3;
int sensorValue = 0;
int debug = 0;

byte server[] = { 192, 168, 0, 1 }; // Server that perl runs
byte mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Sample mac
byte ip[4];
byte gateway[4];
byte subnet[4];

Client client(server, 7791);

void setup() {
  int result = Dhcp.beginWithDHCP(mac); // Get IP from DHCP
  
  if(result == 1) {
    Dhcp.getLocalIp(ip);
    Dhcp.getSubnetMask(subnet);
    Dhcp.getGatewayIp(gateway);
    
    Ethernet.begin(mac, ip, gateway, subnet); // Etheret init
    delay(100);
  } else {
    Serial.begin(9600);
    Serial.println("DHCP failed.");
  }
}

void loop() {
  sensorValue = digitalRead(readPin);    
  if (debug) Serial.println(sensorValue);
  if (client.connected() || client.connect()) {
    send_sensor_value(sensorValue); // Send sensor value
  } else {
    client.stop();
    Ethernet.begin(mac, ip, gateway, subnet); // Retry
  }
  delay(2000); // 2secs
}

void send_sensor_value(int sv) {
    client.print(sv); // Send value to server
    client.flush();
}

さて、あとはこのスケッチから事業部長がいるかいないかのデータを受けとり、Twitterや社内IRCで「いる?」という問い合わせに反応するプログラムを書くだけです。今回はPerlプログラムで下記のように書きました。

#!perl

use strict;
use AnyEvent;
use AnyEvent::Socket;
use AnyEvent::Twitter::Stream;
use AnyEvent::HTTP;
use AnyEvent::IRC::Client;
use HTTP::Request::Common;
use Net::Twitter;

use constant STAY => 1;
use constant AWAY => 0;

my $condvar = AnyEvent->condvar;
my $i = 0;
my @statuses;

sub status_avg {
    my $one  = scalar( grep { /^1$/ } @statuses );
    my $zero = scalar( grep { /^0$/ } @statuses );
    return $one > $zero;
}

# Check stream on Twitter
AnyEvent::Twitter::Stream->new(
    username => 'TWITTER_USERNAME',
    password => 'TWITTER_PASSWORD',
    method   => 'filter',
    track    => '#foobar',
    on_tweet => sub {
        my $tweet = shift;
        my $twit = Net::Twitter->new(
            username => 'TWITTER_USERNAME',
            password => 'TWITTER_PASSWORD',
        );
        my $time = scalar localtime;
        $twit->update(
            "@$tweet->{user}->{screen_name} "
                . (status_avg() ? 'たぶんいます'
                                : 'たぶんいません')
                . " [$time]"
        );
        warn "posted";
    },
    on_error => sub {
        warn "ERROR: " . join( ', ', @_ );
        $condvar->send;
    },
    on_eof => sub {
        $condvar->send;
    },
);

# Check IRC
my $timer;
my $con = AnyEvent::IRC::Client->new;
$con->reg_cb(
    connect => sub {
        my ( $con ) = @_;
        warn "connected";
    },  
    registered => sub {
        my ( $con ) = @_;
        warn "registered";
        $con->enable_ping( 60 );
    },
    publicmsg => sub {
        my ( $con, $chan, $msg ) = @_;
        if ( $chan eq '#FOOCHANNEL' and
                $msg->{ command } eq 'PRIVMSG' ) {
            my $line = $msg->{ params }->[ 1 ];
            if ( $line =~ /いる[??]/ ) {
                $con->send_chan(
                    $chan, 'NOTICE',
                    $chan, status_avg() ? 'たぶんいます'
                                        : 'たぶんいません',
                );
            } 
        }
    },
);
$con->send_srv( 'JOIN', '#FOOCHANNEL' );
$con->connect( 'irc.example.com', '6667', {
    nick => 'NICKNAME',
    user => 'USERNAME',
    real => 'REALNAME',
} );

# Run tcp server on port 7791.
tcp_server undef, 7791, sub {
    my ($fh, $host, $port) = @_;
    my $poller; $poller = AnyEvent->io(
        fh   => $fh,
        poll => 'r',
        cb   => sub {
            my $r = sysread $fh, my $buf, 1024;
            if ( $r == 0 ) {
                undef $poller;
                return;
            } 
            $i = 0 if $i > 30; # Max status is 30.
            $statuses[$i] = $buf > 0 ? STAY : AWAY;
            warn $statuses[$i];
            $i++;
            syswrite $fh, $buf;
        },
    );
};

$condvar->recv;


あとはスケッチをArduinoにアップロードして起動するのと、Perlプログラムを起動したらOKです!

なお、今回のシステムのデータの流れとしては下記のようになっています。

structure

Arduinoから送信されたデータをPerlのプログラムで保持し、Twitterや社内IRCからの問い合わせに対して返答するといった具合です。なお「いる/いない」の精度を上げるために過去30回の「いる/いない」を保持してカウントが多い方を返答するようにしています。この辺は今後調整が必要かもしれません。

で、実際に動作している様子は下記のようになります。これはIRCのログをキャプチャしたもので、「***checker」というのがチェック用ボットが「いる?」という問いに答えてくれています。

buchochecker_irc

終わりに

今回は急ぎ足でArduinoで組まれた簡単なシステムをご紹介しました。しかし、Arduinoのスケッチを書くためのProcessing言語の紹介や、そもそもArduinoでどんなことができるのか、使用したセンサーはどんなものなのか、なぜこのような回路なのかなど詳細が省かれているため、その辺に関しましては次回機会がありましたらご紹介したいと思います。

なお、Arduinoの情報は http://arduino.cc/ やネットで検索すると様々な情報が出てきますのでそちらも参考にしてみてください。