Interfacing DHT11 Temperature Humidity Sensor with Raspberry Pi Pico
In this tutorial we will learn Interfacing of DHT11 Temperature Humidity Sensor with Raspberry Pi Pico. We will write a MicroPython code for DHT11 Sensor. We will use 0.96″ I2C OLED Display and disply the DHT11 temperature and Humidity value on it.
The DHT11 is a basic, ultra low-cost digital temperature and humidity sensor. It uses a capacitive humidity sensor and a thermistor to measure the surrounding air. This sensor can be easily interfaced with any microcontroller such as Arduino or RP2040 Raspberry Pi Pico to measure humidity and temperature instantaneously. You can make a Weather Station project with DHT11 Sensor.
This post explains, the method of retrieving the Humidity & Temperature data from the DHT11 sensor using Raspberry Pi Pico & MicroPython Code. The retrieved data will be displayed on Python Shell Window and later on OLED Display. But before moving ahead, please follow the Raspberry Pi Pico Getting Started Tutorial to learn more about the Pico Board in detail.
Bill of MaterialsThe list of components that you need for this project is given below. You can purchase all the components from Amazon.
S.N.Components NameQuantityPurchase Links 1Raspberry Pi Pico1Amazon | AliExpress 20.96" I2C OLED Display1Amazon | AliExpress 3DHT11 Sensor1Amazon | AliExpress 4Jumper Wires1Amazon | AliExpress 5Breadboard1Amazon | AliExpress DHT11 Humidity Temperature SensorThe DHT11 is a basic, ultra low-cost digital temperature and humidity sensor. It uses a capacitive humidity sensor and a thermistor to measure the surrounding air and spits out a digital signal on the data pin (no analog input pins needed). The temperature range of DHT11 is from 0 to 50 degrees Celsius with a 2-degree accuracy. The humidity range of this sensor is from 20 to 80% with 5% accuracy.
DHT11 sensor has four pins- VCC, GND, Data Pin, and a not connected pin. A pull-up resistor of 5k to 10k ohms is provided for communication between sensor and micro-controller.
It’s fairly simple to use, but requires careful timing to grab data. The only real downside of this sensor is you can only get new data from it once every 2 seconds, so when using the library, sensor readings can be up to 2 seconds old. To learn more about the DHT11 Sensor, you can check the DHT11 Datasheet.
Setting up DHT11 Sensor with Raspberry Pi PicoThe hardware setup and hookup guide for DHT11 Sensor with Raspberry Pi Pico board & OLED Display is super easy. The connection diagram is given below.
Connect the DHT11 digital output pin to GP28 of Pico Board. Connect the SCL & SDA pin of OLED Display to Raspberry Pi Pico GP9 & GP8 Pin. Supply DHT11 & OLED Display with 3.3V VCC & Connect their GND pins to Pico GND Pin.
DHT11 Raspberry Pi Pico MicroPython CodeThe DHT11 MicroPython Code for Raspberry Pi Pico comprises of so many dependencies. We have to write MicroPython code for the DHT11 Library and also for the OLED Display.
The code comprises of 3 parts: 1. SSD1306.py 2. dht.py 3. main.py
SSD1306.pyFirst open a New Tab, and copy the following code. Save the file with the name SSD1306.py & then run or download it to the Raspberry Pi Pico Board.
# MicroPython SSD1306 OLED driver, I2C and SPI interfaces from micropython import const import framebuf # register definitions SET_CONTRAST = const ( 0x81 ) SET_ENTIRE_ON = const ( 0xA4 ) SET_NORM_INV = const ( 0xA6 ) SET_DISP = const ( 0xAE ) SET_MEM_ADDR = const ( 0x20 ) SET_COL_ADDR = const ( 0x21 ) SET_PAGE_ADDR = const ( 0x22 ) SET_DISP_START_LINE = const ( 0x40 ) SET_SEG_REMAP = const ( 0xA0 ) SET_MUX_RATIO = const ( 0xA8 ) SET_COM_OUT_DIR = const ( 0xC0 ) SET_DISP_OFFSET = const ( 0xD3 ) SET_COM_PIN_CFG = const ( 0xDA ) SET_DISP_CLK_DIV = const ( 0xD5 ) SET_PRECHARGE = const ( 0xD9 ) SET_VCOM_DESEL = const ( 0xDB ) SET_CHARGE_PUMP = const ( 0x8D ) # Subclassing FrameBuffer provides support for graphics primitives # http://docs.micropython.org/en/latest/pyboard/library/framebuf.html class SSD1306 ( framebuf . FrameBuffer ) : def __init__ ( self , width , height , external_vcc ) : self . width = width self . height = height self . external_vcc = external_vcc self . pages = self . height // 8 self . buffer = bytearray ( self . pages * self . width ) super ( ) . __init__ ( self . buffer , self . width , self . height , framebuf . MONO_VLSB ) self . init_display ( ) def init_display ( self ) : for cmd in ( SET_DISP | 0x00 , # off # address setting SET_MEM_ADDR , 0x00 , # horizontal # resolution and layout SET_DISP_START_LINE | 0x00 , SET_SEG_REMAP | 0x01 , # column addr 127 mapped to SEG0 SET_MUX_RATIO , self . height - 1 , SET_COM_OUT_DIR | 0x08 , # scan from COM[N] to COM0 SET_DISP_OFFSET , SET_COM_PIN_CFG , 0x02 if self . width > 2 * self . height else 0x12 , # timing and driving scheme SET_DISP_CLK_DIV , SET_PRECHARGE , 0x22 if self . external_vcc else 0xF1 , SET_VCOM_DESEL , 0x30 , # 0.83*Vcc SET_CONTRAST , 0xFF , # maximum SET_ENTIRE_ON , # output follows RAM contents SET_NORM_INV , # not inverted # charge pump SET_CHARGE_PUMP , 0x10 if self . external_vcc else 0x14 , SET_DISP | 0x01 , self . write_cmd ( cmd ) self . fill ( 0 ) self . show ( ) def poweroff ( self ) : self . write_cmd ( SET_DISP | 0x00 ) def poweron ( self ) : self . write_cmd ( SET_DISP | 0x01 ) def contrast ( self , contrast ) : self . write_cmd ( SET_CONTRAST ) self . write_cmd ( contrast ) def invert ( self , invert ) : self . write_cmd ( SET_NORM_INV | ( invert & 1 ) ) def show ( self ) : x1 = self . width - 1 if self . width == 64 : # displays with width of 64 pixels are shifted by 32 self . write_cmd ( SET_COL_ADDR ) self . write_cmd ( x0 ) self . write_cmd ( x1 ) self . write_cmd ( SET_PAGE_ADDR ) self . write_cmd ( 0 ) self . write_cmd ( self . pages - 1 ) self . write_data ( self . buffer ) class SSD1306_I2C ( SSD1306 ) : def __init__ ( self , width , height , i2c , addr = 0x3C , external_vcc = False ) : self . i2c = i2c self . addr = addr self . temp = bytearray ( 2 ) self . write_list = [ b "\x40" , None ] # Co=0, D/C#=1 super ( ) . __init__ ( width , height , external_vcc ) def write_cmd ( self , cmd ) : self . temp [ 0 ] = 0x80 # Co=1, D/C#=0 self . temp [ 1 ] = cmd self . i2c . writeto ( self . addr , self . temp ) def write_data ( self , buf ) : self . write_list [ 1 ] = buf self . i2c . writevto ( self . addr , self . write_list ) class SSD1306_SPI ( SSD1306 ) : def __init__ ( self , width , height , spi , dc , res , cs , external_vcc = False ) : self . rate = 10 * 1024 * 1024 dc . init ( dc . OUT , value = 0 ) res . init ( res . OUT , value = 0 ) cs . init ( cs . OUT , value = 1 ) self . spi = spi self . dc = dc self . res = res self . cs = cs import time self . res ( 1 ) time . sleep_ms ( 1 ) self . res ( 0 ) time . sleep_ms ( 10 ) self . res ( 1 ) super ( ) . __init__ ( width , height , external_vcc ) def write_cmd ( self , cmd ) : self . spi . init ( baudrate = self . rate , polarity = 0 , phase = 0 ) self . cs ( 1 ) self . dc ( 0 ) self . cs ( 0 ) self . spi . write ( bytearray ( [ cmd ] ) ) self . cs ( 1 ) def write_data ( self , buf ) : self . spi . init ( baudrate = self . rate , polarity = 0 , phase = 0 ) self . cs ( 1 ) self . dc ( 1 ) self . cs ( 0 ) self . spi . write ( buf ) self . cs ( 1 ) dht.pyAfter uploading the SSD1306 program, open a New Tab again and copy the following code. Save the file with the name dht.py & then run or download it to the Raspberry Pi Pico Board.
import array import micropython import utime from machine import Pin from micropython import const class InvalidChecksum ( Exception ) : class InvalidPulseCount ( Exception ) : 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 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 ( ) def humidity ( self ) : self . measure ( ) return self . _humidity 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 ) 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 val = 1 - val unchanged = 0 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 for idx in range ( 0 , len ( pulses ) , 2 ) : binary = binary HIGH_LEVEL )> 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 ( ) main.pyFinally open a New Tab again and copy the following code for main file. Save the file with the name main.py & then run or download it to the Raspberry Pi Pico Board.
from machine import Pin , I2C from ssd1306 import SSD1306_I2C import utime as time from dht import DHT11 , InvalidChecksum WIDTH = 128 # oled display width HEIGHT = 64 # oled display heighti2c = I2C ( 0 , scl = Pin ( 9 ) , sda = Pin ( 8 ) , freq = 200000 ) # Init I2C using pins GP8 & GP9 (default I2C0 pins)
print ( "I2C Address : " + hex ( i2c . scan ( ) [ 0 ] ) . upper ( ) ) # Display device address print ( "I2C Configuration: " + str ( i2c ) ) # Display I2C config oled = SSD1306_I2C ( WIDTH , HEIGHT , i2c ) # Init oled display while True : time . sleep ( 1 ) 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 ) ) # Clear the oled display in case it has junk on it. oled . fill ( 0 ) # Add some text oled . text ( "Temp: " , 10 , 10 ) oled . text ( str ( sensor . temperature ) , 50 , 10 ) oled . text ( "*C" , 90 , 10 ) oled . text ( "Humi: " , 10 , 30 ) oled . text ( str ( sensor . humidity ) , 50 , 30 ) oled . text ( "%" , 90 , 30 ) time . sleep ( 1 ) oled . show ( ) Monitoring Humidity & Temperature DataNow finally our project is ready and we can measure the temperature Humidity Data of the surrounding. As soon as the main.py is uploaded, the Shell window will start showing the tempeerature & Humidity Value.
Similarly the OLED Display will also display the temperature & Humidity value on the screen. The data is refreshed and displayed after the interval of every two seconds.
Video Tutorial & Guide Raspberry Pi Pico Complete Guide| Pinout+Features+ADC+I2C+OLED+Internal Temperature Sensor+DHT11 Previous Article Read Temperature Sensor Value from Raspberry Pi Pico Next Article IoT Bidirectional Visitor Counter using ESPP8266 & MQTT Related Posts ADXL375 Accelerometer with Raspberry Pi Pico & MicroPython Updated: July 24, 2025 Interface BMI160 with Raspberry Pi Pico & MicroPython Updated: February 2, 2025 2K Shift Register 74HC595 with Raspberry Pi Pico & MicroPython Updated: February 2, 2025 1 3K Interfacing XBee Module with Raspberry Pi Pico & MicroPython Updated: February 2, 2025 3K Modbus RTU with Raspberry Pi Pico & MicroPython Updated: February 2, 2025 7K Thermal Fever Detector with MLX90640 & OpenCV Raspberry Pi Updated: February 2, 2025 6K 13 Comments Thank you, in my case work with: in the main.py “pin = Pin(28, Pin.IN, Pin.PULL_UP)” ALAN SWINDELLS on April 19, 2021 3:38 AMNice bit of code – with a few extensions to main.py (most now written and working when powered from a Pi4 via Thonny) and nearly ready to control a temperature and humidity controlled cabinet. The question is, how can I get it to function independently from the Pi4?, i.e. just powered via USB or battery. I am very new to this game, and assumed that main.py would assure that everytihng would run fine in that situation.
Brad Johnson on June 5, 2021 11:50 PMRead Get started with MicroPython on Raspberry Pi Pico by Gareth Halfacree and Ben Everard starting on page 104.
Joshua Sherrill on December 25, 2021 10:45 AMi’m having problems with the main.py, “>>> %Run -c $EDITOR_CONTENT I2C Address : 0X3C I2C Configuration: I2C(0, freq=200000, scl=9, sda=8) Traceback (most recent call last): File “”, line 14, in File “SSD1306.py”, line 110, in init File “SSD1306.py”, line 31, in init NameError: name ‘Height’ isn’t defined
Please Help?trying to run on Pico – when I run main.py I get an error : ImportError: can’t import name SSD1306_I2C
hello , could you please help me to understand , why i see this error while run the “Main.py” Traceback (most recent call last): File “”, line 3, in ImportError: no module named ‘ssd1306’
hi , i also see the similar error when try to run “main.py” error: Traceback (most recent call last): File “”, line 3, in ImportError: no module named ‘ssd1306’
Clear the oled display in case it has junk on it. < code >oled . fill ( 0 )Traceback (most recent call last): File “”, line 26, in AttributeError: ‘tuple’ object has no attribute ‘fill’ I’m honestly at a loss.
Joshua Sherrill on January 31, 2022 3:55 AMDid you try “SSD1306” instead of “ssd1306”? It gave me an error for not using the correct capitalization.
how to round up the temp and hum with first digits ptrjns79 on July 13, 2022 11:25 PMI had this, it was because I saved it as suggested, with UPPERCASE. I renamed SSD1306.py to ssd1306.py and it seemed to work.
ptrjns79 on July 13, 2022 11:26 PMI had this, it was because I saved it as suggested, with UPPERCASE. I renamed SSD1306.py to ssd1306.py and it seemed to work..
Thanks for the nice writeup. I have a D091-12832-I2C oled display, so needed to change some settings. Like: HEIGHT = 32 (and not 64) And to this: oled.text(“Temp: “,0,0) oled.text(str(sensor.temperature),50,0) oled.text(“*C”,90,0)
< code >oled . text ( "Humi: " , 0 , 20 ) oled . text ( str ( sensor . humidity ) , 50 , 20 ) oled . text ( "%" , 90 , 20 )Now everything fits into the small screen. I saved everything to the pico but does not start without my PC. So needs to figure out why. All the best, Nandor
CommentsCancel reply Latest Posts ESP32 IoT Vehicle Motion Analyzer with MPU6050 & LIS3MDL March 10, 2026 Building a Smart Sensor Node with a BLE Microcontroller February 26, 2026 High-Accuracy Pitch, Roll, Yaw with ESP32 & BNO08x IMU February 16, 2026 DIY Colorimeter using AS7265x Spectroscopy Sensor & ESP32 February 1, 2026 Flight Black-Box Motion Recorder System using ESP32 & BMI160 December 7, 2025 ESP8266 & DHT11 Humidity Temperature Monitor on ThingSpeak October 19, 2025 IoT based Battery SoC (%) Monitoring System with ESP32 September 28, 2025 Speed-Run Translations: Making Fast-Moving Meme Videos Accessible Worldwide September 22, 2025 Top Posts & Pages Categories- Arduino Projects (197)
- Articles (59)
- Learn Electronics (19)
- Product Review (15)
- Tech Articles (27)
- 555 Timer Projects (21)
- Op-Amp Circuits (7)
- Power Electronics (13)
- ESP32 MicroPython (7)
- ESP32 Projects (78)
- ESP32-CAM Projects (15)
- ESP8266 Projects (76)
- LoRa/LoRaWAN Projects (22)
- AMB82-Mini IoT AI Camera (4)
- BLE Projects (18)
- STM32 Projects (19)
- Raspberry Pi Pico Projects (57)
- Raspberry Pi Pico W Projects (12)
- Raspberry Pi Projects (24)
“‘How to Electronics’ is a vibrant community for electronics enthusiasts and professionals. We deliver latest insights in areas such as Embedded Systems, Power Electronics, AI, IoT, and Robotics. Our goal is to stimulate innovation and provide practical solutions for students, organizations, and industries. Join us to transform learning into a joyful journey of discovery and innovation.
Copyright © How To Electronics. All rights reserved. Ad Blocker Enabled! Ad Blocker Enabled!Looks like you're using an ad blocker. Please allow ads on our site. We rely on advertising to help fund our site.