10000 DHT22 driver on esp8266 stopped working between v1.9.3 and master · Issue #4233 · micropython/micropython · GitHub
[go: up one dir, main page]

Skip to content

DHT22 driver on esp8266 stopped working between v1.9.3 and master #4233

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

Closed
larsks opened this issue Oct 11, 2018 · 15 comments
Closed

DHT22 driver on esp8266 stopped working between v1.9.3 and master #4233

larsks opened this issue Oct 11, 2018 · 15 comments

Comments

@larsks
Copy link
Contributor
larsks commented Oct 11, 2018

This works just fine running the v1.9.3 image from http://micropython.org/resources/firmware/esp8266-20171101-v1.9.3.bin:

>>> import dht
>>> import machine
>>> d = dht.DHT22(machine.Pin(4))
>>> d.measure()

But using firmware built from 338635c, that consistently results in:

>>> d.measure()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "dht.py", line 16, in measure
OSError: [Errno 110] ETIMEDOUT

I see the same behavior running the image from http://micropython.org/resources/firmware/esp8266-20180511-v1.9.4.bin. The error occurs when running d.measure() multiple times (e.g., it's not just the first time we try to access the sensor).

I'm going to try to spend some quality time with git bisect this
evening, but I thought I'd post this here in case someone else has
already encountered this problem.

@larsks
Copy link
Contributor Author
larsks commented Oct 12, 2018

It broke in 033c32e, which is:

diff --git a/ports/esp8266/esp_mphal.h b/ports/esp8266/esp_mphal.h
index 194e56f64..940ca4727 100644
--- a/ports/esp8266/esp_mphal.h
+++ b/ports/esp8266/esp_mphal.h
@@ -86,7 +86,7 @@ void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin);
     } while (0)
 #define mp_hal_pin_od_high(p) do { \
         if ((p) == 16) { WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1)); } \
-        else { gpio_output_set(1 << (p), 0, 1 << (p), 0); } \
+        else { gpio_output_set(0, 0, 0, 1 << (p)); /* set as input to avoid glitches */ } \
     } while (0)
 #define mp_hal_pin_read(p) pin_get(p)
 #define mp_hal_pin_write(p, v) pin_set((p), (v))

@larsks
Copy link
Contributor Author
larsks commented Oct 12, 2018

...and if I git revert 033c32e on master, I can once again use my DHT22. I don't understand anything about the change in 033c32e, so I'm hoping someone more familiar with the platform can comment.

@larsks
Copy link
Contributor Author
larsks commented Oct 12, 2018

NB: The solution to #4116 does not resolve this issue (that was a suggestion from irc, but may or may not actually be relevant).

Oh, and I should mention that I am also using a Wemos D1 Mini.

@adritium
Copy link

@dpgeorge made the change to deal with a hardware glitch 033c32e

esp8266/esp_mphal.h: Fix I2C glitching by using input mode for od_high.

Certain pins (eg 4 and 5) seem to behave differently at the hardware level
when in open-drain mode: they glitch when set "high" and drive the pin
active high for a brief period before disabling the output driver. To work
around this make the pin an input to let it float high.

Looks like his hack broke something else

@robert-hh
Copy link
Contributor

It works for me at pin 4 (and e.g. 5, 13, 15).
AM2302
Wemos D1 Mini
MicroPython v1.9.4-651-g0f6f86ca-dirty on 2018-10-156

@dpgeorge
Copy link
Member

@larsks Thanks for taking the time to do bisect to track down the commit. I can see how that commit might have affected the DHT driver.

Unfortunately I can't reproduce the problem. On an Adafruit Huzzah Feather the DHT code above works just fine for me, on pins 4, 5, 12, 13, 14, 15. First and subsequent measures all work.

I suspect it's an issue with pulling up the DHT's data line. Since it's an open drain pin it should be pulled up to high with a resistor, say 10k Ohm. You can do this with an external resistor, or try the internal one on the esp8266 via:

d = dht.DHT22(Pin(4, Pin.IN, Pin.PULL_UP))

The reason it might have worked before without a pull-up is because the esp8266 pin was glitching when set to open-drain-high and driving the line high for a brief moment, which would have put enough charge on the wire to make it act like it was pulled high. Now it doesn't do that so there needs to be a resistor pulling it up.

@larsks
Copy link
Contributor Author
larsks commented Oct 17, 2018

@dpgeorge Thanks for looking into this! Unfortunately, explicitly creating the Pin with mode set to Pin.PULL_UP does not seem to have an impact on the behavior. But would it in any case? Looking at drivers/dht/dht.c, the very first thing that happens in dht_readinto is:

mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(pin_in);
mp_hal_pin_open_drain(pin);

Wouldn't that override any attempt to explicitly set the mode when creating the Pin object in micropython?

I'm seeing this on multiple Wemos D1 boards, which is odd since it seemed to work for @robert-hh. Robert, can you provide details of how you wired up the DHT? Did you use an external pull-up or anything? I have the signal line wired directly to GPIO4 (which seems to be a fairly common way of wiring things up).

I should note that the same boards seem to work fine using e.g. https://github.com/SuperHouse/esp-open-rtos/blob/master/examples/dht_sensor/dht_sensor.c.

@dpgeorge
Copy link
Member

But would it in any case? Looking at drivers/dht/dht.c, the very first thing that happens in dht_readinto is:

Well I'm not sure. It may be that the setting for the pull-up resistor being enabled is retained even after re-configuring it as an open drain pin.

In any case, can you try an external pull up? It definitely needs an external pull up otherwise the pin will just float.

I should note that the same boards seem to work fine using e.g.

Ok. But do note the following:
https://github.com/SuperHouse/esp-open-rtos/blob/master/examples/dht_sensor/dht_sensor.c#L26-L29

@robert-hh
Copy link
Contributor

@larsks I wired the module directly, Pin of the module -> board.

  • looking at it I see a pull up resistor on the board, value 4.7 kOhm.
  • measuring the impedance between data and Vcc I get 2.3 kOhm
    So there is an external pull-up.

@quantalume
Copy link

I'm experiencing this same problem. Tried multiple sensors, all of which work with earlier firmware builds but not 1.9.4 release. Tried with and without pull-up resistor. Sensors work just fine using the Arduino environment (no pull-up required).

@dpgeorge
Copy link
Member

I tested a DHT22 with a Wemos D1 mini pro and could not reproduce this error. I didn't use an external pull-up, and I ran this code:

import time, machine, dht
d = dht.DHT22(machine.Pin(4))
while 1:
    d.measure()
    time.sleep(0.25)

Note that the DHT sensors require a delay between subsequent reads or they may give a ETIMEDOUT error (because they are not ready for the next measurement).

I should note that the same boards seem to work fine using e.g. https://github.com/SuperHouse/esp-open-rtos/blob/master/examples/dht_sensor/dht_sensor.c.

This esp-open-rtos DHT driver puts the pin in open-drain mode, which is how it originally worked in uPy, so that at least is consistent.

I'm experiencing this same problem. Tried multiple sensors, all of which work with earlier firmware builds but not 1.9.4 release. Tried with and without pull-up resistor. Sensors work just fine using the Arduino environment (no pull-up required).

@quantalume what Arduino DHT driver did you use exactly? Looking at the Adafruit Arduino DHT driver, that code explicitly enables the pull-up when reading data from the DHT: https://github.com/adafruit/DHT-sensor-library/blob/master/DHT.cpp#L159 , so that could explain why it works (uPy just sets it to input).

@quantalume what value pull-up resistor did you try?

With a correct value for the pull-up (low enough, eg 4.7k), and enough delay between subsequent reads (eg 0.5s), I don't see why it shouldn't work with the uPy driver as it is currently.

dpgeorge added a commit to dpgeorge/micropython that referenced this issue Jan 21, 2019
The original behaviour of open-drain-high was to use the open-drain mode of
the GPIO pin, and this seems to make driving a DHT more reliable.  See
issue micropython#4233.
@dpgeorge
Copy link
Member

A fix for this is provided in #4415.

@larsks
8000 Copy link
Contributor Author
larsks commented Jan 22, 2019

Hey, my DHT22 sensors are working again! Thanks @dpgeorge!

@dpgeorge
Copy link
Member

Great, thanks @larsks for testing and confirming!

@dpgeorge
Copy link
Member

The above PR was merged in f102ac5 and 18d3a5d which should fix this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants
0