.
EVAL-ADT7420-PMDZ is a simple temperature measurement board around ADT7420 sensor. Pull-ups are 10K. The board is described at
. It works well with Arduino Uno (EVAL-ADT7420-PMDZ powered from 3.3 volts coming from Uno), but I can't read even the chip ID register using Moteino M0 as host - available bytes count is zero on the read attempt. The power LED on EVAL-ADT7420-PMDZ is steady on, indicating that the power should be OK. Moteino M0 is powered via USB. ADT7420 draws 265 µA max if powered from 3.3 volts
, also 10K pull-ups) works on both Arduino Uno and Moteino M0.
ADT7420 control code I use (it is based on Analog Devices definitions and code here
#include <Wire.h>
#define ADT7420_I2C_ADDRESS 0x48
#define ADT7420_CHIP_ID 0xCB
#define ADT7420_TEMP_IS_NEG_MASK 0x8000
/* ADT7420 register addresses */
#define ADT7420_TEMP_MSB_REG 0x00
#define ADT7420_TEMP_LSB_REG 0x01
#define ADT7420_STATUS_REG 0x02
#define ADT7420_CONFIG_REG 0x03
#define ADT7420_T_HIGH_SETPOINT_MSB_REG 0x04
#define ADT7420_T_HIGH_SETPOINT_LSB_REG 0x05
#define ADT7420_T_LOW_SETPOINT_MSB_REG 0x06
#define ADT7420_T_LOW_SETPOINT_LSB_REG 0x07
#define ADT7420_T_CRIT_SETPOINT_MSB_REG 0x08
#define ADT7420_T_CRIT_SETPOINT_LSB_REG 0x09
#define ADT7420_T_HYST_SETPOINT_REG 0x0A
#define ADT7420_ID_REG 0x0B
#define ADT7420_SOFTWARE_RESET 0x2F
/* ADT7420 status bits */
#define ADT7420_DATA_NOT_READY 0x80
/* ADT7420 configuration bits */
#define ADT7420_CONTINUOUS_CONVERSION_MODE 0x00
#define ADT7420_ONE_SHOT_MODE 0x20
#define ADT7420_ONE_SAMPLE_PER_SECOND_MODE 0x40
#define ADT7420_SHUTDOWN_MODE 0x60
#define ADT7420_RESOLUTION_13_BITS 0x00
#define ADT7420_RESOLUTION_16_BITS 0x80
static const struct {
uint8_t RegAddr;
char RegName[32];
} ADT7420_RegAddr2RegName_table[] = {
{ ADT7420_TEMP_MSB_REG, "ADT7420_TEMP_MSB_REG" },
{ ADT7420_TEMP_LSB_REG, "ADT7420_TEMP_LSB_REG" },
{ ADT7420_STATUS_REG, "ADT7420_STATUS_REG" },
{ ADT7420_CONFIG_REG, "ADT7420_CONFIG_REG" },
{ ADT7420_T_HIGH_SETPOINT_MSB_REG, "ADT7420_T_HIGH_SETPOINT_MSB_REG" },
{ ADT7420_T_HIGH_SETPOINT_LSB_REG, "ADT7420_T_HIGH_SETPOINT_LSB_REG" },
{ ADT7420_T_LOW_SETPOINT_MSB_REG, "ADT7420_T_LOW_SETPOINT_MSB_REG" },
{ ADT7420_T_LOW_SETPOINT_LSB_REG, "ADT7420_T_LOW_SETPOINT_LSB_REG" },
{ ADT7420_T_CRIT_SETPOINT_MSB_REG, "ADT7420_T_CRIT_SETPOINT_MSB_REG" },
{ ADT7420_T_CRIT_SETPOINT_LSB_REG, "ADT7420_T_CRIT_SETPOINT_LSB_REG" },
{ ADT7420_T_HYST_SETPOINT_REG, "ADT7420_T_HYST_SETPOINT_REG" },
{ ADT7420_ID_REG, "ADT7420_ID_REG" },
{ ADT7420_SOFTWARE_RESET, "ADT7420_SOFTWARE_RESET" },
};
int nADT7420_Regs = sizeof ADT7420_RegAddr2RegName_table / sizeof *ADT7420_RegAddr2RegName_table;
typedef enum {
ADT7420_NO_ERR,
ADT7420_CHIP_ID_ERR,
ADT7420_CONFIG_REG_ERR
} enErrNums;
typedef enum {
I2C_BYTE = 1,
I2C_WORD
} enNumBytes;
#define SERIAL_BAUD 115200
#if defined (MOTEINO_M0)
#if defined(SERIAL_PORT_USBVIRTUAL)
#define Serial SERIAL_PORT_USBVIRTUAL // Required for Serial on Zero based boards
#endif
#endif
unsigned long delayTime = 3000;
unsigned long ADT7420_min_relaxationTime = 240 + 20; // minimum of 240 ms for 1-shot mode
unsigned long ADT7420_timeout = 1000 - ADT7420_min_relaxationTime;
enErrNums err;
uint8_t avail_bytes, idReg, statusReg, configReg, otherReg;
uint16_t measurementWord;
float temperature;
uint8_t configADT7420 = ADT7420_RESOLUTION_16_BITS | ADT7420_ONE_SHOT_MODE;
void setup() {
Serial.begin(SERIAL_BAUD);
Serial.println("ADT7420 on Moteino M0 study");
Wire.begin();
Wire.setClock(400000);
// check ADT7420 chip ID
avail_bytes = ADT7420_readByte ((uint8_t)ADT7420_I2C_ADDRESS,
(uint8_t)ADT7420_ID_REG,
idReg,
"in setup");
// program configuration into ADT7420
I2Cdev_sendByte ((uint8_t)ADT7420_I2C_ADDRESS,
(uint8_t)ADT7420_CONFIG_REG,
configADT7420);
// read ADT7420 configuration back
avail_bytes = ADT7420_readByte ((uint8_t)ADT7420_I2C_ADDRESS,
(uint8_t)ADT7420_CONFIG_REG,
configReg,
"in setup");
}
void loop() {
unsigned long ADT7420_extra_relaxationTime = 0;
unsigned long ADT7420_addTime = 10;
// check ADT7420 chip ID
avail_bytes = ADT7420_readByte ((uint8_t)ADT7420_I2C_ADDRESS,
(uint8_t)ADT7420_ID_REG,
idReg,
"loop head");
// program configuration into ADT7420
I2Cdev_sendByte ((uint8_t)ADT7420_I2C_ADDRESS,
(uint8_t)ADT7420_CONFIG_REG,
configADT7420);
// read ADT7420 configuration back
avail_bytes = ADT7420_readByte ((uint8_t)ADT7420_I2C_ADDRESS,
(uint8_t)ADT7420_CONFIG_REG,
configReg,
"before measurement read");
delay(ADT7420_min_relaxationTime);
avail_bytes = I2Cdev_readByte ((uint8_t)ADT7420_I2C_ADDRESS,
(uint8_t)ADT7420_STATUS_REG,
statusReg);
while ((statusReg & (uint8_t)ADT7420_DATA_NOT_READY) == (uint8_t)ADT7420_DATA_NOT_READY) {
delay(ADT7420_addTime);
ADT7420_extra_relaxationTime += ADT7420_addTime;
if (ADT7420_extra_relaxationTime > ADT7420_timeout) {
Serial.println("ADT7420 timeout error");
return;
}
avail_bytes = I2Cdev_readByte ((uint8_t)ADT7420_I2C_ADDRESS,
(uint8_t)ADT7420_STATUS_REG,
statusReg);
}
// read ADT7420 status
avail_bytes = ADT7420_readByte ((uint8_t)ADT7420_I2C_ADDRESS,
(uint8_t)ADT7420_STATUS_REG,
statusReg,
"after dwell");
avail_bytes = I2Cdev_readWord ((uint8_t)ADT7420_I2C_ADDRESS,
(uint8_t)ADT7420_TEMP_MSB_REG,
measurementWord);
// read ADT7420 configuration after the measurement, for 1-shot mode IC should be sleeping
avail_bytes = ADT7420_readByte ((uint8_t)ADT7420_I2C_ADDRESS,
(uint8_t)ADT7420_CONFIG_REG,
configReg,
"after measurement read");
temperature = ADT7420_Hex_To_Celsius (measurementWord);
Serial.print ("got measurement word, available bytes: ");
Serial.print (avail_bytes);
Serial.print (", reg content: 0x");
Serial.print (measurementWord, HEX);
Serial.print (", temperature: ");
Serial.print (temperature);
Serial.println ("°C");
if (ADT7420_extra_relaxationTime) {
Serial.print ("Extra relaxation time:");
Serial.println (ADT7420_extra_relaxationTime);
}
delay(delayTime-ADT7420_min_relaxationTime-ADT7420_extra_relaxationTime);
}
void I2Cdev_sendByte (uint8_t I2C_addr, uint8_t reg_addr, uint8_t val) {
Wire.beginTransmission(I2C_addr);
Wire.write(reg_addr);
Wire.write(val);
Wire.endTransmission();
}
int I2Cdev_readByte (uint8_t I2C_addr, uint8_t reg_addr, uint8_t &val) {
int avail;
Wire.beginTransmission(I2C_addr);
Wire.write(reg_addr);
Wire.endTransmission(false);
Wire.requestFrom(I2C_addr, (uint8_t)I2C_BYTE); // requesting 1 byte
avail = Wire.available();
val = Wire.read();
return avail;
}
int I2Cdev_readWord (uint8_t I2C_addr, uint8_t reg_addr, uint16_t &val) {
int avail;
Wire.beginTransmission(I2C_addr);
Wire.write(reg_addr);
Wire.endTransmission(false);
Wire.requestFrom(I2C_addr, (uint8_t)I2C_WORD); // requesting 2 bytes
avail = Wire.available();
val = Wire.read();
val <<= 8;
val |= Wire.read();
return avail;
}
float ADT7420_Hex_To_Celsius (uint16_t hex_val) {
// Check the status of the temperature sign bit (MSB)
if ((hex_val & (uint16_t)ADT7420_TEMP_IS_NEG_MASK) ==
(uint16_t)ADT7420_TEMP_IS_NEG_MASK) {
/* If sign bit is 1 use the negative temperature equations */
if ((configADT7420 & (uint8_t)ADT7420_RESOLUTION_16_BITS) ==
(uint8_t)ADT7420_RESOLUTION_16_BITS) {
return ((float)(hex_val - 65536))/128; /* 16-bit temperature word data */
} else {
return ((float)((hex_val >> 3) - 8192))/16; /* 13-bit temperature word data */
}
} else {
/* If sign bit is 0, use the positive temperature equations */
if ((configADT7420 & (uint8_t)ADT7420_RESOLUTION_16_BITS) ==
(uint8_t)ADT7420_RESOLUTION_16_BITS) {
return (float)hex_val/128; /* 16-bit temperature word data */
} else {
return ((float)(hex_val >> 3))/16; /* 13-bit temperature word data */
}
}
}
int ADT7420_readByte (uint8_t I2C_addr, uint8_t reg_addr, uint8_t &val, char *msg) {
int avail = I2Cdev_readByte (I2C_addr, reg_addr, val);
if (strlen(msg)) {
char reg_name[32];
for (int i = 0; i < nADT7420_Regs; i++) {
if ((uint8_t)ADT7420_RegAddr2RegName_table[i].RegAddr == reg_addr) {
strcpy (reg_name, ADT7420_RegAddr2RegName_table[i].RegName);
break;
}
}
Serial.print("ADT7420 device at I2C addr. 0x");
Serial.print(I2C_addr, HEX);
Serial.print(", reading ");
Serial.print(reg_name);
Serial.print(" ");
Serial.print(msg);
Serial.print(", available bytes: ");
Serial.print(avail);
Serial.print(", reg content: 0x");
Serial.println(val, HEX);
}
return avail;
}