버저(Buzzer)를 이용한 작은별 동요 실행 > 스마트기기시스템

본문 바로가기

[실습] 버저(Buzzer)를 이용한 작은별 동요 실행

필기자
23시간 37분전 49 0

본문

버저(Buzzer)를 이용한 작은별 동요 실행

목 적
  • 라즈베리파이에 버저(Buzzer) 액추레이터 사용법을 이해한다.
  • 버저(Buzzer) 액추레이터를 응용하여 단음 작은별 동요를 실행한다.
목 차
1. 버저(Buzzer) 액츄레이터 모듈 설치
2. 버저(Buzzer) 액츄레이터 구동 및 응용

1. 버저(Buzzer) 액츄레이터 모듈 설치
  • 액티브 버저 모듈
    • 액티브 버저 모듈은 전기 신호를 받았을 때 소리를 내는 장치임.
    • 내장된 발진 회로를 가지고 있어서 단순히 전원을 공급하면 특정 주파수로 소리를 낼 수 있음.
    • 액티브 버저는 로봇, 알람 시스템, 사용자 인터페이스 피드백 등 다양한 응용 프로그램에 사용됨.
  • 기본 사양
    • 전원 공급: 일반적으로 3.3V 또는 5V DC
    • 소비 전류: 약 30mA
    • 작동 주파수: 주로 2kHz 내외
      • 가청 주파수 : 20Hz ~ 20,000Hz(20kHz)
    • 소리 크기: 약 85 dB 정도
  • GPIO 연결
    • VCC : 3.3V 또는 5V Power(핀 1 또는 2)
    • GND : Ground 접지(핀 2)
    • IN : 입력 핀으로 LOW 또는 HIGH 신호에 따라 버저가 활성화됨
      • GPIO 17(핀 11)
3529946169_DJE3hY0y_42e2c8ee62dbe766e720712d5c8cf997fd446184.png

3529946169_pM8aJFYy_6557e55d0ce34dfcc7aad52666b2fb8d0a0a9d1b.png

2. 버저(Buzzer) 액츄레이터 구동 및 응용
  • 기본 구동 프로그램 : 라즈베리파이 가상환경에서 파이썬 코딩
    • VSCode에서 buzzer.py 파일 생성
    • GPIO 17핀(핀 11)을 출력 모드로 설정
    • GPIO 17핀을 순회하면 On/Off 코딩

3529946169_s3Vfro4c_ce19ec4801e27747499de3a3a19a97e0dbaf76f0.png


#twinkle_buzzer.py
import RPi.GPIO as GPIO
import time

# GPIO 모드 설정
GPIO.setmode(GPIO.BCM)

# 사용할 GPIO 핀의 번호를 설정한다. 여기서는 17번 핀을 사용한다.
BUZZER_PIN = 17
GPIO.setup(BUZZER_PIN, GPIO.OUT)

try:
    while True:
        # 부저를 켠다.
        GPIO.output(BUZZER_PIN, GPIO.HIGH)
        print("Buzzer on")
        time.sleep(1) # 1초 동안 대기

        # 부저를 끈다.
        GPIO.output(BUZZER_PIN, GPIO.LOW)
        print("Buzzer off")
        time.sleep(1) # 1초 동안 대기

except KeyboardInterrupt:
    # 프로그램 종료 시 GPIO 핀 상태를 초기화한다.
    GPIO.cleanup()

 
  • 계이름 응용 구동 프로그램 : 라즈베리파이 가상환경에서 파이썬 코딩
    • VSCode에서 buzzer_melody.py 파일 생성
    • 주파수 대역과 음 지속 시간을 이용하여 계이름(도레미파...시도) 소리 출력

import RPi.GPIO as GPIO
import time
# GPIO 모드 설정
GPIO.setmode(GPIO.BCM)
# Buzzer 핀 설정
BUZZER_PIN = 17
GPIO.setup(BUZZER_PIN, GPIO.OUT)
pwm = None
# PWM 인스턴스 생성 및 초기 주파수 설정
pwm = GPIO.PWM(BUZZER_PIN, 100) #부저의 경우 MAX 2000(2kHz), 출력 범위(약 1Hz ~ 10kHz)
pwm.start(0)  
# 주요 음표의 주파수 (단위: Hz)
notes = {
    'C4': 261.63,
    'D4': 293.66,
    'E4': 329.63,
    'F4': 349.23,
    'G4': 392.00,
    'A4': 440.00,
    'B4': 493.88,
    'C5': 523.25  # 추가된 높은 도 음표
}
# 간단한 멜로디 (음표와 지속 시간)
melody = [('C4', 0.5), ('D4', 0.5), ('E4', 0.5), ('F4', 0.5),
          ('G4', 0.5), ('A4', 0.5), ('B4', 0.5), ('C5', 0.5)]  # 마지막 음을 높은 도로 변경
def play(note, duration):
    pwm.ChangeFrequency(notes[note])
    pwm.ChangeDutyCycle(50)  # 켜짐
    time.sleep(duration)  # 음표 지속 시간
    pwm.ChangeDutyCycle(0)  # 꺼짐
try:  
    for note, duration in melody:
        play(note, duration)
        time.sleep(0.1)  # 음표 사이의 간격
finally:
    if pwm is not None:
        try:
            pwm.stop()
        except:
            pass
        del pwm  # __del__ 호출 시 오류 방지
    GPIO.cleanup()
  • PWM(Pulse Width Modulation) 이론
용어 설명
PWM (펄스폭 변조) 디지털 핀에서 출력 신호의 ON/OFF 비율을 조절하여 아날로그처럼 동작하게 하는 방식
DutyCycle(듀티 사이클) 하나의 주기 내에서 ON(신호 High) 상태가 차지하는 비율(%)
예: 50%면 ON/OFF 비율이 1:1 (음색이 변함, 예: 10%는 얇고 날카로운 소리, 90%는 두껍고 탁한 소리)
Frequency(주파수) 1초당 반복되는 PWM 신호의 횟수(Hz)
응용 분야 모터 속도 조절, LED 밝기 조절, 부저(Buzzer) 음정 제어 등

3529946169_G4JCEqTg_06be45685960d4bacd538c5ef6bbbb0bd14e0365.png
  • 소리의 원리
항목 설명
진동수(Hz) 초당 공기의 압력이 몇 번 변화하는가
주파수 ↑ 음의 높이가 높아짐 (예: 도 → 미 → 솔)
주파수 ↓ 음의 높이가 낮아짐
부저(PWM) 전기적 ON/OFF로 진동을 만들어 공기를 흔듦
공기 진동(파동)을 받아 음높이로 인식
가청 주파수 약 20Hz ~ 20,000Hz
 
  • PWM에서 LED 밝기 조절 공식
    • 전압, 전류, 저항, 전력
      • 전압 (V)  →  수압 (물을 밀어주는 힘)
      • 전류 (A)  →  수량 (실제 흐르는 물의 양)
      • 저항 (Ω)  →  파이프 좁기 (굵을수록 저항 작음, 좁을수록 저항 큼)
      • 전력 (W)  →  물레방아 회전력 (실제 일하는 양)
    • 공급 전압 Vsupply = 3.3V (라즈베리파이 GPIO 기준), 저항 R = 50Ω (GPIO 내부 저항), 듀티사이클 80%
    • LED 순방향 전압(Vf)은 색상마다 다름 (데이터시트 KY-009 5050 RGB 기준)
      • 빨강: 1.8V ~ 2.4V (대표값 2.0V)
      • 초록: 2.8V ~ 3.6V (데이터시트 기준, 실사용 시 약 2.7V로 낮아짐)
      • 파랑: 2.8V ~ 3.6V (데이터시트 기준, 실사용 시 약 2.7V로 낮아짐)
    • LED 밝기 단위 : mcd (밀리칸델라)
      • mcd는 특정 방향으로 얼마나 밝게 빛나는지를 나타내는 광도 단위이다.
      • 데이터시트 기준값 (KY-009 5050 RGB, 20mA 기준)
        • 빨강: 300 ~ 500 mcd
        • 초록: 500 ~ 700 mcd
        • 파랑: 200 ~ 400 mcd
      • 단, 데이터시트 mcd 값은 20mA 정격 전류 기준이므로, 이 실습(GPIO 내부 저항만 사용, 전류 다름)에서는 데이터시트 값을 그대로 적용할 수 없다.
      • 정확한 밝기(mcd)와 평균 전류의 비례 관계는 직접 실험으로 측정해야 한다.
        • 조도계 (lux meter) 준비
        • LED와 조도계 거리 고정
        • 듀티사이클 10% ~ 100% 단계별 변화
        • 각 단계별 조도 (lux) 측정
        • 평균 전류 vs 조도 그래프 작성
  1. 순간 전류 (옴의 법칙):
    I = (Vsupply − Vf) / R
  2. 평균 전류 (옴의 법칙 × 듀티사이클) ∝ LED 밝기 :
    Iavg = I × 듀티사이클

※ 색상별 순간 전류 (3.3V 기준, R = 50Ω GPIO 내부 저항)

색상 Vf (데이터시트) Vf (실사용 추정) 순간 전류 I (mA)
I = (3.3 − Vf) / 50
mcd (데이터시트, 20mA 기준)
빨강 1.8V ~ 2.4V 2.0V (3.3 − 2.0) / 50 = 26mA 300 ~ 500 mcd
초록 2.8V ~ 3.6V 약 2.7V ※ (3.3 − 2.7) / 50 = 12mA 500 ~ 700 mcd
파랑 2.8V ~ 3.6V 약 2.7V ※ (3.3 − 2.7) / 50 = 12mA 200 ~ 400 mcd

※ 초록/파랑은 데이터시트 기준 Vf가 3.2V이지만, LED는 비선형 소자이므로 전류가 낮아지면 실제 Vf도 함께 낮아진다. 3.3V GPIO 환경에서는 약 2.7V 수준에서 동작점이 형성되어 정상 발광한다.

※ Keyes CNT1 모듈은 전류 제한 저항이 내장되어 있지 않으므로, GPIO 내부 저항(약 50Ω)만으로 전류가 제한된다. 빨강의 경우 GPIO 핀 권장 전류(16mA)를 초과하므로, 정식 회로 설계 시에는 외부 저항(150Ω 권장) 추가를 권장한다.

※ 위 mcd 값은 20mA 정격 전류 기준이며, 실습 환경의 전류와 다르므로 실제 밝기는 데이터시트 값과 다를 수 있다. 정확한 밝기 측정이 필요한 경우 조도계를 이용한 직접 실험이 필요하다.

빨강 LED 기준 듀티사이클별 평균 전류 (I = 26mA)

듀티사이클 (%) 순간 전류 (mA)
I = (3.3−2.0)/50
평균 전류 (mA)
Iavg = I × 듀티
10% 26 26 × 0.1 = 2.6
20% 26 26 × 0.2 = 5.2
30% 26 26 × 0.3 = 7.8
40% 26 26 × 0.4 = 10.4
50% 26 26 × 0.5 = 13.0
60% 26 26 × 0.6 = 15.6
70% 26 26 × 0.7 = 18.2
80% 26 26 × 0.8 = 20.8
90% 26 26 × 0.9 = 23.4
100% 26 26 × 1.0 = 26.0

[문제: 부저를 이용한 동요 재생 실습]
  • 다음 작은별 악보를 보고 부저 프로그램을 완성하여라.

3529946169_uzm2GhxL_7c8374f12e5a3a05485adf20e2e6581582ea0dff.png


import RPi.GPIO as GPIO
import time
# GPIO 설정
GPIO.setmode(GPIO.BCM)
BUZZER_PIN = 27
GPIO.setup(BUZZER_PIN, GPIO.OUT)
# PWM 초기화
pwm = GPIO.PWM(BUZZER_PIN, 100)
pwm.start(0)
one_beat = 0.4 # 1박 = 0.4초  -> 60 / 0.4 = 150 BPM
# 음표 주파수 (Hz)
notes = {
    'C4': 261.63,
    'D4': 293.66,
    'E4': 329.63,
    'F4': 349.23,
    'G4': 392.00,
    'A4': 440.00,
    'B4': 493.88,
    'C5': 523.25,
}
# 반짝반짝 작은별 멜로디 (one_beat 기준으로 구성)
melody = [
    ('C4', 1), ('C4', 1), ('G4', 1), ('G4', 1),
    ('A4', 1), ('A4', 1), ('G4', 2),
    ('F4', 1), ('F4', 1), ('E4', 1), ('E4', 1),
    ('D4', 1), ('D4', 1), ('C4', 2),
    ('G4', 1), ('G4', 1), ('F4', 1), ('F4', 1),
    ('E4', 1), ('E4', 1), ('D4', 2),
    ('G4', 1), ('G4', 1), ('F4', 1), ('F4', 1),
    ('E4', 1), ('E4', 1), ('D4', 2),
    ('C4', 1), ('C4', 1), ('G4', 1), ('G4', 1),
    ('A4', 1), ('A4', 1), ('G4', 2),
    ('F4', 1), ('F4', 1), ('E4', 1), ('E4', 1),
    ('D4', 1), ('D4', 1), ('C4', 2),
]
# 음 재생 함수
def play(note, beats):
    pwm.ChangeFrequency(notes[note])
    pwm.ChangeDutyCycle(50)
    time.sleep(one_beat * beats)
    pwm.ChangeDutyCycle(0)
    time.sleep(0.05)
# 연주 실행
try:
    print(f"{60/one_beat}bpm으로 연주합니다.")
    for note, beats in melody:
        play(note, beats)
finally:
    if pwm is not None:
        try:
            pwm.stop()
        except:
            pass
        del pwm
    GPIO.cleanup()

 
[문제: 3Color LED와 부저를 이용한 동요 재생 실습]
  • 3컬러 RGB LED는 아래와 같이 연결되어 있다.
    • 빨강: GPIO 18
    • 초록: GPIO 23
    • 파랑: GPIO 24
  • 작은별 멜로디를 부저로 연주한다.
  • 각 음이 재생될 때, 해당 음에 지정된 색상으로 RGB LED가 점등된다.
  • 음이 끝나면 LED는 꺼진다.
  • 사용된 음표에 대한 색상 매핑은 아래와 같다.
 
음표 색상 RGB 상태(GPIO)
C4 빨강 (1, 0, 0)
D4 초록 (0, 1, 0)
E4 파랑 (0, 0, 1)
F4 노랑 (1, 1, 0)
G4 하늘 (0, 1, 1)
A4 보라 (1, 0, 1)
B4 흰색 (1, 1, 1)
C5 빨강 (1, 0, 0)


import RPi.GPIO as GPIO
import time
# GPIO 설정
GPIO.setmode(GPIO.BCM)
# 핀 번호
BUZZER_PIN = 17
RED_PIN = 18
GREEN_PIN = 23
BLUE_PIN = 24
# 핀 모드 설정
GPIO.setup(BUZZER_PIN, GPIO.OUT)
GPIO.setup(RED_PIN, GPIO.OUT)
GPIO.setup(GREEN_PIN, GPIO.OUT)
GPIO.setup(BLUE_PIN, GPIO.OUT)
# 부저 PWM 초기화
pwm = GPIO.PWM(BUZZER_PIN, 100)
pwm.start(0)
# 음표 주파수
notes = {
    'C4': 261.63,
    'D4': 293.66,
    'E4': 329.63,
    'F4': 349.23,
    'G4': 392.00,
    'A4': 440.00,
    'B4': 493.88,
    'C5': 523.25
}
# 색상 매핑 (C5도 빨강으로 수정)
colors = {
    'C4': (1, 0, 0),  # 빨강
    'D4': (0, 1, 0),  # 초록
    'E4': (0, 0, 1),  # 파랑
    'F4': (1, 1, 0),  # 노랑
    'G4': (0, 1, 1),  # 하늘
    'A4': (1, 0, 1),  # 보라
    'B4': (1, 1, 1),  # 흰색
    'C5': (1, 0, 0)   # 빨강으로 수정
}
# 작은별 멜로디
# melody = [('C4', 0.5), ('C4', 0.5), ('G4', 0.5), ('G4', 0.5)]
melody = [
    ('C4', 0.5), ('C4', 0.5), ('G4', 0.5), ('G4', 0.5),
    ('A4', 0.5), ('A4', 0.5), ('G4', 1.0),
    ('F4', 0.5), ('F4', 0.5), ('E4', 0.5), ('E4', 0.5),
    ('D4', 0.5), ('D4', 0.5), ('C4', 1.0),
    ('G4', 0.5), ('G4', 0.5), ('F4', 0.5), ('F4', 0.5),
    ('E4', 0.5), ('E4', 0.5), ('D4', 1.0),
    ('G4', 0.5), ('G4', 0.5), ('F4', 0.5), ('F4', 0.5),
    ('E4', 0.5), ('E4', 0.5), ('D4', 1.0),
    ('C4', 0.5), ('C4', 0.5), ('G4', 0.5), ('G4', 0.5),
    ('A4', 0.5), ('A4', 0.5), ('G4', 1.0),
    ('F4', 0.5), ('F4', 0.5), ('E4', 0.5), ('E4', 0.5),
    ('D4', 0.5), ('D4', 0.5), ('C4', 1.0)
]
# LED 색상 출력 함수
def set_color(r, g, b):
    GPIO.output(RED_PIN, r)
    GPIO.output(GREEN_PIN, g)
    GPIO.output(BLUE_PIN, b)
# 음 재생 함수
# 음 재생 함수
def play_note(note, duration):
    freq = notes.get(note, None)  # 기본값을 None으로 설정하고 유효한 주파수인지 확인
    rgb = colors.get(note, (0, 0, 0))
    if freq:  # freq가 None이 아니면 실행
        pwm.ChangeFrequency(freq)
        pwm.ChangeDutyCycle(50)
        set_color(*rgb)
        time.sleep(duration)
        pwm.ChangeDutyCycle(0)
        set_color(0, 0, 0)
        time.sleep(0.05)
# 실행
try:
    for note, dur in melody:
        play_note(note, dur)
except Exception as e:
    print(f"실행 중 예외 발생: {e}")
finally:
    if pwm is not None:
        try:
            pwm.stop()
        except:
            pass
        del pwm  # __del__ 호출 시 오류 방지
    GPIO.cleanup()

댓글목록0

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