본문으로 바로가기
728x90
728x90

1. 아두이노 보드를 사용한 부저 제어 실습 (1)

 

블랙베리에 있는 부저를 제어하는 실습을 하기에 앞서 부저의 작동 원리에 대해 알아보겠습니다.

 

부저 내부에는 얇은 판이 있습니다. 피에조 효과에 의해 이 얇은 판에 전압을 가하면 얇은 판에는 기계적인 변형이 생기게 됩니다.

또한 소리의 높낮이는 음파의 진동수(주파수)에 따라 달라집니다.

이 점들을 이용해서 우리는 부저(의 내부에 있는 얇은 판) 특정한 주파수의 전압을 인가하면 신호에 따라 얇은 판이 진동하면서 공기를 진동시켜 원하는 높이의 음을 낼 수 있게 됩니다.

 

 

부저를 제어해 소리를 내는 실습을 하기 위해서는 부저가 연결된 핀에서 특정 주파수를 가진 신호를 발생시키는 기능이 필요합니다. 이를 위해 이번 실습에서는 아두이노에서 제공하는 tone 함수를 사용할 것입니다. tone 함수는 핀에 특정 주파수(50% 듀티 사이클)의 구형파를 발생시키는 함수입니다.

 

 

2. 아두이노 보드를 사용한 부저 제어 실습 (2)

 

 

 

(1) 부저의 핀 번호를 정의합니다.
 
(2) 음악을 연주하는데 사용할 음계의 주파수와 박자의 길이를 밀리초(mSec)로 정의합니다.
 
(3) 음악을 연주하는데 사용할 음계와 박자 배열을 선언하고 초기화 합니다.
 

(4) 이전에 연주된 음계를 저장하는 변수를 선언합니다.

 

 

3. 아두이노 보드를 사용한 부저 제어 실습 (3)

 

 

 

소리를 출력하는데 사용된 함수들은 아래와 같습니다.

 

tone(pin, freq) : 특정 핀에 특정 주파수의 구형파를 발생시키는 함수입니다.

 

noTone(pin) : 특정 핀에 tone 함수에 의해 시작된 구형파 발생을 멈추는 함수입니다.

 

setup 에서는 아래와 같은 동작을 합니다.

 
(5) 음계와 박자 배열의 길이가 다른지 확인합니다. 배열의 길이가 다르면 더 이상 프로그램이 진행되지 않습니다.
 
(6) 음계 배열의 길이만큼 for문을 반복합니다.
   1) 현재 연주하려는 음이 이전에 연주한 음과 같다면 각각을 구분하기 위해 부저 소리를 잠깐 멈춥니다.
   2) for문이 반복된 횟수에 따라(, i에 따라) 음계와 박자 배열에서 적절한 위치의 값을 연주합니다.
      delay
함수는 음을 지속하기 위해 사용됩니다.
   3) 현재 연주된 음을 prevNote 변수에 저장합니다.

 

(7) 연주가 끝나면 부저 소리를 끕니다.

 

 

블랙베리에 프로그램을 업로드하면 음악이 연주됩니다.

 

//////////////  부저
#define BUZZER_PIN            5

#define OCTAVE_4_DO           262
#define OCTAVE_4_RE           294
#define OCTAVE_4_MI           330
#define OCTAVE_4_SOL          392
#define OCTAVE_4_LA           440
#define OCTAVE_4_TI           494
#define OCTAVE_5_DO           523

#define WHOLE_NOTE            1300
#define HALF_NOTE             WHOLE_NOTE/2
#define QUATER_NOTE           WHOLE_NOTE/4
#define DOTTED_QUATER_NOTE    WHOLE_NOTE*3/8
#define EIGHTH_NOTE           WHOLE_NOTE/8
#define SIXTEENTH_NOTE        WHOLE_NOTE/16
#define SHORT_DELAY           10

int melody[] = {OCTAVE_4_MI, OCTAVE_4_RE, OCTAVE_4_DO, OCTAVE_4_RE,
                OCTAVE_4_MI, OCTAVE_4_MI, OCTAVE_4_MI,
                OCTAVE_4_RE, OCTAVE_4_RE, OCTAVE_4_RE,
                OCTAVE_4_MI, OCTAVE_4_SOL, OCTAVE_4_SOL,
                OCTAVE_4_MI, OCTAVE_4_RE, OCTAVE_4_DO, OCTAVE_4_RE,
                OCTAVE_4_MI, OCTAVE_4_MI, OCTAVE_4_MI,
                OCTAVE_4_RE, OCTAVE_4_RE, OCTAVE_4_MI, OCTAVE_4_RE,
                OCTAVE_4_DO};
int note[] = {DOTTED_QUATER_NOTE, EIGHTH_NOTE, QUATER_NOTE, QUATER_NOTE,
              QUATER_NOTE, QUATER_NOTE, HALF_NOTE,
              QUATER_NOTE, QUATER_NOTE, HALF_NOTE,
              QUATER_NOTE, QUATER_NOTE, HALF_NOTE,
              DOTTED_QUATER_NOTE, EIGHTH_NOTE, QUATER_NOTE, QUATER_NOTE,
              QUATER_NOTE, QUATER_NOTE, HALF_NOTE,
              QUATER_NOTE, QUATER_NOTE, QUATER_NOTE, QUATER_NOTE,
              WHOLE_NOTE};

int prevNote = 0;

void setup() {
  if (sizeof(melody) != sizeof(note))
    while(1) {};  // 두 배열의 사이즈가 다르면 연주할 수 없음
    
  for (int i = 0 ; i < sizeof(melody)/sizeof(int) ; i++) {
    if (prevNote == melody[i]) { // 현재 출력하려는 음이 이전 음과 같을 때
      noTone(BUZZER_PIN); // 잠깐 끊어서 구분함
      delay(SHORT_DELAY);
    }
    tone(BUZZER_PIN, melody[i]);
    delay(note[i]);
    prevNote = melody[i];
  }
  noTone(BUZZER_PIN);
}

void loop() {
}

 

아래의 소스는 몇 가지 사운드를 출력하는 예제입니다. 실행해 보고 마음에 드는 것을 사용해 보세요.

 

/*
  [부저 경고음 통합 예제]
  - 질문에서 준 멜로디(작은별/학교종 느낌) 1회 재생
  - 작업 이벤트용 경고음 함수들(발견/단계완료/전체완료/경고/오류/위험/확인요청/시작)
  - setup()에서 순서대로 테스트 재생

  BUZZER_PIN = 5
*/

#include <Arduino.h>

//////////////  부저
#define BUZZER_PIN            5

// 음계(질문 예제 + 확장)
#define OCTAVE_4_DO           262
#define OCTAVE_4_RE           294
#define OCTAVE_4_MI           330
#define OCTAVE_4_SOL          392
#define OCTAVE_4_LA           440
#define OCTAVE_4_TI           494
#define OCTAVE_5_DO           523

#define C4  262
#define D4  294
#define E4  330
#define F4  349
#define G4  392
#define A4  440
#define B4  494
#define C5  523
#define E5  659
#define G5  784

// 박자(질문 예제)
#define WHOLE_NOTE            1300
#define HALF_NOTE             (WHOLE_NOTE/2)
#define QUATER_NOTE           (WHOLE_NOTE/4)
#define DOTTED_QUATER_NOTE    (WHOLE_NOTE*3/8)
#define EIGHTH_NOTE           (WHOLE_NOTE/8)
#define SIXTEENTH_NOTE        (WHOLE_NOTE/16)
#define SHORT_DELAY           10

// 경고음용 gap
#define GAP_SHORT 20
#define GAP_MED   80
#define GAP_LONG  200


// ===== 공통 유틸 =====
void beep(int freq, int dur, int gap = GAP_SHORT) {
  tone(BUZZER_PIN, freq);
  delay(dur);
  noTone(BUZZER_PIN);
  delay(gap);
}

void beepSeparated(int freq, int dur, int gap = GAP_SHORT) {
  noTone(BUZZER_PIN);
  delay(10);
  tone(BUZZER_PIN, freq);
  delay(dur);
  noTone(BUZZER_PIN);
  delay(gap);
}

// ===== 작업 이벤트용 경고음 패턴들 =====

// 1) 작업 시작
void soundStart() {
  beep(C4, SIXTEENTH_NOTE);
  beep(E4, SIXTEENTH_NOTE);
  beep(G4, EIGHTH_NOTE, GAP_MED);
}

// 2) 특정한 것 발견
void soundFound() {
  beepSeparated(E5, SIXTEENTH_NOTE);
  beepSeparated(E5, SIXTEENTH_NOTE, GAP_MED);
}

// 3) 단계 완료/성공
void soundStepDone() {
  beep(C4, EIGHTH_NOTE);
  beep(E4, EIGHTH_NOTE);
  beep(C5, QUATER_NOTE, GAP_LONG);
}

// 4) 전체 작업 완료
void soundAllDone() {
  beep(C4, EIGHTH_NOTE);
  beep(G4, EIGHTH_NOTE);
  beep(C5, EIGHTH_NOTE);
  beep(G4, EIGHTH_NOTE);
  beep(C5, QUATER_NOTE, GAP_LONG);
}

// 5) 주의/경고(짧-짧-길 x3)
void soundWarning() {
  for (int i = 0; i < 3; i++) {
    beep(A4, SIXTEENTH_NOTE);
    beep(A4, SIXTEENTH_NOTE);
    beep(A4, EIGHTH_NOTE, GAP_MED);
  }
  delay(GAP_LONG);
}

// 6) 오류/실패(하강 + 길게)
void soundError() {
  beep(C5, EIGHTH_NOTE);
  beep(G4, EIGHTH_NOTE);
  beep(E4, HALF_NOTE, GAP_LONG);
}

// 7) 긴급/위험(사이렌 느낌)
void soundDanger() {
  for (int i = 0; i < 6; i++) {
    beep(G5, SIXTEENTH_NOTE, GAP_SHORT);
    beep(E5, SIXTEENTH_NOTE, GAP_SHORT);
  }
  delay(GAP_LONG);
}

// 8) 사용자 확인 필요
void soundNeedConfirm() {
  beep(F4, EIGHTH_NOTE, GAP_MED);
  beep(F4, EIGHTH_NOTE, GAP_LONG);
}

void setup() {

  // 아래는 테스트용: 이벤트 경고음들을 순서대로 들려줌
  soundStart();       delay(500);
  soundFound();       delay(500);
  soundStepDone();    delay(500);
  soundWarning();     delay(500);
  soundError();       delay(500);
  soundDanger();      delay(500);
  soundAllDone();     delay(500);
  soundNeedConfirm(); delay(500);

  // 끝
  noTone(BUZZER_PIN);
}

void loop() {
  // 실제 프로젝트에서는 여기서 조건에 따라
  // soundFound(), soundError() 같은 함수를 호출하면 됩니다.
}

 

 

 

728x90
728x90