• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Output Consistency

TucsonDon

Member
I am using a MikroElektronika Temp-Hum 3 click to measure temp & humidity, and having an issue with getting a consistent display.

C:
void ReadOutsideTemp(void)
{
int Temp;
unsigned int Hum;
    uint8_t RawTempHum[4];
    i2c1_readDataBlock(TempHum, TempL, RawTempHum, 4);      //read click board
    Temp = RawTempHum[1] << 8 | RawTempHum[0];
    Hum = RawTempHum[3] << 8 | RawTempHum[2];
    Temp = (Temp / 2^16)*165 - 40;
    Hum = (Hum / 2^16)*100;
    if (SysConfigbits.TempFormat == ON) Temp = (Temp * 9 / 5) + 32; //change from °C to °F
    SysTemp.Out = Temp;     //for lcd display
SysTemp.RH = Hum;   //for lcd display

TempDisplay(); //display on LCD
}
I have the hdc2010 configured for:
Temp-14 bit
Hum-14 bit
auto sample 1 every minute w/ an IOC on RB1 for DRDY

temp is from -120° to 120° and humidity can display from 0 - 220% and changes with every display update
how can I display a more accurate and consistent reading[/code]
 

Attachments

Last edited:

ronsimpson

Well-Known Member
Most Helpful Member
Try averaging the last 10 readings.
----edited----
How bad is the noise. +/-1 number?
 
Last edited:

TucsonDon

Member
I tried to average and that didn't work. I have work the formula using both the programmer and scientific calculator and think the issue is how I am implementing the exponents.
This is what I have:

C:
int Temp;
float THResult;

THResult = (Temp / 2^16)*165 - 40;
the formula is from the hdc2010 data sheet.
 

rjenkinsgb

Well-Known Member
Most Helpful Member
the formula is from the hdc2010 data sheet.
All the values should be floats (or be cast to floats) for that to be guaranteed work properly as shown.

See if this works differently?

C:
int Temp;
float THResult;

THResult = ((float) Temp / 65536.0) * 165.0 - 40.0;
I'd probably use a long for storage and keep the results shifted by eg. 8 bits more than the raw values. That allows integer maths with fractional precision.
 

DrG

Active Member
Instead of using:

Hum = (Hum / 2^16)*100;

Run it using:

Hum /= 65536;
Hum *= 100;

Same for Temp:

Instead of :

Temp = (Temp / 2^16)*165 - 40;

Use:
temp /= 65536;
temp *= 165;
temp -= 40;


See if you get a different result. Then, change both to floats.
Also, and I am too lazy to go look, but don't you have to mask the unused bits first?

Of course, I could be wrong.
 

DrG

Active Member
All the variables should be floats (or be cast to floats) for that to work properly as shown.

I'd probably use a long for storage and keep the results shifted by eg. 8 bits more than the raw values. That allows integer maths with fractional precision.
Beat me by a minute. Also, there is no good reason to use 2^16 instead of the constant.
 

DrG

Active Member
Also, and I am too lazy to go look, but don't you have to mask the unused bits first?
Now, I see from the data sheet, "The humidity register is a 16-bit result register in binary format (the 2 LSBs D1 and D0 are always 0).", so no, you don't need any masking on humidity.

To add to what has already been said in #4 and working with your code, this should be more accurate.
C:
void ReadOutsideTemp(void)
{
  uint16_t Temp, Hum;
  uint8_t RawTempHum[4];
  float fTemp, fHum;
 
  i2c1_readDataBlock(TempHum, TempL, RawTempHum, 4);      //read click board
  Temp = RawTempHum[1] << 8 | RawTempHum[0];
  Hum = RawTempHum[3] << 8 | RawTempHum[2];
  //Temp = (Temp / 2^16)*165 - 40;
  //Hum = (Hum / 2^16)*100;
  fTemp = ((float)Temp / 65536.0) * 165.0 - 40.0;
  fHum = ((float)Hum / 65536.0) * 100.0;
  if (SysConfigbits.TempFormat == ON) fTemp = (fTemp * 9 / 5) + 32; //change from °C to °F
  SysTemp.Out = fTemp;     //for lcd display
  SysTemp.RH = fHum;   //for lcd display
  TempDisplay(); //display on LCD
}
 

TucsonDon

Member
rjenkinsgb & DrG thanks for your input. I got it to work with:
C:
void ReadOutsideTemp(void)
{
uint8_t RawTempHum[4];
int Temp = 0;
int Hum = 0;
double THResult = 0;
i2c1_readDataBlock(TempHum, TempL, RawTempHum, 4);      //read click board
Temp = RawTempHum[1] << 8 | RawTempHum[0];
Hum = RawTempHum[3] << 8 | RawTempHum[2];

THResult = (double)(Temp / (pow (2,16)))*165 - 40;
SysTemp.Out = (float)THResult;

THResult = 0;
THResult = (double)(Hum / (pow (2,16)))*100;
SysTemp.RH = (float)THResult;

TempDisplay();
}
once I figured out the pow function from math.h it started to work.
 

DrG

Active Member
Terrific. I am glad you got it working and I don't want to belabor this point, but why use
(pow (2,16)) instead of the constant 65536.0? I know the data sheet uses 2^16 and you may want to follow that strictly, but is there another reason?
 

TucsonDon

Member
DrG I used it because of the datasheet, and because of my inexperience it was the easiest for me to figure out.
 

EE World Online Articles

Loading

 
Top