Arduiono を使ってサーミスタで温度を測る
◆まえがき
サーミスタで温度測定をやってみました。最終的には現在取り組み中の、ペルチェを使った温度発生装置に組み込むつもりなのですが、まずはサーミスタ単体の使いこなし方をマスターすることから始めました。
◆使ったサーミスタ

秋月で買っておいた超小型のサーミスタです。小さな温度センサーが必要なら、熱電対が一番性能が良いのですが、オペアンプや零接点が必要で、何も無いところから作ろうとすると厄介です。その点、このサーミスタなら素子部がゴマ粒くらいしかないので、対象物への影響は最小限になります。それに回路も簡単なもので済みます。
◆サーミスタを使った温度測定
サーミスタで温度測定を行う場合、抵抗から温度へ計算式を使えば簡単に出来るはずです。しかし、ネットを調べてみたら、そういう計算式を使う方法は敬遠されているようであまり事例がありませんでした。式の中に対数の計算があるので、マイコンではプログラム作りが難しいというのがその理由のようです。
そんな事情から、いろいろな代替手段が使われていました。例えば、抵抗値と温度のテーブルを用意しておく、あるいは、近似式で計算する方法などがよく使われているようでした。
しかし、別にそんなことしなくても Arduino なら実用的な速度で計算出来そうです。ということで、抵抗から温度を求める計算式を使う方式でやってみました。
◆サーミスタの温度、抵抗の計算式
・温度から抵抗値を求める式:
(1)
・抵抗から温度を求める式:
(2)
この記事では (2 )式を使って温度を求めることにします。
◆回路図

Arduinoから出ている3.3Vを使い、R1の75kΩとサーミスタで分圧した電圧をアナログポートの 0 に入力して測定します。アナログポートは1.1Vフルスケールで使うので、サーミスタの抵抗が最大に上がった時でも、電圧が1.1Vを超えないような値にR1を設定します。なお、使ったサーミスタのR0は10kΩです。
この回路ではサーミスタに加わる電圧が最大でも1.1Vなので、素子の自己発熱による誤差の影響を小さく出来ます。
ちなみに、電源電圧の5Vから分圧する手、あるいはADCのフルスケール(Vref)を電源電圧で使う手などいろいろ考えられますが、それぞれ一長一短だと思います。
ともかくこの回路でサーミスタの電圧を測定すれば、計算で抵抗が判ります。抵抗が判れば(2)式で温度が判るというストーリーです。それをプログラムにしたのが次のリストです。
◆温度測定のテストプログラム
サーミスタで温度測定をやってみました。最終的には現在取り組み中の、ペルチェを使った温度発生装置に組み込むつもりなのですが、まずはサーミスタ単体の使いこなし方をマスターすることから始めました。
◆使ったサーミスタ

秋月で買っておいた超小型のサーミスタです。小さな温度センサーが必要なら、熱電対が一番性能が良いのですが、オペアンプや零接点が必要で、何も無いところから作ろうとすると厄介です。その点、このサーミスタなら素子部がゴマ粒くらいしかないので、対象物への影響は最小限になります。それに回路も簡単なもので済みます。
◆サーミスタを使った温度測定
サーミスタで温度測定を行う場合、抵抗から温度へ計算式を使えば簡単に出来るはずです。しかし、ネットを調べてみたら、そういう計算式を使う方法は敬遠されているようであまり事例がありませんでした。式の中に対数の計算があるので、マイコンではプログラム作りが難しいというのがその理由のようです。
そんな事情から、いろいろな代替手段が使われていました。例えば、抵抗値と温度のテーブルを用意しておく、あるいは、近似式で計算する方法などがよく使われているようでした。
しかし、別にそんなことしなくても Arduino なら実用的な速度で計算出来そうです。ということで、抵抗から温度を求める計算式を使う方式でやってみました。
◆サーミスタの温度、抵抗の計算式
・温度から抵抗値を求める式:

・抵抗から温度を求める式:

この記事では (2 )式を使って温度を求めることにします。
◆回路図

Arduinoから出ている3.3Vを使い、R1の75kΩとサーミスタで分圧した電圧をアナログポートの 0 に入力して測定します。アナログポートは1.1Vフルスケールで使うので、サーミスタの抵抗が最大に上がった時でも、電圧が1.1Vを超えないような値にR1を設定します。なお、使ったサーミスタのR0は10kΩです。
この回路ではサーミスタに加わる電圧が最大でも1.1Vなので、素子の自己発熱による誤差の影響を小さく出来ます。
ちなみに、電源電圧の5Vから分圧する手、あるいはADCのフルスケール(Vref)を電源電圧で使う手などいろいろ考えられますが、それぞれ一長一短だと思います。
ともかくこの回路でサーミスタの電圧を測定すれば、計算で抵抗が判ります。抵抗が判れば(2)式で温度が判るというストーリーです。それをプログラムにしたのが次のリストです。
◆温度測定のテストプログラム
/* サーミスタによる温度測定(B値を使った温度の計算)
2019/11/8 ラジオペンチ http://radiopench.blog96.fc2.com/
*/
void setup() {
analogReference(INTERNAL); // ADCは内部refを使用(フルスケール=1.1V)
Serial.begin(115200);
}
void loop() {
float V, R, T; // 電圧、抵抗、温度
long x;
x = 0;
for (int n = 0; n < 10; n++) {
x += analogRead(0); // A0からサーミスタの電圧を読んで累積
}
// V = x * 1.1 / 10230.0; // 1023で割るのは間違い。平均電圧の計算 (1.1V=1023)(10回ループで1.2ms)
V = x * 1.1 / 10240.0; // 正しくはこちら。平均電圧の計算 (1.1V=1024)(10回ループで1.2ms)
R = thermistorR(V, 3.3, 75000.0); // 電圧からサーミスタの抵抗値を計算(50μs)
T = thermistorT(R, 3431.0, 10000.0, 25.0); // 抵抗値から温度を計算(180μs)
Serial.print(V, 3); // 電圧を出力
Serial.print(", "); Serial.print(R, 1); // 抵抗値
Serial.print(", "); Serial.println(T, 1); // 温度
delay(500);
}
float thermistorR(float Vx, float V0, float Rs) { // サーミスタの抵抗値計算
// Vx:サーミスタの電圧(V)、V0:元電圧(V)、Rs:直列抵抗の値(Ω)(上側に接続)
return Vx * Rs / (V0 - Vx);
}
float thermistorT(float R, float B, float R0, float T0) { // 抵抗値から温度を計算
// R:サーミスタ抵抗(Ω)、B:B値、R0:基準温度の時の抵抗(Ω)、T0:基準温度(℃)
return 1 / ((1.0 / B) * log(R / R0) + (1.0 / (T0 + 273.15))) - 273.15; // (logは自然対数で計算される)
}
後で簡単に流用出来るように機能単位で関数にまとめ、必要なパラメータは関数の引数で渡すようにしました。これでNTCサーミスタなら何でも使えるはずです(たぶん)。
実行時間はコメントの中に書いておきましたが、抵抗から温度を計算する時間は180μsでした。よほどの高速処理が必要な場合以外はこれで大丈夫だと思います。
Log の関数は Arduino のリファレンスには書いてないのですが、math.h をインクルードしなくても使えました。実は math.h は何も宣言しなくても最初からインクルードされているようです。 宣言があっても使わなければコンパイラで自動的に削られるので、便利になるだけで副作用は無い、ということだと思います
◆実行結果

これはシリアルに出しているデータ例で、サーミスタの電圧、抵抗、温度の順で出力されます。手で触って25℃を通過させ様子ですが、ちゃんと10kΩをまたいで変化しているので、計算は大丈夫そうです。
◆被測定部の様子

ペルチェ制御の温度プレートにサーミスタを取り付けた様子です。まあ取り付けたと言っても、アルミ粘着テープで貼っただけです。左側は温度センサーのLM35Zで、こっちはTO-92パッケージなのでサイズが大きく、さらにモールドの奥に感熱部があるので、応答速度が遅くオフセットが大きいのが不満でした。これをサーミスタに交換することを考えています。
◆まとめ
サーミスタは非直線性が大きいので使い難く、精度も悪いという印象を持っていたのですが、使ってみたらそんなことはありませんでした。大昔にそういう悪い印象を刷り込まれていて、まじめに使ったことが無かったのがそんな誤解の原因だったようです。
これでサーミスタで温度測定する方法が判ったので、ペルチェの温度制御の方に組み込んでいくことにします。たぶん応答時間が変わるので、PIDのパラメーターチューニングをもう一度やらないといけないんでしょうね。面倒くさいけど楽しそうな作業ではあります。
実行時間はコメントの中に書いておきましたが、抵抗から温度を計算する時間は180μsでした。よほどの高速処理が必要な場合以外はこれで大丈夫だと思います。
Log の関数は Arduino のリファレンスには書いてないのですが、math.h をインクルードしなくても使えました。実は math.h は何も宣言しなくても最初からインクルードされているようです。 宣言があっても使わなければコンパイラで自動的に削られるので、便利になるだけで副作用は無い、ということだと思います
◆実行結果

これはシリアルに出しているデータ例で、サーミスタの電圧、抵抗、温度の順で出力されます。手で触って25℃を通過させ様子ですが、ちゃんと10kΩをまたいで変化しているので、計算は大丈夫そうです。
◆被測定部の様子

ペルチェ制御の温度プレートにサーミスタを取り付けた様子です。まあ取り付けたと言っても、アルミ粘着テープで貼っただけです。左側は温度センサーのLM35Zで、こっちはTO-92パッケージなのでサイズが大きく、さらにモールドの奥に感熱部があるので、応答速度が遅くオフセットが大きいのが不満でした。これをサーミスタに交換することを考えています。
◆まとめ
サーミスタは非直線性が大きいので使い難く、精度も悪いという印象を持っていたのですが、使ってみたらそんなことはありませんでした。大昔にそういう悪い印象を刷り込まれていて、まじめに使ったことが無かったのがそんな誤解の原因だったようです。
これでサーミスタで温度測定する方法が判ったので、ペルチェの温度制御の方に組み込んでいくことにします。たぶん応答時間が変わるので、PIDのパラメーターチューニングをもう一度やらないといけないんでしょうね。面倒くさいけど楽しそうな作業ではあります。
- 関連記事