아두이노에서 소리내기

학습 목표

1. 소리내기 이론

2. 소리의 높낮이 (음계, SCALE)

12음계 7음계 주파수 주파수 계산식
C 261.63 Hz 440 X 2(-9/12)
C# 277.18 Hz 440 X 2(-8/12)
D 293.66 Hz 440 X 2(-7/12)
D# 311.13 Hz 440 X 2(-6/12)
E 329.63 Hz 440 X 2(-5/12)
F 349.23 Hz 440 X 2(-4/12)
F# 369.99 Hz 440 X 2(-3/12)
G 392.00 Hz 440 X 2(-2/12)
G# 415.30 Hz 440 X 2(-1/12)
A 440.00 Hz 440 X 2(0/12)
A# 446.16 Hz 440 X 2(1/12)
B 493.88 Hz 440 X 2(2/12)

3. 소리 만들기

3.1 소리 발생 원리

3.2 예제 1: 표준 라(A)음 내기

3.2.1 하드웨어 구성

3.2.2 Sketch 프로그램

/*
 주파수가 440Hz인 라(A)음을 1초동안 출력
*/
void setup( ) {
   pinMode(7, OUTPUT);        // 피에조와 연결된 핀 7을 출력으로 설정
}

void loop( ) {
    for (int  k=0; k<440; k++) {  // 주파수 갯수만큼 반복 (1초 동안)
        digitalWrite(7, HIGH);  // HIGH 펄스
        delayMicroseconds(1136);// HIGH 펄스 지속시간
        digitalWrite(7, LOW);   // LOW 펄스
        delayMicroseconds(1136);// LOW 펄스 지속시간
    }
    delay(1000);
}

-[토의] 위 코드의 for 문에서 440 번 반복하는 것은 어떠한 의미를 가지는가?

3.3 예제 2

3.3.1 하드웨어 구성

3.3.2 Sketch 프로그램

/*
  피에조를 통하여 ‘도레미파솔라시’ 출력
*/

void setup() {
  pinMode(7,OUTPUT);  
}

void loop() {
  scalePlay(262);  // 도 (주파수 262Hz)  
  scalePlay(294);  // 레 (주파수 294Hz)
  scalePlay(330);  // 미 (주파수 330Hz)
  scalePlay(349);  // 파 (주파수 349Hz)
  scalePlay(392);  // 솔 (주파수 392Hz)
  scalePlay(440);  // 라 (주파수 440Hz)
  scalePlay(494);  // 시 (주파수 494Hz)
  exit(0);         // loop 종료
}

/*
  파라미터로 주어진 주파수 값(freq)으로 1초 동안 음을 내기 위한 함수
  freq: 주파수 값
*/
void scalePlay(int freq) {
  int T = 1000000/freq;     // 펄스주기 (마이클마이크로초 단위)
  int t = T/2;        // 펄스주기의 1/2

  for (int k=0; k<freq; k++) { // 주파수 갯수만큼 반복 (1초 동안)
    digitalWrite(7, HIGH);     // HIGH 펄스 출럭
    delayMicroseconds(t);      // HIGH 펄스 지속시간
    digitalWrite(7, LOW);      // LOW 펄스 출럭
    delayMicroseconds(t);      // LOW펄스 지속시간
  }
}

4. tone( )과 noTone( ) 함수

4.1 예제 3

4.2 예제 4

4.2.1 하드웨어 구성

4.2.2 프로그램 코드

- 전체 코드

    const  int  piezo=7;
    char code[ ]= {'C', 'D', 'E', 'F', 'G', 'A', 'B'};
    unsigned int  freq[ ]= {262, 294, 330, 349, 392, 440, 494};
    char mData[ ]="CCGGAAGpFFEEDDCpGGFFEEDpGGFFEEDpCCGGAAGpFFEEDDCp";
    const  byte mSize=sizeof(mData);

    void  setup( ) {
        pinMode(piezo, OUTPUT);
    }

    void loop( ) {
        int  playT=500;   // 1박자를 0.5초
        for (int  m=0; m<mSize; m++) {
            for(int k=0; k<7; k++) {
                if( mData[m]==code[k] ) {        // 배열 mData[]의 문자와 배열 code[] 의 문자 비교하여 인텍스 k 검색
                    tone(piezo, freq[k], playT);  // freq[k]의 값을 tone( )함수 전달
                  delay(playT);                 // 1박자 연주
                }
            }
            if (mData[m]=='p') {                // 배열 mData[]의 문자가 'p' 인 경우
              delay(playT);                     // 1박자 더 쉼
            }
        }
        noTone(piezo);
        delay(2000);
        exit(0);
    }  

4.2.3 프로그램 코드 (다른 방식의 구현)

#define C 262
#define D 294
#define E 330
#define F 349
#define G 392
#define A 440
#define B 494

const  int  piezo=7;
int mData[] = {C,C,G,G,A,A,G,F,F,E,E,D,D,C};
const byte mSize = sizeof(mData)/sizeof(mData[0]);

void setup() {
  pinMode(piezo, OUTPUT);  
}

void loop() {
  int playT=500;
  for (int i=0; i < mSize; i++) {
    if (i==6 || i==13)
        playT=1000;
    else
        playT=500;
    tone(7,mData[i],playT);
    delay(playT);
  }
  exit(0);
}

4.3 예제 5: 간이형 키보드 만들기

4.3.1 하드웨어 구성

d

4.3.2 1단계

4.3.3 2단계

4.3.4 3단계 (코드 축약 버전)

5. 연습문제

  1. 음과 박자를 고려하여, 다음 동요를 연주하는 스케치를 작성하여 보자.