Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

These units do work with negative (freezing) temps, correct decoding algorithm #2

Open
eharris opened this issue Jun 4, 2020 · 5 comments

Comments

@eharris
Copy link

eharris commented Jun 4, 2020

I tested with a unit and have verified that these do work and read negative temps. According to their marketing materials, they only claim the device supports 0-50 degrees C, but the mobile app shows the range as -20C to 60C. I have personally verified that my unit reads sub-freezing temps (although I didn't have a way to test all the way down to -20C).

The decoding algorithm description could use updating to be less complicated and more accurate. Converting to a binary string isn't needed. The algorithm I used is (pseudocode):

Join the 3 data bytes together and convert to an integer, then:

if (val & 0x800000) {
    is_negative = true;
    val = val ^ 0x800000;
}
humidity = (val % 1000) / 10;
temp = int(val / 1000) / 10;
if (is_negative) {
    temp = 0 - temp;
}
# If desire Farenheit
temp = temp * 9 / 5 + 32;
@Thrilleratplay
Copy link
Owner

The official operating temperature range, according to Govee, for the H5075 is 0°C - 50°C (32°F - 122°F). It may display and send negative temperatures but I would be suspicious of those values. Also standard LCDs do not do well in freezing temperatures.

@JZ-SmartThings
Copy link

JZ-SmartThings commented Nov 29, 2020

I see that there has bee some discussion about negative temperature... the below seems to work for me and reports pretty accurately in tests with my fridge & freezer...


    - lambda: |-
        for (auto data : x.get_manufacturer_datas()) {
            if(data.data.size()==6) {
              const int basenum = (int16_t(data.data[1]) << 16) + (int16_t(data.data[2]) << 8) + int16_t(data.data[3]);
              float temperature = (basenum / 10000.0f);
              ESP_LOGD("custom", "Govee Two Reported Temp: %f", temperature);
              if(temperature>=839.0) {
                temperature = temperature-839;
                temperature = -temperature * 9.0/5.0 + 32.0;
              } else {
                temperature = temperature * 9.0/5.0 + 32.0;
              }
           }

@landonsilla
Copy link

@JZ-SmartThings Thanks! This seems to work for me. But what's with the 839 number? Where does this magic number come from?

(I have corroborated that number being best for me to, just figuring it out empirically .... I just want to know the meaning of that number)

@Thrilleratplay
Copy link
Owner

@landonsilla I'm going to try my best to explain where the 839 comes from and hopefully I get correct.

The data received is three octets, FF FF FF, but to represent a 32bit integer 4 octets are needed. Simple, we pad it with zeros, but because BLE is little endian, they are padded on the end to be FF FF FF 00. However, a signed 32bit integer has an upper bound of 2,147,483,647 using a two's compliment representation. In hex, the four octets that represent this is 0x7FFFFFFF.

Anything beyond 0x7F FF FF FF is considered negative in two's compliment. Meaning 0x80000000 is equal to -1. To figure this out based on the data received we need to take the value, subtract the upper bound of 0x7FFFFFFF and multiply by negative 1. As we cannot store anything beyond the limit of signed integer, we have to use an unsigned int. What is 0x80000000 as an unsigned integer, 8,388,608. Remember we need to divided the values provided by 10,000,
This leaves us with 838.8608, rounding or casting to an int gives us 839.

I am trying to do this from memory and quick Googling, so I apologize if this is still confusing or if the terminology is off.

@landonsilla
Copy link

That is super great! I love it! This takes me back to my college days.

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

No branches or pull requests

4 participants