5ドル!ラズパイ・ゼロ(Raspberry pi Zero)でIoT (15) アナログ温度センサ3 零下対応S-8120C
■プラス電源だけでマイナス温度が測れる温度センサ
ラズパイは3.3Vと5Vが利用できるので、センサもその電圧だけで動作するのが便利です。LM35は、0℃以下を測るにはマイナスの電源が必要です。
アナログ出力の温度センサS-8120Cは3.3Vで動作し、-30℃は1.951V、+30℃は1.474Vという出力なので、扱いやすいです。温度と出力電圧は完全には比例していません。
●S-8120Cのスペック
- 温度と出力電圧の関係;-8.20mV/℃
- 電源電圧;2.4~10V
- 消費電流;4.5uA
●モジュール化
IC自体は小型なので、入出力にデータシートに書かれているコンデンサを含めて利用しやすい形状にしたモジュールが秋月電子通商から購入できます。2017年9月現在5個入りで200円と低価格です。
データシートには、出力の負荷容量を100pF以下にするように書かれています。テスト用回路に従って100pFが入っているので、負荷容量を軽くするために取り除きました。
リード線をはんだ付けしました。
●接続
1mV単位で計測しないといけないので、16ビットA-DコンバータLTC2450を利用します。連載13回を参照します。前回のLM35とセンサ部分を除いて同じ配線です。Vddは5Vではなく3.3Vにつなぎます。GNDとVoutは同じ配線です。
●温度と出力電圧の関係
データシートには、-30~100℃の範囲で、次の関係が書かれています。
Vout [mV] = -8.2 [mV] x Ta [℃] +1705 [mV] Ta [℃] = ( Vout [mV] - 1705 [mV] ) / -8.2 [mV] |
しかし、これでは±2.5℃のずれが生じます。すこし大きめの誤差に見えます。データシートには、-30℃から100℃までの温度と出力電圧のグラフが載っているので、10℃単位で読み取ってエクセルに入れます。
エクセルの機能を使って2次曲線で近似すると、
y = 0.0005 * x^2 - 0.0299 * x - 1.3426 |
なので、補正した温度は、下記のように求められます。これによって、±2.5℃から約±0.1℃の誤差に減少します。
Delta_Ta [℃] = 0.0005 * Ta^2 - 0.0299 * Ta - 1.3426 |
●プログラム
SPI接続のA-DコンバータのLTC2450はspidevライブラリを、I2C接続のキャラクタLCD表示器はsmbusライブラリを利用します。変換待ちをするsleep()用にtimeライブラリを使います。
LCDcommand()とwriteLCD()はLCD用の関数です。LCDcommand()は、LCDへ直接命令を送信します。writeLCD()は、引数に入っている文字列を表示します。initLCD()はLCDの初期化コードを送信します。
プログラムのmainでは、最初に、LT2450から前のデータを読み出し、もう一度読むと最新のA-D変換のデータが読み出されます。S-8120Cの出力電圧を1000倍してmVの単位にします(mvolt1)。 -8.2mV/℃の変換を行います(tempS8120C )。エクセルで導き出した2次関数の補正式を計算します(delta_tempS8120C )。補正を適用します(True_tempS8120C)。
画面には、測定電圧、 -8.2mV/℃の変換結果の温度、補正の値、補正後の温度を表示します。補正後の温度をround()で小数点第2位を四捨五入し、LCDへ表示します。計算上は±0.1℃の精度が得られていますが、検証していません。
#!/usr/bin/env python
import spidev
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.29989
spi = spidev.SpiDev()
spi.open(0,0)
#LCD AQM0802/1602
def LCDcommand( 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 initLCD():
LCDcommand(0x38);LCDcommand(0x39);LCDcommand(0x14);LCDcommand(0x73);LCDcommand(0x56);LCDcommand(0x6c);LCDcommand(0x38);LCDcommand(_clear);LCDcommand(display_On)
#main
initLCD()
adcLTC2450 = spi.xfer2([0x00,0x00])
time.sleep(0.05)
adcLTC2450 = spi.xfer2([0x00,0x00])
data = (adcLTC2450[0] << 8) | adcLTC2450[1]
mvolt1 = (Vref*data/65535) * 1000
tempS8120C = (mvolt1 - 1705) / -8.2
delta_tempS8120C = 0.0005 * tempS8120C*tempS8120C - 0.0299 * tempS8120C -1.3426
True_tempS8120C = tempS8120C + delta_tempS8120C
print (str(mvolt1) +"V "+ str(round(tempS8120C,2))+"C "+ str(round(True_tempS8120C,2))+"C")
writeLCD("T="+str(round(True_tempS8120C,1)) + "C")
spi.close()
(※)2018年後半から、speedの指定が必須になっています。open後に記述します。
spi.open(0, 0) # port 0,cs 0
spi.max_speed_hz = 1000000 # 1MHz
●実行結果
コラム アナログ出力の温度センサ
LM35とS-8120Cを使いましたが、入手しやすいアナログ出力の温度センサはほかにもたくさんあります。下記のセンサは秋月電子通商で入手できます。
ディジタル出力の温度センサに比べてA-D変換が必要なので、コストと手間が多いセンサですが、A-D変換器が多チャネル入力であれば、ほかの種類のセンサも同時に利用できるメリットもあります。
- LM60BIZ 測定温度範囲;-25~+125℃ 6.25mV/℃
- LM61CIZ 測定温度範囲;-30~100℃ +10mV/℃
- LM335Z 測定温度範囲;-40~+100℃ +10mV/°K
- S8100B 測定温度範囲;-40~+100℃ -80mV/°K
- MCP9701-E/TO 測定温度範囲;-40~+125℃ +19.5mV/℃
- MCP9700-E/TO 測定温度範囲;-40~+125℃ +10mV/℃