Closed r0bc94 closed 1 year ago
Thanks for reporting this issue. I need to check the datasheet, might take a few days.
Found a sensor, so did a testrun with an Arduino UNO and example DHT20.ino and library version 0.1.4
Breathing against the sensor to change the temperature and humidity, seems to work pretty well.
first, sorry for the premature issue creation without any description. I've accidentally hit the "Create Issue" button.
No problem
Can you try just one the DHT20.ino example?
I notice a fairly strange baudrate in your code, any specific reason? just curious, has nothing to do with the bug.
I ran your test-sketch on an UNO and indeed it hangs ... added 2 lines and it worked.
I modified your sketch to this, please give it a try.
#include "DHT20.h"
DHT20 dht;20;
void setup() {
// put your setup code here, to run once:
Serial.begin(74880);
dht20.begin(SERIAL_DATA_PIN, SERIAL_CLOCK_PIN);
Wire.setClock(400000); // <<<<<<<<<<<<<<<<<<<<<<<<
delay(1000); // <<<<<<<<<<<<<<<<<<
}
void loop() {
// put your main code here, to run repeatedly:
// dht20.resetSensor(); <-- Without this, the read value would always be the same, even if read() returns 0.
uint8_t read_status = dht20.read();
if (read_status != DHT20_OK) {
Serial.printf("Failed to read from DHT22 - Status: %d", read_status);
}
float humid = dht20.getHumidity();
float temp = dht20.getTemperature();
Serial.printf("Temperature: %f Humid: %f\n", temp, humid);
delay(5000);
}
give it a try
If I use
Wire.setClock(100000):
it hangs... so there is something wrong in the I2C communication.
Wire.setClock(200000); works
@r0bc94 if you run your sketch, what does the output looks like?
@r0bc94
For me this makes sense, as in the read procedure described in the DHT20 Datasheet, you have to initialize the Sensor before each read by sending the 0x71 command and checking the return value. I've glanced over you code but I could not find such call,
mmm I do not call it in DHT20.ino and it still works.
It is in line 238 in readStatus()
uint8_t DHT20::readStatus()
{
_wire->beginTransmission(DHT20_ADDRESS);
_wire->write(0x71);
_wire->endTransmission();
delay(1); // needed to stabilize timing
_wire->requestFrom(DHT20_ADDRESS, (uint8_t)1);
delay(1); // needed to stabilize timing
return (uint8_t) _wire->read();
}
No clue yet, the Wire.setClock() does somehow tickle the sensor, but even from the low level code I got no clue.
There should be at least some notes added in the readme.md file.
For me this makes sense, as in the read procedure described in the DHT20 Datasheet, you have to initialize the Sensor before each read by sending the 0x71 command and checking the return value.
Datasheet is only referring to power-on process, not to every read (or I missed it)
7.4 Sensor Reading Process 1.After power-on, wait no less than 100ms. Before reading the temperature and humidity value, get a byte of status word by sending 0x71. If the status word and 0x18 are not equal to 0x18, initialize the 0x1B, 0x1C, 0x1E registers, details ... Note: The calibration status check in the first step only needs to be checked when the power is turned on. No operation is required during the acquisition process.
Thank you for your response. Unfortunately, I'm currently away and will be back home to test this in a few days.
I notice a fairly strange baudrate in your code, any specific reason? just curious, has nothing to do with the bug.
I've set this baudrate to be able to see the debug messages and stack traces which are generated by the eps8266. Those information are only send with the given baudrate. I don't really know why its such a "strange" Baudrate. This Stackoverflow reply suggest that it has something to do with the crystal oscillator used for the esp: https://stackoverflow.com/a/41011637 (Please note that I'm not very experienced).
Again, I've I'm back home I also try out the different i2c speeds.
Datasheet is only referring to power-on process, not to every read (or I missed it)
Its possible that I got this wrong and the issue I'm seeing has a totally different cause.
~However I'm wondering where such initial call (aka after powering everything on) is executed in your Library. In my understanding, what happens when generating a measurement is the following:~
~1. When initially calling begin()
the i2c Bus is set up and the start sequence is executed
read()
, the read - Command 0xAC
together with both fixed parameters is send to the sensor~However, I dont't see the initial execution of this mentioned calibration sequence (sending 0x71
and comparing the return value) anywhere except in the dedicated resetSensor()
method. Again, I'm not really experienced and might have missed this.~
Sorry, I've missed your reply and the part, where 0x71
is basically send to the sensor in the isMeasuring()
method. However, the Status command is only queried after the measurement has started. In regards to the Datasheet, I still did not find that 0x71
is executed before the read - command.
You ask good questions, and you analyze the code quite well. I will try to find some answers tomorrow as it is unclear what causes the hanging sensor. And why the i2c speed makes things work.
need to create a test (or more) to see why the sensor gives one meaningful fixed value if frozen. A fixed random value would be less unexpected.
To be continued tomorrow.
@r0bc94 Did several tests with following results
I will create a 0.2.0 version which embeds resetSensor() in every requestData() so it is checked before every read, both synchronous and asynchronous.
Created a new branch - https://github.com/RobTillaart/DHT20/tree/develop Will be merged later today ==> new version 0.2.0
Hello, thank you. I will probably be able to test this in todays evening when I'm back home. But I'm confident that this will fix the issue.
But I'm confident that this will fix the issue.
Me too, that's why I ask someone else to verify ...
I've again tried out your new version on the develop
branch and this seems to have fixed this issue. Now the sensor readings are changing after each read()
as expected :smile: .
Super, will merge after my current task Thanks for testing!
Just found this issue today when looking for a driver for the DHT20. I'd like to add that the 0x71
referred to in the datasheet is really the sensor's I2C address + the read bit (0x38 << 1) | 0x1 == 0x71
, and is not a command to be written after the address is sent. When the datasheet says:
Before reading the temperature and humidity value, get a byte of status word by sending 0x71. If
the status word & 0x18
are not equal to 0x18, ...
what they meant is most probably to just read a status byte before triggering each measurement (and set up some registers if needed; see datasheet). Therefore line 229 below is in fact sending an invalid command:
This might be why the sensor hangs, but I still need to probe the I2C wires to see what's really going on. I'll add an update if I find anything.
what they meant is most probably to just read a status byte before triggering each measurement (and set up some registers if needed; see datasheet). Therefore line 229 below is in fact sending an invalid command:
OK that would mean that it would be enough to just call requestFrom() to read the data.
uint8_t DHT20::readStatus()
{
_wire->requestFrom(DHT20_ADDRESS, (uint8_t)1);
delay(1); // needed to stabilize timing
return (uint8_t) _wire->read();
}
I'll try to verify this asap.
This might be why the sensor hangs, but I still need to probe the I2C wires to see what's really going on. I'll add an update if I find anything.
Thanks for diving into this issue, always interested in new insights.
@shuyuan-liu Testrun with DHT20_I2C_speed.ino on an UNO
DHT20_I2C_speed.ino
DHT20 LIBRARY VERSION: 0.2.0
NOTE: datasheet states 400 KHz as maximum.
50000 0 56.5 20.2
100000 0 56.2 20.3
150000 0 55.9 20.3
200000 0 55.7 20.2
250000 0 55.6 20.2
300000 0 55.5 20.3
350000 0 56.8 20.3
400000 0 63.4 20.3
450000 0 65.2 20.3
500000 0 64.6 20.3
550000 0 63.5 20.3
600000 0 65.4 20.6
650000 0 77.4 21.2 <<<< breathing towards the sensor
700000 0 82.8 21.2
750000 0 85.5 21.3
800000 0 87.0 21.3
done...
@shuyuan-liu So apparently your interpretation is better. The four lines of code are not needed.
I'll make a PR for this a.s.a.p.
(page 11 datasheet)
The white byte = I2C address + read == 0x71. The first byte is the status byte followed by hum + temp etc.
@shuyuan-liu
PR created here - https://github.com/RobTillaart/DHT20/pull/10 Please verify if the develop branch works for you.
@RobTillaart latest develop branch works with esp8266, thanks! I also tested various clock speeds mentioned in the Arduino Wire documentation and they all work, for both master and develop:
Set Clock Speed | Measured Clock Speed | Works? |
---|---|---|
10000 (10 k) | 7.14 k | :heavy_check_mark: |
100000 (100 k) | 76 k | :heavy_check_mark: |
40000 (400 k) | 358 k | :heavy_check_mark: |
This is different from your results where 100 k or below didn't work, would you mind testing the different speeds again?
his is different from your results where 100 k or below didn't work, would you mind testing the different speeds again?
I did just an hour ago see a few posts back. FIrst column is the I2C speed.
Oops sorry I missed that!
No problem, happens to me all the time :)
Do you think the develop can be merged? Besides the removed lines there is no big change (getAddress() which is a no brainer + some minor edits)
The code looks OK to me. As you said no big changes so probably can be merged.
Merged, build is running, released as 0.2.1
Hello,
first, sorry for the premature issue creation without any description. I've accidentally hit the "Create Issue" button.
In order to try out your library, I wrote a fairly simple program based on your examples to gather the temperature values on my DHT20. The code looks like so:
When commenting out the
resetSensor()
method, thegetX()
- Methods will always return the same value, even ifread()
is called before. In order for to get an updated value, I have to callresetSensor()
in each iteration.For me this makes sense, as in the read procedure described in the DHT20 Datasheet, you have to initialize the Sensor before each read by sending the
0x71
command and checking the return value. I've glanced over you code but I could not find such call, neither in thebegin()
nor in theread()
method. Again, I could be wrong here but in my understanding, the calibration of the sensor must be checked before each read.I am using an ESP8266 micro controller (Wemos D1 Mini). Maybe this behavior is also different on other MCUs.