온습도 센서 이용한 온습도 측정 > 스마트기기시스템

본문 바로가기

[실습] 온습도 센서 이용한 온습도 측정

필기자
2026-04-27 17:30 884 0

본문

ASAIR-DHT22 온습도 센서를 이용한 온습도 측정

목 적
  • 라즈베리파이에 온습도 센서 사용법을 이해한다.
  • adafruit-circuitpython-dht 라이브러리 활용법을 이해한다.
  • Adafruit Blinka 라이브러리의 GPIO 제어 방식과 한계를 이해한다.
  • 하드웨어 PWM과 소프트웨어 PWM의 차이를 이해한다.
  • 온습도 측정값을 활용한 응용 프로그램 작성법을 이해한다.
목 차
1. ASAIR-DHT22 온습도 센서 모듈 설치
2. adafruit-circuitpython-dht 라이브러리 설치 및 명세
3. ASAIR-DHT22 온습도 센서 모듈 구동


1. ASAIR-DHT22 온습도 센서 모듈 설치
  • ASAIR-DHT22 온습도 센서
    • ASAIR-DHT22 센서는 온도와 습도를 측정할 수 있는 디지털 센서
    • 높은 정밀도와 안정성을 제공하며, 라즈베리파이와 같은 마이크로컨트롤러와 쉽게 통합할 수 있음.
    • 내장된 디지털 신호 처리 기능으로 온도와 습도 데이터를 정확하게 제공함.
    • 홈 자동화, 날씨 스테이션, 스마트 농업 등 다양한 응용 분야에 사용됨.
    • 기본 사양
      • 전원 공급: 3.3V ~ 5.5V DC
      • 소비 전류: 최대 1.5mA
      • 온도 측정 범위: -40°C ~ 80°C
      • 온도 정확도: ±0.5°C
      • 습도 측정 범위: 0-100% RH
      • 습도 정확도: ±2%
      • 응답 시간:
        • 습도: 5-30초 (63% 응답 기준)
        • 온도: 약 2초
    • GPIO 연결
      • GND  : Ground 접지(핀 14)
      • VCC : 5V Power(핀 2)
      • DATA : GPIO 18(핀 12)
      • NC : 사용하지 않음
    • ASAIR-DHT22 센서와 같은 온습도 센서를 연결할 때 GPIO 18(PCM_CLK)와 GPIO 4(GPCLK0)를 사용하는 이유
      • 두 핀 모두 기본적으로 특정 기능(PCM 클럭 또는 일반 목적 클럭)을 가지고 있지만 기능이 필요하지 않은 경우 일반 GPIO 핀으로 많이 사용됨.
      • 다른 GPIO 핀들의 I2C, SPI, UART 등과 같은 통신 기능을 가지고 있지 않아, 이런 특정 통신 기능과 충돌하지 않음.
    • NC 핀이란
      • NC (Not Connected) 핀은 전자 부품이나 회로에서 사용되지 않는 핀을 의미
    • NC 핀의 목적 및 역할
      • 회로 설계 시 표준화된 핀 배열을 유지하면서 특정 핀을 사용하지 않도록 할 수 있음.
      • 미래의 업그레이드나 다른 버전에서 추가 기능을 위해 남겨둔 핀일 수 있음.
      • 일부 회로에서는 특정 핀이 사용되지 않음으로써 다른 회로에 간섭을 줄일 수 있음.
    • NC 핀을 사용하지 않는 이유
      • NC 핀은 물리적으로 존재하지만, 내부적으로 회로에 연결되지 않았기 때문에 어떤 기능도 수행하지 않음.
      • 회로를 단순하게 유지하기 위해 사용하지 않는 핀은 무시하는 것이 일반적임.
      • NC 핀을 명확하게 구분해두면 다른 핀과 혼동을 피할 수 있음.
3232235521_unLvdtSF_db894a616b9641ba75137dd3d2c7bc745ff5331f.png
3232235521_61uA8ZCm_eefc280dbd3be11ea54069fa285ffa513ae167f0.png


2. adafruit-circuitpython-dht 라이브러리 설치 및 명세
  • 라이브러리 설치
    • DHT 센서 드라이버 라이브러리 설치
    • 의존성으로 Adafruit Blinka(GPIO 추상화 계층)가 자동 설치됨
    • 설치 후 import board, import digitalio, import pwmio, import adafruit_dht 모두 사용 가능

#adafruit-circuitpython-dht 라이브러리 설치
pip install adafruit-circuitpython-dht
  • Adafruit Blinka란
    • Adafruit가 만든 호환성 계층(compatibility layer) 라이브러리
    • CircuitPython(마이크로컨트롤러용 파이썬)에서 동작하는 코드를 라즈베리파이 같은 일반 리눅스 보드에서도 동작하게 해줌
    • board.D18 같은 핀 객체를 보드에 맞게 자동 매핑해 줌 → 같은 코드를 다른 보드(아두이노, ESP32 등)에서도 거의 그대로 사용 가능
    • 발음: 블링카(Blinka), 핀란드어로 "깜박이다(blink)"라는 뜻
    • GPIO 외에도 SPI, I²C, UART 같은 통신 프로토콜 모듈(busio)도 제공하지만, 본 단원에서는 DHT22 활용에만 집중
  • board 모듈 (Blinka 제공)
    • 라즈베리파이 GPIO 핀을 객체로 표현
    • D 뒤의 숫자는 BCM(GPIO) 번호를 의미
    • 라즈베리파이의 모든 GPIO 핀이 board.D0 ~ board.D27 객체로 매핑됨
    • 전체 핀 매핑표
      Blinka BCM 물리 핀 특수 기능
      board.D2 GPIO 2 3 I²C SDA
      board.D3 GPIO 3 5 I²C SCL
      board.D4 GPIO 4 7 GPCLK0
      board.D5 GPIO 5 29 -
      board.D6 GPIO 6 31 -
      board.D7 GPIO 7 26 SPI CE1
      board.D8 GPIO 8 24 SPI CE0
      board.D9 GPIO 9 21 SPI MISO
      board.D10 GPIO 10 19 SPI MOSI
      board.D11 GPIO 11 23 SPI SCLK
      board.D12 GPIO 12 32 하드웨어 PWM0
      board.D13 GPIO 13 33 하드웨어 PWM1
      board.D14 GPIO 14 8 UART TXD
      board.D15 GPIO 15 10 UART RXD
      board.D16 GPIO 16 36 -
      board.D17 GPIO 17 11 실습 LED 연결
      board.D18 GPIO 18 12 하드웨어 PWM0, DHT22 데이터 핀
      board.D19 GPIO 19 35 하드웨어 PWM1
      board.D20 GPIO 20 38 -
      board.D21 GPIO 21 40 -
      board.D22 GPIO 22 15 -
      board.D23 GPIO 23 16 -
      board.D24 GPIO 24 18 -
      board.D25 GPIO 25 22 -
      board.D26 GPIO 26 37 -
      board.D27 GPIO 27 13 실습 버튼 연결
  • digitalio 모듈 (Blinka 제공) - 디지털 입출력
    • GPIO 핀의 디지털 ON/OFF 제어를 담당
    • 주요 클래스
      • digitalio.DigitalInOut(pin) : GPIO 핀 객체 생성
    • 주요 속성/메서드 (DigitalInOut 객체에서 사용)
      • .direction  : 핀 방향 설정 (입력/출력)
        • digitalio.Direction.OUTPUT : 출력 모드
        • digitalio.Direction.INPUT  : 입력 모드
      • .value      : 핀의 HIGH/LOW 값
        • 출력 모드일 때 : True 대입 → HIGH 출력, False 대입 → LOW 출력
        • 입력 모드일 때 : 현재 핀 상태를 읽음 (True/False 반환)
      • .deinit()  : 핀 자원 해제
  • 프로그램 예시 - 출력 핀 (LED 1초 간격 깜박임)
    • GPIO 17번 핀에 LED 연결
    • 1초 간격으로 LED ON/OFF 무한 반복
    • Ctrl+C로 종료 시 자원 해제

import time
import board
import digitalio

# 1. 핀 객체 생성 (GPIO 17)
led = digitalio.DigitalInOut(board.D17)

# 2. 방향 설정 (출력 모드)
led.direction = digitalio.Direction.OUTPUT

# 3. 1초 간격으로 LED ON/OFF 반복
try:
    while True:
        led.value = True    # LED ON
        print('LED ON')
        time.sleep(1)
        led.value = False  # LED OFF
        print('LED OFF')
        time.sleep(1)
except KeyboardInterrupt:
    # 4. 자원 해제
    led.deinit()
    print('\n프로그램 종료')
  • 프로그램 예시 - 입력 핀 (버튼 폴링)
    • GPIO 27번 핀에 버튼 연결
    • 0.1초 간격으로 버튼 상태를 계속 읽으며, 눌림 상태가 바뀔 때만 출력
    • Blinka는 이벤트(인터럽트)를 지원하지 않으므로 폴링 방식 사용
    • Ctrl+C로 종료

import time
import board
import digitalio

# 1. 핀 객체 생성 (GPIO 27)
button = digitalio.DigitalInOut(board.D27)

# 2. 방향 설정 (입력 모드)
button.direction = digitalio.Direction.INPUT

# 3. 폴링 방식으로 버튼 상태 감시
prev_state = button.value
print('버튼 입력 대기 중... (Ctrl+C 종료)')
try:
    while True:
        curr_state = button.value
        # 상태가 바뀐 순간에만 출력 (눌림 검출)
        if curr_state != prev_state:
            if curr_state:
                print('버튼 떼짐 (HIGH)')
            else:
                print('버튼 눌림 (LOW)')
            prev_state = curr_state
        time.sleep(0.1)  # 0.1초 간격 폴링
except KeyboardInterrupt:
    # 4. 자원 해제
    button.deinit()
    print('\n프로그램 종료')
  • 디지털 LED + 버튼 통합 실습 - 버튼으로 LED 제어
    • 버튼을 누르고 있는 동안에만 LED가 켜지는 코드
    • GPIO 17 (LED), GPIO 27 (버튼) 사용
    • 0.05초 간격으로 폴링하여 버튼 상태에 따라 LED 제어

import time
import board
import digitalio

# LED 설정 (GPIO 17, 출력)
led = digitalio.DigitalInOut(board.D17)
led.direction = digitalio.Direction.OUTPUT

# 버튼 설정 (GPIO 27, 입력)
button = digitalio.DigitalInOut(board.D27)
button.direction = digitalio.Direction.INPUT

print('버튼을 누르면 LED가 켜집니다. (Ctrl+C 종료)')
try:
    while True:
        # 버튼이 눌리면 button.value가 False (LOW)
        if not button.value:
            led.value = True
        else:
            led.value = False
        time.sleep(0.05)
except KeyboardInterrupt:
    led.deinit()
    button.deinit()
    print('\n프로그램 종료')
  • RPi.GPIO와 Blinka digitalio 코드 비교
    동작 RPi.GPIO Blinka (digitalio)
    핀 모드 설정 GPIO.setmode(GPIO.BCM) (별도 설정 불필요)
    핀 객체 생성 GPIO.setup(17, GPIO.OUT) led = digitalio.DigitalInOut(board.D17)
    방향 설정 GPIO.setup(17, GPIO.OUT) led.direction = digitalio.Direction.OUTPUT
    HIGH 출력 GPIO.output(17, GPIO.HIGH) led.value = True
    LOW 출력 GPIO.output(17, GPIO.LOW) led.value = False
    입력값 읽기 GPIO.input(27) button.value
    이벤트 감지 GPIO.add_event_detect() 지원하지 않음 (폴링 사용)
    자원 해제 GPIO.cleanup() led.deinit()
  • pwmio 모듈 (Blinka 제공) - PWM(펄스폭 변조) 제어
    • LED 밝기, 모터 속도 등 아날로그처럼 동작하게 만드는 PWM 신호 생성
    • 주요 클래스
      • pwmio.PWMOut(pin, frequency, duty_cycle) : PWM 출력 객체 생성
    • 주요 속성/메서드 (PWMOut 객체에서 사용)
      • .frequency  : PWM 주파수 (Hz)
        • 객체 생성 시 frequency 인자로 초기값 지정
        • 속성에 값을 대입하여 동적으로 변경 가능
      • .duty_cycle : 듀티 사이클 (0 ~ 65535, 16비트 정수)
        • 0      → 0% (항상 OFF)
        • 32768 → 약 50%
        • 65535 → 100% (항상 ON)
        • RPi.GPIO의 0~100(%)와 단위가 다르므로 환산 필요
      • .deinit() : PWM 정지 및 자원 해제
  • 프로그램 예시 - LED 듀티 단계별 변화 관찰
    • GPIO 12번 핀에 LED 연결 (하드웨어 PWM 가능 핀)
    • 주파수 1000Hz, 듀티 0% → 25% → 50% → 75% → 100%로 1초씩 유지하며 반복
    • 각 단계별 LED 밝기 차이를 눈으로 확인

import time
import board
import pwmio

# 1. PWM 출력 객체 생성 (GPIO 12, 1000Hz, 초기 듀티 0)
led = pwmio.PWMOut(board.D12, frequency=1000, duty_cycle=0)

# 2. 듀티 사이클 단계 (0%, 25%, 50%, 75%, 100%)
duty_steps = [0, 25, 50, 75, 100]

print('LED 밝기 단계별 변화 (Ctrl+C 종료)')
try:
    while True:
        for percent in duty_steps:
            duty = int(percent / 100 * 65535)
            led.duty_cycle = duty
            print(f'듀티: {percent:3d}% ({duty})')
            time.sleep(1)
except KeyboardInterrupt:
    # 3. 자원 해제
    led.deinit()
    print('\n프로그램 종료')
  • 하드웨어 PWM
    • SoC(BCM2835/BCM2711) 칩 내부에 PWM 전용 회로가 내장
    • CPU 부하 거의 없음, 정밀한 타이밍 보장
    • 고주파(수 MHz)까지 안정적으로 출력 가능
    • 라즈베리파이는 GPIO 12, 13, 18, 19의 4개 핀에서만 사용 가능
    • PWM 채널은 2개 (PWM0, PWM1)
      • PWM0 채널 : GPIO 12, GPIO 18
      • PWM1 채널 : GPIO 13, GPIO 19
      • 같은 채널을 공유하는 두 핀은 동일한 주파수/듀티로만 동작
  • 소프트웨어 PWM
    • CPU가 직접 ON/OFF를 반복하여 PWM을 흉내냄
    • 모든 GPIO 핀에서 사용 가능
    • CPU 부하 발생, 다른 작업이 끼어들면 타이밍 흔들림
    • 주파수 한계 : 약 1kHz
      • 1초에 1000번 ON/OFF = 1주기 1ms = 듀티 50%면 500µs ON/500µs OFF
      • 리눅스가 RTOS가 아니므로 µs 단위 타이밍 흔들림 발생
      • 1kHz 이상은 듀티 정확도가 떨어지고 CPU 부하가 급증
    • LED 밝기 조절 정도엔 충분, 정밀 모터 제어나 오디오 신호 같은 고주파 용도엔 부적합
  • 라이브러리별 PWM 지원 비교
    라이브러리 하드웨어 PWM 소프트웨어 PWM 최대 주파수 (안정) 듀티 사이클 단위 사용 가능 핀
    RPi.GPIO 지원하지 않음 지원 (모든 핀) 약 1 kHz 0 ~ 100 (%) 모든 GPIO
    pwmio (Blinka) 지원 지원하지 않음 수 MHz 0 ~ 65535 (16비트) GPIO 12, 13, 18, 19
    pigpio 지원 지원 (DMA 기반, 안정적) HW: 수 MHz / SW: 수십 kHz 0 ~ 1000000 모든 GPIO
  • 듀티 사이클 단위 환산
    • RPi.GPIO 50%  →  pwmio 약 32768 (= 65535 × 0.5)
    • 퍼센트(0~100)를 16비트값으로 환산: duty = int(percent / 100 × 65535)
  • PWM LED 실습 - LED 밝기 점진적 페이드 (Blinka pwmio 사용)
    • GPIO 12번 핀에 LED 연결 (하드웨어 PWM 가능 핀)
    • 밝기를 0% → 100% → 0%로 부드럽게 변화시켜 페이드 효과 구현
    • 주파수 1000Hz 고정, duty_cycle 0.05초 간격으로 5%씩 변화 (한 사이클 약 4초)

import time
import board
import pwmio

# PWM 출력 객체 생성 (GPIO 12, 1000Hz, 초기 듀티 0)
led = pwmio.PWMOut(board.D12, frequency=1000, duty_cycle=0)

print('LED 페이드 인/아웃 (Ctrl+C 종료)')
try:
    while True:
        # 0 → 100% (밝아짐)
        for percent in range(0, 101, 5):
            led.duty_cycle = int(percent / 100 * 65535)
            print(f'듀티: {percent:3d}%')
            time.sleep(0.05)
        # 100% → 0% (어두워짐)
        for percent in range(100, -1, -5):
            led.duty_cycle = int(percent / 100 * 65535)
            print(f'듀티: {percent:3d}%')
            time.sleep(0.05)
except KeyboardInterrupt:
    led.deinit()
    print('\n프로그램 종료')
  • RPi.GPIO와 Blinka pwmio 코드 비교
    동작 RPi.GPIO Blinka (pwmio)
    핀 모드 설정 GPIO.setmode(GPIO.BCM) (별도 설정 불필요)
    핀 출력 모드 설정 GPIO.setup(12, GPIO.OUT) (객체 생성 시 자동 처리)
    PWM 객체 생성 pwm = GPIO.PWM(12, 1000) led = pwmio.PWMOut(board.D12, frequency=1000, duty_cycle=0)
    PWM 시작 pwm.start(0) (객체 생성과 동시에 시작)
    듀티 사이클 변경 (50%) pwm.ChangeDutyCycle(50) led.duty_cycle = 32768
    듀티 사이클 단위 0 ~ 100 (%) 0 ~ 65535 (16비트 정수)
    주파수 변경 pwm.ChangeFrequency(500) led.frequency = 500
    최대 안정 주파수 약 1 kHz 수 MHz
    PWM 정지 pwm.stop() led.deinit()
    자원 해제 GPIO.cleanup() led.deinit()
    사용 가능 핀 모든 GPIO (소프트웨어 PWM) GPIO 12, 13, 18, 19 (하드웨어 PWM)
  • 주의: GPIO 17, 27 같은 일반 핀에 pwmio.PWMOut을 호출하면 오류 발생
    • 예: pwmio.PWMOut(board.D17, ...) → ValueError 또는 RuntimeError
    • 모든 핀에서 PWM이 필요한 경우에는 RPi.GPIO의 소프트웨어 PWM 사용
  • Blinka 라이브러리의 한계
    • 이벤트(인터럽트) 미지원
      • RPi.GPIO의 add_event_detect 같은 콜백 등록 기능이 없음
      • 버튼 입력 등은 while 루프로 직접 값을 읽는 폴링(polling) 방식만 가능
      • 이벤트 기반 제어가 필요한 경우 RPi.GPIO 또는 별도 패치 사용 필요
    • 하드웨어 PWM만 지원
      • pwmio는 GPIO 12, 13, 18, 19에서만 동작
      • 그 외 핀에서 PWM이 필요하면 RPi.GPIO 소프트웨어 PWM 사용 (단, 약 1kHz 이내로 제한됨)
    • 듀티 사이클 단위 차이
      • pwmio는 0~65535(16비트), RPi.GPIO는 0~100(%)
      • 코드 이식 시 환산 필요
    • 실습 환경에서의 RPi.GPIO vs Blinka 기능 비교
      기능 RPi.GPIO (+ gpio_patch) Blinka
      디지털 출력 지원 지원
      디지털 입력 지원 지원
      이벤트 감지 (콜백) 지원 (gpio_patch로 폴링 fallback 처리) 지원하지 않음
      모든 핀 PWM 지원 (소프트웨어 PWM, 약 1kHz 한계) 지원하지 않음 (하드웨어 4개 핀만)
      고주파 PWM 지원하지 않음 지원 (4개 핀, 수 MHz)
      듀티 사이클 단위 0 ~ 100 (직관적) 0 ~ 65535 (환산 필요)
    • 정리
      • Blinka는 센서 라이브러리(adafruit_dht 등) 의존성과 간단한 GPIO 제어용으로 적합
      • 이벤트 처리, 모든 핀 PWM이 필요한 경우 기존 RPi.GPIO를 병행 사용
      • 고주파 PWM이 필요한 경우 Blinka pwmio (GPIO 12/13/18/19) 사용
3. ASAIR-DHT22 온습도 센서 모듈 구동
  • adafruit_dht 모듈
    • DHT 시리즈 센서 전용 드라이버 라이브러리
    • 1-Wire 타이밍 제어, 데이터 파싱, 체크섬 검증을 모두 내부에서 처리
    • 주요 클래스
      • adafruit_dht.DHT22(pin) : DHT22 센서 객체 생성
      • adafruit_dht.DHT11(pin) : DHT11 센서 객체 생성
    • 주요 속성/메서드 (DHT22/DHT11 객체에서 사용)
      • .temperature : 현재 온도(°C, float)
        • 속성을 읽는 시점에 1-Wire 통신이 시작되며 측정이 발생
        • 측정 실패 시 None 또는 RuntimeError 발생
      • .humidity    : 현재 습도(%, float)
        • 속성을 읽는 시점에 측정이 발생
        • 측정 실패 시 None 또는 RuntimeError 발생
      • .exit()       : 센서 자원 해제(GPIO 정리)
  • 주요 예외 처리
    • RuntimeError : 일시적 통신 실패(타이밍 누락) → 무시하고 다음 측정 시도
    • Exception    : GPIO 점유 충돌 등 치명적 오류 → exit() 호출 후 종료
  • 라즈베리파이 가상환경에서 파이썬 코딩
    • VSCode에서 dht22_sensor.py 파일 생성
    • DHT22 센서에서 온도와 습도 데이터를 읽어 주기적으로 출력하는 코드 실습

import time
import board
import adafruit_dht
# DHT22 센서 설정 (GPIO 18)
dht_device = adafruit_dht.DHT22(board.D18)
while True:
    try:
        # 센서에서 온도와 습도 읽기
        temperature = dht_device.temperature
        humidity = dht_device.humidity
        # 데이터 출력
        if humidity is not None and temperature is not None:
            print(f'온도: {temperature:.1f}°C')
            print(f'습도: {humidity:.1f}%')
        else:
            print('읽기 실패. 데이터가 없습니다.')
    except RuntimeError as error:
        # 센서에서 데이터를 읽는 중 오류 발생 처리
        print(error.args[0])
   
    except Exception as error:
        dht_device.exit()
        raise error
    # 10초 동안 대기
    time.sleep(10)
  • 코드 라인별 해설
    • import board
      • Adafruit Blinka 라이브러리의 모듈
      • 라즈베리파이 GPIO 핀을 객체 형태로 추상화하여 제공
    • import adafruit_dht
      • DHT 시리즈 센서 전용 드라이버 라이브러리
      • 내부에서 1-Wire 통신, 데이터 파싱, 체크섬 검증까지 모두 처리
    • dht_device = adafruit_dht.DHT22(board.D18)
      • DHT22 센서 객체 생성
      • board.D18 → BCM GPIO 18번 핀(물리 핀 12)을 데이터 핀으로 지정
    • temperature = dht_device.temperature
      • 이 속성을 읽는 시점에 실제 측정이 발생(라이브러리가 1-Wire 통신 시작)
      • 측정 성공 시 float(섭씨 온도) 반환, 실패 시 None 또는 RuntimeError
    • humidity = dht_device.humidity
      • 마찬가지로 호출 시점에 측정 발생
      • 측정 성공 시 float(% RH) 반환
    • if humidity is not None and temperature is not None:
      • 측정값이 None인 경우(일시적 실패)에 대비한 방어 코드
    • except RuntimeError as error:
      • 일시적인 타이밍 실패는 정상적으로 자주 발생함
      • 오류 메시지만 출력하고 다음 루프에서 재측정 시도
    • except Exception as error:
      • RuntimeError 외의 치명적 오류 발생 시 처리
      • dht_device.exit()로 GPIO 자원을 해제한 후 예외를 다시 던져 프로그램 종료
    • time.sleep(10)
      • 10초 간격으로 측정 반복
      • 너무 자주 측정하면 센서가 정확한 값을 제공하지 못함
※ 실측 시 주의사항
  • 10초 대기 시간을 갖는 이유
    • DHT22 센서의 제한 사항으로 인해 최소 2초의 간격을 두고 데이터를 요청해야 하며, 너무 자주 데이터를 요청하면 센서가 정확한 값을 제공하지 못함.
    • 자주 데이터를 요청하면 전력 소비가 증가함으로, 10초 간격으로 데이터를 요청함으로써 전력 소비를 줄일 수 있음.
    • 온도와 습도는 일반적으로 빠르게 변하지 않으므로, 10초 간격으로 데이터를 요청하면 실시간 모니터링에 충분히 적절한 데이터를 얻을 수 있음.
  • RuntimeError가 자주 발생하는 이유
    • DHT22는 마이크로초(µs) 단위로 비트 신호를 송신함
    • 라즈베리파이 OS(Linux)는 실시간 운영체제(RTOS)가 아니므로, 다른 작업이 끼어들면 비트 타이밍을 놓칠 수 있음
    • 이 경우 라이브러리는 RuntimeError를 발생시키며, 이는 비정상이 아닌 정상적으로 자주 일어나는 현상임
    • 따라서 try/except로 감싸 무시하고 다음 측정으로 넘어가는 구조가 표준 패턴임
  • 첫 측정값의 신뢰도
    • 전원 인가 직후 센서 내부 회로가 안정화되기 전에는 측정값이 부정확할 수 있음
    • 첫 1~2회 측정값은 무시하거나, 일정 시간 워밍업 후 사용하는 것이 안정적





--------------------------------------- 다음 오프라인 강의때 실습 -----------------------------------

[응용 문제: 온도 센서와 Blinka 라이브러리 실습]
  • 응용 예시 1 : 온도 임계치에 따른 LED 제어 (Blinka digitalio 사용)
    • 온도가 28°C 이상일 때 LED를 켜고, 미만일 때 LED를 끄는 코드
    • GPIO 17번 핀에 LED 연결
    • RPi.GPIO 없이 Blinka의 digitalio 모듈만으로 LED 제어
    • 10초 간격으로 측정 후 LED 상태 갱신

import time
import board
import digitalio
import adafruit_dht

# LED 설정 (GPIO 17)
led = digitalio.DigitalInOut(board.D17)
led.direction = digitalio.Direction.OUTPUT

# DHT22 센서 설정 (GPIO 18)
dht_device = adafruit_dht.DHT22(board.D18)

# 임계 온도
THRESHOLD = 28.0

print('온도 모니터링 시작 (Ctrl+C 종료)')
try:
    while True:
        try:
            temperature = dht_device.temperature
            humidity = dht_device.humidity
            if temperature is not None:
                print(f'온도: {temperature:.1f}°C / 습도: {humidity:.1f}%')
                if temperature >= THRESHOLD:
                    led.value = True
                    print('LED ON (고온 경고)')
                else:
                    led.value = False
                    print('LED OFF')
        except RuntimeError as error:
            print(error.args[0])
        time.sleep(10)
except KeyboardInterrupt:
    led.deinit()
    dht_device.exit()
    print('\n프로그램 종료')
  • 응용 예시 2 : 온도에 따른 LED 밝기 PWM 제어 (Blinka pwmio 사용)
    • 온도가 높아질수록 LED를 더 밝게 표시
    • 측정 범위: 20°C ~ 35°C → 듀티 사이클 0% ~ 100%로 매핑
    • GPIO 12번 핀에 LED 연결 (하드웨어 PWM 가능 핀)
    • 주의: GPIO 18은 DHT22 데이터 핀으로 사용 중이므로 PWM 핀으로 사용 불가

import time
import board
import pwmio
import adafruit_dht

# PWM LED 설정 (GPIO 12, 1000Hz)
led = pwmio.PWMOut(board.D12, frequency=1000, duty_cycle=0)

# DHT22 센서 설정 (GPIO 18)
dht_device = adafruit_dht.DHT22(board.D18)

# 온도 → 듀티 사이클(0~65535) 매핑 함수
def temp_to_duty(temp, t_min=20.0, t_max=35.0):
    if temp <= t_min:
        return 0
    if temp >= t_max:
        return 65535
    percent = (temp - t_min) / (t_max - t_min)
    return int(percent * 65535)

print('온도 → LED 밝기 매핑 시작 (Ctrl+C 종료)')
try:
    while True:
        try:
            temperature = dht_device.temperature
            if temperature is not None:
                duty = temp_to_duty(temperature)
                led.duty_cycle = duty
                percent = duty / 65535 * 100
                print(f'온도: {temperature:.1f}°C / 듀티: {duty} ({percent:.1f}%)')
        except RuntimeError as error:
            print(error.args[0])
        time.sleep(10)
except KeyboardInterrupt:
    led.deinit()
    dht_device.exit()
    print('\n프로그램 종료')



 

댓글목록0

등록된 댓글이 없습니다.
게시판 전체검색