Arduinoで温度を測定する

Arduino

温度を測定する

温度を測定する素子サーミスタ

大雑把に言って、金属は温度が上昇すると電気抵抗が大きくなります。逆に、半導体は温度が上昇すると電気抵抗が小さくなるものが多いです。このような、温度変化によって抵抗が変化する性質を利用して温度を測定するように作られたのがサーミスタという素子です。

※サーミスタthermistorは、thermal(温度)とregistor(抵抗)を組み合わせて作られた造語です

サーミスタは温度変化に対する電気抵抗の変化が大きい抵抗体です。温度と抵抗値の関係により、NTCサーミスタPTCサーミスタCTRサーミスタに分類されます。

NTCサーミスタは、温度が上昇すると抵抗値がゆるやかに減少するサーミスタです。温度と抵抗の関係を比較的簡単な式で近似できるため、温度センサによく使われます。

PTCサーミスタは、ある温度を超えると急激に抵抗値が増大する性質を持っています。大きな電流が流れると自己発熱して温度が上昇し抵抗値も増大することから、電流制限素子として使われます。

CTRサーミスタは、ある温度を超えると急激に抵抗値が減少する性質を持っています。

今回はNTCサーミスタを利用して温度測定の実験を行います。

抵抗値と温度の関係

簡易公式

NTCサーミスタでは、絶対温度(K) \(T\) における抵抗値 \(R_T\) は、近似的に次の式で求めることができます。

基準の絶対温度(K) \(T_0\) での抵抗値を \(R_0\) として、

\[
R_T=R_0\times {\Large e}^{\left\{B\left(\frac{1}{T}-\frac{1}{T_0}\right)\right\}}
\]

ここで、式中の \(B\) はサーミスタの特性を表す値で『B定数』といいます。サーミスタのカタログやデータシートには、大抵はこのB定数の値が掲載されています。

逆に、サーミスタの抵抗値 \(R_T\) から絶対温度 \(T\) を求める式は以下の通りです。

\[
T=\frac{1}{\displaystyle\frac{1}{B}{}\log_e\left(\frac{R_T}{R_0}\right)+\frac{1}{T_0}}
\]

スタインハート・ハート式

前出の簡易式よりも精度を高めた近似式として、スタインハート・ハート式があります。

スタインハート・ハート式では、サーミスタの抵抗値を \(R_T\) とすると、絶対温度 \(T\) は、

\[T=\displaystyle\frac{1}{a+b\log_e{R_T}+c\ (\log_e{R_T})^3}\]

で求められます。式中の \(a\)、\(b\)、\(c\) をスタインハート・ハート係数と呼びます。これらの値がデータシートに記載されている場合には、スタインハート・ハート式の方が精度良く求めることができます。

絶対温度\(T\)からサーミスタの抵抗値\(R_T\)を求める場合は以下の通りです。

\[
R_T=\exp\left(\left(y-\frac{x}{2}\right)^\frac{1}{3}-\left(y+\frac{x}{2}\right)^\frac{1}{3}\right)
\]

ただし、式中の \(x\)、\(y\) は

\begin{align}
x &= \frac{1}{C}\left(a-\displaystyle\frac{1}{T}\right) \\ \\
y &= \sqrt{\left(\frac{b}{3c}\right)^3+\frac{x^2}{4}}
\end{align}

です。

データシートからB定数、スタインハート・ハート係数を求める

B定数やスタインハート・ハート係数が公開されていなくても、実測値から求めることができます。

B定数を求める

B定数を測定値から求めるには、温度と抵抗値の関係が2組必要です。

絶対温度 \(T_1\) におけるサーミスタの抵抗値を\(R_1\)
絶対温度 \(T_2\) におけるサーミスタの抵抗値を\(R_2\)

とすると、B定数は

\[
B=\frac{\log_e{R_1}-\log_e{R_2}}{\displaystyle\frac{1}{T_1}-\frac{1}{T_2}}
\]

となります。

スタインハート・ハート係数を求める

スタインハート・ハート係数を測定結果から求めるには、温度と抵抗値の関係が3組必要です。

絶対温度 \(T_1\) におけるサーミスタの抵抗値を \(R_1\)
絶対温度 \(T_2\) におけるサーミスタの抵抗値を \(R_2\)
絶対温度 \(T_3\) におけるサーミスタの抵抗値を \(R_3\)

とすると、

\begin{array}{ccc}
L_1=\log_e{R_1} ,& L_2=\log_e{R_2} ,& L_3=\log_e{R_3} \\ \\
Y_1=\displaystyle\frac{1}{T_1} ,& Y_2=\displaystyle\frac{1}{T_2} ,& Y_3=\displaystyle\frac{1}{T_3} \\ \\
\gamma_2=\displaystyle\frac{Y_2-Y_1}{L_2-L_1} ,& \gamma_3=\displaystyle\frac{Y_3-Y_1}{L_3-L_1}
\end{array}

と置いて、

\begin{align}
c&=(\frac{\gamma_3-\gamma_2}{L_3-L_2})(L_1+L_2+L_3)^{-1} \\ \\
b&=\gamma_2-c(L_1^2+L_1L_2+L_2^2) \\ \\
a&=Y_1-(b+L_1^2c)L_1
\end{align}

となります。B定数に較べると計算量が多いですが、関数電卓などを使えばそれほど苦労せずに求められるでしょう。

計算例

それでは計算の例として、高精度サーミスタの定番の1つ、 103AT のデータシートを見ながら、B定数およびスタインハート・ハート係数を求めてみましょう。

以下は103ATのデータシートに掲載されている、温度と抵抗値の対応表です(データシートはこちら

温度(℃)温度(K)抵抗値(kΩ)
-50223.15329.5
-40233.15188.5
-30243.15111.3
-20253.1567.77
-10263.1542.47
0273.1527.28
10283.1517.96
20293.1512.09
25298.1510.00
30303.158.313
40313.155.827
50323.154.160
60333.153.020
70343.152.228
80353.151.668
85358.151.451
90363.151.266
100373.150.9731
B定数の計算例

まず、B定数を計算してみましょう。温度と抵抗値の対応表より、以下の2組のデータを用います。

\(T_1\)=298.15 K(25 ℃) のとき、\(R_1\)=10.00 kΩ
\(T_2\)=358.15 K(85 ℃) のとき、\(R_2\)=1.451 kΩ

\begin{align}
B&=\frac{\log_e{R_1}-\log_e{R_2}}{T_1-T_2}\\ \\
&=\frac{\log_e(10.00\times10^3)\ -\ \log_e(1.451\times10^3)}{\displaystyle\frac{1}{298.15}\ -\ \frac{1}{358.15}}\\ \\
&=3435
\end{align}

よって、B定数は3435と求められました。

実はメーカが公開しているデータシートにはB値も記載されていて、ここで求めた値と一致しています。…それも当然で、このメーカではデータシート掲載のB値を 298.15 K(25℃) と 358.15 K(85℃) のときの抵抗値から求めている(つまり上とまったく同じ計算をしている)のです。

スタインハート・ハート式の係数

今度は、スタインハート・ハート式の係数を求めてみましょう。温度と抵抗値の対応表より次の3組のデータを用います。

\(T_1\)=223.15 K (-50 ℃)のとき、\(R_1\)=329.5 kΩ
\(T_2\)=298.15 K (25 ℃)のとき、\(R_2\)=10.00 kΩ
\(T_3\)=358.15 K (85 ℃)のとき、\(R_3\)=1.451 kΩ

ここから順に各係数を求めていくと、

\begin{align}
L_1&=\log_e{R_1}=\log_e(329.5\times10^3)=12.70533\\ \\
L_2&=\log_e{R_2}=\log_e(10.00\times10^3)=9.21034\\ \\
L_3&=\log_e{R_2}=\log_e(1.451\times10^3)=7.28000
\end{align}

\begin{align}
Y_1&=\frac{1}{T_1}=\frac{1}{223.15}=0.0044813\\
Y_2&=\frac{1}{T_2}=\frac{1}{298.15}=0.0033540\\
Y_3&=\frac{1}{T_3}=\frac{1}{358.15}=0.0027921
\end{align}

\begin{align}
\gamma_2&=\frac{Y_2-Y_1}{L_2-L_1}\\ \\
&=\frac{0.0033540-0.0044813}{9.21034-12.70533}\\ \\
&=0.00032254742\\ \\
\gamma_3&=\frac{Y_3-Y_1}{L_3-L_1}\\ \\
&=\frac{0.0027921-0.0044813}{7.28000-12.70533}\\ \\
&=0.00031135433
\end{align}

\begin{align}
c&=\left(\frac{\gamma_3-\gamma_2}{L_3-L_2}\right)(L_1+L_2+L_3)^{-1}\\ \\
&={\scriptsize\left(\frac{0.00031135433-0.00032254742}{7.28000-9.21034}\right)\frac{1}{12.70533+9.21034+7.28000}}\\ \\
&=0.000000198608458\\ \\

b&=\gamma_2-c(L_1^2+L_1L_2+L_2^2)\\ \\
&={\scriptsize 0.00032254742-0.000000198608458(12.70533^2+12.70533 \times9.21034+9.21034^2)}\\ \\
&=0.0002503977\\ \\

a&=Y_1-(b+L_1^2c)L_1\\ \\
&={\scriptsize 0.0044813-(0.0002503977+12.70533^2\times0.000000198608458)\times12.70533}\\ \\
&=0.00089257596
\end{align}

となります。103ATのデータシートにはスタインハート・ハート式の各係数は記載されていませんが、このように温度と抵抗値の対応表から求めることができます。それなりに計算は面倒ですが…。

…というわけで、計算フォームを作ってみました。

温度 ℃ 抵抗値
温度 ℃ 抵抗値
温度 ℃ 抵抗値
a=
b=
c=

ご自由にお使い下さい。ただし完全無保証ということで。

2つの方法による抵抗値の計算と誤差

公開値:メーカが公開しているデータシート掲載の各温度毎の抵抗値
B計算値:B定数の簡易式で計算した抵抗値
SH計算値:スタインハート・ハート式で計算した抵抗値

として、誤差も含めて一覧表にしました(抵抗値の単位はすべてkΩ)。

B定数の簡易式では低温で誤差が大きくなっているのに対して、スタインハート・ハート式では全温度域で誤差が0.5%未満になっていることがわかります。なお、当前のことですが、定数・係数を求めるのに使った温度ではどちらの式でも誤差が0になっています。

温度(℃)温度(K)公開値B計算値(誤差%)SH計算値(誤差%)
-50223.15329.5480.5(+46)329.5(+0.0)
-40233.15188.5248.3(+32)187.9(-0.30)
-30243.15111.3135.5(+22)110.9(-0.35)
-20253.1567.7777.52(+14)67.53(-0.35)
-10263.1542.4746.29(+9.0)42.31(-0.38)
0273.1527.2828.70(+5.2)27.21(-0.25)
10283.1517.9618.41(+2.5)17.93(-0.15)
20293.1512.0912.17(+0.67)12.09(-0.04)
25298.1510.0010.00(±0.0)10.00(±0.0)
30303.158.3138.269(-0.52)8.315(+0.03)
40313.155.8275.759(-1.2)5.833(+0.10)
50323.154.1604.101(-1.4)4.165(+0.13)
60333.153.0202.981(-1.3)3.024(+0.15)
70343.152.2282.207(-0.93)2.230(+0.11)
80353.151.6681.662(-0.33)1.669(+0.05)
85358.151.4511.451(±0.0)1.451(±0.0)
90363.151.2661.272(+0.46)1.266(-0.02)
100373.150.97310.9870(+1.4)0.9722(-0.10)

特性の例

103AT の温度・抵抗値の特性をグラフにするとこのようになります(後で計算式を使うため、メーカ公開値ではなくスタインハート・ハート式での計算値をプロットしています)。B定数の簡易式を使っても大まかな傾向は同じです。

サーミスタを利用した測定回路の例

Arduino では直接抵抗値を測定することはできません。そこで、『アナログ入力』でやったように、固定抵抗とサーミスタとで電源電圧を分圧し、その電位を測定する方法がよく利用されます。

NTC サーミスタは温度が高いほど抵抗値が小さくなるので、この図のように GND 側に抵抗を接続して分圧すると『温度が高い→電位が高い』となって判り易いでしょう。

サーミスタの抵抗値を \(R_T\) 、分圧に使用する抵抗の抵抗値を \(R_1\) 、電源の電位を \(V_0\) とすると、Arduino の A0 端子で測定される電位 \(V\) は、

\[
V=\frac{R_1}{R_T+R_1}V_0
\]

となります。さらに、温度 \(T\) とサーミスタの抵抗値 \(R_T\) の関係式(スタインハート・ハート式)を代入すると、

\[
V=\frac{R_1}{\exp\left(\left(y-\displaystyle\frac{x}{2}\right)^\frac{1}{3}-\left(y+\displaystyle\frac{x}{2}\right)^\frac{1}{3}\right)+R_1}V_0
\]

となります。

この式に、電源電圧 \(V_0\)=5.0 V、分圧に用いる抵抗 \(R_1\)=10.0 kΩ および前項で求めたスタインハート・ハート式の各係数を代入してグラフをプロットすると、下図のようになります。

この例では、温度が 0 ~ 40℃ のあたりの傾斜が急で、それより温度が高い範囲および低い範囲では傾斜がなだらかになるという、S字を横に引き延ばしたようなグラフになっています。

このグラフの傾斜は、温度変化に対する電位の変化率をあらわしています。グラフの傾斜が大きい部分は、温度の変化に対する電位の変化が大きいため、温度の分解能が高くなります(精密に測定することができます)。逆にグラフの傾斜が小さい(水平に近い)部分では、温度が変化しても電位がわずかしか変化しないため、温度の分解能が低くなります。

分圧抵抗による特性の変化

\(R_1\) の値をかえてグラフをプロットしてみると下図のようになります。

\(R_1\) を大きくするほど傾斜の急な部分がグラフの左(温度の低い側)に、
\(R_1\) を小さくするほど傾斜の急な部分がグラフの右(温度の高い側)に移動することが判ります。
このように、\(R_1\) を変化させることによって、温度を正確に測定できる範囲を調整することができます。

\(R_1\)=10 kΩ では 0 ~ 40℃ くらいの範囲で傾斜が急になっています。人が生活する部屋の気温を測定するならばこの特性がよさそうです。

\(R_1\)=50 kΩ では -40 ~ -10℃ くらいの範囲で傾斜が急になっています。冷凍庫の温度管理ならばこの特性がよさそうです。

\(R_1\)=2 kΩ では、50 ~ 100℃ くらいの範囲で傾斜が急になっています。この特性では、煮物の鍋の温度管理でもしましょうか…。

おおまかにいって、\(R_1\) を、測定したい温度範囲の中央付近の温度におけるサーミスタの抵抗値と同じくらいの値にするとよさそうです。

※なお、実際のサーミスタはこのグラフに描かれているより測定可能な温度範囲が狭いものが多いです

測定電位からサーミスタの抵抗値を算出する式は以下の通りになります。

\[
R_T=\left(\frac{V_0}{V}-1\right)\ R_1
\]

この式をB定数の簡易式に代入すると、以下の通り測定電位 \(V\) から温度 \(T\) を求める式を得られます。

\[
T=\frac{1}{\displaystyle\frac{1}{B}{}\log_e\left(\frac{\left(\displaystyle\frac{V_0}{V}-1\right)R_1}{R_0}\right)+\frac{1}{T_0}}
\]

また、スタインハート・ハート式で測定電位から温度を求める式は以下のようになります。

\[T=\displaystyle
\frac{1}
{a
+b\log_e{\left\{\left(\displaystyle\frac{V_0}{V}-1\right)R_1\right\}}
+c\ \log_e{\left\{\left(\displaystyle\frac{V_0}{V}-1\right)R_1\right\}}^3
}\]

製作&実験

使用部品

部品名(品番)数量備考
NTCサーミスタ1
抵抗器(10kΩ)14本帯では茶黒橙+誤差、5本帯では茶黒黒赤+誤差
ブレッドボード1小型のもの
ジャンパ線3赤×1、黒×1、緑×1

NTCサーミスタ

今回使用したサーミスタはこの写真のものです。直径わずか2mmほどの球体から脚が2本生えた形状です。極性はありません。非常に小さいので、落としてなくさないように十分ご注意を。また脚も非常に細く、乱暴に扱うと根元からもげてしまいそうです。

型番不明で表面にも何の記述もないのですが、スタインハート・ハート式の各係数の値は以下の通りと判っています。

a=0.001129148
b=0.000234125
c=0.0000000876741

抵抗器

今回は室温での測定実験を行いますので、先に書いたとおり分圧に用いる抵抗は 10 kΩ とします。正確な測定を行う場合は抵抗器も誤差の小さいものを使うべきですが、簡易的な実験ならば安価に入手できるもので充分です。

回路

Arduino の 5 V 端子と GND 端子との間をサーミスタと 10 kΩ の抵抗で分圧し、中間点の電位をArduino のアナログ入力端子 A0 で測定します。

配線

配線に難しい部分はないと思います。

  • サーミスタと抵抗のそれぞれの一方の脚が同じ列になるようにブレッドボードに挿す
  • Arduino の 5V 端子サーミスタの空いている方の脚 を赤いジャンパ線で接続
  • Arduino の GND 端子抵抗の空いている方の脚 を黒いジャンパ線で接続
  • Arduino の A0 端子サーミスタと抵抗の接続部分 を緑のジャンパ線で接続

これだけです。サーミスタの脚が細いので、ブレッドボードに挿すときに根元から折れてしまわないように注意して下さい。

実物はこちら。

プログラム

C++
#define SENSOR_PIN 0

// スタインハート・ハート式の係数
double a=0.00089257596;
double b=0.0002503977;
double c=0.000000198608458;

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

void loop() {
  int v=analogRead(SENSOR_PIN);
  double R=(1023.0/v-1)*10000;
  double T=1/(a+b*log(R)+c*pow(log(R),3))-273.15;
  Serial.println(T);
  delay(500);
}

プログラムの解説

定数設定など
C++
#define SENSOR_PIN 0

// スタインハート・ハート式の係数
double a=0.00089257596;
double b=0.0002503977;
double c=0.000000198608458;

まず、#define でアナログ入力端子の番号を定数 SENSOR_PIN として設定しています。

次に double 型のグローバル変数としてスタインハート・ハート式の定数を設定しています。

setup()
C++
void setup() {
  Serial.begin(9600);
}

測定とは直接関係ない、PC とのシリアル通信の設定を行っています。

測定電圧からサーミスタの抵抗値を求める
C++
void loop() {
  int v=analogRead(SENSOR_PIN);
  double R=(1023.0/v-1)*10000;
  double T=1/(a+b*log(R)+c*pow(log(R),3))-273.15;
  Serial.println(T);
  delay(500);
}

変数vは、アナログ入力端子(SENSOR_PIN番)からの読取値です。Arduino UNO ではアナログ入力の分解能が 10bit のため、入力端子の電位が 0V のときに読取値 0、入力端子の電位が 5V のとき読取値 210-1=1023 となります。

先に書いたとおり、本来サーミスタの抵抗値 \(R_T\) を求める式は

\[
R_T=\left(\frac{V_0}{V}-1\right)\ R_1
\]

ですが、読取値 \(v\) と端子電位 \(V\) は比例関係にあるため、\(\displaystyle\frac{V_0}{V}\) のかわりに \(\displaystyle\frac{1023}{v}\) としても結果は同じになります。

なお、プログラム中では 1023 ではなく 1023.0 となっていますが、整数/整数だと割り算の結果も整数になってしまうので、1023.0 と記述することで浮動小数点数として扱うようにしてます。

温度の計算
C++
void loop() {
  int v=analogRead(SENSOR_PIN);
  double R=(1023.0/v-1)*10000;
  double T=1/(a+b*log(R)+c*pow(log(R),3))-273.15;
  Serial.println(T);
  delay(500);
}

先に解説したスタインハート・ハート式の計算です。

log(x) は自然対数(ネイピア数eを底とする対数)です。公式のリファレンスマニュアルになぜか記載が無いのですが問題なく使えます。C++ではmath.hをインクルードしないと使えないような気がしますが、ソースで判るとおりArduinoではインクルードなしで使えます。ちなみに常用対数(10を底とする対数)を表す関数は log10(x) です。

pow(x, y) は指数関数です。\(x^y\) を表します。

式の計算結果は絶対温度(K)ですが、表示を一般になじみ深い摂氏(℃)にするため、最後に273.15を引いています

求めた温度 T は Serial.println() で PC に送信しています。
あまり密に測定を繰り返しても仕方ないので、delay(500) で 500ms のウェイトを入れています。

実行

素子自体の熱容量も小さいためか、非常にレスポンスが早いです。素子をちょっと指先で触っただけで温度が上昇します。

まとめ

  • サーミスタは、温度によって抵抗値が変化する素子である
  • 測定した抵抗値から、『スタインハート・ハート式』によって温度を求められる

コメント

タイトルとURLをコピーしました