2009/08/13

Arduinoの温度計を読んでTwitterに投稿するスクリプト

温度計とLCDを付けたArduinoですが、今日はArduinoで読んだ温度計の値をMacで受け取って、それをTwitterに投稿するところまでやりました。以下はPerlのスクリプトとArduinoのプログラムです。「Net::Twitter::Lite」と「Device::SerialPort」の二つのモジュールをインストールすればよいだけです。モジュールのインストールに関しては、リンク先を参照。

cpan を使いperl module をインストールする

cpanを動かすとftp接続がうまくいかない場合があるんですが、その時はモジュールをcpanのHPからダウンロードして、Authorの名前のディレクトリに置いて、「make install *** 」とやると成功したりしなかったり。後、「Net::Twitter」というモジュールもあるんですが、なんだか特殊?らしくてうまくインストールできませんでした。::Liteは簡易版らしいのですが、今回欲しい機能としては問題ありません。

Perlのスクリプトは特に難しいところはないんですが、$port->lookfor() でデータが来てるかどうかをポーリングしてるところが目新しいかなー、ぐらいで後は特に難しくありませんね。難しいところはモジュールが全部やってくれます。Twitterへの投稿も1行で済むのがいい。データが来たらTwitterに投稿します。投稿間隔を決めてるのは、Arduinoのプログラムです。

#*** Perのスクリプト ***#
use Net::Twitter::Lite;
use Device::SerialPort;

$user = "yourlogin";
$password = "youpassword";
my $nt = Net::Twitter::Lite
->new(username => $user, password => $password);

# Set up the serial port
# 9600, 81N on the USB ftdi driver
$serialSpeed = 9600;
my $port = Device::SerialPort
->new("/dev/tty.usbserial-A7006SWY");
$port->databits(8);
$port->baudrate($serialSpeed);
$port->parity("none");
$port->stopbits(1);

while(1)
{
# Poll to see if any data is coming in
my $temp = $port->lookfor();

if($temp)
{
($sec,$min,$hour,$mday,$mon,$year,$wno) = localtime(time);
@wdays = ('SUN','MON','TUE','WED','THU','FRI','SAT');
$nitizi = sprintf("%04d/%02d/%02d(%s) %02d:%02d",
$year+1900,$mon+1,$mday,$wdays[$wno],$hour,$min);

my $result = eval { $nt->update("$nitizi: $temp Celsius ") };
}
}

以下はArduinoのプログラムです。1分間隔でシリアルポートに温度計の値を送ります。精度をあげるために10ms毎に計測を行い、30秒での平均値を出力することにしました。

/*** Arduinoのプログラム ***/
int ANPIN_Temp = 0; /* Analog Input Pin */

/*** Constant ***/
int TEMPLOOPMAX = 3000; /* Max Loop Count for Temp meas loop */

/*** Variable ***/
double sumTemp; /* Sum of Temp. */
double dispTemp; /* Averaged Temp for Display */
int tempLoopCount; /* Temp. Loop Counter */

void setup()
{
Serial.begin(9600);
}

void loop()
{
col = 0;
sumTemp = 0;
dispTemp = 0;
tempLoopCount = 0;

/*** Measure Temp. by 100 times and Average it ***/
while(tempLoopCount < TEMPLOOPMAX)
{
sumTemp += analogRead(ANPIN_Temp); /* Read Temp. and Sum it */
delay(10); /* delay 10ms to let the ADC recover */
tempLoopCount++;
}

/* Ave. Temp.[bit] x 5V / 1024bit x (1c / 0.01V) */
dispTemp = (sumTemp / TEMPLOOPMAX) * 5 / 1024 * 100;
Serial.println(dispTemp);

delay(30000);
}

<関連記事>
ArduinoにLCDを付けて温度計を表示させてみた
噂の4Dパズル「ロンポス」
Arduinoに温度センサーを付けてみた

<追伸>
最近地震が多いですねぇ。しかし、東名高速の崩落ってのも怖い話です。もしもその時車が走ってたらと思うと、ぞっとしますね。道路が弱ってたのか、地盤が弱ってたのか。人工物なんて、あっけないものです。とにかく渋滞になる前に、会津若松行っておいてよかった。明日とかは大変そうだなぁ。