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

Fix negative temperatures #12

Merged
merged 2 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Should also work for compatible sensors like the DHT12, or KY-015.
Should also work for compatible sensors like the DHT12 or KY-015.

Copy link
Member Author

Choose a reason for hiding this comment

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

done.

*/
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
25 changes: 23 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,21 @@ 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.
byte1 := data[TEMPERATURE_INDEX_]
temperature10/int := ?
if (byte1 & 0x80 == 0) or (byte1 & 0x04 == 1):
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe spell out the range implied by 0x04 constant?

Copy link
Member Author

Choose a reason for hiding this comment

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

done and fixed a typo. (It should have been "0x40").
done.

Copy link
Contributor

Choose a reason for hiding this comment

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

done and fixed a typo. (It should have been "0x40"). done.

That's kinda what I expected :)

// 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