Go Down

Topic: Class for DHT11, DHT21 and DHT22 (temperature & humidity) (Read 62 times) previous topic - next topic

robtillaart

#120
Oct 05, 2014, 09:45 pm Last Edit: Oct 05, 2014, 09:48 pm by robtillaart Reason: 1
Quote
Another solution is to see what absolute values loopCountHIGH has, it should have a bimodal distribution .
Discriminating between the  26uSec loops (==ZERO) and the 70uSec loops (==ONE)  is easier than discriminating between 50 and 70uSec


added some print statements : (short test 200 reads)
The HIGH period in terms of loops have a variation of ~10
ZERO = 22 - 30
ONE = 82 - 89

The low period varies between 46 - 54

TIMEOUT = 400 ===>  TIMEOUT/9 == 45 might be a good divider...   (but not today ;)
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart

Some experiments and insights further:

clocking in bits with micros()
- When using micros() there are 2 micros() calls needed and a 32 bits compare. 16 an 8 Mhz have proven to work reliable. (16Mhz experiment 20K reads -> 0 errors) At clock speeds of 4 MHz and lower the duration of the calls to micros() add up to approx the time of a bit, especially if additional interrupts take time. Therefore for 4Mhz and lower the micros() way will not work.
Extrapolated duration of call to micros()
16 MHz - 3.5 uS
8MHz - 7 uS
4MHz - 14 uS  => 2 calls ~ 28uSec ~~> ZERO HIGH time


clocking in bits with loop counts
- compare loop counts is simpler and faster (only 16 bit compare) thus more suitable for lower [sub 8Mhz] clock speeds. I have no experimental confirmation yet.
- loop counts show quite some variation (see post above) and are therefore less reliable (16 Mhz experiment gave 4 errors in 10K reads)  An interrupt (e.g. Serial) during HIGH period will decrease the HIGH counter which can result in recognizing a ONE as a ZERO. An interrupt during LOW period will decrease LOW counter which can result in recognizing a ZERO as a ONE. At lower clock speeds the effects of interrupts will increase as they are processed slower.
- comparing the loop count of the high period against a fixed threshold can fail for the same reason, however only if the interrupt is in the high period so chance is 2x lower but still.  (16 Mhz experiment gave 0 errors in 10K reads). This threshold can be calculated during the first part of the readSensor function. [Threshold == acknowledge loop/2 ]

t.b.c.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart

Update of the DHT library to version 0.1.15

+ reduced # micros calls 2->1 in inner loop. => footprint -18
  detection of the zero/one is now done by measuring the length of LOW+HIGH period, => reuse a time stamp
+ improved wait for acknowledge - (thanks to 68tjs)
+ merged two loopCounters into one again.
+ dht22_test sketch displays some statistics every 20 reads (used to run 10000 reads with zero errors)


links:
- http://playground.arduino.cc//Main/DHTLib - (version not updated, but as backgrounder useful)
- https://github.com/RobTillaart/Arduino/tree/master/libraries/DHTlib - (code only)


As always comments and remarks are welcome.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart

footnote for the 0.1.15 version
Did quite some testing last few days with the idea (originally from 68tjs) of comparing LOW period and HIGH period of every bit. This resulted in additional testing with a fixed threshold and the HIGH period only. Smaller footprints, but also a few errors (5 in 10000 reads, not bad).

Then I suddenly got the insight that if I measured the whole bit period LOW+HIGH (about 80 or 130 uSec) - and just wait for the falling edge - I could reuse one call to micros(). With hindsight quite obvious. That insight proved to be very stable (10000++ reads, zero fails) and with the insights of previous posts I expect it to work reliable on 8 Mhz and even on 4 Mhz.

@16Mhz the inner loop runs at least 70 times, so at 4Mhz the inner loop would run at least 17 times, (precondition no interrupts!!). So even 2 and 1 Mhz with no interrupts might be possible. unfortunately no way to verify that quickly.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart

#124
Oct 08, 2014, 11:22 pm Last Edit: Oct 08, 2014, 11:50 pm by robtillaart Reason: 1
some first tests at lower clock speeds  (
used trick described here - http://forum.arduino.cc/index.php?topic=271364.msg1913233#msg1913233 -

@8MHz  -> 98%
TOT   OK   CRC   TO   UNK
100   98   2   0   0


@4 Mhz -> 82%
TOT   OK   CRC   TO   UNK
100   82   12   6   0


@2MHz -> 3%
TOT   OK   CRC   TO   UNK
100   3   9   88   0


@1MHz -> 0%

TOT   OK   CRC   TO   UNK
100   0   0   100   0


So there is definitely room for improvement ;)

Note for 4, 2 and 1 Mhz I have tweaked the delayMicroseconds()  implementation so it compiled, not yet tuned.

update:
@4Mhz is already critical, other serial speed => drops result ~50%    (seems that higher baud rate scores better)
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Clemens

Hi Rob, again many thanks for your excellent work also on this lib!

A question about temperature: As we know the DHT33 has an integrated DS18B20 for temperature measure http://shop.boxtec.ch/digital-humiditytemperature-sensor-dht33-rht04-p-40541.html. 

I like to use the DHT33 and about 5 DS18B20 only sensors in a project. So my question is: Do I have to use two different libs one for the DHT33 and one for the DS18B20s or can I use the DHTxx lib for reading the single DS18B20 sensors also?

robtillaart


Hi Rob, again many thanks for your excellent work also on this lib!

Welcome, try to continuous improve it.

Quote
A question about temperature: As we know the DHT33 has an integrated DS18B20 for temperature measure http://shop.boxtec.ch/digital-humiditytemperature-sensor-dht33-rht04-p-40541.html. 

I like to use the DHT33 and about 5 DS18B20 only sensors in a project. So my question is: Do I have to use two different libs one for the DHT33 and one for the DS18B20s or can I use the DHTxx lib for reading the single DS18B20 sensors also?

Yes you need two libraries, although both use a so called "1-wire" protocol, they are as incompatible as can be ;)

The DS18 series have an internal address, so you can have multiple sensors on 1-Wire. The DS18 have more features in terms of alarm and parasite mode. The DHT series have no such internal address or parasite mode and in fact the DHT just dumps a stream of bits where the DS is register oriented.

I have a DHT33 for testing purposes (>250K reads already) and it works very well.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart

Update of the DHT library to version 0.1.17  (0.1.16 was an intermediate one)

+ replaced micros() with adaptive loopcount
+ removed DHTLIB_INVALID_VALUE (user should decide if value is usable)
+ more detailed errors per phase of handshake
+ added DHTLIB_ERROR_CONNECT
+ added DHTLIB_ERROR_ACK_L  DHTLIB_ERROR_ACK_H

- version 0.1.14 and up are not compatible with pre 1.0 Arduino
+ added fix for pre 1.0 (not tested)


links:
- http://playground.arduino.cc//Main/DHTLib - (version not updated, but as backgrounder useful)
- https://github.com/RobTillaart/Arduino/tree/master/libraries/DHTlib - (code only)


As always comments and remarks are welcome.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart

#128
Oct 15, 2014, 08:43 am Last Edit: Oct 17, 2014, 10:26 pm by robtillaart Reason: 1
footnote for the 0.1.17 version
There are some bits that are always zero in the protocol. These are the first bits of the humidity. The current (0.1.17) implementation use these to learn the loop-count (duration) of a zero of the individual sensor. This count is used to discriminate between zero's and ones in the rest of the handshake. The robustness for 16Mhz and 8Mhz is almost perfect - see numbers below.  Tested with 4 Mhz and lower but these are not good.

Furthermore most important change in the interface is that DHTLIB_INVALID_VALUE is not used any more. The received bits are converted to temperature /humidity and it is up to the user to determine if the values are good. The reason for this change is that during testing I noticed that time out often occurred on the last bit(s) of the CRC, resulting good values for T&H which were thrown away. That does not happen any more. The read() functions still return an error (!=0) if something went wrong so the user should inspect that. In fact the errors now indicate where the handshake went wrong.  

test results:
@16 Mhz zero errors in 16K reads
@8 Mhz seven errors in 10K reads

dht22_test.ino
16000000
LIBRARY VERSION: 0.1.17
...
TOT   OK   CRC   TO   UNK
16000   16000   0   0   0

dht22_test.ino
8000000
LIBRARY VERSION: 0.1.17
...
TOT   OK   CRC   TO   UNK
10000   9993   5   2   0

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Go Up