8000 Add option in DHT driver to do the measure without blocking interrupts by EddieParis · Pull Request #6946 · micropython/micropython · GitHub
[go: up one dir, main page]

Skip to content
8000

Add option in DHT driver to do the measure without blocking interrupts #6946

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
19 changes: 19 additions & 0 deletions docs/esp8266/tutorial/dht.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
20 changes: 15 additions & 5 deletions drivers/dht/dht.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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);
Expand Down Expand Up @@ -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);
11 changes: 8 additions & 3 deletions drivers/dht/dht.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

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

We could consider putting a retry loop here in case self.irq_block is false to free the users from doing that. I would avoid the infinite loop, though.. so maybe some fixed amount of retries should be introduced?

Copy link
Contributor Author
@EddieParis EddieParis Feb 24, 2021

Choose a reason for hiding this comment

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

I prefer to let the user decide to manage that as he prefers. In my case, I have other things to do so I can't lock main loop for too long, so I retry later. DHT is already really slow, not worth adding more delays.

Copy link
Contributor

Choose a reason for hiding this comment

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

Seems valid argument, indeed. I was just afraid that anybody has to implement this loop while using this argument anyways.

Copy link
Contributor

Choose a reason for hiding this comment

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

With a DHT sensor you have to implement a try:except: retry.. loop anyway because they are not very stable.

if (buf[0] + buf[1] + buf[2] + buf[3]) & 0xFF != buf[4]:
raise Exception("checksum error")
raise DHTChecksumError("Measure failed")


class DHT11(DHTBase):
Expand Down
0