下手の横好きのスクラップブック!!

下手の横好きの、いろいろな記録です。
電子工作・PIC・Arduino・太陽光発電・写真などetc

1-Wire温度センサーDS18B20で気温を計測する

2013-01-11 | Arduino

DS18B20は、1本のライン(バスとGNDで2本)に複数のセンサーを接続して温度を計測することが可能です。

    

主な特徴は
 データ線から電源を供給できる。
 温度測定範囲 -55℃~+125℃
 -10°~+125℃で±0.5℃の精度
 個々のデバイスにシリアル番号があり同一バス上に複数個のデバイスが接続できる。
 電源 3.0V~5.5V
  センサーの距離を大幅に伸ばすことが出来る。

DS18B20のマニュアルは「DS18B20 日本語マニュアル」を参考にさせて頂きました。

DS18B20をArduinoで使うためには、ライブラリが必要となります。
入手先は「http://www.pjrc.com/teensy/td_libs_OneWire.html」で、「Download: OneWire.zip (Version 2.1)」をクリックしてダウンロードします。
ZIPファイルを解凍すると、OneWireファイルが作成されますので、それをArduino1.0.1のlibrariesにコピーします。

DS18B20は複数のデバイスを接続可能ですが、今回は2個使用します。(手持ちが2個しかないので)

回路図

   

スケッチはダウンロードしたライブラリーの中の「example]に 「DS18x20_Temperature」が用意されておりますのでそれを利用します。
このスケッチはシリアルモニターで計測値を観測するようになっておりますが、LCDにも表示するように若干修正を加えました。
なお、このスケッチでは、マイナス温度が異常値が表示されますので0℃~125℃の範囲での利用になります。
マイナス温度も測定範囲に加えたい場合は「こちら」が参考になると思います。
また、LCDの表示はデバイスそれぞれの値が交互に表示されます

シリアルモニターの表示
上側がデバイス1
下側がデバイス2

スケッチ

 

#include <OneWire.h>
#include <LiquidCrystal.h>
// OneWire DS18S20, DS18B20, DS1822 Temperature Example
//
// http://www.pjrc.com/teensy/td_libs_OneWire.html
//
// The DallasTemperature library can do all this work for you!
// http://milesburton.com/Dallas_Temperature_Control_Library

 

OneWire  ds(9);  // on pin 9
LiquidCrystal lcd(2,3,8,5,6,7);

 

void setup(void) {
  Serial.begin(9600);
  lcd.begin(16,2);
  lcd.clear();
}

 

void loop(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
 
  if ( !ds.search(addr)) {
    Serial.println("No more addresses.");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }
 
  Serial.print("ROM =");
  for( i = 0; i < 8; i++) {
    Serial.write(' ');
    Serial.print(addr[i], HEX);
  }

 

  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }
  Serial.println();
 
  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      Serial.println("  Chip = DS18S20");  // or old DS1820
      type_s = 1;
      break;
    case 0x28:
      Serial.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      Serial.println("  Chip = DS1822");
      type_s = 0;
      break;
    default:
      Serial.println("Device is not a DS18x20 family device.");
      return;
  }

 

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

 

  delay(1000);     // maybe 750ms is enough, maybe not

 

  // we might do a ds.depower() here, but the reset will take care of it.
 
  present = ds.reset();
  ds.select(addr);   
  ds.write(0xBE);         // Read Scratchpad

 

  Serial.print("  Data = ");
  Serial.print(present,HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {       // we need 9 bytes
 
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  
  }
  Serial.print(" CRC=");
  Serial.print(OneWire::crc8(data, 8), HEX);
  Serial.println();

 

  // convert the data to actual temperature

 

  unsigned int raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // count remain gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    if (cfg == 0x00) raw = raw << 3;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
    // default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");
  Serial.print(fahrenheit);
  Serial.println(" Fahrenheit");
 
  lcd.clear();
  lcd.print("T= ");
  lcd.print(celsius);
  //lcd.setCursor(0, 1);
  //lcd.print("F= ");
  //lcd.print(fahrenheit);

 

}

 

コメント (5)    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« 我が家の太陽光発電 201... | トップ | 平成25年初春歌舞伎公演「... »
最新の画像もっと見る

5 コメント

コメント日が  古い順  |   新しい順
2チャンネルLED温度計キットとarduino (奥田登)
2013-04-15 19:07:42
私も作成しましたが、長い距離はarduinoだとダメな様で、(10m×2セットでダメ、1セットだと受けれました)2チャンネルLED温度計キットだと拾えるので、これと、arduino組み合わせて、SDカードに記録取りたく思います。本業建築設計なので、マイコン知識全くないので、お知恵お貸しください。よろしくお願いします。
返信する
抵抗値か給電用にトランジスタ (通りすがり)
2013-04-24 15:10:49
他を探して検索中に偶然見かけました。
長距離(10m)程度で6個程度のセンサーを使うなら4.7kΩを2kΩ程度まで値を下げると良いですよ。(http://japan.maximintegrated.com/app-notes/index.mvp/id/148)
それ以上距離や数なら、給電用にFETかトランジスターを使いましょう。トランジスター2SA1015と2kΩ3.3V駆動で30m12個まで成功しました。
----
ds.reset();
// ds.select(addr);
ds.write(0xcc,1); //全てに命令
ds.write(0x44,1); // start conversion, with parasite power on at the end
digitalWrite(supply, LOW); //給電開始
delay(1000); // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.
digitalWrite(supply, HIGH); //給電中止
-----
返信する
うまく行きました。 (奥田)
2013-04-29 23:32:53
4.7kをパラでかませて、5m迄単線それに2m、3m、5mのセンサーつけて、aruduinoで計測できました。トランジスターのかませ方がよくわからなかったのですが、とりあえずの抵抗値の変更だけで行けました。有り難うございます。
返信する
情報ありがとうございます (下手の横好き)
2013-05-02 13:52:49
参考にさせていたき、長い距離の実験もしたいと思っております。
返信する
トランジスタ (通りすがり)
2013-05-02 18:04:18
トランジスターをDS18B20の給電に使うなら「PNPトランジスタの接続回路」で検索すると良いよ。
2SA1015(PNPトランジスタ)を使うと仮定すると、Arduinoのデジタルピンに制限抵抗10kΩを繋ぐ、その先にトランジスターのベース(B)と電源に対して10kΩを繋ぐ。トランジスターのエミッタ(E)を電源、コレクタ(C)をOneWireバスに接続(4.7kΩとDS18B20の間)。
PNPトランジスタはマイコン側の出力LOWで給電、HIGHで給電停止と直感的な操作と反対なので要注意です。

マイナス温度は、サンプルコードがビット演算しているので判りづらいですね。
デジタル値(16進)で考えると0℃=0x0000,-0.0625℃(12bit分解能での最初のマイナス温度)=0x0000-0x0001=0xFFFFになります。つまり一番左のビットが1になると氷点下です。

//デジタル値を求める
int P = (data[1]<<8)+ data[0])
//SignBitを求める
int SignBit = P & 0x8000; //先頭ビットをAND
//氷点下時の演算
if (SignBit){
P = (P ^ 0xffff) + 1; //XORで反転、1を加える
float Temperature = P * -0.0625 //物理値
}
返信する

コメントを投稿

Arduino」カテゴリの最新記事