In this article, we connect a KY-015 Temperature Sensor to a Raspberry Pi Pico 2, any rp2350 type board will be suitable. There are many good ones, I actually used a Pimoroni one as it was on hand
Overview
We will use Micropython for these examples but of course you can use the Arduino IDE as well if you have Raspberry Pi Pico support enabled
The KY-015 is a DHT11 is a low-cost, digital sensor widely used for measuring temperature and humidity in various applications. It consists of a thermistor for temperature sensing and a capacitive humidity sensor, combined with a basic signal processing unit.
The sensor outputs calibrated digital data, making it simple to interface with microcontrollers, such as Arduino, Raspberry Pi, or ESP8266. Its compact size, low power consumption, and ease of use make it an ideal choice for hobbyists and small-scale IoT projects.
The DHT11 operates within a temperature range of 0°C to 50°C and a humidity range of 20% to 90%, with an accuracy of ±2°C for temperature and ±5% for humidity.
While it is affordable and beginner-friendly, the DHT11 has limitations, such as relatively slow response times and lower accuracy compared to more advanced sensors like the DHT22 or SHT series.
Nevertheless, it remains popular for basic environmental monitoring, such as weather stations, home automation systems, and agricultural applications where high precision is not critical.
Later sensors use I2C, one drawback is that the device is slow – you need sleeps/delays between readings,
- Operating Voltage: 3.3V to 5V
- Current Consumption: 1.5mA
- Temperature Measurement Range: 32ºF to 122ºF( 0ºC to 50ºC)
- Temperature Measurement Accuracy: ±2ºC
- Temperature Measurement Resolution: 1ºC
- Humidity Measurement Range: 20% to 90% RH
- Humidity Measurement Resolution: ±5% RH
- Digital Out Signal Transmission Range:
- Dimensions: .75in X 1.77in (2cm x 4.5cm)
The sensor looks like this
Parts Required
You can connect to the module using dupont style jumper wire.
Name | Link |
Raspberry Pi Pico 2 | |
37 in one sensor kit | |
Connecting cables |
Schematic/Connection
Pico | SENSOR |
---|---|
GPIO27 | S |
3v3 | + |
GND | – |
The part I had was Pico but the pinout for a Pico 2 is the same – so this works just fine
Code Examples
Basic example – this requires a file called dht.py and the example code.
dht.py
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()
code.py
from machine import Pin import utime as time from dht import DHT11, InvalidChecksum while True: time.sleep(1) pin = Pin(27, Pin.OUT, Pin.PULL_DOWN) sensor = DHT11(pin) t = (sensor.temperature) h = (sensor.humidity) print("Temperature: {}".format(sensor.temperature)) print("Humidity: {}".format(sensor.humidity)) time.sleep(1)
REPL Output
>> %Run -c $EDITOR_CONTENT
Temperature: 19.2
Humidity: 48.0
Temperature: 19.2
Humidity: 48.0
Temperature: 19.3
Humidity: 48.0
Temperature: 19.5
Humidity: 48.0
Temperature: 19.3
Humidity: 49.0
Temperature: 19.7
Humidity: 50.0