Bugfix for DHT module to avoid timeouts on high system load
I found an error in the DHT module, if the system load is high: I have many Python threads running and the DHT module constantly reports a timeout error. If system load is low, there is no error.
I have a fix for the problem: You should extend the atomic section to include the 18ms waiting. Simply move the mp_hal_quiet_timing_enter() before the mp_hal_delay_ms(18), see below. I see no problem to loose the 18ms because the DHT measurements should only be every 2-3 seconds.
The 18ms may be reduced for DHT22, because the data sheet needs at least 1ms delay. I use a 3ms delay with the DHT22 with no problems. But for DHT11 we need 18ms. So I would let the delay at 18ms.
The fix is easy, in the file:
micropython/drivers/dht/dht.c
ORIGINAL (line 51):
// issue start command
mp_hal_pin_od_high_dht(pin);
mp_hal_delay_ms(250);
mp_hal_pin_od_low(pin);
mp_hal_delay_ms(18);
mp_uint_t irq_state = mp_hal_quiet_timing_enter();
CHANGE TO:
// issue start command
mp_hal_pin_od_high_dht(pin);
mp_hal_delay_ms(250);
mp_hal_pin_od_low(pin);
// the atomic section should be before the delay of 18ms
// otherwise we have timeout errors on high system load
// Stefan Hammes, 2020-03-31
mp_uint_t irq_state = mp_hal_quiet_timing_enter();
mp_hal_delay_ms(18);
Or with diff:
$ diff dht.c-orig dht.c
55d54
< mp_hal_delay_ms(18);
56a56,58
> // the atomic section should be before the delay of 18ms
> // otherwise we have timeout errors on high system load
> // Stefan Hammes, 2020-03-31
57a60,61
>
> mp_hal_delay_ms(18);
This gives correct DHT readings even with extremly high system load.
Please include this in the source code. Thanks.
Keep up the good work!
Stefan Hammes, Karlsruhe, Germany
Fixed DHT timing error, Issue #5848
I fixed an error in the DHT driver which occurs if the system load is high: If there are many Python threads running, the DHT driver constantly reports a timeout error ETIMEDOUT. If the system load is low, there is no error.
The solution is to wait uninterruptable with mp_hal_delay_us_fast instead of interruptable with mp_hal_delay_ms.
As a further optimization if have added a parameter to the function dht_readinto to know if we have DHT11 or DHT22. The reason: DHT11 needs 18ms waiting after pulling the bus low, but DHT22 needs only 1-3ms waiting after pulling the bus low.
The python classes DHT11 and DHT22 have also been extended to store the DHT version in a member variable.
This solves the issue #5848 as was discussed with dpgeorge.
Stefan Hammes, Karlsruhe