サーミスタによる温度測定

機器の温度監視で最も使われるセンサがNTCサーミスタです。安価で感度が高い一方、出力は抵抗値です。さらに温度に対して直線的に変化しないため、ADC値から温度へ変換する部分でつまずきがちです。本記事では、分圧回路の設計からB定数による温度変換、計算を軽くするテーブル方式、精度を左右するポイントまで、順に解説します。

NTCサーミスタの基礎:抵抗値とB定数

NTCサーミスタは、温度が上がると抵抗値が下がる素子です。仕様は主に2つの値で表されます。1つは基準温度(通常25℃)での抵抗値で、10kΩ品が定番です。もう1つがB定数で、温度変化に対する抵抗値変化の感度(特性カーブの傾き)を表します。B定数は製品によって幅があり、実用上は3000K〜5000K程度がよく使われます(用途や品種によっては2000K〜6000K程度まで存在します)。2つの温度間の抵抗値から算出されるため「B25/85」のように算出温度を明示して表記されます。データシートでこの2つを確認することが出発点です。

※B定数は便宜上「定数」として扱いますが、材料や温度域によって見かけ上は変化します。

分圧回路でADCにつなぐ

サーミスタの抵抗値はそのままでは読めないため、固定抵抗と直列にして電圧に変換し、その分圧点をADCで読みます。本記事では「電源側に固定抵抗、GND側にサーミスタ」という構成で説明します。固定抵抗には、測定したい温度範囲の中心付近でのサーミスタ抵抗値と同程度(10kΩ品なら10kΩ)を選ぶと、感度のよい電圧範囲を使えます。

このとき大切なのが、ADCの基準電圧を分圧回路と同じ電源にしておくことです。分圧の出力は電源電圧との比で決まるため、基準電圧も同じ電源にすると電源変動が打ち消されます(レシオメトリック測定)。電源とは別の基準電圧を使うと、電源のふらつきがそのまま温度誤差になります。
※分圧回路の励起(VCC)とADCのVrefが同一電源で、両者が同じ変動を受ける構成で有効です(ノイズ成分は別途対策が必要)。

ADC値から抵抗値を逆算する

分圧の式を変形すると、ADC値からサーミスタの抵抗値が求まります。「固定抵抗が電源側」の構成では次のようになります(ADC_MAXは12ビットなら4095)。※以下は「電源側(VCC側)にR_FIX、GND側にR_th、ADCは中点」という構成の場合です。

R_th = R_FIX × adc ÷ (ADC_MAX − adc)
※ADC_MAXは「最大コード値」です(12ビットなら通常4095)。使用するADCドライバが「分解能(4096)」で扱う場合は読み替えてください。

adcがADC_MAXのときは分母が0になりゼロ除算が発生します。一方、adcが0のときは抵抗値が0となり、以降の対数計算が成立しません(いずれも断線・短絡時に起こり得ます)。そのため、コードでは範囲ガードを必ず入れる必要があります。実機ではノイズなどで端点付近に張り付くこともあるため、端点と完全に一致する値だけを異常とみなさず、しきい値(ガードバンド)を設けることで検出漏れや誤検出を減らせます。このガードバンド判定は、センサ異常(断線・短絡)の検出にもそのまま活用できます。

B定数式で温度に変換する

抵抗値と絶対温度の関係は指数関数で近似されます。B定数の定義式は下記のとおりです。この式をTについて解くと温度が求まります(コード内コメント参照)。ここでlnは自然対数(C言語ではlogf())です。温度は摂氏ではなくケルビンで計算する点にも注意が必要です。

B = ln(R/R0) ÷ (1/T − 1/T0)
※ここでのT、T0は絶対温度(ケルビン)です。

#include <math.h>
#include <stdint.h>
#define B_CONST    3435.0f    /* B定数 [K](データシート値) */
#define R0_OHM     10000.0f   /* 25℃での抵抗値 [Ω]          */
#define T0_KELVIN  298.15f    /* 基準温度 25℃ = 298.15K      */
#define R_FIX      10000.0f   /* 分圧の固定抵抗 [Ω]          */
#define ADC_MAX    4095u      /* 12ビットADC                  */
#define ADC_MIN_TH 20u        /* 下限ガードバンド(断線・短絡判定) */
#define ADC_MAX_TH 4075u      /* 上限ガードバンド(断線・短絡判定) */
float thermistor_to_celsius(uint16_t adc)
{
    if ((adc <= ADC_MIN_TH) || (adc >= ADC_MAX_TH)) {
        return -999.0f;                    /* 断線・短絡などの異常 */
    }
    /* ADC値からサーミスタ抵抗値を逆算 */
    float r_th = R_FIX * (float)adc / (float)(ADC_MAX - adc);
    /* B定数式: 1/T = 1/T0 + (1/B)・ln(R/R0) */
    float inv_t = 1.0f / T0_KELVIN + logf(r_th / R0_OHM) / B_CONST;
    return (1.0f / inv_t) - 273.15f;       /* ケルビン → 摂氏 */
}

※このサンプルでは戻り値の-999.0fで異常を表現していますが、実装ではboolで成否を返して温度を出力引数にする、またはNANを返すなど、システムの方針に合わせてください。

logfの計算コストが高いときはテーブル+補間で

logf()と浮動小数点演算は、FPUのないマイコンでは処理時間もコードサイズも無視できません。温度範囲が決まっている用途では、5℃刻み程度で「ADC値→温度」の対応表をあらかじめ計算しておき、実行時は表引きと線形補間だけで済ませる方式が定番です。表はPCやスプレッドシートで生成してconst配列としてROMに置きます。テーブルと補間の実装は別記事「ルックアップテーブルと補間の実装」で詳しく扱います。

精度を左右する4つのポイント

  • B定数式は2点間の近似:算出温度(B25/85なら25〜85℃)から離れるほど誤差が増えます。広範囲・高精度が必要ならSteinhart-Hart式(3定数近似)やメーカ提供のR/T表を使います。Steinhart-Hart式は、B定数式より広い温度域で近似精度を高めるために用いられます。
  • 固定抵抗の精度:分圧の相方なので、固定抵抗の誤差はそのまま温度誤差になります。許容差1%以下の高精度品を使い、温度係数にも注意します。
  • 自己発熱:サーミスタ自身に流れる電流による発熱で、実際より高い温度を示します。仕様書の熱放散定数(自己発熱で1℃上げるのに必要な電力)を確認し、測定電流を小さくするか、測定時だけ通電する設計にします。
  • ノイズ:ADC値は複数回読んで平均やメディアンを取ります。

ありがちなトラブル

  • 温度の動きが逆:固定抵抗とサーミスタの上下(電源側/GND側)が想定と逆になっています。逆算式が回路構成と一致しているか確認してください。
  • 全体的にずれる:ケルビン換算(273.15)の入れ忘れ、B定数や25℃抵抗値の取り違え、基準電圧の不一致が定番です。
  • 常に少し高めに出る:自己発熱を疑います。固定抵抗を大きくして電流を減らすと改善します。

まとめ

サーミスタの温度変換は「分圧→抵抗値逆算→B定数式」の3段階です。レシオメトリック測定・範囲ガード・自己発熱対策の3点を押さえれば、実用十分な温度計測がローコストで実現できます。

組み込みソフトの世界 トップへ戻る