diff --git a/docs/esp8266/tutorial/dht.rst b/docs/esp8266/tutorial/dht.rst index 1602e8a337455..92e837966b936 100644 --- a/docs/esp8266/tutorial/dht.rst +++ b/docs/esp8266/tutorial/dht.rst @@ -63,3 +63,22 @@ To make newer I2C sensors work in backwards compatible 1-wire mode, you must connect both pins 3 and 4 to GND. This disables the I2C interface. DHT22 sensors are now sold under the name AM2302 and are otherwise identical. + +NOTE: if your are using a PWM channel in parallel of your measure, there can +be some glitches on the PWM channel at the measure time. This is because +the DHT drivers locks interrupts for accurate protocol timing handling, +and the PWM driver relies on these interrupts. The constructor of the DHT +objects has an extra argument irq_lock which can be set to False. +The risk is low, but in case of timing issues a DHTChecksumError can be +raised, catch it and retry. Depending on your use case, consider limiting +the number of retries. + + >>> import dht + >>> import machine + >>> d = dht.DHT22(machine.Pin(4), False) + >>> while True: + >>> try: + >>> d.measure() + >>> break + >>> except dht.DHTChecksumError: + >>> pass diff --git a/drivers/dht/dht.c b/drivers/dht/dht.c index 81754ac15f43f..4c4061fa298b8 100644 --- a/drivers/dht/dht.c +++ b/drivers/dht/dht.c @@ -37,7 +37,11 @@ #define mp_hal_pin_od_high_dht mp_hal_pin_od_high #endif -STATIC mp_obj_t dht_readinto(mp_obj_t pin_in, mp_obj_t buf_in) { +STATIC mp_obj_t dht_readinto(mp_obj_t pin_in, mp_obj_t buf_in, mp_obj_t irq_lock) { + mp_uint_t irq_state = 0; + + const bool do_lock = mp_obj_is_true(irq_lock); + mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(pin_in); mp_hal_pin_open_drain(pin); @@ -54,7 +58,9 @@ STATIC mp_obj_t dht_readinto(mp_obj_t pin_in, mp_obj_t buf_in) { mp_hal_pin_od_low(pin); mp_hal_delay_ms(18); - mp_uint_t irq_state = mp_hal_quiet_timing_enter(); + if (do_lock) { + irq_state = mp_hal_quiet_timing_enter(); + } // release the line so the device can respond mp_hal_pin_od_high_dht(pin); @@ -84,11 +90,15 @@ STATIC mp_obj_t dht_readinto(mp_obj_t pin_in, mp_obj_t buf_in) { buf[i / 8] = (buf[i / 8] << 1) | (ticks > 48); } - mp_hal_quiet_timing_exit(irq_state); + if (do_lock) { + mp_hal_quiet_timing_exit(irq_state); + } return mp_const_none; timeout: - mp_hal_quiet_timing_exit(irq_state); + if (do_lock) { + mp_hal_quiet_timing_exit(irq_state); + } mp_raise_OSError(MP_ETIMEDOUT); } -MP_DEFINE_CONST_FUN_OBJ_2(dht_readinto_obj, dht_readinto); +MP_DEFINE_CONST_FUN_OBJ_3(dht_readinto_obj, dht_readinto); diff --git a/drivers/dht/dht.py b/drivers/dht/dht.py index 1163b382bbc77..a86c1927111ff 100644 --- a/drivers/dht/dht.py +++ b/drivers/dht/dht.py @@ -7,16 +7,21 @@ from pyb import dht_readinto +class DHTChecksumError(Exception): + pass + + class DHTBase: - def __init__(self, pin): + def __init__(self, pin, irq_block=True): self.pin = pin self.buf = bytearray(5) + self.irq_block = irq_block def measure(self): buf = self.buf - dht_readinto(self.pin, buf) + dht_readinto(self.pin, buf, self.irq_block) if (buf[0] + buf[1] + buf[2] + buf[3]) & 0xFF != buf[4]: - raise Exception("checksum error") + raise DHTChecksumError("Measure failed") class DHT11(DHTBase):
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: