
投稿日 2013/07/02
アナログデバイセズ社の高精度・高分解能温度センサー ADT7410を使用してみました。
ADT7410はDIPモジュールに乗せて秋月電子で販売されています。
インターフェースはI2Cですので、温度表示用キャラクタLCDもI2CのAQM0802Aを使用しました。
電源は3.3Vで統一できます。

高温、低温時のロジック出力 INTとCT端子は未接続になっているので使えませんが、ソフト的に処理することは可能なようです。
今回は細かい設定は一切行わず、シンプルに温度データを読んで表示するだけとしました。
マイコンは、マイクロチップ社のアンドロイドADKデモボード DM240415を使用しましたので、CPUはPIC24FJ256GB110です。もちろんI2CをサポートしているPICであれば何でも使えるはずです。
I2Cの信号 SCLとSDAのプルアップは5.6KΩを使用し、CPUのSCL1, SDA1につなぎました。電源とGND以外はたった2本です。回路は秋月の資料等を見てください。
一秒間隔でサンプリングし、LED1を点滅させています。

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)