ADT7410 I2C温度センサー

投稿日 2013/07/02

アナログデバイセズ社の高精度・高分解能温度センサー ADT7410を使用してみました。

 

ADT7410はDIPモジュールに乗せて秋月電子で販売されています。

 

インターフェースはI2Cですので、温度表示用キャラクタLCDもI2CのAQM0802Aを使用しました。

 

電源は3.3Vで統一できます。

ADT7410_1.jpg

高温、低温時のロジック出力 INTとCT端子は未接続になっているので使えませんが、ソフト的に処理することは可能なようです。

 

今回は細かい設定は一切行わず、シンプルに温度データを読んで表示するだけとしました。

 

マイコンは、マイクロチップ社のアンドロイドADKデモボード DM240415を使用しましたので、CPUはPIC24FJ256GB110です。もちろんI2CをサポートしているPICであれば何でも使えるはずです。

 

I2Cの信号 SCLとSDAのプルアップは5.6KΩを使用し、CPUのSCL1, SDA1につなぎました。電源とGND以外はたった2本です。回路は秋月の資料等を見てください。

 

一秒間隔でサンプリングし、LED1を点滅させています。

ADT7410_2.jpg

ADT7410モジュール(右)と8x2 LCD AQM0802A

 

ADT7410の制御はデータシートに従いますが、2つのTemperature Value Registor(レジスタアドレス0X00と0X01)を連続で読みたかったのですが、タイミング的なものかうまく読み取れないので、それぞれ別々に読んでいます。

 

0X00がMSB、0X01がLSB側で、13bitです。

 

特に直線補正が不要とのことなので、データシートにある演算式で温度に変換しています。

 

0度が0で、負の温度は正の2の補数ですので、MSBの符号を見て負ならビット反転させ+1します。

 

13ビットで分解能が0.0625度ですので、16で割ると温度になります。

 

例えば,
25度は、 0000110010000b = 400 16で割る -> 25度
-25度は、1111001110000b = -400 反転して+1して16で割る -25度 (-符号はMSBビットを見て判断)

 

1ビット当たり0.0625度の精度なので、小数2桁で四捨五入し、小数1桁まで表示します。

 

ソースコード(Delay_us, Delay_ms, LCDの制御部は省略)
文字数制限でコメントを入れられません。 
浮動小数点数の文字変換は「電子工作の実験室」を参考にさせていただいてます。

 

関連記事: オンボード I2C 8x2 キャラクタLCD AQM0802A

 

main.c
#include <p24fj256gb110.h>

 

_CONFIG2(FNOSC_PRIPLL & POSCMOD_HS & PLL_96MHZ_ON & PLLDIV_DIV2)
_CONFIG1(JTAGEN_OFF & FWDTEN_OFF & ICS_PGx2)

 

#define LED1 LATEbits.LATE0

 

unsigned char return_flg;
unsigned char high_byte;
unsigned char low_byte;
int temp_value;
float temp;
char string[10];

 

int main(void){

AD1PCFGL = 0xFFFF;
AD1PCFGH = 0xFFFF;


PMD1 = 0xFFFF;
PMD2 = 0xFFFF;
PMD3 = 0xFFFF;
PMD4 = 0xFFFF;
PMD5 = 0xFFFF;
PMD6 = 0xFFFF;

_I2C1MD = 0; //I2C1 on
_T1MD = 0; //Timer1 on

LATA = 0;
LATB = 0;
LATC = 0;
LATD = 0;
LATE = 0;

TRISA = 0;
TRISB = 0;
TRISC = 0;
TRISD = 0;
TRISE = 0;

I2C1BRG = 157; //100KHz I2C
I2C1CON = 0x8000; //enable I2C1

lcd_init();
lcd_write(0, 0, "Temp. " );
lcd_write(0, 1, " XXX.XC" );

while(1){
Delay_ms(950);
LED1 = 1;
Delay_ms(50);
LED1 = 0;

if((ADT7410_Get_regvalue(0x02) & 0x80) == 0){
high_byte = ADT7410_Get_regvalue(0x00);
low_byte = ADT7410_Get_regvalue(0x01);

if(high_byte & 0x80){

high_byte = ~high_byte + 1;
lcd_write(1, 1, "-" );

} else {

lcd_write(1, 1, " " );

}

temp_value = (high_byte << 5) | (low_byte >> 3);
temp = (float)temp_value / 16.0;
ftostring(3, 1, temp, string);
lcd_write(2, 1, string);
}
}
}

 

I2C_ADT7401.c
#include <p24fj256gb110.h>

 

#define ADT7410_I2C_ADDR 0x90 //0x48 << 1
#define WRITE_MODE 0x00
#define READ_MODE 0x01

 

extern Delay_us(int);
extern Delay_ms(int);
extern unsigned char return_flg;

 

void ADT7410_Put_regvalue(unsigned char reg_address, unsigned char data);
unsigned char ADT7410_Get_regvalue(unsigned char reg_address);

 

void ADT7410_Put_regvalue(unsigned char reg_address, unsigned char byte){
return_flg = 0;
I2C1CONbits.SEN = 1;
while(I2C1CONbits.SEN == 1);

I2C1TRN = ADT7410_I2C_ADDR | WRITE_MODE;
while(I2C1STATbits.TRSTAT);
if (I2C1STATbits.ACKSTAT){

I2C1CONbits.PEN = 1;
while(I2C1CONbits.PEN);
return_flg = 1;
return;

}

I2C1TRN = reg_address;
while(I2C1STATbits.TRSTAT);
if (I2C1STATbits.ACKSTAT){

I2C1CONbits.PEN = 1;
while(I2C1CONbits.PEN);
return_flg = 1;
return;

}

I2C1TRN = byte;
while(I2C1STATbits.TRSTAT);
if(I2C1STATbits.ACKSTAT){

I2C1CONbits.PEN = 1;
while(I2C1CONbits.PEN);
return_flg = 1;
return;

}
 

I2C1CONbits.PEN = 1;
while(I2C1CONbits.PEN);
return;

}

 

unsigned char ADT7410_Get_regvalue(unsigned char reg_address) {
unsigned char reg_value;

return_flg = 0;
I2C1CONbits.SEN = 1;
while(I2C1CONbits.SEN == 1);
I2C1TRN = ADT7410_I2C_ADDR | WRITE_MODE;
while(I2C1STATbits.TRSTAT);
if (I2C1STATbits.ACKSTAT){

I2C1CONbits.PEN = 1;
while(I2C1CONbits.PEN);
return_flg = 1;
return(0);

}

Delay_us(10);
I2C1TRN = reg_address;
while(I2C1STATbits.TRSTAT);
if (I2C1STATbits.ACKSTAT){

I2C1CONbits.PEN = 1;
while(I2C1CONbits.PEN);
return_flg = 1;
return(0);

}

Delay_us(10);
I2C1CONbits.RSEN = 1;
while(I2C1CONbits.RSEN);

I2C1TRN = ADT7410_I2C_ADDR | READ_MODE;
while(I2C1STATbits.TRSTAT);
if (I2C1STATbits.ACKSTAT){

I2C1CONbits.PEN = 1;
while(I2C1CONbits.PEN);
return_flg = 1;
return(0);

}

Delay_us(10);
I2C1CONbits.RCEN = 1;
while(I2C1CONbits.RCEN);
reg_value = I2C1RCV;
while(I2C1STATbits.RBF);
I2C1CONbits.ACKDT = 1;

Delay_us(10);
I2C1CONbits.PEN = 1;
while(I2C1CONbits.PEN);
return(reg_value);
}



 

(JF1VRR)