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

2009年6月14日日曜日

温度センサ LM35DZ

LM35DZ
温度センサのLM35DZとArduinoで温度測定をしてみました。
ほとんど参考のリンク先からの引用です。詳しく記載されています。
































参考
エレキジャック フィジカル・コンピューティング 連載(22)Arduinoで何でも制御
エレキジャック フィジカル・コンピューティング 連載(23)Arduinoで何でも制御

材料
温度センサ LM35DZ
最高/最低機能付 小型温度計モジュール


回路図

GNDをマイナス電源に接続し、V+にプラスの電源を接続すると、真中のVoutに温度に応じた出力電圧が得られます。
0℃で0Vとして10mV/℃と、1℃当たり10mVの出力が得られます。25℃の場合、250mVの出力が得られます。
(参考リンク先からの引用)


今回、基準電圧として5VをV+に入力します。温度に対してVoutピンから検出できる値は0〜1023なので、温度換算の計算式は以下のようになります。

 xV : 取得した電圧値
 aVal : 取得したアナログ値(0〜1023)

とすると、

 xV : 5V = aVal : 1024

となり、

 xV = ( 5V × aVal ) / 1024

例)取得したアナログ値が 50 の場合、

 xV = ( 5 × 50 ) / 1024
 xV = 0.2441...

つまり、取得した電圧は約244mV なので、温度は24.4℃となります。


Arduinoスケッチ


/* 
1秒ごとに摂氏温度を計測
10秒ごとに平均摂氏、最大摂氏温度、最小摂氏温度を
シリアルモニタに出力
*/
// DateTimeライブラリをインポート
#include <DateTime.h>
// プログラム開始日付時刻
int year = 2009; // 年
int month = 6; // 月
int day = 14; // 日
int hour = 18; // 時
int minute = 3; // 分
int second = 0; // 秒
int A_inPin = 0; // アナログ入力ピン番号
int A_val; // アナログ入力値(0〜1023)
int outputTerm = 10; // 計測結果出力ターム(10秒ごとに平均摂氏値を出力する)
float v = 5; // 基準電圧値( V )
float tempC = 0; // 摂氏値( ℃ )
float tempCPlus = 0; // 10秒ごとの合計摂氏値( ℃ )
float maxTempC = 0; // 10秒ごとの最大摂氏( ℃ )
float minTempC = 0; // 10秒ごとの最小摂氏( ℃ )
voidsetup(){
// シリアル通信速度
Serial.begin(9600);
// DateTime ライブラリの makeTime() メソッドで日付時刻作成
time_t prevtime = DateTime.makeTime(second, minute, hour, day, month, year);
// DateTime ライブラリの sync() メソッドで初期設定(日付時刻設定)
DateTime.sync(prevtime);
}
void loop(){
// 1秒に一回、10秒間分温度計測
for (int i = 0; i < outputTerm; i++ ) {
// アナログピンから計測値を取得(0〜1023)
A_val = analogRead( A_inPin );
// 摂氏に換算
tempC = ((v * A_val) / 1024) * 100;
// 現for文ループ内で使わなくなった変数は解放
A_val = 0;
// 平均値を取得するために1秒ごとの値を10秒分合計しておく
tempCPlus += tempC;
// 1秒過去の最大摂氏値と現在の摂氏値を比較
// 大きい方を格納

maxTempC = max( maxTempC, tempC );
// 1秒過去の最小摂氏値と現在の摂氏値を比較
// for文1ループ目のみ、現在の摂氏値を格納
if (i == 0) minTempC = tempC;// 小さい方を格納
minTempC = min( minTempC, tempC );
// 現for文ループ内で使わなくなった変数は解放
tempC = 0;
// 1秒間ストップ
delay(1000);
}
// 10秒間の平均摂氏値
tempC = tempCPlus / outputTerm;
// 日付時刻更新
DateTime.available();
// シリアルモニタに出力
// 日付時刻
Serial.print(DateTime.Year+1900,DEC);
Serial.print("/");
Serial.print(DateTime.Month,DEC);
Serial.print("/");
Serial.print(DateTime.Day,DEC);
Serial.print(" ");
Serial.print(DateTime.Hour,DEC);
Serial.print(":");
Serial.print(DateTime.Minute,DEC);
Serial.print(":");
Serial.print(DateTime.Second,DEC);
// 10秒間の平均摂氏値
Serial.print(" Temp / ");
Serial.print( outputTerm );
Serial.print("sec | Average : ");
Serial.print( tempC );
Serial.print(", ");
// 10秒ごとの最大摂氏値
Serial.print("Max : ");
Serial.print( maxTempC );
Serial.print(", ");
// 10秒ごとの最小摂氏値
Serial.print("Min : ");
Serial.println( minTempC );
// 次loop()ループの計測に影響を及ぼさないように変数の値を0に戻す
tempCPlus = 0;
maxTempC = 0;
minTempC = 0;
}


やたらと長くなってしまいましたが、やっていることはシンプルです。

まず、setup()関数内で、DateTimeライブラリで、プログラムを開始する日付時刻をセットします。
その後はひたすらloop()関数内を繰り返します。
loop()関数がひとまわりする間に、
1秒間に一回温度を計測し、それを10秒間繰り返します。
摂氏温度を10秒分合計し、それを10で割って平均摂氏温度を取得します。ついでにその10秒間の最大摂氏・最小摂氏も取得します。
ArduinoIDEのシリアルモニタで結果を出力します。10秒ごとに計測した日付時刻、平均摂氏温度、最大摂氏温度、最小摂氏温度が表示されます。

なぜ10秒間分の平均値をわざわざだしているのかというと、計測温度の精度をなるべく高めるためです。


実験してみました。
本当に的確な温度を計測できているのかを確認するために、秋月で購入した
最高/最低機能付 小型温度計モジュールと比べてみます。










左がLM35DZ、右がデジタル温度計の温度検出部です。
温めたお湯に同時にいれて、計測温度を比較してみます。










微妙に誤差があります。
LM35DZも個体差があるらしく、二つのLM35DZで計測しても誤差がでるそうなのでこれくらいは許容範囲です。






















追記
スケッチの先頭にあるDateTimeライブラリは標準でArduinoIDEにインストールされていないので、上記のスケッチをコピーして実行しようとするとエラーになります。
以下のリンクからDateTimeライブラリをダウンロードして解凍し、指定のディレクトリ内に配置しなければなりません。

こちらからダウンロード

ダウンロードして解凍したら、DateTimeというフォルダができます。
その中のDateTimeフォルダとDateTimeStringsフォルダをすでにインストールしてあるArduino内の以下のディレクトリにコピーします。

コピー先ディレクトリ
arduino-0016/hardware/libraries/

以上で、DateTimeライブラリとDateTimeStringsライブラリが使えるようになります。


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

13 件のコメント:

  1. 結構正確に出力していますね。しかも、この温度センサは扱いやすそうですね。
    複数接続して気温と土の中の温度の差やピーク時の時差など観察できそうです。
    あるいは、室内の床から天井まで縦に等間隔で配置すれば、室内の上下の温度差をグラデーションで表現できそうです(Processingと連結してグラフィカルにも)。Arduino Megaなら16個アナログ入力端子があるので、もっと細かく表現できますね。

    返信削除
  2. LM35DZは、どこで温度測定するんでしょうか?トランジスタ自体がセンサーなんでしたっけ?
    なんか、金属片の先で測定できる方法ってありますか?
    土の温度を測定するのに、ICを埋めておくと水をやるのも大変そうですし。

    あと、processingに送っておいた後、温度データその他をテキストやエクセルのようなファイルに保存できるんでしょうか?

    返信削除
  3. Lucellinoさんへ
    ProcessingのReferenceの中のOutput>Filesに「PrintWriter」という機能があって、「~.txt」ファイルで外部保存できます。
    建築発明工作ゼミの「Processing ドラッグした図形の動きを記録/保存/再生する」にそれに近いサンプルがあります。
    http://kousaku-kousaku.blogspot.com/2008/11/processing.html

    返信削除
  4. Lucellinoさん

    半導体センサの内部構造までは詳しくないのですが、LM35DZの黒いプラスチックの部分を指でつまんだり水につけるだけで測定できました。参考リンク先に防水加工のやり方が載っています。

    kousakuさん

    Arduino duemilanoveだけではアナログインピンがたりないのでmegaがいいなと思っていました。Arduinoとセンサの組み合わせでスタンドアロンで動作させてwebサーバにデータをアップしていこうと思っていましたので。しかしmegaだとEthernetShildが使えないらしくて、ちょっと考え中です。

    返信削除
  5. kousakuさん
    情報ありがとうございます。
    さっそく試してみたいと思います。

    planetさん
    センサ自体で測定するんですね。
    リンク先で見つかりませんでしたが、、ちょっと探してみます。
    あと、入力増やしたいとのことですが、arduino2台って同時に動かすことってできないんですかね?

    返信削除
  6. Lucellinoさん

    防水加工はここに載っています。
    http://www.eleki-jack.com/FC/2009/02/24arduinoarduino6.html

    あと、processingのプログラムからテキストデータをファイルに保存したい場合は以下の関数が使えそうです。
    http://pripro.org/p5ref/index.php?name=saveStrings_

    なにかの本で、複数のarduinoをつなぐという記述があったような。もうすこしリサーチします。

    返信削除
  7. polanetさん

    URLと関数の情報ありがとうございます。
    エポキシで固めれば大丈夫そうですね。

    Gainerだったら複数接続大丈夫なんですけどね。
    あと、Funnelサーバ(Gainer、Arduino、xbeeとFLASH、processing、MAX/MSPどれでも動かせるミドルウェア的なもの)というのを使えば複数同時に動かせるかもしれません。

    http://funnel.cc/

    返信削除
  8. Lucellinoさん
    GainerとFunnel使っているんですか。もしよかったら、なにかシンプルなデモをブログでみせてもらえたら嬉しいです。
    Funnelって前からちょっと気になっていたんですが、情報が少ないし、ハードウェア系はわからないことだらけだし、まずはArduino、という感じで手がでませんでした。

    返信削除
  9. 情報すくないですよね。入門本とか出してほしいですね。
    僕も詳しいことは分からないんですが、ちょっとしたサンプルを探しておきます。

    返信削除
  10. 複数のArduinoをProcessingとシリアル通信させて使うのであれば、建築発明工作ゼミの「Arduino-Processing シリアル通信6」にサンプルがあります。
    http://kousaku-kousaku.blogspot.com/2008/10/arduino-processing.html

    また2台のArduinoを直接シリアル通信させれば連動して使うことができます。

    Ethernetシールドのかわりに、Xportを使ってもいいと思います。またWiPortをつかえばWifi環境をつくることもできます。サンプルは四谷工作研究所の「WiPort─ネットワークで、基盤にアクセスする」にあります。
    http://www.artstudium.org/kousaku/2007/06/wiport.html

    XportやWiPortは若松通商で取り扱っています。
    http://www.wakamatsu-net.com/cgibin/biz/page.cgi?cate=3806&page=0

    返信削除
  11. Lucellinoさん
    ありがとうございます。楽しみにしております。
    蛇足ですが、「ビジュアライジング・データ」というprocessing本がありまして、かなり高度な使い方が豊富に載っています。もしよかったらのぞいてみてください。

    kousakuさん
    Xportすてきですね。高性能に見合って難しそうですが、Arduino本のMaking Things Talk の中にLANTRONIX製品と接続する例が載っていたので、EthernetShildで行きずまったらやってみようかと思います。

    返信削除
  12. Arduino2個通信させるのに
    xbee使ってますがお手軽で良いですよ。

    返信削除
  13. tobiasさん

    2008のブログで観てみました。
    無線でできるんですね。電源の問題がありますが、屋外の植物観察とかに使えそうです。

    返信削除

*