DHT11 With Raspberry Pi Pico

24K617

Intro: DHT11 With Raspberry Pi Pico

The DHT11 is a commonly used temperature and humidity sensor. The sensor comes with a dedicated NTC to measure temperature and an 8-bit microcontroller to output the values of temperature and humidity as serial data. The sensor is also factory calibrated and hence easy to interface with other microcontrollers. The sensor can measure temperature from 0°C to 50°C and humidity from 20% to 90% with an accuracy of ±1°C and ±1%.

STEP 1: Step 1 : Connect Pins of DHT11 With the Pins of Raspberry Pi Pico

DHT11 pin > Pi Pin

Vcc > Pin 36

GND > Pin 38

Data > Pin4(GPIO28)

STEP 2: Step 2 :Write the Code Save It As Dht11.py and Run It

import array
import micropython
import utime
from machine import Pin
from micropython import const
 
class InvalidChecksum(Exception):
    pass
 
class InvalidPulseCount(Exception):
    pass
 
MAX_UNCHANGED = const(100)
MIN_INTERVAL_US = const(200000)
HIGH_LEVEL = const(50)
EXPECTED_PULSES = const(84)
 
class DHT11:
    _temperature: float
    _humidity: float
 
    def __init__(self, pin):
        self._pin = pin
        self._last_measure = utime.ticks_us()
        self._temperature = -1
        self._humidity = -1
 
    def measure(self):
        current_ticks = utime.ticks_us()
        if utime.ticks_diff(current_ticks, self._last_measure) < MIN_INTERVAL_US and (
            self._temperature > -1 or self._humidity > -1
        ):
            # Less than a second since last read, which is too soon according
            # to the datasheet
            return
 
        self._send_init_signal()
        pulses = self._capture_pulses()
        buffer = self._convert_pulses_to_buffer(pulses)
        self._verify_checksum(buffer)
 
        self._humidity = buffer[0] + buffer[1] / 10
        self._temperature = buffer[2] + buffer[3] / 10
        self._last_measure = utime.ticks_us()
 
    @property
    def humidity(self):
        self.measure()
        return self._humidity
 
    @property
    def temperature(self):
        self.measure()
        return self._temperature
 
    def _send_init_signal(self):
        self._pin.init(Pin.OUT, Pin.PULL_DOWN)
        self._pin.value(1)
        utime.sleep_ms(50)
        self._pin.value(0)
        utime.sleep_ms(18)
 
    @micropython.native
    def _capture_pulses(self):
        pin = self._pin
        pin.init(Pin.IN, Pin.PULL_UP)
 
        val = 1
        idx = 0
        transitions = bytearray(EXPECTED_PULSES)
        unchanged = 0
        timestamp = utime.ticks_us()
 
        while unchanged < MAX_UNCHANGED:
            if val != pin.value():
                if idx >= EXPECTED_PULSES:
                    raise InvalidPulseCount(
                        "Got more than {} pulses".format(EXPECTED_PULSES)
                    )
                now = utime.ticks_us()
                transitions[idx] = now - timestamp
                timestamp = now
                idx += 1
 
                val = 1 - val
                unchanged = 0
            else:
                unchanged += 1
        pin.init(Pin.OUT, Pin.PULL_DOWN)
        if idx != EXPECTED_PULSES:
            raise InvalidPulseCount(
                "Expected {} but got {} pulses".format(EXPECTED_PULSES, idx)
            )
        return transitions[4:]
 
    def _convert_pulses_to_buffer(self, pulses):
        """Convert a list of 80 pulses into a 5 byte buffer
        The resulting 5 bytes in the buffer will be:
            0: Integral relative humidity data
            1: Decimal relative humidity data
            2: Integral temperature data
            3: Decimal temperature data
            4: Checksum
        """
        # Convert the pulses to 40 bits
        binary = 0
        for idx in range(0, len(pulses), 2):
            binary = binary << 1 | int(pulses[idx] > HIGH_LEVEL)
 
        # Split into 5 bytes
        buffer = array.array("B")
        for shift in range(4, -1, -1):
            buffer.append(binary >> shift * 8 & 0xFF)
        return buffer
 
    def _verify_checksum(self, buffer):
        # Calculate checksum
        checksum = 0
        for buf in buffer[0:4]:
            checksum += buf
        if checksum & 0xFF != buffer[4]:
            raise InvalidChecksum()

STEP 3: Step 3: Then Write This Code and Save It As Main.py and Run It

from machine import Pin, I2C
import utime as time
from dht import DHT11, InvalidChecksum

while True:
    time.sleep(5)
    pin = Pin(28, Pin.OUT, Pin.PULL_DOWN)
    sensor = DHT11(pin)
    t  = (sensor.temperature)
    h = (sensor.humidity)
    print("Temperature: {}".format(sensor.temperature))
    print("Humidity: {}".format(sensor.humidity))

STEP 4: Step 4 : Output

9 Comments

When I run the code only gives me
Temperature: 0.0
Humidity: 0.0
or
Temperature: 23.0
Humidity: 59.8
Do you know how to fix this?
I get this error can you help me ?

Traceback (most recent call last):
File "<stdin>", line 9, in <module>
File "dht.py", line 53, in temperature
File "dht.py", line 38, in measure
InvalidPulseCount: Expected 84 but got 0 pulses

I think the new version if MicroPython actually has a library called 'dht'

1. I saved the Dht11.py file as dhtlib.py
2. In my main.py I changed
from dht import DHT11, InvalidChecksum
to
from dhtlib import DHT11, InvalidChecksum

Code works perfect! When I tried using the inbuilt library (dht from micropython) I was getting values like 650ºc which is not right. I know get 25ºc and 65% humidity.

Cheers.
I got this code working but I tried to port it to a web server I have running on the pico that can be polled every minute. If I keep polling it every few seconds it continues to work but if I wait a certain amount of time the program crashes and I get the message "InvalidPulseCount: Expected 84 but got 0 pulses". Is there a maximum sample period after which the I2C bus times out? I did not see anything in the code that would imply this.
Schematic is right? for DHT11, left S pin should be connected to yellow cable and Center Pin(VCC) should be connected to Red Line.
You might consider adding "self.close()" before raising InvalidPulseCount. Otherwise the serial port may not close properly and the user won't be able to reconnect to the pico until the port gets closed.
The dht11 in the diagram is shown plugged in the bar on breadboard. Usually short circuited.
Its not working for me. When I run Main, it says it can't find DHT11, but it is saved on my Pico in the root. Its called DHT11.py and I can see it in the directory.
The import statement in main.py is looking for a file called dht.py - it does not import from the file you created in step 2. To fix this, in step 2, save the file as dht.py, instead of Dht11.py,