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

HTU21D humidity measurements are sometimes incorrect #1278

Closed
fivdi opened this issue Jan 22, 2017 · 9 comments
Closed

HTU21D humidity measurements are sometimes incorrect #1278

fivdi opened this issue Jan 22, 2017 · 9 comments

Comments

@fivdi
Copy link
Contributor

fivdi commented Jan 22, 2017

If humidity is measured using a HTU21D connected to a C.H.I.P. and humidity increases above approximately 56% Johnny-Five starts to report negative humidity values.

For example, let's say that humidity values are displayed with the following program:

var five = require("johnny-five");
var chipio = require('chip-io');
var board = new five.Board({io: new chipio()});

board.on("ready", function() {
  var hygrometer = new five.Hygrometer({
    controller: "HTU21D",
    bus: 1
  });

  hygrometer.on("data", function() {
    console.log(this.relativeHumidity + " %");
  });
});

Here's some typical output of this program when the humidity increases:

28.465789794921875 %
28.435272216796875 %
28.435272216796875 %
28.397125244140625 %
28.397125244140625 %
28.366607666015625 %
28.366607666015625 %
28.328460693359375 %
28.328460693359375 %
28.297943115234375 %
28.297943115234375 %
28.267425537109375 %
28.267425537109375 %
28.824371337890625 %
28.824371337890625 %
28.824371337890625 %
29.762786865234375 %
29.762786865234375 %
30.945343017578125 %
30.945343017578125 %
32.173675537109375 %
32.173675537109375 %
33.371490478515625 %
33.371490478515625 %
34.622711181640625 %
34.622711181640625 %
34.622711181640625 %
35.782379150390625 %
35.782379150390625 %
37.178558349609375 %
37.178558349609375 %
38.269561767578125 %
38.269561767578125 %
39.330047607421875 %
39.330047607421875 %
40.398162841796875 %
40.398162841796875 %
41.397613525390625 %
41.397613525390625 %
42.374176025390625 %
42.374176025390625 %
42.374176025390625 %
43.350738525390625 %
43.350738525390625 %
44.296783447265625 %
44.296783447265625 %
45.395416259765625 %
45.395416259765625 %
45.395416259765625 %
46.257537841796875 %
46.257537841796875 %
47.119659423828125 %
47.119659423828125 %
47.928375244140625 %
47.928375244140625 %
48.714202880859375 %
48.714202880859375 %
49.507659912109375 %
49.507659912109375 %
50.240081787109375 %
50.240081787109375 %
50.964874267578125 %
50.964874267578125 %
50.964874267578125 %
51.651519775390625 %
51.651519775390625 %
52.361053466796875 %
52.361053466796875 %
53.017181396484375 %
53.017181396484375 %
53.719085693359375 %
53.719085693359375 %
54.344696044921875 %
54.344696044921875 %
54.947418212890625 %
54.947418212890625 %
54.947418212890625 %
55.542510986328125 %
55.542510986328125 %
56.129974365234375 %
56.129974365234375 %
-68.31307983398438 %
-68.31307983398438 %
-67.74087524414062 %
-67.74087524414062 %
-67.20681762695312 %
-67.20681762695312 %
-67.20681762695312 %
-66.69564819335938 %
-66.69564819335938 %
-66.16159057617188 %
-66.16159057617188 %
-65.62753295898438 %
-65.62753295898438 %
-65.15451049804688 %
-65.15451049804688 %
-65.15451049804688 %
-64.69674682617188 %
-64.69674682617188 %
-64.23898315429688 %
-64.23898315429688 %
-63.804107666015625 %
-63.804107666015625 %
-63.254791259765625 %
-63.254791259765625 %
-62.850433349609375 %
-62.850433349609375 %
-62.850433349609375 %
-62.446075439453125 %
-62.446075439453125 %

This appears to be an issue with signed/unsigned values. This line of code converts the raw humidity data from the sensor to a signed 16 bit value:

              computed.humidity = int16(data[0], data[1]);

Modifying this code to convert the raw humidity data to an unsigned 16 bit value fixes the issue:

              computed.humidity = uint16(data[0], data[1]);

It looks like the same issue also exists for temperature values.

@fivdi
Copy link
Contributor Author

fivdi commented Jan 23, 2017

I can make a PR for fixing this if it's seen as a bug.

@HipsterBrown
Copy link
Contributor

@fivdi Thanks for making a thorough issue. It makes sense to change the humidity to an unsigned integer since the value should never be negative. I don't believe that is an issue for temperature values, according to Adafruit's HTU21D description:

The temperature output has an accuracy of ±1°C from -30~90°C.

So there is the possibility for negative values from that component.

I can make a PR for fixing this if it's seen as a bug.

Since it appears that is an issue with the humidity value, a PR would be very helpful. 👍

@dtex
Copy link
Collaborator

dtex commented Jan 24, 2017

I'm very curious why that first bit is changing in the i2cRead. Doesn't that imply there is a bug somewhere in the firmata/firmata.js chain?

@fivdi
Copy link
Contributor Author

fivdi commented Jan 24, 2017

The temperature output has an accuracy of ±1°C from -30~90°C.

So there is the possibility for negative values from that component.

The conversion of the raw 16 bit value to a Celsius is performed with this code:

 return toFixed((175.72 * raw / 65536) - 46.85, 2);

If raw is a 16 bit unsigned value, the temperature in degrees Celsius can still be negative.

I'm very curious why that first bit is changing in the i2cRead. Doesn't that imply there is a bug somewhere in the firmata/firmata.js chain?

The first bit isn't being changed by i2cRead or firmata/firmata.js. The test was performed on a C.H.I.P. using the C.H.I.P IO plugin where firmata/firmata.js doesn't play a role. The error is occuring because two unsigned bytes that were read using i2cRead are being incorrectly converted to a signed 16 bit integer here. They should be converted to an unsigned 16 bit integer.

@dtex
Copy link
Collaborator

dtex commented Jan 24, 2017

Sorry I have firmata on the brain, specifically various number types in the protocol. Makes sense now.

@fivdi
Copy link
Contributor Author

fivdi commented Jan 25, 2017

A similar test with temperature shows that there's a similar problem.

Here's the test program:

var five = require("johnny-five");
var chipio = require('chip-io');
var board = new five.Board({io: new chipio()});

board.on("ready", function() {
  var thermometer = new five.Thermometer({
    controller: "HTU21D",
    bus: 1
  });

  thermometer.on("change", function() {
    console.log(this.celsius + "°C", this.fahrenheit + "°F");
  });
});

And here's the output when the temperature constantly increases:

chip@chip:~/chip-io$ node temperature-htu21d.js 
1485366370044 Device(s) C.H.I.P.  
1485366370079 Connected C.H.I.P.  
1485366370153 Repl Initialized  
>> 22.66°C 72.79°F
22.69°C 72.84°F
22.71°C 72.88°F
22.69°C 72.84°F
22.7°C 72.86°F
22.71°C 72.88°F
22.72°C 72.9°F
22.73°C 72.91°F
22.75°C 72.95°F
22.73°C 72.91°F
22.76°C 72.97°F
22.78°C 73°F
22.77°C 72.99°F
22.78°C 73°F
22.79°C 73.02°F
22.78°C 73°F
22.8°C 73.04°F
22.81°C 73.06°F
22.82°C 73.08°F
22.93°C 73.27°F
23.18°C 73.72°F
23.6°C 74.48°F
24.11°C 75.4°F
24.7°C 76.46°F
25.27°C 77.49°F
25.79°C 78.42°F
26.33°C 79.39°F
26.89°C 80.4°F
27.39°C 81.3°F
27.87°C 82.17°F
28.33°C 82.99°F
28.75°C 83.75°F
29.15°C 84.47°F
29.57°C 85.23°F
29.97°C 85.95°F
30.38°C 86.68°F
30.77°C 87.39°F
31.16°C 88.09°F
31.57°C 88.83°F
31.97°C 89.55°F
32.37°C 90.27°F
32.73°C 90.91°F
33.09°C 91.56°F
33.45°C 92.21°F
33.78°C 92.8°F
34.09°C 93.36°F
34.4°C 93.92°F
34.73°C 94.51°F
35.05°C 95.09°F
35.35°C 95.63°F
35.67°C 96.21°F
35.96°C 96.73°F
36.26°C 97.27°F
36.53°C 97.75°F
36.84°C 98.31°F
37.21°C 98.98°F
37.54°C 99.57°F
37.85°C 100.13°F
38.15°C 100.67°F
38.44°C 101.19°F
38.75°C 101.75°F
39.05°C 102.29°F
39.33°C 102.79°F
39.56°C 103.21°F
39.78°C 103.6°F
40.02°C 104.04°F
40.23°C 104.41°F
40.43°C 104.77°F
40.69°C 105.24°F
40.93°C 105.67°F
-134.52°C -210.14°F
-134.25°C -209.65°F
-133.96°C -209.13°F
-133.7°C -208.66°F
-133.48°C -208.26°F
-133.24°C -207.83°F
-133°C -207.4°F
-132.7°C -206.86°F
-132.39°C -206.3°F
-132.1°C -205.78°F
-131.81°C -205.26°F
-131.49°C -204.68°F
-131.18°C -204.12°F
-130.9°C -203.62°F
-130.59°C -203.06°F
-130.3°C -202.54°F
-129.99°C -201.98°F
-129.68°C -201.42°F
-129.37°C -200.87°F
-129.04°C -200.27°F
-128.73°C -199.71°F
-128.4°C -199.12°F
-128.08°C -198.54°F
-127.79°C -198.02°F
-127.5°C -197.5°F
-127.28°C -197.1°F
-127.03°C -196.65°F
-126.82°C -196.28°F
-126.6°C -195.88°F
-126.39°C -195.5°F
-126.2°C -195.16°F
-126.02°C -194.84°F
-125.87°C -194.57°F
-125.73°C -194.31°F
-125.64°C -194.15°F
-125.53°C -193.95°F
-125.43°C -193.77°F
-125.37°C -193.67°F
-125.28°C -193.5°F

(To exit, press ^C again or type .exit)
>> -125.22°C -193.4°F
-125.15°C -193.27°F
-125.07°C -193.13°F
-125°C -193°F

1485366377903 Board Closing.  
chip@chip:~/chip-io$ 

Changing this line of code from:

              computed.temperature = int16(data[0], data[1]);

to:

              computed.temperature = uint16(data[0], data[1]);

fixes it.

@HipsterBrown
Copy link
Contributor

Thanks for confirming @fivdi. Can you create a PR with those fixes and updated tests?

@balda
Copy link

balda commented Feb 8, 2017

Same bug with SHT31D and SI7021 (#1282)

@fivdi
Copy link
Contributor Author

fivdi commented Feb 27, 2017

#1296 is a PR for fixing this issue.

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