ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Raspberry Pi] 온도 습도 센서 동작 + 7 segment
    Raspberry Pi/Build with Pi 2026. 4. 4. 14:52

    오늘은 온습도 센서 동작과 온습도 센서에서 측정한 온도와 습도를 7 segment로 출력을 해보도록 하겠다.

     

    온도 습도 센서 동작

    온습도 센서는 아래 이미지와 같이 생겼다.

     

    먼저 이 녀석도 자세히 보면, S, VCC, GND라고 적혀있는데 

     

    전원(VCC, +) : 3.3V 공급 (1번핀)

    접지(GND, -) : Ground (6번핀)

    Data(S, out) : 온도/습도 값을 보내는 신호선 > GPIO4 (7번핀)

     

    으로 연결하면된다. 연결 후 모습은 아래와 같다.

    온습도 센서 연결

    이제 연결을 했다면 라즈베리파이를 켜서, 코드를 작성해 실행을 해보도록 하자.

    라즈베리파이를 켰다면 먼저 환경 설정이 필요하다. 가상환경을 만들어서 해보도록 하자.

    먼저 작업 폴더 생성, 그리고 해당 폴더에 가상환경을 설정한 다음, DHT 센서용 라이브러리를 설치하면 된다.(라이브러리 설치는 전역으로 설치해도 상관없다.)

     

    설치가 완료되었다면, 아래 코드를 작성하면 된다.

    import time
    import board
    import adafruit_dht
    
    # DHT11 센서 + GPIO4
    dhtDevice = adafruit_dht.DHT11(board.D4)
    
    while True:
        try:
            temperature_c = dhtDevice.temperature
            humidity = dhtDevice.humidity
    
            print(f" Temp: {temperature_c}°C   Humidity: {humidity}%")
    
        except RuntimeError as error:
            print("읽기 오류:", error.args[0])
            time.sleep(1.0)
            continue
    
        except Exception as error:
            dhtDevice.exit()
            raise error
    
        time.sleep(1.0)

    이제 코드를 실행하면, 다음과 같이 결과가 출력된다. 출력이 된다면 정상적으로 센서가 동작하고 있다는 의미이다.

     

    7 segment 

    7-Segment Display는 숫자를 표시하기 위해 7개의 막대 모양 LED를 표시한 장치이다. 7세그먼트는 각 획마다 a부터 g까지 이름이 붙어있으며, 오른쪽 하단의 소수점은 dp(decimal point)라고 부른다.

     

    https://devicemart.blogspot.com/2019/05/4-digit-fnd.html

    그럼 이제 이걸 연결을 해보도록 하자.

    회로 구성은 아래와 같이 연결하면 된다. (처음에 너무 복잡해서 블로그를 참고하였다..감사합니담)

    https://blog.naver.com/hhgintro/222034114801

    먼저 연결을 제대로 했다면, 이제 실제 잘 동작하는지 테스트를 해보자. 테스트 코드는 아래오 같고, 테스트 방식은 문자를 입력하면 해당 위치의 LED가 켜지는지 확인하면 된다. 정상적으로 다 출력이 된다면 다음은 숫자 출력 까지 확인을 해보도록 하자.

    import time
    import RPi.GPIO as GPIO
    
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)
    
    SEG_PINS = {
        'A': 11,
        'B': 4,
        'C': 23,
        'D': 8,
        'E': 7,
        'F': 10,
        'G': 18,
        'DP': 25
    }
    
    DIGIT_PIN = 22   # D1만 테스트
    
    NUM_MAP = {
        '0': ['A', 'B', 'C', 'D', 'E', 'F'],
        '1': ['B', 'C'],
        '2': ['A', 'B', 'D', 'E', 'G'],
        '3': ['A', 'B', 'C', 'D', 'G'],
        '4': ['B', 'C', 'F', 'G'],
        '5': ['A', 'C', 'D', 'F', 'G'],
        '6': ['A', 'C', 'D', 'E', 'F', 'G'],
        '7': ['A', 'B', 'C'],
        '8': ['A', 'B', 'C', 'D', 'E', 'F', 'G'],
        '9': ['A', 'B', 'C', 'D', 'F', 'G'],
    }
    
    for pin in SEG_PINS.values():
        GPIO.setup(pin, GPIO.OUT)
        GPIO.output(pin, GPIO.LOW)   # 일단 OFF 가정
    
    GPIO.setup(DIGIT_PIN, GPIO.OUT)
    GPIO.output(DIGIT_PIN, GPIO.HIGH)  # 일단 OFF 가정
    
    
    def all_off():
        # common cathode처럼 가정
        GPIO.output(DIGIT_PIN, GPIO.HIGH)
        for pin in SEG_PINS.values():
            GPIO.output(pin, GPIO.LOW)
    
    
    def set_segments(seg_list):
        # 반전 논리: ON = HIGH, OFF = LOW
        for name, pin in SEG_PINS.items():
            if name in seg_list:
                GPIO.output(pin, GPIO.HIGH)
            else:
                GPIO.output(pin, GPIO.LOW)
    
    
    def show_segments(seg_list, duration=2.0):
        end_time = time.time() + duration
        while time.time() < end_time:
            GPIO.output(DIGIT_PIN, GPIO.HIGH)   # 잠깐 끄기
            set_segments(seg_list)
            GPIO.output(DIGIT_PIN, GPIO.LOW)    # 자리 ON
            time.sleep(0.003)
            GPIO.output(DIGIT_PIN, GPIO.HIGH)   # 자리 OFF
    
    
    print("=== 반전 논리 수동 7세그 테스트 ===")
    print("입력: A B C D E F G DP / 0~9 / OFF / Q")
    
    try:
        while True:
            cmd = input("\n입력> ").strip().upper()
    
            if cmd == "Q":
                break
            elif cmd == "OFF":
                all_off()
                print("모두 OFF")
            elif cmd in SEG_PINS:
                print(f"{cmd} 세그먼트 표시")
                show_segments([cmd], duration=2.0)
            elif cmd in NUM_MAP:
                print(f"숫자 {cmd} 표시")
                show_segments(NUM_MAP[cmd], duration=2.0)
            else:
                print("잘못된 입력")
    
    except KeyboardInterrupt:
        pass
    
    finally:
        all_off()
        GPIO.cleanup()

    정상적으로 출력이 된다면, 다음은 1234를 출력해보도록 하자. 만약 출력이 하나가 안된다면 배선 문제일 가능성이 클 것 같다.(왜냐하면 나는 배선 하나 잘못 꽂아서 30분 동안 허우적 허우적했다...)

     

    1234출력 코드는 다음과 같다.

    import time
    import RPi.GPIO as GPIO
    
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)
    
    SEG_PINS = {
        'A': 11,
        'B': 4,
        'C': 23,
        'D': 8,
        'E': 7,
        'F': 10,
        'G': 18,
        'DP': 25
    }
    
    DIGIT_PINS = {
        0: 22,
        1: 27,
        2: 17,
        3: 24
    }
    
    NUM_MAP = {
        '0': ['A', 'B', 'C', 'D', 'E', 'F'],
        '1': ['B', 'C'],
        '2': ['A', 'B', 'D', 'E', 'G'],
        '3': ['A', 'B', 'C', 'D', 'G'],
        '4': ['B', 'C', 'F', 'G'],
        '5': ['A', 'C', 'D', 'F', 'G'],
        '6': ['A', 'C', 'D', 'E', 'F', 'G'],
        '7': ['A', 'B', 'C'],
        '8': ['A', 'B', 'C', 'D', 'E', 'F', 'G'],
        '9': ['A', 'B', 'C', 'D', 'F', 'G'],
        ' ': []
    }
    
    for pin in SEG_PINS.values():
        GPIO.setup(pin, GPIO.OUT)
        GPIO.output(pin, GPIO.LOW)
    
    for pin in DIGIT_PINS.values():
        GPIO.setup(pin, GPIO.OUT)
        GPIO.output(pin, GPIO.HIGH)
    
    def all_digits_off():
        for pin in DIGIT_PINS.values():
            GPIO.output(pin, GPIO.HIGH)
    
    def set_segments(char, dp=False):
        on_segments = set(NUM_MAP.get(char, []))
        if dp:
            on_segments.add('DP')
    
        for name, pin in SEG_PINS.items():
            GPIO.output(pin, GPIO.HIGH if name in on_segments else GPIO.LOW)
    
    def show_display(display_data, duration=2.0):
        end_time = time.time() + duration
        while time.time() < end_time:
            for i in range(4):
                all_digits_off()
                char, dp = display_data[i]
                set_segments(char, dp)
                GPIO.output(DIGIT_PINS[i], GPIO.LOW)
                time.sleep(0.002)
                GPIO.output(DIGIT_PINS[i], GPIO.HIGH)
    
    try:
        while True:
            data = [
                ('1', False),
                ('2', False),
                ('3', False),
                ('4', False),
            ]
            show_display(data, duration=2.0)
    
    except KeyboardInterrupt:
        pass
    
    finally:
        all_digits_off()
        for pin in SEG_PINS.values():
            GPIO.output(pin, GPIO.LOW)
        GPIO.cleanup()

     

    이제 1234까지 제대로 출력이 된다면 모든 준비는 끝이 났다...! 

    이제 온습도 센서가 측정한 온도와 습도 값을 7 Segment에 출력을 해보자

     

    이제 7 Segment 선이 꽂혀잇는 상태에서 온습도 센서만 꽂으면 된다. 기존에 S를 GPIO4에 꽂았었는데, 7 Segment 실험 중에 사용해버렸으니 S만 GPIO12로 변경을 해서 꽂아주자.

     

    회로 구성이 완료가 되었다면, 이제 마지막 테스트를 해볼 차례이다. 

     

    온습도 센서가 온도와 습도를 측정하면 2초에 한번씩 번갈아가면서 온도와 습도를 출력하도록 구현해보았다. 

     

    소수점 자리로 출력되는 값이 온도이고 정수는 습도 값이다.

     

    import time
    import RPi.GPIO as GPIO
    import board
    import adafruit_dht
    
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)
    
    # DHT11 (GPIO12)
    dht_device = adafruit_dht.DHT11(board.D12)
    
    SEG_PINS = {
        'A': 11,
        'B': 4,
        'C': 23,
        'D': 8,
        'E': 7,
        'F': 10,
        'G': 18,
        'DP': 25
    }
    
    DIGIT_PINS = {
        0: 22,
        1: 27,
        2: 17,
        3: 24
    }
    
    NUM_MAP = {
        '0': ['A', 'B', 'C', 'D', 'E', 'F'],
        '1': ['B', 'C'],
        '2': ['A', 'B', 'D', 'E', 'G'],
        '3': ['A', 'B', 'C', 'D', 'G'],
        '4': ['B', 'C', 'F', 'G'],
        '5': ['A', 'C', 'D', 'F', 'G'],
        '6': ['A', 'C', 'D', 'E', 'F', 'G'],
        '7': ['A', 'B', 'C'],
        '8': ['A', 'B', 'C', 'D', 'E', 'F', 'G'],
        '9': ['A', 'B', 'C', 'D', 'F', 'G'],
        ' ': []
    }
    
    # 초기화 (common cathode)
    for pin in SEG_PINS.values():
        GPIO.setup(pin, GPIO.OUT)
        GPIO.output(pin, GPIO.LOW)
    
    for pin in DIGIT_PINS.values():
        GPIO.setup(pin, GPIO.OUT)
        GPIO.output(pin, GPIO.HIGH)
    
    def all_digits_off():
        for pin in DIGIT_PINS.values():
            GPIO.output(pin, GPIO.HIGH)
    
    def set_segments(char, dp=False):
        on_segments = set(NUM_MAP.get(char, []))
        if dp:
            on_segments.add('DP')
    
        for name, pin in SEG_PINS.items():
            GPIO.output(pin, GPIO.HIGH if name in on_segments else GPIO.LOW)
    
    def show_display(display_data, duration=2.0):
        end_time = time.time() + duration
        while time.time() < end_time:
            for i in range(4):
                all_digits_off()
                char, dp = display_data[i]
                set_segments(char, dp)
                GPIO.output(DIGIT_PINS[i], GPIO.LOW)
                time.sleep(0.002)
                GPIO.output(DIGIT_PINS[i], GPIO.HIGH)
    
    # -----------------------------
    # 온도 표시용 (소수점 1자리)
    # -----------------------------
    def make_temp_data(temp):
        if temp is None:
            return [(' ', False)] * 4
    
        temp = round(temp, 1)   # 소수점 1자리
    
        t_str = f"{temp:.1f}"   # 예: 24.3
    
        if len(t_str) == 4:
            # 24.3
            return [
                (t_str[0], False),
                (t_str[1], True),   # 소수점
                (t_str[3], False),
                (' ', False)
            ]
        else:
            # 예: 9.5
            return [
                (' ', False),
                (t_str[0], True),
                (t_str[2], False),
                (' ', False)
            ]
    
    # -----------------------------
    # 습도 표시용 (정수)
    # -----------------------------
    def make_hum_data(hum):
        if hum is None:
            return [(' ', False)] * 4
    
        h = int(hum)
        s = str(h).rjust(4)
    
        return [(c, False) for c in s]
    
    try:
        while True:
            try:
                temp = dht_device.temperature
                hum = dht_device.humidity
    
                print(f"Temp: {temp}°C   Humidity: {hum}%")
    
                # 온도 표시
                temp_data = make_temp_data(temp)
                show_display(temp_data, duration=2.0)
    
                # 다시 읽기
                temp = dht_device.temperature
                hum = dht_device.humidity
    
                print(f"Temp: {temp}°C   Humidity: {hum}%")
    
                # 습도 표시
                hum_data = make_hum_data(hum)
                show_display(hum_data, duration=2.0)
    
            except RuntimeError as error:
                print("센서 오류:", error.args[0])
                show_display([(' ', False)] * 4, duration=1.0)
    
    except KeyboardInterrupt:
        print("종료")
    
    finally:
        all_digits_off()
        for pin in SEG_PINS.values():
            GPIO.output(pin, GPIO.LOW)
        GPIO.cleanup()
        dht_device.exit()

     

     

    정상적으로 작동한다면 이제 온습도가 7 Segment에 출력이 될 것이다...!

     

    https://youtu.be/vTXr3S94-Yk

Designed by Tistory.