このブログへの投稿/アップロードについて(コメントは誰でも、投稿は受講者+スタッフのみ)
コメント/投稿/ラベルについて(基本事項)投稿時間の設定(下書き/予定など)プログラム(ソースコード)を投稿する際の注意点Processingのプログラム(Applet)を表示する方法
ArduinoやProcessingについては「建築発明工作ゼミ2008」の方にまとめてあります。
秋葉原の電子工作マップ、Arduino販売店についてはこちら。 :

2009年6月28日日曜日

Arduinoで計測した値を指定のwebサーバに送信、保存する

上に乗っかっているのがEthernet Shield、下にあるのがArduino。



















参考
「Arduino Ethernet Shield」--イーサネットシールドを使って、ArduinoをWebサーバとして機能させる
「Processing HTTPサーバ/Webページ表示」--Networkライブラリを使ってWebサーバとして機能させる
Arduino と Ruby で温湿ネットロガー
Hobby Robotics » Arduino, Xport, PHP and the Internet
Making Things Talk -Arduinoで作る「会話」するモノたち
PHP マニュアル

材料
Arduino Duemilanove
Arduino Ethernet Shield
温度センサ LM35DZ



ゼミで行う植物データの計測とデータの記録方法はそれこそ手書きでメモを取ったり、写真や映像に記録したりといろいろな方法があるのだと思います。
今回は、温度計測の値を指定のレンタルサーバに送信し、サーバのテキストファイルに記録保存してみます。
まず、この記録方法のメリットとデメリットを考えてみました。

メリット
・Arduinoを使用して計測記録するのが前提である場合、記録データは指定したweb上のサーバに保存するので、Arduinoと自宅のPC( もしくはMac )を常時接続しなくてもよい。
・記録したデータはwebにあるので、ネットに接続できる環境にいるならばいつでも記録データを閲覧できる。

デメリット
・ちょっとだけ設定が難しい(目的はあくまでも植物の観察なのですが、そこに行くまでが面倒です)。
・自宅webサーバを組める技術がない場合、レンタルサーバを借りなければならない(今回は、月500円のYahoo giocities を使っています)。
・サーバサイドスクリプトを書かなければいけない(今回は、PHP使います)。
・ネットワークの知識がちょっとだけ必要。


回路図

回路図は以前アップした「温度センサ」の時と変わりません。Ethernet Shieldは、Arduinoをネットに接続してデータの送受信を行えるようにするシールドで、上の写真のようにArduinoに装着します。
ピンはArduinoとほぼ同じように使えます。

全体的な流れですが、

・まず、以前アップした温度計測の時と同じようにArduinoでデータを取得する(今回は最大温度と最小温度の計測は省きます)。
・ルータに接続したEthernet Shield から、ArduinoのEthernetライブラリを使って指定のサーバにデータをアップ。
・受け取ったデータを、下記のPHPスクリプトで指定のディレクトリにテキストデータとして保存する。

となります。















Arduinoのスケッチ

#include <Ethernet.h>
int    A_inPin    = 0;     // アナログ入力ピン番号
int    A_val;              // アナログ入力値(0?1023)
int    outputTerm = 10;    // 計測結果出力ターム(10秒ごとに平均摂氏値を出力する)
float  v          = 5;     // 基準電圧値( V )
int    tempC      = 0;     // 摂氏値( ℃ )
float  tempCPlus  = 0;     // 10秒ごとの合計摂氏値( ℃ )
float  maxTempC   = 0;     // 10秒ごとの最大摂氏( ℃ )
float  minTempC   = 0;     // 10秒ごとの最小摂氏( ℃ )
/* サーバのポート番号を定義 */
#define PORT 80
// Ethernet Shild MACアドレス
byte mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
// Ethernet Shild IPアドレス
byte ip[] = { 10 , 0 , 1 , 100 };
// 接続先のIPアドレス
byte server[] = { 123, 456, 789, 012 };
// 指定したIPアドレスとポートに接続するクライアントを生成
Client client = Client(server, PORT);

void setup(){
Serial.begin(9600);
// Ethernetライブラリとネットワーク設定を初期化
Ethernet.begin(mac, ip);
delay(1000);
Serial.println("connecting...");
}

void loop(){
// 1秒に一回、10秒間分温度計測
for (int i = 0; i < outputTerm; i++ ) {
// アナログピンから計測値を取得(0~1023)
A_val =  analogRead( A_inPin );
// 摂氏に換算
tempC = ((v * A_val) / 1024) * 10000;
// 現for文ループ内で使わなくなった変数は解放
A_val = 0;
// 平均値を取得するために1秒ごとの値を10秒分合計しておく
tempCPlus += tempC;
// 現for文ループ内で使わなくなった変数は解放  
tempC = 0;
// 1秒間ストップ
delay(1000);
}
// 10秒間の平均摂氏値
tempC = tempCPlus / outputTerm;
// 現loop()ループ内で使わなくなった変数は解放
tempCPlus = 0;
// 指定したwebサーバへの接続開始
// 成功
if (client.connect()) {
Serial.println("connected");
// 指定のwebサーバのPHPスクリプトにGET送信
// 'temp'という名前で計測した温度値を送信
client.write("GET /temp_write.php?temp=");
client.print(tempC, DEC);
client.write(" HTTP/1.1\n");
client.write("HOST: www.○○○.net\n\n");
// 接続を終了
client.stop();
// 失敗
} else {
Serial.println("connection failed");
client.stop();
}
// 現loop()ループ内で使わなくなった変数は解放
tempC = 0;
delay(20000);
}


IPアドレスは参考リンクを参照しました。接続先(webサーバ)のIPアドレスは、下記のPHPスクリプトを使いました。

<?php
$ipAddress = gethostbyname($_SERVER['SERVER_NAME']);
print $ipAddress;
?>
テキストエディタなどでこのPHPスクリプトを作成し、 'print_ip.php' と命名して下記のディレクトリ構成図のtemp_write.phpと同列に設置し、webブラウザのURLに

http://www.○○○.net/print_ip.php

と打ち込めば、このスクリプトが実行されたサーバのIPアドレスがわかります。

上記スケッチの

client.write("GET /temp_write.php?temp=");
client.print(tempC, DEC);
client.write(" HTTP/1.1\n");
client.write("HOST: www.○○○.net\n\n");

の部分が、PHPスクリプトに値を送信している箇所です。「temp」という名前の「tempC」の値を送信しています。
注意しなければならないのは、write()メソッドは byte型か char型のデータしか正しく送信しないので、int型の変数値を送信するときは print()メソッドを使うことです。
もし、複数の値を送信したければ、

client.write("GET /temp_write.php?temp=");
client.print(tempC, DEC);
client.write("&water_temp=");
client.print(water_temp, DEC);
...

などと「&」でつなげてゆきます。そうすると、リクエスト文字列は

GET /temp_write.php?temp=○○○&water_temp=○○○

となります。

データをアップするwebサーバのディレクトリ構成は右のようになります。

Document Root
+ / data
|   + data.txt
+ / temp_write.php


Document Rootとはこの場合、http://www.○○○.net/ となります(○○○の部分は設定した私のドメイン)。webブラウザのURL入力部分に

http://www.○○○.net/temp_write.php

と打ち込めば、temp_write.php の処理が実行されます。

http://www.○○○.net/data/data.txt

と打ち込めば、このデータファイルが画面に表示されます。
(セキュリティをまったく考慮していないということです。)









PHPスクリプト(temp_write.php)

<?php
// 'temp' という名前で Arduino からGET送信された温度の値を受け取る
$strTempVal = $_GET['temp'];
// 値をフォーマット(小数点以下の数値を1桁まで切り詰める)+ 改行コード
$strTempVal = number_format(($strTempVal / 100), 1) . "\n";
// データを保存するテキストファイルの相対パス
$strDataFilePath = 'data/data.txt';
// データを保存するテキストファイルを追記モードでオープン
$fp = fopen($strDataFilePath, "a");
// 送信された値をテキストファイルに書き込み
fwrite($fp, $strTempVal);
// ファイルポインタをクローズ
fclose($fp);
?>


これで、

/data/data.txt

に、値が下のように記録されていきます。

23.4
23.6
22.7
23.1



あとは、processing applet test(2) でやったように、processing などでデータを好きに加工表示できます。
注意しなければならないのは、processing などで加工表示するためにデータを読みに行く時、PHPスクリプトの書き込みとバッティングするとデータが壊れる可能性があるので、Arduino の DateTime ライブラリなどではなく、NTP ライブラリなどでネットから時刻を取得し、書き込みと読み込みの時刻を完全にずらせるように調整する必要があります。



植物・農業・エレクトロニクス・音楽...。実験とプロジェクトのblog。 ▶ projects : Biotope

2 件のコメント:

  1. お世話になります。
    setup() 内の Ethernet.begin(mac, ip); がコメントと一体化されてて気付くのに時間がかかりました。

    返信削除
  2. 訂正しておきました。ありがとうございます。

    返信削除

*