rwaldron / johnny-five

JavaScript Robotics and IoT programming framework, developed at Bocoup.
http://johnny-five.io
Other
13.25k stars 1.76k forks source link

HTU21D humidity measurements are sometimes incorrect #1278

Closed fivdi closed 7 years ago

fivdi commented 7 years ago

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 commented 7 years ago

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

HipsterBrown commented 7 years ago

@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. :+1:

dtex commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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

fivdi commented 7 years ago

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 commented 7 years ago

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

balda commented 7 years ago

Same bug with SHT31D and SI7021 (#1282)

fivdi commented 7 years ago

https://github.com/rwaldron/johnny-five/pull/1296 is a PR for fixing this issue.