가청 주파수 진동을 스피커나 피에조(piezo)에 출력
12등분된 음의 높이
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) |
도레미파솔라시는 12음계 중 7개만을 표현
C(도), D(레), E(미), F(파), G(솔), 라(A), 시(B)
옥타브에 따른 음계의 주파수
펄스: 일정한 주기로 반복되는 파동
주파수: 단위펄스가 1초에 반복하는 회수
주기(T): 단위펄스가 반복하는데 걸리는 시간
원하는 소리의 주파수로 전기신호를 만들어 스피커나 피에조(piezo)에 입력하면 스피커나 피에조의 물리적인 구조로 인하여 진동을 일으켜 소리 발생
음계의 주파수와 주기
라(A)음 : 440Hz의 주파수(약 2272μ초의 주기)
베이스 보드 JP9의 PIEZO와 아두이노 보드의 디비털입출력 핀 7번 연결
/*
주파수가 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 번 반복하는 것은 어떠한 의미를 가지는가?
/*
피에조를 통하여 ‘도레미파솔라시’ 출력
*/
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펄스 지속시간
}
}
tone(pin,freq,dtime ) : 소리를 나게 하는 함수
noTone(pin ) : 소리가 나지 않도록 하는 함수
tone( )함수를 이용하여 ‘도레미파솔라시’ 출력
void setup( ) {
pinMode( 7, OUTPUT );
}
void loop( ) {
tone(7, 262,1000); // '도' 음
delay(1000);
tone(7, 294, 1000); // '레' 음
delay(1000);
tone(7, 330, 1000); // '미' 음
delay(1000);
tone(7, 349, 1000); // '파' 음
delay(1000);
tone(7, 392, 1000); // '솔' 음
delay(1000);
tone(7, 440, 1000); // '라' 음
delay(1000);
tone(7, 494, 1000); // '시' 음
delay(1000);
exit(0); // loop 종료
}
반짝반짝 작은 별의 연주
연주할 곡의 계이름 코드를 문자 배열로 표시 (코드 사이의 'p'는 앞의 음이 2박자임을 나타냄)
char mData[ ]="CCGGAAGpFFEEDCCpGGFFEEDpGGFFEEDpCCGGAAGpFFEEDDCp";
sizeof()함수를 사용하여 저장된 배열의 크기 측정
const byte mSize = sizeof(mData);
'도레미파솔라시' 코드는 배열 code[]에 저장, 각 코드의 순서에 따른 각 음의 주파수는 배열 freq[]에 저장
char code[ ] = {'C', 'D', 'E', 'F', 'G', 'A', 'B'};
int freq[ ] = {262, 294, 330, 349, 392, 440, 494};
다음과 같은 절차로 악보가 연주됨
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);
}
#define 문을 이용하여 각 계이름 코드에 대한 주파수 상수 값을 정의
#define C 262
#define D 294
#define E 330
#define F 349
#define G 392
#define A 440
#define B 494
연주할 곡의 계이름 코드를 int 배열로 표시
int mData[] = {C,C,G,G,A,A,G,F,F,E,E,D,D,C};
mData[] 배열의 원소의 개수 구하기
byte mSize = sizeof(mData)/sizeof(mData[0]);
mData[] 배열의 계이름 연주
모든 계이름을 한 박자로 연주
void loop() {
int playT = 500;
for (int i=0; i < mSize; i++) {
tone(7,mData[i],playT);
delay(playT);
}
exit(0);
}
배열 인덱스 6, 13번째 계이름만 두박자로 연주하고 나머지는 한박자로 연주
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);
}
전체코드
#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);
}
2번 핀에 연결된 버튼에 대해서 다음과 같이 동작하는 코드
int piezo = 7; //피에조가 연결된 디지털입출력 핀
int sw = 2; // 디지털입출력 2번 핀을 버튼스위치와 연결
int freq= 262; // 도의 주파수
int val = 0; // 변수의 초기값
void setup() {
pinMode(piezo, OUTPUT); // 출력 핀 설정
pinMode(sw, INPUT); // 입력 핀 설정
}
void loop() {
if (digitalRead(sw)==1) { // 버튼 스위치가 눌러진 경우
tone(piezo,freq); // '도(262)'의 주파수 출력
while(digitalRead(sw)==1) {} // 버튼 스위치가 계속 눌러진 경우
noTone(piezo);
}
}
버튼 스위치 입력에 따라 도, 레, 미, 파 연주
int piezo = 7; //피에조가 연결된 디지털입출력 핀
int sw[4] = {2, 3, 4, 5}; // 4개 스위치 지정
int freq[4]= {262, 294, 330, 349}; // 도, 레, 미, 파의 주파수
int val = 0; // 변수의 초기값
void setup() {
pinMode(piezo, OUTPUT); // 출력 핀 설정
for(int k=0; k<4; k++) {
pinMode( sw[k], INPUT); // 입력 핀 설정
}
}
void loop() {
if (digitalRead(sw[0])==1) {
tone(piezo,freq[0]);
while(digitalRead(sw[0])==1) {}
noTone(piezo);
} else if (digitalRead(sw[1])==1) {
tone(piezo,freq[1]);
while(digitalRead(sw[1])==1) {}
noTone(piezo);
} else if (digitalRead(sw[2])==1) {
tone(piezo,freq[2]);
while(digitalRead(sw[2])==1) {}
noTone(piezo);
} else if (digitalRead(sw[3])==1) {
tone(piezo,freq[3]);
while(digitalRead(sw[3])==1) {}
noTone(piezo);
}
}
for 문과 배열을 이용하여 중복 코드 단순화
int piezo = 7; //피에조가 연결된 디지털입출력 핀
int sw[4] = {2, 3, 4, 5}; // 4개 스위치 지정
int freq[7]= {262, 294, 330, 349}; // 도, 레, 미, 파의 주파수
int val = 0; // 변수의 초기값
void setup() {
pinMode(piezo, OUTPUT); // 출력 핀 설정
for(int k=0; k<4; k++) {
pinMode( sw[k], INPUT); // 입력 핀 설정
}
}
void loop() {
for(int k=0; k<4; k++) {
val = digitalRead(sw[k]);
if(val) { // k번째 스위치가 눌렸는지 검사
tone(piezo, freq[k]); // k번째 주파수 출력
while(digitalRead(sw[k])); //스위치가 계속 눌려지고 있는지 검사
noTone(piezo); //스위치 눌림이 끝나면 소리 정지
}
}
}
음과 박자를 고려하여, 다음 동요를 연주하는 스케치를 작성하여 보자.