LoginSignup
0
0

More than 3 years have passed since last update.

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

Posted at

概要

  • 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変換値に利用されているのが分かりますね。

参考

0
0
1

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
  3. You can use dark theme
What you can do with signing up
0
0