Go Down

Topic: Temperature sensor read-write from register (Read 375 times) previous topic - next topic

nilonha

I'm trying to change a configuration register in a temperature sensor IC, ADT7410,  with the following register mapping from spec sheet:


If image doesn't show above (preview doesn't show it), link to image is below:
https://drive.google.com/file/d/1hJhPXU8bWZnwrdln6k-D4CkVwnoiLQB2/view?usp=sharing

So I want to write a hex value 0x80 to register 0x03. I2C slave address is 0x48.
Note that I have used a library for this device and it is working fine, I can get temperature readings.

Here's my code:

Code: [Select]
#include <Wire.h>
byte a ;

void setup() {
 
Wire.begin();

//writing step
Wire.beginTransmission(0x48);//Slave I2C address
Wire.write(0x03);//position pointer to config reg address
Wire.write(0x80);//write config reg with 16bit mode
Wire.endTransmission();

//reading back step
Wire.beginTransmission(0x48);//Slave I2C address
Wire.write(0x03);//position pointer to config reg address
Wire.requestFrom(0x48, 1);//request 1 byte of data from slave
byte a = Wire.read();//assign value to a
Wire.endTransmission();

Serial.begin(9600);


}

void loop() {
Serial.print("Config=");
Serial.println(a,HEX);
delay(1000);

}




Here's what I get, printed to serial monitor:
Config=0
Config=0
Config=0
Config=0
.
.
.
.


On a second issue, if I move the Serial.print statement from the void loop() part into the setup, it just doesn't work. Is this a known issue with wire and Serial working together, yes?

So questions I have;
1)What am I doing wrong on the register write-read?
2)How to I deal with the Serial.print x wire issue?

Thanks,

Nilo

UKHeliBob

Global
Code: [Select]
byte a ;

In setup()
Code: [Select]
 byte a = Wire.read();//assign value to a
You have two different variables named a.  One global and one local to the setup() function

Then in loop()
Code: [Select]
 Serial.println(a, HEX);
Which one is being printed, do you think ?
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

GolamMostafa

#2
Dec 09, 2018, 08:56 pm Last Edit: Dec 09, 2018, 08:57 pm by GolamMostafa
Try  the following version of your program:

Code: [Select]
#include <Wire.h>
byte a ;

void setup()
{
   Serial.begin(9600);  
   Wire.begin();

   //writing step
   Wire.beginTransmission(0x48);//Slave I2C address
   Wire.write(0x03);//position pointer to config reg address
   Wire.write(0x80);//write config reg with 16bit mode
   Wire.endTransmission();

   //reading back step
   Wire.beginTransmission(0x48);//Slave I2C address
   Wire.write(0x03);//position pointer to config reg address
   Wire.endTransmission();

   Wire.requestFrom(0x48, 1);//request 1 byte of data from slave
   a = Wire.read();//assign value to a
   //Wire.endTransmission();

   Serial.print("Config=");
   Serial.println(a, HEX);  
}

void loop()
{

//delay(1000);

}

nilonha

Golam, your code brings the issue of question 2. no printout to serial monitor.

I changed the code:
Code: [Select]
byte a = Wire.read();//assign value to a

to:
Code: [Select]
a = Wire.read();//assign value to a

Serial monitor output is Config=C
It should be Config=80, yes?

GolamMostafa

#4
Dec 09, 2018, 09:40 pm Last Edit: Dec 09, 2018, 09:51 pm by GolamMostafa
If you are using UNO, then check that you have 2x10k pull-up connected to I2C Bus lines and A0/A1 pins of ADT7410 are shorted to GND. Re-run the following following program which includes few more lines to check that I2C bus transaction is OK.
Code: [Select]
#include <Wire.h>
byte a ;

void setup()
{
   Serial.begin(9600);  
   Wire.begin();

   //writing step
   Wire.beginTransmission(0x48);//Slave I2C address
   Wire.write(0x03);//position pointer to config reg address
   Wire.write(0x80);//write config reg with 16bit mode
   byte busStatus = Wire.endTransmission();
   if (busStatus != 0x00)
   {
      Serial.println("I2C Transaction has failed...!");
      while(1);
    }

   //reading back step
   Wire.beginTransmission(0x48);//Slave I2C address
   Wire.write(0x03);//position pointer to config reg address
   Wire.endTransmission();

   Wire.requestFrom(0x48, 1);//request 1 byte of data from slave
   a = Wire.read();//assign value to a
   //Wire.endTransmission();

   Serial.print("Config=");
   Serial.println(a, HEX);  
}

void loop()
{

//delay(1000);

}


BTW:  
(1)  Before we were reading 0x00; now, you are reading 0x0C. Is it genuine or noise? Configuration bit has not changed; but, some other bits have changed which you have not requested.

(2)  If the above codes do still fail, try to read the ID of the sensor; you should get a value: 0xC0 - 0xCF as per data sheet. Just change the address value from 0x03 (Config Reg) to 0x0B (ID Reg) and comment out un-needed lines.

nilonha

With the above code
If you are using UNO, then check that you have 2x10k pull-up connected to I2C Bus lines and A0/A1 pins of ADT7410 are shorted to GND. Re-run the following following program which includes few more lines to check that I2C bus transaction is OK.
Code: [Select]
#include <Wire.h>
byte a ;

void setup()
{
   Serial.begin(9600); 
   Wire.begin();

   //writing step
   Wire.beginTransmission(0x48);//Slave I2C address
   Wire.write(0x03);//position pointer to config reg address
   Wire.write(0x80);//write config reg with 16bit mode
   byte busStatus = Wire.endTransmission();
   if (busStatus != 0x00)
   {
      Serial.println("I2C Transaction has failed...!");
      while(1);
    }

   //reading back step
   Wire.beginTransmission(0x48);//Slave I2C address
   Wire.write(0x03);//position pointer to config reg address
   Wire.endTransmission();

   Wire.requestFrom(0x48, 1);//request 1 byte of data from slave
   a = Wire.read();//assign value to a
   //Wire.endTransmission();

   Serial.print("Config=");
   Serial.println(a, HEX); 
}

void loop()
{

//delay(1000);

}


BTW: 
(1)  Before we were reading 0x00; now, you are reading 0x0C. Is it genuine or noise? Configuration bit has not changed; but, some other bits have changed which you have not requested.

(2)  If the above codes do still fail, try to read the ID of the sensor; you should get a value: 0xC0 - 0xCF as per data sheet. Just change the address value from 0x03 (Config Reg) to 0x0B (ID Reg) and comment out un-needed lines.

I'm using an arduino Micro with 10K pull-up resistors. I2C is working since temperature can be read and vary with external heating when I use a library found online.

Using the code above return no printout to serial monitor, nothing. Modifying it to the code below returns the following:

New code:

Code: [Select]
#include <Wire.h>
byte a ;
byte busStatus;
void setup()
{
   
   Wire.begin();

   //writing step
   Wire.beginTransmission(0x48);//Slave I2C address
   Wire.write(0x03);//position pointer to config reg address
   Wire.write(0x80);//write config reg with 16bit mode
   busStatus = Wire.endTransmission();
 

   //reading back step
   Wire.beginTransmission(0x48);//Slave I2C address
   Wire.write(0x03);//position pointer to config reg address
   Wire.endTransmission();

   Wire.requestFrom(0x48, 1);//request 1 byte of data from slave
   a = Wire.read();//assign value to a
   //Wire.endTransmission();

 
}

void loop()
{
if (busStatus != 0x00)
   {
      Serial.println("I2C Transaction has failed...!");
      while(1);
    }
    else
    {
      Serial.println("I2C Transaction OK...!");
    }
       Serial.print("Config=");
   Serial.println(a, HEX);
delay(1000);

}


New printout:
I2C Transaction OK...!
Config=C

As per your suggestion, reading the IC ID from 0x0B returns D, which is obviously not correct (outside range 0xC0 to 0cCF).


I have other IC's and after replacement, reg 0x03 now returns D. Changed reg address to 0x0b, 0x00 or 0x01 (adc address) and still returns D.
So there is definitely something fishy here, just not making sense. Monitored power lines and I2C bus with oscilloscope and no signs of noise.

cattledog

Quote
Note that I have used a library for this device and it is working fine, I can get temperature readings.
Can you please provide a link to the library you are using successfully?


GolamMostafa

#8
Dec 10, 2018, 05:31 am Last Edit: Dec 10, 2018, 07:32 am by GolamMostafa
Let us avoid the use of Library Functions and try to read the Temperature Registers directly from the sensor; compute the temperature value and show it on Serial Monitor. This will help us to understand the reasons of being denied to access the Configuration and ID Registers.
Code: [Select]
#include <Wire.h>
float tempC;
int x = 0, y = 0;

void setup()
{
   Serial.begin(9600);  
   Wire.begin();
}

void loop()
{

   Wire.beginTransmission(0x48);//Slave I2C address
   Wire.write(0x00);//position pointer to Temp Reg. Address
   Wire.endTransmission();

   Wire.requestFrom(0x48, 2);//request 2 byte of data from slave
   x = Wire.read();    //Temp value of MSByte ; test value = 0x0C for 25 degC
   y = Wire.read();    //Temp value of LSByte ; test value = 0x80 for 25 degc

   y = y>>3;    //see data sheets      
   for (int i= 0, j=5; i<7, j<12; i++, j++)  //test value : xy (0x0C80) ----> 0x0190*0.0625 = 25 degC
   {
    bitWrite(y, j, bitRead(x, i));
   }
   //Serial.println(y, HEX);    //test value = 0x0190
   tempC = (float)y*0.0625;     //test value = 25.00 degC sign-bit + 12-bit temp = 13-bit resolution
   Serial.println(tempC, 2);
  
   delay(1000);
}


BTW:  Rub the sensor by fingers and check that the Serial Monitor shows changing temperature. Please, report the result.

nilonha

Tested and it did report temperature. Blowing on sensor increases reading, but reading seems to be few degrees off and doesn't rise as quickly as it did with the library.

GolamMostafa

#10
Dec 10, 2018, 06:37 am Last Edit: Dec 10, 2018, 01:13 pm by GolamMostafa
OK! This is a good news that we can access the registers of the sensor. Now, we have to search for the way of changing the resolution to 16-bit by writing 0x80 into the Configuration Register. Notice that there is a 1-sec delay in my test program.

Thanks for the good efforts! K+.

BTW:  If you become successful in the journey of accessing the Configuration and ID Registers, please let us know what you have done.

nilonha

I have seen some indication of issues with I2C rise time requirements for this IC and will be investigating on that direction now. Specs say rise time < 0.3us and I2C bus freq < 400Khz. AtMega328 is max 400Khz I2C, so it should not be an issue, but who knows!

GolamMostafa

#12
Dec 10, 2018, 06:41 pm Last Edit: Dec 10, 2018, 06:42 pm by GolamMostafa
I have seen some indication of issues with I2C rise time requirements for this IC and will be investigating on that direction now. Specs say rise time < 0.3us and I2C bus freq < 400Khz. AtMega328 is max 400Khz I2C, so it should not be an issue, but who knows!
It could be an issue. You reported that the temperature reading was few degrees off, and you also received wrong values from the Config, and ID Registers. Try with Arduino UNO. The default speed of UNO is 100 kHz. Until you become successful in the acquisition of correct ID and Config. values from the sensor, you should not use this sensor for temperate measurement in your intended project; because, there is something that is not really right!  

nilonha

#13
Dec 11, 2018, 04:56 pm Last Edit: Dec 11, 2018, 04:59 pm by nilonha
Feedback on I2C bus speed investigation.
Thought I had this taken care of, I really did, but ..
In summary, I2C bus from arduino was crap, huge rising time with high state not even reaching 5V.
I tested both default 400Khz and 100Khz, both garbage. Used Wire.setClock() for selecting the frequency.
I was using 10K resistors for the pull-up. After changing it to 1K, things became much better with reasonable time rise and 5V high state.
But all this didn't do a dent on fixing the issue  :smiley-confuse:
Note that the above was observed on I2C bus with arduino stand alone, not connected to ADT7410. Just the external pull-up resistors. That indicates that arduino board is to blame for the crappy wave forms, somehow having a high internal capacitance that is affecting the switching response.
After further testing with other arduino boards (nano and micro) without success, noticed that reading of reg 0x03 (supposedly reg 0x03) was changing with temperature :smiley-mad: . So all this time, I have been reading reg 0x00, which is the MSB for the internal ADC on the 7410.
Conclusion so far is that the write commands are not working, 7410 points to reg 0x00 by default at start-up and that is what has been read so far. Reading command is of course working.
Saga continues...


GolamMostafa

Do you have any other sensor like BME280 or DS1307/DS3231 RTC Modules? Please, operate these devices before blaming the Arduino. I have started believing that the ADT7410 sensors that you own could be belonging to a 'defective batch'.

Go Up