View previous topic :: View next topic |
Author |
Message |
ihsan
Joined: 30 Nov 2023 Posts: 9
|
SHT45 and HDC3022 |
Posted: Mon Jan 08, 2024 2:36 am |
|
|
hello dear friends,
I want to measure temperature and humidity for a project. So I use 2 different sensor are sht45 and hdc3022. There are calculating temperature method and calculating humidity method to datasheet for both. sht45 temperature float result and hdc3022 temperature float result are same but sht45 humidity float result and hdc3022 humidity float result are different.
sht45 humidity raw result and hdc3022 humidity raw result are same. I can not decide to use which calculating method. I need help. Can you help me
Code: |
#include <main.h>
#define HDT3022_BASE_ADDR 0x8C
#define SHT45_BASE_ADDR 0x88
unsigned int8 CRC_calc(unsigned int8 msg[], int len);
void main()
{
float temperature, humidity, temperature_sht, humidity_sht, temp_average, rh_average;
int16 temperature_raw, humidity_raw, temperature_raw_sht, humidity_raw_sht;
int8 CRC1, CRC2;
unsigned int8 msg_t[3], msg_h[3], data[6];
while(TRUE)
{
i2c_start();
i2c_write(HDT3022_BASE_ADDR);
i2c_write(0x24);
i2c_write(0x00);
i2c_stop();
delay_ms(1055);
i2c_start();
i2c_write(HDT3022_BASE_ADDR | 0x01);
msg_t[0] = i2c_read(); //MSB
msg_t[1] = i2c_read(); //LSB
msg_t[2] = i2c_read();
CRC1 = CRC_calc(msg_t, 3);
temperature_raw = make16(msg_t[0], msg_t[1]);
msg_h[0] = i2c_read(); //MSB
msg_h[1] = i2c_read(); //LSB
msg_h[2] = i2c_read();
CRC2 = CRC_calc(msg_h, 3);
humidity_raw = make16(msg_h[0], msg_h[1]);
i2c_stop();
temperature = -45 + (175* (temperature_raw / 65535.0));
humidity = 100 * (humidity_raw / 65535.0);
delay_ms(500);
i2c_start();
i2c_write(SHT45_BASE_ADDR);
i2c_write(0xFD);
i2c_stop();
delay_ms(105);
i2c_start();
i2c_write(SHT45_BASE_ADDR | 0x01);
for(int i = 0; i< 6; i++)
{
data[i] = i2c_read();
}
i2c_stop();
temperature_raw_sht = make16(data[0], data[1]);
humidity_raw_sht = make16(data[3], data[4]);
temperature_sht = -45 + (175* (temperature_raw / 65535.0));
humidity_sht = -6 + 125 * (humidity_raw / 65535.0);
temp_average = (temperature + temperature_sht) / 2;
rh_average = (humidity + humidity_sht) / 2;
}
}
unsigned int8 CRC_calc(unsigned int8 msg[], int len)
{
unsigned int8 t_crc = 0xFF;
for(int i = 0; i < len; i++)
{
t_crc ^= msg[i];
for (int j = 0; j < 8; j++)
{
if (t_crc & 0x80)
t_crc = (t_crc << 1) ^ 0x31;
else
t_crc = (t_crc << 1);
}
}
return t_crc;
}
|
|
|
|
ihsan
Joined: 30 Nov 2023 Posts: 9
|
|
Posted: Mon Jan 08, 2024 2:46 am |
|
|
sht45 temperature calculating = -45 + (175* (temperature_raw / 65535.0))
sht45 humidity calculating = -6 + 125 * (humidity_raw / 65535.0)
hdc3022 temperature calculating = -45 + (175* (temperature_raw / 65535.0))
hdc3022 humidity calculating = 100 * (humidity_raw / 65535.0)
formulas in datasheet |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Mon Jan 08, 2024 6:25 am |
|
|
You must use whatever the manufacturer supplies in the datasheet for their sensor.
You cannot use SHT45 equation for the HDC3022 or the HDC3022 equation for the SHT45 sensor. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Mon Jan 08, 2024 7:49 am |
|
|
I'm unbelievably surprised that the two sensors are returning the same raw
value. Tends to imply something is very wrong. They are different internally
and even two identical sensors will return values that differ a little.
As Jay says, you need to use the right formula for each. |
|
|
ihsan
Joined: 30 Nov 2023 Posts: 9
|
|
Posted: Tue Jan 09, 2024 12:59 am |
|
|
Thanks your response temtronic and Ttelmah. I checked my code and there are two mistakes in my code. I defined temperature_raw_sht variable and humidity_raw_sht variable but I used temperature_raw and humidity_raw for both.
I have new problem now. If I want to read one of both, I can read datas but If I want to read both I can read hdc3022 datas but I can not read sht45 datas. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Tue Jan 09, 2024 1:58 am |
|
|
There is a common issue with the SHT45 code. You must _NACK_ the
last read.
So:
Code: |
i2c_start();
i2c_write(SHT45_BASE_ADDR);
i2c_write(0xFD);
i2c_stop();
delay_ms(105);
i2c_start();
i2c_write(SHT45_BASE_ADDR | 0x01);
for(int i = 0; i< 6; i++)
{
if (i==5)
data[i]=i2c_read(0);
else
data[i] = i2c_read();
}
i2c_stop();
|
Look at the diagram in section 4.1.
You should be doing this on the 3022 as well (it is a required part of the
I2C spec), but the 3022, handles NACK 'smartly', and will terminate the
transaction when this is received, or when the whole packet has been
sent 'automatically', so does not get confused if this does not come.
In I2C this is the 'marker' from the master to say it has finished reading. |
|
|
ihsan
Joined: 30 Nov 2023 Posts: 9
|
|
Posted: Tue Jan 09, 2024 4:22 am |
|
|
Thanks Ttelmah for your response. I use 16f88. I use your code and I can read datas of both. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Tue Jan 09, 2024 5:13 am |
|
|
Good news.
It is one of the commonest mistakes done by people with I2C!...
You could also shorten the time delays you have for the sensors to return the
data. The 3020 needs just under 15mSec 'worst case', and the 45 under
9mSec. |
|
|
|