Skip to content

Commit

Permalink
Fix negative temperatures (#12)
Browse files Browse the repository at this point in the history
The DHT22 supports negative temperatures which weren't read correctly.

Fixes #10.
  • Loading branch information
floitsch authored Jan 6, 2025
1 parent e6aa5e4 commit 5b0abf1
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 12 deletions.
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,17 @@ lot of code.

## Implementation details

The DHT11 and DHT22 drivers are timing sensitive, and the drivers are therefore implemented using the RMT controller which allows for precise timings.
The DHT11 and DHT22 drivers are timing sensitive, and the drivers are therefore implemented
using the RMT controller which allows for precise timings.

## Compatibility

The driver has been tested on DHT11 and DHT22 sensors.

It should work with other sensors that use the same protocol:
DHT12, KY-015, DHT33, AM2320, AM2321, or AM2322.

If you have one of these sensors, please let us know if it works.

## Features and bugs

Expand Down
4 changes: 3 additions & 1 deletion package.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
name: dhtxx
description: Drivers for the DHT11 and DHT22 (aka AM2302 or RHT03) humidity and temperature sensors.
description: |
Drivers for the DHT11 and DHT22 (aka AM2302 or RHT03) humidity and temperature sensors.
Other compatible sensors: DHT12, KY-015, DHT33, AM2320, AM2321, or AM2322.
environment:
sdk: ^2.0.0-alpha.1
13 changes: 11 additions & 2 deletions src/dht11.toit
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,16 @@
import gpio
import .driver_ as driver

/**
Driver for the DHT11 sensor.
Should also work for compatible sensors like the DHT12 or KY-015.
*/
class Dht11 extends driver.Driver:
static HUMIDITY_INTEGRAL_PART_ ::= 0
static HUMIDITY_DECIMAL_PART_ ::= 1
static TEMPERATURE_INTEGRAL_PART_ ::= 2
static TEMPERATURE_DECIMAL_PART_ ::= 3

/**
Constructs an instance of the Dht11 driver.
Expand All @@ -19,7 +28,7 @@ class Dht11 extends driver.Driver:
super pin --in_channel_id=in_channel_id --out_channel_id=out_channel_id --max_retries=max_retries

parse_temperature_ data/ByteArray -> float:
return data[driver.Driver.TEMPERATURE_INTEGRAL_PART_].to_float
return data[TEMPERATURE_INTEGRAL_PART_].to-float + data[TEMPERATURE_DECIMAL_PART_] * 0.1

parse_humidity_ data/ByteArray -> float:
return data[driver.Driver.HUMIDITY_INTEGRAL_PART_].to_float
return data[HUMIDITY_INTEGRAL_PART_].to-float + data[HUMIDITY_DECIMAL_PART_] * 0.1
28 changes: 26 additions & 2 deletions src/dht22.toit
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@ import gpio
import io show BIG_ENDIAN
import .driver_ as driver

/**
Driver for the DHT22 sensor.
Should also work for compatible sensors like the DHT33, AM2320, AM2321, or AM2322.
*/
class Dht22 extends driver.Driver:
static HUMIDITY_INDEX_ ::= 0
static TEMPERATURE_INDEX_ ::= 2

/**
Constructs an instance of the Dht22 driver.
Expand All @@ -20,7 +27,24 @@ class Dht22 extends driver.Driver:
super pin --in_channel_id=in_channel_id --out_channel_id=out_channel_id --max_retries=max_retries

parse_temperature_ data/ByteArray -> float:
return (BIG_ENDIAN.uint16 data driver.Driver.TEMPERATURE_INTEGRAL_PART_) / 10.0
// The temperature is a big-endian 16-bit integer.
// Some sensors use the first bit to indicate the sign of the temperature; others
// encode the value as 2's complement.
// Since valid temperature values can only be in a small range, we can use the
// second bit to determine which approach the sensor uses.
// If the first two bits were 1 and the sensor wasn't using 2's complement, then
// the temperature would be lower than -64 degrees which is outside the supported
// range.
byte1 := data[TEMPERATURE_INDEX_]
temperature10/int := ?
if (byte1 & 0x80 == 0) or (byte1 & 0x40 == 1):
// The temperature is positive or the sensor uses 2's complement.
temperature10 = BIG-ENDIAN.int16 data TEMPERATURE_INDEX_
else:
// The temperature is negative, but the sensor uses the first bit to indicate the sign.
temperature10 = BIG-ENDIAN.uint16 data TEMPERATURE_INDEX_
temperature10 = -(temperature10 & 0x7FFF)
return temperature10 * 0.1

parse_humidity_ data/ByteArray -> float:
return (BIG_ENDIAN.uint16 data driver.Driver.HUMIDITY_INTEGRAL_PART_) / 10.0
return (BIG_ENDIAN.uint16 data HUMIDITY_INDEX_) * 0.1
6 changes: 0 additions & 6 deletions src/driver_.toit
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,6 @@ class DhtResult:
return "T: $(%.2f temperature), H: $(%.2f humidity)"

abstract class Driver:
static HUMIDITY_INTEGRAL_PART_ ::= 0
static HUMIDITY_DECIMAL_PART_ ::= 1
static TEMPERATURE_INTEGRAL_PART_ ::= 2
static TEMPERATURE_DECIMAL_PART_ ::= 3
static CHECKSUM_PART_ ::= 4

channel_in_ /rmt.Channel
channel_out_ /rmt.Channel
max_retries_ /int
Expand Down

0 comments on commit 5b0abf1

Please sign in to comment.