0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

温度センサDS18B20の調査

Last updated at Posted at 2024-09-12

はじめに

データシート

通信方式は 1-Wire bus方式です。

購入した温度センサDS18B20
image.png

目的

温度制御に利用するうえで、以下の点を調べました。

  1. 最小制御周期
  2. 測定結果の精度
    1. センサ同士の誤差
    2. 時間的なブレ
    3. 電源電圧の影響
  3. 温度応答性

結論

  1. 最小制御周期 → 1秒周期で可能(センサ自体の熱容量からして、もっと粗くてもいいけど)
  2. 測定結果の精度
    • センサ同士の誤差 → 測定単位1でブレる。ほぼないと見ていい
    • 時間的なブレ → 測定単位1でブレる。ほぼないと見ていい
    • 電源電圧の影響 → 測定単位1でブレる。ほぼないと見ていい
  3. 温度応答性
    • 7秒遅れがあるとみなして良い

通信について:1-Wire bus

通信は以下の流れになります。

  1. バスリセット(スレーブの存在確認)
  2. データ送信・受診

バスリセット

マスタ:480us以上LOW → スレーブ:60~240usLOWにして返す
image.png

スレーブが存在することを確認します。

データ送受信

スロット時間幅(1bitデータ時間幅)を60~120usとして、HIGH/LOWを使用して送受信する。
image.png

時間定義

image.png

image.png

通信プロトコル

image.png

以下の順にデータを送信します。
1.バスリセット
2. ROMコマンド
3. ファンクションコマンド

コマンド

  • SEARCH ROM → 0xF0
  • READ ROM → 0x33
  • MATCH ROM → 0x55
  • SKIP ROM → 0xCC
  • ALARM SEARCH → 0xEC
    image.png

信号測定

Arduino側
#include <OneWire.h>
OneWire ds(8);  // This is where DQ of your DS18B20 will connect.
void setup(void) {
  Serial.begin(9600);
  getDeviceAddress();
}



void getDeviceAddress(void) {
  byte i;
  byte addr[8];
  Serial.println("Getting the address...\n\r");
  /* initiate a search for the OneWire object we created and read its value into

    addr array we declared above*/

  while (ds.search(addr)) {
    Serial.print("The address is:\t");
    //read each byte in the address array
    for ( i = 0; i < 8; i++) {
      Serial.print("0x");
      if (addr[i] < 16) {
        Serial.print('0');
      }
      // print each byte in the address array in hex format
      Serial.print(addr[i], HEX);
      if (i < 7) {
        Serial.print(", ");
      }
    }
    // a check to make sure that what we read is correct.
    if ( OneWire::crc8( addr, 7) != addr[7]) {
      Serial.print("CRC is not valid!\n");
      return;
    }
  }
  ds.reset_search();
  return;
}



void loop(void) {

  // do nothing

}
  • センサ接続していないとき
    image.png
    480usLOWに落としている。本来はスレーブがHIGHにして返すため、それがない今はこれ以上の通信は起きない

  • センサを接続すると
    image.png
    image.png
    センサがLOWにすることでバスリセットに返答している。
    image.png
    こんな感じで読み取れる。長=0,短=1であるため、これはB00001111=0x0F=サーチコマンド
    image.png
    image.png

全部読み解くのは大変

実測:温度測定

Arduino側
#include <OneWire.h>
#include <DallasTemperature.h> 

#define ONE_WIRE_BUS 8 // データ(黄)で使用するポート番号
#define SENSER_BIT    9      // 精度の設定bit 

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

DeviceAddress temp0 = { 0x28, 0x61, 0x64, 0x0B, 0x4A, 0x1E, 0xED, 0x0F }; //1つ目のDS18B20のアドレス
DeviceAddress temp1 = { 0x28,0xFF,0xDC,0x12,0x86,0x16,0x04,0x9C }; //2つ目のDS18B20のアドレス

void setup(void){   
  Serial.begin(9600);
  while (!Serial) {
  ; // wait for serial port to connect. Needed for native USB port only
  }
  sensors.setResolution(SENSER_BIT);
  delay(1000);
}

void loop(void){
  sensors.requestTemperatures();              // 温度取得要求
  delay(800);
  Serial.println(sensors.getTempC(temp0)); //1つ目のDS18B20から温度の取得、シリアルモニタに表示
  delay(1000);
}

image.png
1.8秒ごとに繰り返す。

温度測定開始コマンドにかかる時間

image.png

約12ms

サンプリング等にかかる時間は分解能によって変わるが、以下の通り。
image.png

測定結果読み込みコマンドにかかる時間

image.png
約34ms(精度によらない、読み込み2byteは変わらないため)

結論

温度測定周期1秒間隔は可能。
分解能を落とせばもう少し可能。

9bit分解能では、以下合計140ms周期が最短である。

  • 測定要求コマンド:12ms
  • サンプリング:94ms
  • 読み込み:34ms

センサの温度変化

熱容量の大きい、室温放置された水にセンサを入れて測定した。測定精度は12bitとした。
測定期間10分:測定回数312回

結果
image.png

標準偏差→0.0287℃

ただし、測定分解能の影響が強いですね。
測定単位1の前後で変化していると見て良さそうです。

<補足>
image.png
センサは$2^{-4} = 0.0625℃$単位で測定しています。

センサ同士の誤差

DS18B20の測定結果+シンワ製温度計2つの温度を比較した。

結果
シンワ温度計→28.0℃(目視)
image.png
センサ同士にズレはほぼない

センサ電源電圧を変化させても測定単位1でブレる(USB電源3.9Vと外部電源5Vの2パターンで比較)→電源によらない

ちなみに、アドレスはこんな感じ
image.png

温度応答性

温水にセンサを突っ込むことで応答性を確認する。

Arduino
#include <MsTimer2.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 8 // データ(黄)で使用するポート番号
#define SENSER_BIT    12 // 精度の設定bit 

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

DeviceAddress temp0 = {0x28, 0x61, 0x64, 0x0B, 0x4A, 0x1E, 0xED, 0x0F};

volatile bool flag_t = false;

void setup(void) {
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  sensors.setResolution(SENSER_BIT);
  MsTimer2::set(1000, mejure);
  MsTimer2::start();
  delay(1000);
}
void mejure() {
  flag_t = true;
  sensors.requestTemperatures();
}

void loop(void) {
  if (flag_t == true) {
    flag_t = false;
    delay(800);
    Serial.println(sensors.getTempC(temp0), 5);
  }
}

82℃のお湯に入れたときの応答
image.png

お湯から出したときの応答
image.png

指数関数的に応答していることがわかると思います。

水槽内の温度は$T_{con}$一定であるとして、温度計(熱容量$C[J/K]$,初期温度$T_0$)に対して、伝熱係数$k$,表面積$A$で熱流束$q$で伝熱したと考えられる。

q = kA(T_{con}-T)

温度計の温度は以下の微分方程式に従うといえる。

C \frac{dT}{dt} = q

上記の方程式を解くと

T= -( T_{con} - T_0) e^{- \frac{kA}{C} t} + T_{con}

温度計の応答性を表している時定数$\tau$は以下のように求められると考えられる。

\tau = \frac{C}{kA}

$1-e^{-1} = 63.2%$となる時刻は、
水中では7秒
気中では82秒

気中は伝熱係数が低いからしょうがないが、結構長いね。12倍ぐらいか。

image.png
image.png

熱伝導性は20倍ぐらいある。
伝導だけではなく対流もあるから、なんとも言えないけども。

応答性

水中での時定数が7秒であることから、計測されるまでに7秒遅れがあると考えて良い。
→ 制御周期によっては発振の原因となるため、注意

結論

  1. 最小制御周期 → 1秒周期で可能(センサ自体の熱容量からして、もっと粗くてもいいけど)
  2. 測定結果の精度
    • センサ同士の誤差 → 測定単位1でブレる。ほぼないと見ていい
    • 時間的なブレ → 測定単位1でブレる。ほぼないと見ていい
    • 電源電圧の影響 → 測定単位1でブレる。ほぼないと見ていい
  3. 温度応答性
    • 7秒遅れがあるとみなして良い
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?