Skip to content

Temperature conversion formula #29

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Conversation

maxic62
Copy link

@maxic62 maxic62 commented Sep 27, 2020

Hello team,

First time for me doing a pull request, so please be gentle with me ;)

I'm experiencing some temperature differences between sensors I already have my room and a project I currently have for controlling my HVAC. The difference was about ~1°C. I have a baby temperature sensor and a Xiaomi Temp sensor v2 (that also use SHT31 sensor)
First I suspected my sensor location in the box I made. But whatever the position (outside the box, in the box near the screen, far from the screen) the temperature was alway upper by ~1°C.
I finally checked the SHT31-D datasheet and discover that the conversion formula was not the same in the library.
I replaced the current formula by the one in the datasheet and now the temperature works like a charm.

Hope this modification can help everyone.
See you,
Max

@ladyada
Copy link
Member

ladyada commented Sep 28, 2020

@dirkmueller hi this relates to some PR from you, maybe check it to see if there was some error in the 'size optimizations'?

@dirkmueller
Copy link
Contributor

@ladyada thanks, I will take a look.

@@ -189,8 +189,8 @@ bool Adafruit_SHT31::readTempHum(void) {
int32_t stemp = (int32_t)(((uint32_t)readbuffer[0] << 8) | readbuffer[1]);
// simplified (65536 instead of 65535) integer version of:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these comments would be obsolete with your change and can be removed then.

stemp = ((4375 * stemp) >> 14) - 4500;
temp = (float)stemp / 100.0f;
stemp = ((175.0f * (float)stemp) / 65535.0f) - 45.0f;
temp = (float)stemp;
Copy link
Contributor

@dirkmueller dirkmueller Sep 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what you're doing here is floor(temp), because you first assign a temperature in celcius(!) to stemp, which is an integer variable (so it contains values like 19, 20, 21) and then you convert it to a float in the line here:

   temp = (float) stemp;

afterwards you have the clipped temperature value as float, so 19.0, 20.0, 21.0 etc. according to the datasheet, the temperature sensor has a resolution of 0.015 °C (accuracy < 0.2°C) so clipping to full digit temperature values actually introduces an error of theoretically up to 1°C. I don't think thats what you wanted to do. So I don't think the code is correct as is.

@dirkmueller
Copy link
Contributor

dirkmueller commented Sep 28, 2020

The datasheet for SH3x specifies a resolution of 0.015 °C, and a range of -40°C to +90°C. so our temperature calculation should be below 0.015 of error in these ranges (readings below -40°C or above 90°C should not occur).

To prove that the current code works, I wrote this test program. you can run it on any system that has a C compiler, it doesn't require any hardware. what it does is it tries every possible legal reading of the raw sensor input, and compares it with the datasheet formular, the current (simplified integer calculation) and a small improved version that I came up with while writing the test app.

The output of that program is:

maxdiff_simplified = 0.012039 maxdiff_improved = 0.009857

with other words, the current code has a maximal error of 0.012, which is an error within the specified resolution error of 0.015. if anyone is concerned about an error of 0.01°C (not 1°C like reported here but 1/100th of that, 0.01°C), we can use the improved integer calculation code instead, which reduces max error down further without increasing code size. As you can see, the only difference is instead of doing fixed-integer calculation with a scaling factor of 100 I'm doing it with 128, which is the maximum that fits into signed 32bit int (31bit). To make it easier to understand, I used an explicit i_size which indicates the scaling factor and kept the const calculations explicit. This looks code wise larger, but the compiler can optimize that to the actual constant numbers immediately at compilation rather than runtime.

The test program is here: https://gist.github.com/dirkmueller/c1ec0aa8c124caccf181b21a45943657

@maxic62
Copy link
Author

maxic62 commented Sep 30, 2020

Hello @dirkmueller ,

has you mentionned before my modification was not correct because of my calculation in int32.
When I've tested, the rounding was very close to the expected value so I conclude too quickly...

And yes, concerning the precision, the error introduced by the simplification is very very low and a lot better for the code size!

Sorry for the disturb

So today I still have ~1°C difference and I still don't understand why

2020-09-30 094713

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants