LoginSignup
0

More than 3 years have passed since last update.

posted at

RaspberryPiとADT7410で16bit解像度 I2C 温度測定をする

概要

  • RaspberryPiと秋月電子製のADT7410モジュールを使って温度測定をしました。デフォルト解像度は13bit幅ですが、Configレジスタ0x03の7ビット目に1を設定する事で16bitで計測してみました。

  • 計測レンジは-55~150℃で、13bitだと0.0625℃きざみ、16bitだと0.0078℃きざみでより細かく計測できます。

構成

20191209_171135.jpg
RaspberryPiのSDA1⇔ADT7410のSDA、SCL1⇔SCL、3V3⇔VDD、GND⇔GNDのように接続します。

ソース

ADT7410_16bit.py
import smbus
from time import sleep

def read_adt7410():
    data = bus.read_word_data(adt7410,reg_val)
    temp = (data&0xff00)>>8 | (data&0x00ff)<<8
    if temp & 0x8000 == 0:
        temp2 = temp / float(128)
        #temp2 = temp * 0.0078125
    else:
        temp2 = (temp - 65536) / float(128)
        #temp2 = (~temp&0xffff+1) / float(128)

    return temp2


bus = smbus.SMBus(1)
adt7410 = 0x48
reg_val = 0x00
reg_conf = 0x03

try:
    bus.write_byte_data(adt7410,reg_conf,0x80)

    while True:
        val = read_adt7410()
        print ("{0:.5f}".format(val))
        sleep(0.5)

except KeyboardInterrupt:
    pass

説明

  • smbusライブラリをインポートして処理します。bus.write_byte_data(adt7410のアドレス0x48,configレジスタのアドレス0x03, configレジスタの7bit目だけ1にするため0x80 = 0b10000000 書き込み) で解像度を13bitから16bitに変更を1回だけしています。

ADT7410データシートP14抜粋
image.png

  • bus.read_word_dataで、wordつまり2bytes=16bitsのAD変換値を得ます。戻り値が[LSB 7:0][MSB 15:8]のようになっているのでMSB、LSBの順になるようにビット演算をします。
  • 16bit目が1ならマイナス温度、0ならプラス温度になるので、それぞれ計算をしています。下記のPositive Temperatureで÷128としているのは×(1/128)をかけているのと同じ、128分の1は0.0078125、これだと理解しやすいです。例えばAD変換値tempが2560の場合、2560×0.0078125=20℃となります。やっかいなのは零下の計算で、AD変換値から65536を引いてから0.0078125をかけています。65536を引いているのはAD変換値の2の補数を得るのと等価だと理解しています。ビットで考えるとわかりやすく、まず65536(10進)=1 0000 0000 0000 0000(2進)です。これに対して-55℃の場合AD変換値が58496(10進)=1110 0100 1000 0000(2進)になることを例とし、式の通りに計算すると(58496-65536)*0.0078125 = -55となります。これを2進数で同じことをすると、(1110 0100 1000 0000)-(1 0000 0000 0000 0000) = (0001 1011 1000 0000)、計算結果は2の補数となっています(全てのビットを反転して+1)。つまり例えば16bitデータに対しては17bit目が1で16bit以下が0の値(=今回の場合65536)をAD変換値から引くことで、2の補数(-値の絶対値)を得られます。それに解像度をかければよいのです。わかりにくい説明ですみません。ちなみに負数計算式はもう一つ32768を引いているものがありますが、これは計測レンジがマイナス側は-55とプラスと比較して少ないことにより、16bitデータの場合負の数であれば16bitは符号ビットなのでもちろん、15bit目も必ず1になります。そのため15bit目を無視して14bitのデータで算出をしようとするもので、この場合14+1=15bit目だけ1の32768を引けば先の計算と同じように2の補数、マイナスの絶対値が出せるというものです。データシートにはありませんがたぶん14bit目も負の場合1固定なので15,14bit目を無視して16384を引くのでも算出できるのではないかと思います。

データシートP12抜粋
image.png

ロジアナ解析

19.36719.JPG

説明

順に説明していきます。

  1. SCLがHIGHの時にSDAがLOWになるとスタートです。
  2. write_byte_dataメソッドで0x03Configレジスタに0x80を書き込んで16bitモードに設定変更しています。i2cは基本的に8bitデータをマスタあるいはスレーブから送信して、受信側デバイスがAck(Acknowledge)を出す、イコールLowにSDAを落とす事で一区切りとする仕様です。
  3. SDAがLOWの時にSCLがHIGHになり、次にSDAがHIGHになるとストップです。通常はSCLがLOWの時のみSDAが変化し、スタート/ストップの特殊な時のみSCLがHIGHの時にSDAが変化する事で区別しています。
  4. 二つ目のスタートはread_word_dataメソッドで、まずはAD変換された温度データが格納されている0x00(MSB)、0x01(LSB)レジスタからデータを読み取っています。対象アドレスは0x00を指定するだけで、wordなので自動インクリメントして16bit分のデータを読み取ってくれます。
  5. このケースの場合、MSB 0x09、LSB 0xAFなので0000 1001 1010 1111 → 2479(10進)、2479*0.0078125≒19.36℃となります。デフォルトの13bitモードでは[LSB 2:0]は閾値Thigh、Tlow、Tcritを超えた場合のみ1がセットされるので0になっているはずですが16bitモードにしているのでAD変換値に利用されているのが分かりますね。

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
0