見出し画像

製品レビュー|電子機器4:K型熱電対アンプモジュール(MAX31855)


1.概要

 購入した製品の使い方および感想用記事です。
 今回は「MAX31855使用 K型熱電対アンプモジュール(3,450円/個(税込))」をレビューしました。

1-1.製品の仕様

 MAX31855はアナログデバイス(ANALOG DEVICES)社の子会社であるマキシム・インテグレーテッド (Maxim Integrated)社(2021年に買収)が製造した高精度熱電対-デジタルコンバータICです。
 熱電対のアナログ値を読み取ろうとするとき電圧が小さいため、Raspberry PiやPicoが搭載するADコンバーター(ADC)では値を読み取ることが出来ません。そこで、より低い電圧値でも高い分解能で値を読み取ることが出来るADCを備えたMAX31855を利用して熱電対から温度を計測していきます。

 MAX31855は冷接点補償を実行し、熱電対からの信号をデジタル化します。データは符号付き14ビットSPI™対応の読取り専用形式で出力されます。このコンバータは、温度を0.25℃まで分解するため、最高+1800℃と最低-270℃の読取りが可能となり、Kタイプ熱電対の場合-200℃〜+700℃の温度範囲で±2℃の熱電対精度を示します。

https://www.analog.com/jp/products/max31855.html#documentation

【基本仕様】
 仕様は下記の通りです。

  1. 特徴

    • 冷接点補償

    • 分解能:14ビット、0.25℃

    • 簡易なSPI対応インタフェース(読取り専用)

    • 熱電対のGNDまたはVCCへの短絡検出

    • 熱電対のオープン検出

  2. 電源:推奨は3.3V。

    • Arduinoなどは標準の電圧5Vのため使用時は注意が必要(今回購入したモジュールの電源電圧Max:5Vのため中に抵抗が入ってる??)

  3. 制御機能:外付けマイコンと組み合わせて、温度自動調整、プロセス
    制御、監視アプリケーションで使用するように設計されている

  4. 適用熱電対:K、J、N、T、E、S、R型熱電対で対応可能

    • 本ICは熱電対の型式に合わせた動作保証がされるため1個のICで1個の型式しか測定不可

【標準動作特性($${V_{CC}}$$ = +3.3V, TA = +25℃, unless otherwise noted.))】

【熱電対ワイヤの接続および公称感度/型番】

【ピン・端子情報】

【ブロック図】

【メモリ関係】

【データ形式】

1-2.製品原理:ADC(MAX31855)

【用途】
 熱電対はゼーベック効果により得られた電流から直流電圧計を接続し熱起電力を測定します。熱電対の型式により発生する熱起電力は異なりますが、下図の通り電圧は非常に低いためRaspberry Pi/Picoだと計測できません。
 よって熱電対の電圧(アナログ)▶デジタルに変換できる性能を持つADCを搭載したICが必要となります。

https://www.chino.co.jp/support/technique/sensor/thermocouples/

【温度変換】
 熱電対の信号をADCの入力チャネルと互換性のある電圧に変換するための信号コンディショニングハードウェアを内蔵しています。
 熱電圧をそれと等価な温度値に変換する前に、熱電対の冷接点側(デバイスの周囲温度)と0℃仮想リファレンスとの差を補正する必要があり、K熱電対の電圧は41.276μV/℃で変化するため、熱電対の特性を次の線形式で近似することができます。

$$
V_{OUT} = 41.276 \times (T_R - T_{AMB})
$$

  • $${V_{OUT} }$$:熱電対の出力電圧(μV)

  • $${T_R}$$:リモート熱電対接合部の温度(℃)

  • $${T_{AMB}}$$:デバイスの温度(℃)

 MAX31855は「温度と電圧の間に直線的関係があるものと想定」しており、すべての熱電対はある程度の非直線性を示すため、デバイスの出力データに適切な補正を適用します。

1-3.製品原理:熱電対

 1-3-1.温度センサの種類

 温度を計測する機器(温度センサ)はタイプが複数あり、多くの種類があります。一般に工業用(プラント)では接触式温度計の「熱電対」と「測温抵抗体」が使用されます。

https://techweb.rohm.co.jp/product/sensor/sensor-device/sensor-device-basic/5166/

 次項で熱電対の計測原理を紹介しますが、測温抵抗体の計測原理は全く異なる(ざっくりでいうとPtは温度が変わると電気抵抗が変わるのを利用)ため本記事では省略します。

 1-3-2.熱電対の種類

 熱電対の原理として、2種類の異なる金属導体の両端を接続して閉回路を作り、一端を加熱するなどして、両端に温度差を生じるとその金属固有の熱起電力が発生し回路中に電流が流れますゼーベック効果)。
  このうちの一端を切り開いて作った2端子間に直流電圧計を接続し熱起電力を測定することにより温度が測定できます。この2種類の金属の組み合わせてゼーベック効果を利用して温度を計測する機器を熱電対と呼びます。

https://www.hakko.co.jp/library/qa/qakit/html/h05030.htm

 熱電対の温度特性は下記法則で保証されています。

  1. 均質回路の法則:金属線が均質であれば局部的に加熱をしても電流が流れないというもので、熱電対の両端が均質であれば途中の温度分布に熱起電力は影響されないことを示します。

  2. 中間金属の法則:回路中に異なった金属が入っても、その両端の温度が等しければこの影響は生じないというもので、熱電対温度センサーに異種金属である端子台やコネクタが使用できる理由となります。

  3. 中間温度の法則:回路中の中間温度が既知である場合、温接点、中間温度、基準接点それぞれの温度差から得た起電力の和と全体の起電力は等しい、というもので、熱電対の温度測定に必要な冷接点補償回路はこの原理に基づいて設計されています。

 重要なポイントは下記の通りです。

  1. 温度計測の箇所:「2種金属の接点間で発生する電力を計測」するため、温度の測定部は金属が接合しているポイント(つまり先端部)のみ

  2. 線の向き:2種金属の差による電流が流れるため、線には必ず+と-があります。つまり、熱電対の線を計測器などに取り付ける場合は適切な位置(+と-)に設置が必要です。

 一般的に熱電対から計測器(今回はMAX31855)の間は補償導線(いわゆる熱電対専用の信号用電線)を使用することで離れた場所でのデータの取得が可能となります。

https://www.rkcinst.co.jp/technical_commentary/14552/

 熱電対は組み合わせる金属種に対して複数の種類があります。ポイントは下記の通りです(※電子工作でなく化学実験/プラント向けです)。

  1. 熱電対の型式:基本的には測定温度レンジ/精度(クラス)で選定

    • よくわからなければとりあえずK型熱電対でヨシッ。他の熱電対と比較して測定温度帯が非常に広いため汎用的に使えます

    • K型熱電対で測定できない高温なら、B型やR型などを選定

    • K型熱電対で測定できない低温なら、T型など選定

  2. 熱電対のその他使用:普段は気にしたことないですが、下記も選定可

    • 熱電対の形状:化学実験/プラントではシース熱電対を使用しますが、シート状など用途に応じた形状があります

    • 設置のしやすさ:例としてシースは径により曲げやすさや弾性が異なるため、場所に応じて選定が必要

    • 計測速度:より高速でデータ取得したい場合はシース径や形状などの仕様選定が必要です

  3. 補償導線:補償導線は熱電対の型に合わせた物を選定する必要あり(例:K型の補償導線をT型などには使用できない。)

  4. 防爆:電子工作では考える必要性はないです。

    • 実業務だと「耐圧防爆」か「本質安全防爆(ツェナバリア)」の選定になると思いますが、メーカーにヒアリングするのがベストです

    • 法律での指定/安全に厳しい会社で無ければ、発生リスクは低いため熱電対まで防爆にしている会社は少なさそうです。

【熱電対の温度レンジ】

https://www.okazaki-mfg.com/Tech_info/TemperatureSensorMANUAL_Latest.pdf
https://www.keyence.co.jp/ss/products/recorder/lab/thermometry/thermocouple.jsp

【シース熱電対の形式】

【コラム:熱電対の補償導線の色】
 化学/工学系の人は特殊な実験をしない限りはK型熱電対を選定しており、青色の導線を見かけたことがあると思います。熱電対の導線の色は規格(JIS C 1610 熱電対用補償導線)によって決められています。

http://www.shin-ncc.com/equipment/

 熱電対用補償導線の規格は2012年に改正されており、旧JISと新JISで導線の色が変わっているものがあります。K型熱電対も色が変わっており、旧JISは青色でしたが、新JISでは緑色になっています(ASTM E230でも色が違うみたいです)。
 新JISに変わってからも私が見てきたK型熱電対の色はほぼ青色でしたが、たまに新JISの色を見かけることがあるため記憶しておくと便利です。

https://netsushin.co.jp/wp-content/uploads/2022/09/netsushin_netsudentsui_kikaku.pdf
https://www.okazaki-mfg.com/Tech_info/TemperatureSensorMANUAL_Latest.pdf

2.部材の購入

2-1.購入品

 部品は秋月電子よりで下記購入しました。
 今回①ADC(MAX31855)、②熱電対、③熱電対をADCの電源に繋ぐためのソケットが必要になります。今回はあり合わせで組んだため③はより最適なものを選定した方が良いと思います。

  1. MAX31855使用 K型熱電対アンプモジュール

  2. K型熱電対 温度測定センサー NR-39B

    • ホームページに記載が無いですが「液体不適用」なので注意(下図)

  3. 組端子台 カバー付 6P

2-2.準備必須品

 その他必需品は下記の通りです。

  • マイコン/シングルボード(Raspberry Pi/Pico)

  • ブレッドボード

  • ジャンピングワイヤー

3.環境構築

3-1.マイコン準備

 センサを制御するためのシングルボードやマイコンの準備を行います。
Raspberry PiやPicoの準備は下記記事参照のこと

 Raspberry PiにGPIOを制御するためのライブラリが無い場合は”RPi.GPIO”を事前にインストールしておきます。
 Picoの場合はMicropythonを使用できるようにしておきます。

[Terminal]
pip install rpi.gpio

3-2.ライブラリ

 今回はシリアル通信(SPI)のため、追加の環境構築が不要(Micropythonのみで実行可能)なPicoを使用しました。

4.使用前の準備

4-1.はんだ付け

 本キットは基板とピンソケットが別詰のためはんだ付けしました。

4-2.部品の組付け

【結論】
 今回は直接補償導線をMAX31855に接続できなかった$${^{※}}$$ため、端子台+ジャンパー線で接続しました。またシリアル通信(SPI)が利用しやすいPicoで実装しました。
 原理的に「補償導線と計測器は直結させるべき」なので、下図配線は間違っておりますが、とりあえずの動作確認(+部品不足)のためこのままいきます。
※購入したK型熱電対 NR-39Bのオスソケットは外すねじがなく、メスコネクタも購入していなかったため

【K型熱電対の接続部】
 
補償導線は下図のように2本になっています。正確に測定したい場合は上図の補償導線を途中でカットし、ストリッパーで被覆を剥いてあげれば直接接続可能です。

【K型熱電対 温度測定センサー NR-39Bの注意点】
 ホームページで探しても見当たらないのですが、「液体不適用」と記載があります。よって校正時にお湯(100℃)に突っ込むのはよくない可能性が高いです。

4-3.詳細な仕様確認

 参考用で確認する仕様を記載しておきました。

 こちらの説明はコードの章で再度詳細に説明予定です。

5.Pythonスクリプトの作成

5-1.任意:デバイス接続の確認

 SPIはI2Cのようにターミナルからの確認方法がないため、目視でしっかり確認しておきます。

[Terminal]
-

5-2.コード作成(実装)

 設計思想は下記の通りです。

  1. MicropythonならSPIを直接操作できるためRaspberry Pi Picoを使用

  2. 学習もかねて、出力がどのようになっているかを確認するための関数や引数を追加

  3. MSB(最上位ビット)が0なら正、1なら負の値となる。つまり正の最大値は”01111111111111(MSB=0, 残りの13bitが1)”である。

  4. 負の値は2の補数から計算

[IN]

 5-2-1.メモリマップの確認

  SPI.read(4)で4byte=32bitのデータを読み込みます。32bitにおいて、各ビットの値には意味(データの種類)が存在します。(下図はイメージ)。

 それぞれの詳細は下図の通りです。下図より温度データは下記であることが確認できます。

  1. 温度データは32bit(4byte)内の、最初の14bitに格納されている。

    • 2byte(16bit)読み込み、最初の8bitと後の6bitを結合させればよい

  2. MSB(最上位ビット)は”Sign”であり、0は正の値、1は負の値を示す

    • 符号付き14ビットという表現をされている

    • つまり実データはMSBを除いた13bit

  3. 最後の2bitは小数点(0.25℃)を表示するために使用

 5-2ー2.14bitデジタル値の温度計算

 上記より14bit(MSBを除く13bit)からの温度計算式を紹介します。
 まとめは下記の通りです。

【14bitデジタル値の温度計算(正の値)】
 温度を正の場合、MSB(最上位ビット)は0のため13bit($${2^{13}=8191}$$で表現できます。2進数(0/1)を10進数に変換する式は下記の通りです。

$$
10進数の値 = \sum_{i=0}^{n} b_i \cdot 2^i
$$

 得られたデジタル値は$${0.25=2^{-2}}$$の分解能を持つため、下記計算式で算出できます。

$$
\begin{aligned}
温度[℃] &= 0.25\times温度データ(符号付き14ビット)
\\&=0.25 \times (D_{30} \cdot 2^{12} +D_{29} \cdot 2^{11} + \ldots + D_{20} \cdot 2^2+ D_{19} \cdot 2^{1} + D_{18} \cdot 2^{0})
\\&=10^{-2} \times (D_{30} \cdot 2^{12} +D_{29} \cdot 2^{11} + \ldots + D_{20} \cdot 2^2+ D_{19} \cdot 2^{1} + D_{18} \cdot 2^{0})
\\&= D_{30} \cdot 2^{10} +D_{29} \cdot 2^{9} + \ldots + D_{20} \cdot 2^0+ D_{19} \cdot 2^{-1} + D_{18} \cdot 2^{-2}
\\&= D_{30} \cdot 1024 +D_{29} \cdot 512 + \ldots + D_{20} \cdot 1+ D_{19} \cdot 0.5 + D_{18} \cdot 0.25
\end{aligned}
$$

14bitデジタル値の温度計算(負の値)
 符号付き14ビットであり、MSB(最上位ビット)が1の時は負の値を表現します(公式データシート参照)。これは2進数(デジタル値)は0と1でしか数値を表現できないため、MSBで正と負を表現します。

 負の数を計算する場合、一般的な情報処理技術として「2の補数」を計算します。計算手順は下記の通りです。

  1. 全てのビットを反転(1▶0, 0▶1に変換)

  2. 反転したビット列に1を加える

 正の値(MSB=0)の最大値は14bit内のMSBを除いた$${13bit=2^{13}=8192}$$であるため、負の値(MSB=1)も同様に-8192まで表現できます。よって、得られたデータから$${14bit=2^{14}=16384}$$を引いてあげると正負の逆転ができ、2の補数による換算と同じ効果が確認できます。

 5-2-3.ビット演算

 以前Python基礎でビット演算を紹介しました。操作に関しては下記記事をご確認ください。

 今回はSPIで得られたデータ(4byte=32bit)の内、最初の1byte(8bit)と次の1byteのうち6bitをつなげて14bitにする必要があります。そのために下記処理を加えてデータにします。

  • 左シフト<<:各桁のビットが指定した値だけ左にずらす

  • 右シフト>>:各桁のビットが指定した値だけ右にずらす

  • OR演算|:各桁のビットに対して論理演算:ORを実行

 処理のイメージは下記の通りです。具体的なコードも記載しましたのでご参考までに。

  • 左シフトで6個つなげるためのスペースをあける

  • 右シフトで不要な2bitを削除

  • OR演算でbitを結合

[IN]
#2進数で表記
x = 0b00000001
y = 0b10110000
print(f'x: {bin(x)}, 16進数表記: {hex(x)}')
print(f'y: {bin(y)}, 16進数表記: {hex(y)}')

#最初の8bitを左に6bitシフト、次の8bitを右に2bitシフト
x_LS6 = x << 6
y_RS2 = y >> 2
print(f'左シフト6後のx: {bin(x_LS6)}, 16進数表記: {hex(x_LS6)}')
print(f'右シフト2後のy: {bin(y_RS2)}, 16進数表記: {hex(y_RS2)}')

#OR演算(論理和で最初と最後の8bitを結合)
result = x_LS6 | y_RS2
print(f'OR演算後|10進数:{result}, 2進数:{bin(result)}, 16進数表記: {hex(result)}')
[OUT]
x: 0b1, 16進数表記: 0x1
y: 0b10110000, 16進数表記: 0xb0
左シフト6後のx: 0b1000000, 16進数表記: 0x40
右シフト2後のy: 0b101100, 16進数表記: 0x2c
OR演算後 10進数:108, 2進数:0b1101100, 16進数表記: 0x6c

5-3.実行

 実行結果は下記の通りであり、温度の計測できました。また途中で先端部(温度計測箇所)を指でつまみましたが1sec程度で十分反応してくれました。

  1. SPIで確認したクロック周波数(baudrate)は設定値10MHzまでは到達していない

  2. SPIオブジェクトのSPI.read()からは4byte(32bit)の情報を抽出

  3. 4byteから14bit抽出し分解能を換算することで温度を計測

[IN]
from machine import Pin, SPI
import time

#SPIピン設定※MAX31855は出力しかないためMISO(Master In Slave Out)は不要
pin_SOMI = Pin(16) #SOMI(Slave Out Master In)
pin_SCSK = Pin(18) #SCSK(Serial Clock)
pin_CS = Pin(17, Pin.OUT) #CS(Chip Select)

pin_CS.value(1) #CSピンをHIGHにして通信終了

#SPI設定
channel_SPI = 0 #SPIチャンネル番号
speed_SPI = 10000000 #SPI通信速度

#SPIオブジェクト生成
spi = SPI(channel_SPI, 
          sck=pin_SCSK, 
          miso=pin_SOMI,
          baudrate=speed_SPI)

print(spi)

#SPIで読み込んだデータの可視化用(学習用)
def calc_bindechex(data):
    binary_str = ' '.join(f'{byte:08b}' for byte in data)
    hex_str = ' '.join(f'{byte:02x}' for byte in data)
    dec_str = ' '.join(f'{byte}' for byte in data)
    return binary_str, hex_str, dec_str
    
    
def read_temperature(verbose=False):
    pin_CS.value(0) #CSピンをLOWにして通信開始
    data = spi.read(4) #データ読み込み
    pin_CS.value(1) #CSピンをHIGHにして通信終了
    
    #データ解析
    T_raw = (data[0] << 6) | (data[1] >> 2)
    #計測データが負の場合(MSBが1の場合)
    if (T_raw > 0b011111_11111111): #MSBが1の場合は負のため、正の最大値は01111111111111になる
        T_raw = T_raw - 16384 #2^14=16384
    T = T_raw * 0.25
    
    if verbose:
        binary_str, hex_str, dec_str = calc_bindechex(data)
        print(f'Data:{data}')
        print(f'Data(2進数):{binary_str}')
        print(f'Data(16進数):{hex_str}')
        print(f"14bitデータ:{T_raw}")
    return T 

while True:
    T = read_temperature(verbose=True)
    print(f"温度:{T}℃", end="\n\n")
    time.sleep(1) #1秒待機
[OUT]
SPI(0, baudrate=8928571, polarity=0, phase=0, bits=8, sck=18, mosi=19, miso=16)

Data:b'\x01\xb0\x1b0'
Data(2進数):00000001 10110000 00011011 00110000
Data(16進数):01 b0 1b 30
14bitデータ:108
温度:27.0℃

Data:b'\x01\xac\x1b0'
Data(2進数):00000001 10101100 00011011 00110000
Data(16進数):01 ac 1b 30
14bitデータ:107
温度:26.75℃

Data:b'\x01\xb4\x1b0'
Data(2進数):00000001 10110100 00011011 00110000
Data(16進数):01 b4 1b 30
14bitデータ:109
温度:27.25℃

Data:b'\x02 \x1b0'
Data(2進数):00000010 00100000 00011011 00110000
Data(16進数):02 20 1b 30
14bitデータ:136
温度:34.0℃

Data:b'\x02@\x1b0'
Data(2進数):00000010 01000000 00011011 00110000
Data(16進数):02 40 1b 30
14bitデータ:144
温度:36.0℃

Data:b'\x02\x1c\x1b0'
Data(2進数):00000010 00011100 00011011 00110000
Data(16進数):02 1c 1b 30
14bitデータ:135
温度:33.75

5-4.校正テスト

 正しく温度を計測できているか校正テストをしてみました。本当は両方やりたいのですが、液体不適用の熱電対だったため1のみ実施しました。

  1. 温度0℃:氷の表面温度

  2. 温度100℃:沸騰中の水

 計測結果は約1.3℃であり、まずまずの結果が得られました。「温度範囲で±2℃の熱電対精度」と「直接補償導線をセンサにいれてない」ことも考慮すれば、仕様範囲内で計測値を読み取ることができています。

6.参考:Raspberry Piで実装

 Raspberry Piでも実装してみました。内容は下記参考にしました。ライブラリを使用して簡単に実装できるため、動作はブラックボックス化していますが説明抜きで使用していきます。

6-1.環境構築

 まずは仮想環境を作成しActivate化してから、Jupyter Notebookを実行できるようjupyterをインストールしました。

[Terminal]
conda create -n max31855 python
conda activate max31855
pip install jupyter

 次にRaspberry PiでSPI通信かつMAX31855の温度計算ができるライブラリとして”adafruit-circuitpython-max31855”を使用します。GITHUBに従って、pip installしました。

[Terminal]
pip install adafruit-circuitpython-max31855

6-2.部品の組付け

 下図の通り配線しました。PINの選択位置は配列的に見やすい場所を選んだだけです。

  • MAX31855(Vin) ⇔ PIN17(3.3V)

  • MAX31855(GND) ⇔ PIN6(Ground)

  • MAX31855(DO) ⇔ GPIO9(MISO)

  • MAX31855(CS) ⇔ GPIO26(BCM5)

  • MAX31855(CLK) ⇔ GPIO11(SCLK)

6-3.Pythonスクリプト

 GitHubのサンプル通りに記載しました。”digitalio.DigitalInOut”の属性DxはGPIOピンのBCM番号を入力すれば認識されます。今回はチップ・セレクト(CS)にGPIO26を選択したためD26としました。
 結果として温度を出力できることを確認しました。

[IN]
import board
import busio
import digitalio
import adafruit_max31855

spi = busio.SPI(board.SCK, 
                MOSI=board.MOSI, 
                MISO=board.MISO)

cs = digitalio.DigitalInOut(board.D26)
max31855 = adafruit_max31855.MAX31855(spi, cs)

print(f'温度:{max31855.temperature} °C')
[OUT]
温度:27.0 °C

7.所感

 簡単な所感は下記の通り

  • I2C通信は他のセンサ(温度センサ:ADT7410モーター制御:PCA9685)のためある程度理解してきた。

  • センサの計測原理のところが十分理解できていないので、外乱の影響や校正方法が十分でない。

  • 他の人がライブラリ作ってくれていると計測がめちゃくちゃ簡単な反面、理解が浅くなるので別途読み込みは必要。


参考資料

別添1:Rasberry Pi/Pico関係

別添2:技術関係

あとがき

 下記のなぜがある程度理解できた。

  • 熱電対の信号がアナログであること

  • データロガーなどで熱電対のアナログ諡号を電圧ユニットで測定できる

  • 熱電対はシンプルな電圧(0-5V, 0-10V)とは別に選択が必要

  • 熱電対の選択時にも型式の指定が必要

https://japan-factory-repair-and-maintenance.com/kyusyu/product/plc2/

この記事が気に入ったらサポートをしてみませんか?