NRF24L01+ と DS18B20+と Arduinoでリモート温度計 1

NRF24L01+を使って無線実験が成功したので、実用的な用途に応用です。本当は家の中の消費電力を計測したいのですが、他の方の製作記事を拝見すると結構大変そうです。今の私には少々荷が重すぎるようですね。なので、すかさず方針変更です。手始めに気温を測る温度計に挑戦です。これなら何とかいけそうです。

でも、一旦冷静になって考えると”気温を測ってどうするの?”という素朴な疑問がわいてきました。「実用的な用途」と言えるかどうかも論議が必要です….結局、結論がなかなか出てきそうにないので、先に進むために今そのことは考えないことにします。

温度を測るセンサーもいろいろあって迷いますが、秋月電子の広告を見て「1wireデジタル温度センサー」という文字が目にとまりました。値段も1つ300円とお手頃です。

Maximの1wireデジタル温度センサー DS18B20+
=特長=
・1wireインターフェースのシンプルなデジタル温度センサー
・すべてのデバイスに対してユニークな64ビットのシリアルコードを付与(内部ROMに書込済)
・データ線から電源を供給可能
・電源電圧:3.0~5.5V
・測定温度範囲:-55℃~+125℃
・精度:±0.5℃(-10℃~;85℃)
・ドリフト:±0.2℃

・・・

他の温度センサーと比べて精度が良いみたいですね。ネットで検索するとO-Famiry 電子工作の部屋さんのWeb中にDS18B20+の説明が書かれていました。またマニュアルの日本語訳もされています。すごいですね、頭がさがります。ありがとうございます。調べて行くとArduinoとの相性も良さそうな事がわかりました。これに決めます。

ArduinoでDS18B20+を使うためにPJRCさんのサイトから
OneWire Library:Download: OneWire.zip (Version 2.1)
このライブラリをダウンロードします。

zipファイルを解凍してできる「OneWire」フォルダをフォルダごとAduino1.0の「libraries」ディレクトリにコピーすると使えるようになります。

まずArduino単体で温度が読み取れるか試してみましょう。ブレッドボードにDS18B20+を配線します。このOnWireデバイスは、一つ一つのデバイスに64ビットのアドレスが割り振られているとのことです。ワンワイヤーと言っても現実には通信に2本の線が必要(パラサイトモード時)なのですが、カスケードにして複数つなぐことができるそうです。トランジスタ風のパッケージの中に、機能がぎっしり詰まっていますね。感心してしまいます。

今回私は、DS18B20+の2番ピン(DQ)はArduinoのデジタル6番ピンにつなぎました。ブレッドボードに配線をすませて、ライブラリ付属のサンプルスケッチ「DS18x20_Temperature」を実行します。

スケッチ中の
OneWire ds(10); // on pin 10
この行は、自分の環境に合わせ、6に変更しておきました。これでシリアルモニターに現在の気温が表示されるはずです。

スケッチを走らせると瞬時に気温が計測され、表示されます。センサーを指で触ると体温に反応して表示される温度が刻々と変化します。応答性能もよさそうです。

ちなみに配線を間違えると85℃の表示がされ、そこから微動だにしません。(なぜこのことを知っているかは秘密です)資料を見ると85℃はパワーオンリセット時にセットされるデフォルト値みたいです。配線には気をつけましょう。壊れなくて良かったです。

先ほどのPJRCさんのwebに、このスケッチには氷点下以下が測れないというBugがあると書かれていましたので、このスケッチを修正してみました。とりあえず接続するDS18B20+は1つなので、アドレス指定の部分は削除してしまいました。
[C]
#include
// OneWire DS18B20 Temperature Reading
// only slightly modified DS18x20_Temperature sketch
// from OneWire library examples bundle.
// http://www.pjrc.com/teensy/td_libs_OneWire.html
//

OneWire ds(6); // on digital pin 6 DS18B20+ (DQ)
const short Resolution = 12; //DS18B20 Resolution 9 – 12 Bit

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

// Thermometer Resolution set (default 12 BITS)

short Sw_value ;
switch (Resolution){
case 9:
Sw_value = 0x1F;
break;
case 10:
Sw_value = 0x3F;
break;
case 11:
Sw_value = 0x5F;
break;
default:
Sw_value = 0x7F;
break;
}
ds.reset();
ds.skip();
ds.write(0x4E); // Write Scratchpad
ds.write(0x00); // User Byte 1 (not in use)
ds.write(0x00); // User Byte 2 (not in use)
ds.write(Sw_value); // set Thermometer Resolution

}

void loop(void) {
byte i;
byte data[12];
float celsius;

ds.reset();
ds.skip();
ds.write(0x44,1); // start conversion, with parasite power on at the end

int Conv_time = 1000;
switch (Resolution ){
case 9 :
Conv_time = 100;
break;;
case 10 :
Conv_time = 200;
break;
case 11 :
Conv_time = 400;
break;
}
delay(Conv_time); // Resolution to 9 BITS conversion time 93.75ms
// 200 : Resolution to 10 BITS conversion time 187.5 ms
// 400 : Resolution to 11 BITS conversion time 375 ms
// 1000 : Resolution to 12 BITS conversion time 750 ms
// we might do a ds.depower() here, but the reset will take care of it.

ds.reset();
ds.skip();
ds.write(0xBE); // Read Scratchpad

for ( i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds.read(); } if (OneWire::crc8(data,8) != data[8]) { Serial.println("CRC is not valid!"); return; } // convert the data to actual temperature int raw = (data[1] <<8) | data[0]; switch ( Resolution){ case 9: raw = raw & 0xFFF8; // 9 bit resolution break; case 10: raw = raw & 0xFFFC; // 10 bit resolution break; case 11: raw = raw & 0xFFFE; // 11 bit resolution break; } celsius = (float)raw / 16.0 ; Serial.print(" Temperature = "); Serial.print(celsius); Serial.println(" C "); } [/C] ちゃんと動くか否か心配なのでテストをすることにしました。昨日まで冷え込んでいたので夜明け前なら外気温は氷点下なると見込んで測ってみました。が、残念ながらあとわずかの所で氷点下になりません。2~3日繰り返しましたが徒労に終わりました。このまま待っていると来冬になってしまいそうなので、DS18B20+を簡単なプローブにして氷と塩を使い測ってみました。まるで理科の実験です。小学校3年生以来ですね。 解像度( Resolution)は9,10,11,12ビットのいずれかで設定することができ、それぞれ0.5℃,0.25℃,0.125℃,0.0625℃単位で測ることができます。設定をしないと12ビットになります。解像度が大きくなるほど温度をデジタルデータに変換する時間がかかりますので、電池駆動で消費電力を少なくしたい時は解像度を低く抑えた方が良いかもしれません。

NRF24L01+ と DS18B20+と Arduinoでリモート温度計 1」への11件のフィードバック

  1. 記事を参考にして作成しているのですが、
    sketch_sep03c:7: error: ‘OneWire’ does not name a type
    sketch_sep03c.cpp: In function ‘void setup()’:
    sketch_sep03c:30: error: ‘ds’ was not declared in this scope
    sketch_sep03c.cpp: In function ‘void loop()’:
    sketch_sep03c:45: error: ‘ds’ was not declared in this scope
    sketch_sep03c:75: error: ‘OneWire’ has not been declared
    検証のところでこのようなエラーが出ます。
    近くに聞ける人がいないので、申し訳有りませんがお教え願えませんか?

    • 奥田さんこんばんは。どうぞよろしくお願いします。

      エラーメッセージを見ると、OneWireライブラリがちゃんとセットされていないように思えます。

      こちらの http://www.pjrc.com/teensy/td_libs_OneWire.html サイトから OneWire.zipをダウンロード。そして、解凍して出来た OneWire ディレクトリをディレクトリごと、お使いのArduinoIDEのlibrariesフォルダ内にコピーします。

      その後ArdinoIDEを起動してコンパイルするとエラーは出ないと思います。

      • 有り難うございます。うまくいきました。複数個繋ぐときはどのようにスケッチすれば良いでしょうか?SDシールドでログとるには、このスケッチの下にSDのスケッチを繋げれば良いのでしょうか?よろしくお願いします。

        • 奥田さんこんにちは。成功おめとうございます。良かったですね。

          お尋ねの件ですが最近物忘れがひどく、この記事の内容もよくわからなくなってしまいました。すみません。

          複数個繋ぐときは記事中に書いてある、Arduino IDEのFile(ファイル)-example(スケッチの例)- OneWier – Ds18x20_Temperatureこのスケッチが動いたと思います。ただ、わたしはDS18B20を1つしか持っていないので確認したわけではありません。

          >このスケッチの下にSDのスケッチを繋げれば…

          SD – Dataloger のスケッチを参考にしてお望みの動作は実現できると思いますが、単純にコピペでは動かないです。「値の受け渡し」などを行うためにスケッチを書き直す作業が必要です。

  2. こんにちは、管理人さん。Arduinoです。電流計はまだまだなんです。いろいろ寄り道中です。ここ2,3日DS18B20に寄り道中です。この記事も見させていただきました。
    他にもあちこち検索してみました。DS18x20_Temperatureも見てみました。
    で、もしご存知でしたら教えてください。
    たとえば同一バス上にDS18B20が2つ(温度計1、温度計2)あるとします。
    私が検索したべーじでは、どれも、
    温度計1計測スタート->時間待ち->温度1結果読み取りと一連の流れの後、
    温度計2計測スタート->時間待ち->温度2結果読み取りとなっています。
    これを、
    温度計1計測スタート->温度計2計測スタート->他の処理(結果が出たころを見計らって)->温度1結果読み取り、->温度2結果読み取りとしたいのですが、
    いくらやってもどちらかが85°になってしまいます。同時に複数のデバイスで
    計測をスタートしてあとでまとめて結果を読みにいくような処理は出来ないのでしょうか?
    もし、管理人さんが過去に実験済みでサンプルプログラムがあれば是非公開を
    お願いします。
    よろしくお願いします。

    • Arduinoさんこんばんは。残念ながら複数を繋げて実験したことはありません。先日も別の方に書いたのですが、DS18B20については細かなところは分からなくなってしまいました。すみません。

      うろ覚えですが、DS18B20は1wireで通信するという制約上、最初にリセットコマンドを送って繋がれている素子をすべて初期化、その後、通信相手の素子を指定してデータのやり取りを行い、その後また全てリセット、という手順の繰り返しだったと思いますので、Arduinoさんの書かれた様な使用法は多分出来ないと思います。

      DS18B20の動作に関しては、O-Familyさんが翻訳された DS18B20のマニュアルに詳しく書かれていますよ。

      http://www.ne.jp/asahi/shared/o-family/ElecRoom/AVRMCOM/DS18B20/DS18B20manual.html

  3. ありがとうございます!!(結論から言うと出来ました)
    御指定のマニュアルを読んだら、「・例えば、マスターがバス上のすべてのDS18B20に、SKIP ROMコマンドに続く「CONVERT T [44h]」コマンドを出すことによって、同時に温度変換を行なわせることができます。」とありました。この44hをバスにブロードキャストしてから、読み出しはデバイスセレクトしてからBEhで1デバイスずつ読み出しますが、バッチリできました。とりあえず、DS18B20を2つ繋げて4,5時間耐久テストを始めます。おそらく問題ないとは思いますが念のため。
    また、管理人さんのページにお世話になるかもしれませんが、どうぞ宜しくお願いします。(今回のようにドキュメントへのリンクを教えていただくだけでも、猛烈に助かります)

    • 間違った事を書いてしまい、すみませんでした。 m(__)m
      でも、目的が叶ってよかったですね。おめでとうございます。
      こちらこそよろしくお願いいたします。

      • まちがっていても気にしないでください!!
        PS.まだ動いています。なんとなく耐久テストもOKのようです。
        では!

  4. 素晴らしいシェアありがとうございます。無事に温度をとることができました。取れた温度をprocessingに送りたいのですが、digital pinから値を読むにはどうすればいいのでしょうか?

    • ワシオさん御訪問ありがとうございます。

      ご質問の趣旨はArduinoとprocessing間の通信手段ということですね。私はprocessingは全然わからないので的確なアドバイスができないのですが、googleで”arduino processing”で検索をしてみたら御参考になりそうなサイトが表示されました。

      例えば http://yoppa.org/tau_bmaw13/4772.html こちらでは2通りの方法が書かれています。

      こちらに書かれているFirmataっては聞いたことがありましたが初めて内容を知ることができました。他にもシリアル通信で値を受け渡す方法もあるみたいですね。

      うまく動作すると良いですね。成功を祈っています。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください