2015년 11월 4일 수요일

아두이노의 tone() 함수로 멜로디 연주하기

 아두이노에는 tone()함수가 제공되는데 부저나 스피커로 음을 발생시킬 수 있는 함수이다. 기본 문법은 다음과 같다.

tone(pin, freq [, duration]);

  • pin : 부저나 스피커가 연결된 디지털 핀번호
  • freq : 주파수 (범위 : 31 ~ 65535)
  • duration : (옵션) 음의 발생 시간

여기서 duration은 주파수 지속시간으로서 이 시간이 지난 후에 noTone()함수가 자동으로 호출되는 것과 같은 효과를 낸다.  duration이  생략되면 noTone()함수가 호출될 때까지 음이 계속 발생된다. 예를 들어서 11번 핀에 부저가 연결되었다면 다음과 같이 한다.

tone(11, 262); // ‘도’음 발생
delay(500);
noTone(11);

이 코드는 ‘도’음을 0.5초간 발생시키는데 다음과 같이 할 수 있다.

tone(11, 262, 500);

이렇게 하면 음 발생 직후 다른 작업을 수행할 수 있으며 500ms후에는 내부 인터럽트가 발생하여 음발생이 자동으로 정지된다. 하지만 단음만 생성할 경우에는 상관없지만 연속음을 생성할 경우에는 주의해야 한다.

tone(11, 262, 500); // ‘도’음
tone(11, 294, 500); // ‘레’음
tone(11, 330, 500); // ‘미’음

이렇게 하면 맨 마지막의 ‘미’음만 발생하게 된다. (왜?) 따라서 올바른 동작을 위해서는 다음과 같이 해야 한다.

tone(11, 262); // ‘도’음 발생
delay(500);
tone(11, 294); // ‘레’음 발생
delay(500);
tone(11, 330); // ‘미’음 발생
delay(500);
noTone(11);
tone(11, 262); // ‘도’
delay(500);
tone(11, 294); // ‘레’
delay(500);
tone(11, 330, 500); // ‘미’

tone()함수는 내부적으로 타이머를 사용하므로 다음과 같은 점들을 주의해야 한다.
  • 이 함수를 사용할 경우 3번 11번 핀의 PWM이 정상적으로 동작되지 않는다.
  • 한 번에 하나의 주파수만 발생시킬 수 있으며 여러 핀에 동시에 다른 음을 발생시킬 수 없다.

 특정 음에 해당되는 주파수를 일일이 숫자로 기입하는 것은 가독성 면에서 좋지 않으며 이를 개선하기 위해서 아두이노에서는 음의 주파수만을 모아놓은 “pitches.h”라는 헤더파일을 제공한다. 내용은 다음과 같다.

/*************************************************
* Public Constants
*************************************************/
#define NOTE_B0  31
#define NOTE_C1  33
#define NOTE_CS1 35
#define NOTE_D1  37
#define NOTE_DS1 39
#define NOTE_E1  41
#define NOTE_F1  44
#define NOTE_FS1 46
#define NOTE_G1  49
#define NOTE_GS1 52
#define NOTE_A1  55
#define NOTE_AS1 58
#define NOTE_B1  62
#define NOTE_C2  65
#define NOTE_CS2 69
#define NOTE_D2  73
#define NOTE_DS2 78
#define NOTE_E2  82
#define NOTE_F2  87
#define NOTE_FS2 93
#define NOTE_G2  98
#define NOTE_GS2 104
#define NOTE_A2  110
#define NOTE_AS2 117
#define NOTE_B2  123
#define NOTE_C3  131
#define NOTE_CS3 139
#define NOTE_D3  147
#define NOTE_DS3 156
#define NOTE_E3  165
#define NOTE_F3  175
#define NOTE_FS3 185
#define NOTE_G3  196
#define NOTE_GS3 208
#define NOTE_A3  220
#define NOTE_AS3 233
#define NOTE_B3  247
#define NOTE_C4  262
#define NOTE_CS4 277
#define NOTE_D4  294
#define NOTE_DS4 311
#define NOTE_E4  330
#define NOTE_F4  349
#define NOTE_FS4 370
#define NOTE_G4  392
#define NOTE_GS4 415
#define NOTE_A4  440
#define NOTE_AS4 466
#define NOTE_B4  494
#define NOTE_C5  523
#define NOTE_CS5 554
#define NOTE_D5  587
#define NOTE_DS5 622
#define NOTE_E5  659
#define NOTE_F5  698
#define NOTE_FS5 740
#define NOTE_G5  784
#define NOTE_GS5 831
#define NOTE_A5  880
#define NOTE_AS5 932
#define NOTE_B5  988
#define NOTE_C6  1047
#define NOTE_CS6 1109
#define NOTE_D6  1175
#define NOTE_DS6 1245
#define NOTE_E6  1319
#define NOTE_F6  1397
#define NOTE_FS6 1480
#define NOTE_G6  1568
#define NOTE_GS6 1661
#define NOTE_A6  1760
#define NOTE_AS6 1865
#define NOTE_B6  1976
#define NOTE_C7  2093
#define NOTE_CS7 2217
#define NOTE_D7  2349
#define NOTE_DS7 2489
#define NOTE_E7  2637
#define NOTE_F7  2794
#define NOTE_FS7 2960
#define NOTE_G7  3136
#define NOTE_GS7 3322
#define NOTE_A7  3520
#define NOTE_AS7 3729
#define NOTE_B7  3951
#define NOTE_C8  4186
#define NOTE_CS8 4435
#define NOTE_D8  4699
#define NOTE_DS8 4978

이 헤더파일은 전역 상수 정의로만 이루어져 있으므로 실행 파일의 용량을 증가시키진 않는다. 따라서 이 파일을 폴도에 복사한 후 인클루드시켜서 필요한 주파수를 사용하면 된다.

#include “pitches.h”
tone(11, NOTE_C3, 1000); // 3도 ‘도’음을 1초간 발생
...

이렇게 주파수(숫자) 대신 상수 이름을 사용하면 가독성이 높아지게 된다.


댓글 없음:

댓글 쓰기