5ドル!ラズパイ・ゼロ(Raspberry pi Zero)でIoT (12) アナログ温度センサ1 LM35DZ

温度測定はIoTに欠かせない

 ラズパイにアナログ入力がないので、連載の(4)から(9)までA-Dコンバータの接続を行いました。アナログ・データの中で温度の測定は一番多いです。そして、温度測定専用のセンサもたくさんの品種が入手できます。工業用で一番利用の多いのはサーミスタです。温度によって抵抗値が変化するデバイスで、低価格が最大のメリットです。

  温度の測定は、計測という意味で使われる以外に、装置自体の健全性を確認するために、CPUやボード自体の温度を定期的に測定することも一般的です。ラズパイはCPUの温度は最新の結果を読み出して利用できます。

温度センサの種類

 アナログ出力の温度センサが一番低価格です。入出力の比例関係という項目は、温度が上がると、出力が線形でないという意味です。ラズパイでは、演算がたやすくできるので、プログラムで正確な温度を計算できます。

種類 温度範囲 価格帯 入出力の比例関係
サーミスタ  マイナスから+100℃を少し超える 数円から十円  比例しない
出力が温度に比例するセンサIC  LM35が代表的 数十円   比例する
高温に対応した熱電対  K型が代表的。-200~+1200℃。ほかにも温度範囲によってセンサが入手できる  数百円  比例しない

 

白金測温抵抗体

(精密な計測に向いている)

 低温用-200~100℃、高温用0~650℃  数百円   比例しない

 最初は、LM35のように、温度と出力電圧が比例しているセンサを利用します。センサ自体は低価格ですが、A-Dコンバータが必要です。

ポピュラなLM35DZ

 CPUや電子デバイスがある温度以上になるとシャットダウンするとか、緊急時に対応するという回路のために開発された温度センサです。摂氏零度で0mVで、1℃上がるごとに10mV出力電圧が上がります。20℃で200mVです。テスタで測るだけで、温度がわかります。

 零度以下も測れますが、マイナスの電源が必要です。零度でオフセットがある別の温度センサを使うほうがよいでしょう。

  • 電源電圧;4~20V
  • 消費電流;約133uA
  • 出力電流;10mA
  • 精度(分解能);0.5℃(25℃時)データシートからは、typical値は-50~150℃で±0.2℃の範囲に読み取れる。

ディジタル化には何ビットのA-Dコンバータが必要か

 LM35は0~100℃で0Vから1.0Vまで変化します。手軽に基準電圧を3.3Vを利用するとすれば、

  • 10ビットA-Dコンバータ 3.3/2^10 = 3.22mV
  • 12ビットA-Dコンバータ 3.3/2^12 = 0.81mV
  • 16ビットA-Dコンバータ 3.3/2^16 = 0.050mV

がLSBの電圧です。10ビットの3.22mVは温度では0.322℃ずつ変化します。分解能0.2℃のセンサの能力を生かせません。

 基準電圧を1.2V(0~120℃対応)にすると、下記のようになります。

  • 10ビットA-Dコンバータ 3.3/2^10 = 1.17mV
  • 12ビットA-Dコンバータ 3.3/2^12 = 0.29mV
  • 16ビットA-Dコンバータ 3.3/2^16 = 0.018mV

 いずれも、12ビットA-Dコンバータを利用すれば温度センサの分解能を生かせます。

 コストを優先し、手軽に温度を測るために、12ビットA-DコンバータMCP3208を使い、基準電圧は電源の3.3Vを利用します。Vrefを3.3Vの電源につなぐとし、最大で±1%の出力電圧精度差があると仮定します。3.3Vの1%は33mVで、温度では3.3℃です。大きな誤差になります。小数点第一を四捨五入し、整数値の温度を得ることにします。多桁のDMMで3.3Vの電圧を測り、プログラム内でVrefに設定すれば、誤差を抑えられます。

接続

 温度センサLM35のアナログ出力をA-DコンバータのMCP3208へつなぎます。gpiozeroライブラリでは、読み取ったデータは0~1.0のディジタル値で得られるので、Vref電圧を掛けてボルトの単位に直します。10mVが1℃なので100倍して摂氏に直し、キャラクタLCD表示器AQM0802に表示します。AQM0802はI2Cの信号のある部分にそのまま挿せば使えるピン配置なので、配線は不要です。

 LM35の電源は4V以上必要なので、GPIOの5V端子につなぎます。MCP3208とLCDは3.3Vで動作します。MCP3208はブレッドボード上で配線しました。下記の図にはありませんが、3.3Vの電源ラインには22uFの電解コンデンサと0.1uFの積層セラミック・コンデンサを入れました。

プログラム

 A-DコンバータのMCP3208はgpiozeroライブラリを、I2C接続のキャラクタLCD表示器はsmbusライブラリを利用します。表示待ちをするsleep()用にtimeライブラリを使います。

 command()とwriteLCD()はLCD用の関数です。command()は、LCDへ直接命令を送信します。writeLCD()は、引数に入っている文字列を表示します。init()はLCDの初期化コードを送信します。

 プログラムのmainでは、最初に、CH0のVCC電圧と、CH1のGNDの電圧を表示します。そのあと、CH2につながっているLM35の出力電圧を100倍して摂氏に変換し、表示します。round()で小数点第一位を四捨五入し、小数点と0を表示したくないので、整数部分だけを[0:2]で取り出してLCDへ表示します。

#!/usr/bin/env python
from gpiozero import MCP3208
import smbus
import time
i2c = smbus.SMBus(1) # 1 is bus number
addr02=0x3e #lcd
_command=0x00;_data=0x40;_clear=0x01;_home=0x02;display_On=0x0f;LCD_2ndline=0x40+0x80
Vref = 3.29476

#LCD AQM0802/1602
def command( code ):
i2c.write_byte_data(addr02, _command, code)
time.sleep(0.1)

def writeLCD( message ):
mojilist=[]
for moji in message:
mojilist.append(ord(moji))
i2c.write_i2c_block_data(addr02, _data, mojilist)
time.sleep(0.1)

def init ():
command(0x38);command(0x39);command(0x14);command(0x73);command(0x56);command(0x6c);command(0x38);command(_clear);command(display_On)

#main
init ()

pot0 = MCP3208(channel=0)
print(str(pot0.value * Vref) + "V-ch0-Vcc")
pot1 = MCP3208(channel=1)
print(str(pot1.value * Vref) + "V-ch1-GND")
while 1:
pot2 = MCP3208(channel=2)
volts2 = pot2.value * Vref
temp2 = volts2 * 100.0
print(str(temp2) + " " + str(round(temp2)) + "C-ch2")
command(_home)
writeLCD("Temp="+str(round(temp2))[0:2] + "C")
time.sleep(1)

実行結果

 7セグメントLEDは、LM35のVout端子を測っている電圧計の表示です。

 全体像です。