Chapter 7. DHT11 온습도 센서와 LCD 시각화
주변의 온도와 습도를 정밀하게 측정하는 DHT11 센서를 다뤄보고, 수집된 데이터를 LCD 화면에 깔끔하게 출력하는 웨더 스테이션의 기초를 다집니다.
DHT11: VCC→3V3, Data→GP15, GND→GND. LCD는 SDA→GP8, SCL→GP9에 연결합니다.
7.1 준비물과 연결 핀
센서와 LCD를 함께 쓰는 장이므로 데이터 선과 I2C 선을 구분해서 연결합니다. LCD 주소가 다르면 Chapter 9의 I2C 스캔 코드로 주소를 먼저 확인하세요.
| 부품 | Pico 2 W 핀 | 역할 |
|---|---|---|
| DHT11 Data | GP15 | 온습도 데이터 입력 |
| LCD SDA / SCL | GP8 / GP9 | I2C 화면 출력 |
| 전원 / GND | 3V3, GND | 공통 전원 기준 |
7.2 실시간 환경 모니터링 소스 코드
MicroPython의 내장 dht 라이브러리를 사용합니다. Chapter 9에서 사용한 LCD 라이브러리가 Pico에 이미 저장되어 있어야 합니다.
import machine
import dht
import time
from pico_i2c_lcd import I2cLcd
# I2C LCD 설정
i2c = machine.I2C(0, sda=machine.Pin(8), scl=machine.Pin(9), freq=400000)
lcd = I2cLcd(i2c, 0x27, 2, 16)
sensor = dht.DHT11(machine.Pin(15))
def lcd_line(row, text):
lcd.move_to(0, row)
lcd.putstr(text[:16].ljust(16))
def show_status(temp=None, hum=None, error=None):
if error:
lcd_line(0, "DHT11 Error")
lcd_line(1, "Check wiring")
print("센서 읽기 실패:", error)
return
lcd_line(0, f"Temp: {temp:>2} C")
lcd_line(1, f"Hum : {hum:>2} %")
print(f"온도: {temp}C, 습도: {hum}%")
print("온습도 모니터링 시스템 시작...")
lcd_line(0, "DHT11 + LCD")
lcd_line(1, "Initializing...")
time.sleep(1)
while True:
try:
sensor.measure()
temp = sensor.temperature()
hum = sensor.humidity()
show_status(temp, hum)
except OSError as e:
show_status(error=e)
# DHT11은 너무 자주 읽으면 실패하므로 2초 이상 간격을 둡니다.
time.sleep(2)
7.3 동작 흐름
Pico는 2초마다 DHT11에 측정을 요청하고 온도와 습도 값을 읽습니다. 정상 값은 LCD 두 줄에 고정 폭으로 표시하고, 읽기 실패가 발생하면 배선 확인 메시지를 띄워 수업 중 디버깅이 쉽도록 했습니다.
💡 DHT11은 왜 다른 센서와 다르게 다루기가 까다로운가요?
HC-SR04나 가변저항과 달리, DHT11은 단일 데이터 핀(1-Wire와 유사한 독자 프로토콜)으로 온도와 습도 값을 순서대로 통신하여 전달합니다. 이 통신 타이밍은 매우 엄격해서 사람이 직접 time.sleep_us()로 구현하기 어렵기 때문에, MicroPython에 내장된 dht 모듈이 이 저수준 통신을 대신 처리해 줍니다. 그래서 우리는 sensor.measure()(측정 요청) → sensor.temperature()(온도 읽기) → sensor.humidity()(습도 읽기) 세 단계만 호출하면 됩니다.
💡 왜 2초보다 자주 측정하면 안 되나요?
DHT11 센서 자체의 하드웨어 한계로, 한 번 측정한 뒤 최소 1~2초의 회복 시간이 필요합니다. 이 간격보다 빠르게 measure()를 호출하면 통신 타이밍이 꼬여 OSError(체크섬 오류 등)가 자주 발생합니다. 코드에서 time.sleep(2)로 충분한 간격을 두는 이유입니다.
💡 DHT11 사용 팁
DHT11은 매우 저렴하고 대중적이지만, 온도는 ±2℃, 습도는 ±5% 정도의 오차가 있을 수 있습니다. 더 정밀한 프로젝트를 원하신다면 DHT22나 BME280 센서를 고려해 보세요. 코드 구조는 거의 동일합니다.
🏆 과제 해결해보기!
과제 1. 온도에 따라 경고 메시지 표시하기
측정한 온도가 28℃ 이상이면 LCD 두 번째 줄에 "Hum : xx % HOT!"처럼 경고를 표시하고, 그렇지 않으면 평소처럼 습도만 표시하는 코드를 작성해 보세요.
과제 2. 최고/최저 온도 기록하기
측정을 반복하는 동안 지금까지 측정된 값 중 가장 높았던 온도와 가장 낮았던 온도를 변수에 저장해두었다가, 매 측정마다 콘솔에 "현재 / 최고 / 최저" 온도를 함께 출력하는 코드를 작성해 보세요.
7.4 Wokwi 시뮬레이션으로 실습하기
Chapter 1의 1.8 실물 없이도 실습! Wokwi 온라인 시뮬레이터에서 소개한 대로, Wokwi를 사용하면 DHT11과 I2C LCD가 아직 없어도 브라우저에서 온습도 모니터링 회로를 미리 실습해 볼 수 있습니다.
DHT11 부품 대체 안내
Wokwi 부품 라이브러리에는 DHT11이 없고 DHT22(wokwi-dht22)만 제공됩니다. 시뮬레이션 목적으로는 DHT22 부품을 사용하되, main.py 코드에서도 dht.DHT11(...) 대신 dht.DHT22(...)로 바꿔서 붙여넣어야 정상 동작합니다. 실제 하드웨어(교실의 실물 DHT11)로 테스트할 때는 원래대로 dht.DHT11(...)을 사용하세요.
📄 diagram.json 예시 (DHT22로 대체 + I2C LCD1602)
{
"version": 1,
"author": "picostudy",
"editor": "wokwi",
"parts": [
{ "type": "wokwi-pi-pico", "id": "pico", "top": 0, "left": 0, "attrs": {} },
{ "type": "wokwi-dht22", "id": "dht1", "top": -60, "left": 200, "attrs": {} },
{ "type": "wokwi-lcd1602", "id": "lcd1", "top": 100, "left": 220, "attrs": { "pins": "i2c" } }
],
"connections": [
[ "pico:GP15", "dht1:SDA", "green", [] ],
[ "pico:3V3", "dht1:VCC", "red", [] ],
[ "pico:GND", "dht1:GND", "black", [] ],
[ "pico:GP8", "lcd1:SDA", "green", [] ],
[ "pico:GP9", "lcd1:SCL", "yellow", [] ],
[ "pico:3V3", "lcd1:VCC", "red", [] ],
[ "pico:GND", "lcd1:GND", "black", [] ]
]
}
아래는 Wokwi 시뮬레이션 전용으로 DHT11을 DHT22로 바꾼 예시 코드입니다. 실제 라이브러리 파일(pico_i2c_lcd.py, lcd_api.py)은 Wokwi 프로젝트의 파일 추가(+) 버튼으로 함께 업로드해야 합니다.
import machine
import dht # 시뮬레이션 전용: DHT11 대신 DHT22 클래스 사용
import time
from pico_i2c_lcd import I2cLcd
i2c = machine.I2C(0, sda=machine.Pin(8), scl=machine.Pin(9), freq=400000)
lcd = I2cLcd(i2c, 0x27, 2, 16)
sensor = dht.DHT22(machine.Pin(15)) # 실제 하드웨어에서는 dht.DHT11(...)로 되돌리기
while True:
try:
sensor.measure()
temp = sensor.temperature()
hum = sensor.humidity()
lcd.move_to(0, 0)
lcd.putstr(f"Temp: {temp:>2} C".ljust(16))
lcd.move_to(0, 1)
lcd.putstr(f"Hum : {hum:>2} %".ljust(16))
except OSError as e:
print("측정 실패:", e)
time.sleep(2)
회로와 코드를 준비했다면 화면 상단의 ▶️ (초록색 재생) 버튼을 눌러 시뮬레이션을 시작하세요. Wokwi 화면에서 DHT22 부품을 클릭하면 가상의 온도·습도 슬라이더가 나타나 값을 자유롭게 바꿔가며 LCD 출력을 확인할 수 있습니다.