-
아두이노 프로젝트 | 젤다의 전설 시간의 오카리나Technology/Arduino 2023. 11. 17. 18:00
1. 시간의 오카리나
일본 닌텐도에서 발매한 게임 <젤다의 전설 시간의 오카리나>에서 나오는 시간의 오카리나를 아두이노 플랫폼으로 구현해보자. 구현하고자 하는 시간의 오카리나는 택트 스위치 5개와 피에조 부저로 구성되어 있으며, 사리아의 노래(saria's song), 폭풍의 노래(song of storms), 젤다의 자장가(zelda's lullaby), 시간의 노래(song of time), 에포나의 노래(epona's song)이 저장되어 있다. 각 스위치를 누르면 이에 해당하는 음계 소리가 나면서 음계가 저장된다. 만약 사용자가 알맞은 음계 6개를 연속적으로 연주하면 정답 효과음과 함께 이에 해당하는 노래가 재생되고, 알맞지 않은 음계 6개를 연속적으로 연주하면 오답 효과음이 재생되며 저장된 음계가 초기화되도록 프로그램을 작성해보자.
2. 프로젝트
2.1. 회로 구성
2.2. 프로그램 작성
// 4옥타브 음계 주파수 정의 #define C4 262 #define D4 294 #define E4 330 #define F4 349 #define G4 392 #define A4 440 #define B4 494 // 5옥타브 음계 주파수 정의 #define C5 523 #define D5 587 #define E5 659 #define F5 698 #define G5 784 #define A5 880 #define B5 988 // 6옥타브 음계 주파수 정의 #define C6 1047 #define D6 1175 #define E6 1319 #define F6 1397 #define G6 1568 #define A6 1760 #define B6 1976 int Switch[] = {12, 11, 10, 9, 8}; // 정수형 배열 선언 후 디지털 핀 번호로 초기화 int Sign[] = {0, 0, 0, 0, 0}; // 정수형 배열 선언 후 0으로 초기화 int Buzzer = 2; // 정수형 변수 선언 후 디지털 핀 번호 2로 초기화 long Note_Serial[] = {0, 0, 0, 0, 0, 0}; // 정수형 배열 선언 후 0으로 초기화 int Counter = 0; // 정수형 변수 선언 후 0으로 초기화 void setup() { // 디지털 12, 11, 10, 9, 8번 핀을 입력(INPUT) 모드로 설정 for (int i = 0; i < 5; i++) { pinMode(Switch[i], INPUT); } pinMode(Buzzer, OUTPUT); // 디지털 2번 핀을 출력(OUTPUT) 모드로 설정 } void loop() { // 디지털 핀 12, 11, 10, 9, 8번 핀으로부터 받은 신호를 배열에 저장 for (int i = 0; i < 5; i++) { Sign[i] = digitalRead(Switch[i]); } delay(100); // 100 ms 대기 // 첫 번째 택트 스위치 if (Sign[0] == 1) // 첫 번째 배열 요소에 저장된 값이 1이면 실행 { // 디지털 12번 핀으로부터 받은 디지털 신호가 1인 동안 실행 while (digitalRead(Switch[0]) == 1) { tone(Buzzer, D4); // 디지털 2번 핀에 D4에 해당하는 디지털 신호 출력 } Note_Serial[Counter] = 1; // 연속적인 음계 정보 저장 Counter = Counter + 1; // 연속적인 음계 개수를 1 늘린 후 저장 } // 두 번째 택트 스위치 else if (Sign[1] == 1) { while (digitalRead(Switch[1]) == 1) { tone(Buzzer, F4); } Note_Serial[Counter] = 2; Counter = Counter + 1; } // 세 번째 택트 스위치 else if (Sign[2] == 1) { while (digitalRead(Switch[2]) == 1) { tone(Buzzer, A4); } Note_Serial[Counter] = 3; Counter = Counter + 1; } // 네 번째 택트 스위치 else if (Sign[3] == 1) { while (digitalRead(Switch[3]) == 1) { tone(Buzzer, B4); } Note_Serial[Counter] = 4; Counter = Counter + 1; } // 다섯 번째 택트 스위치 else if (Sign[4] == 1) { while (digitalRead(Switch[4]) == 1) { tone(Buzzer, D5); } Note_Serial[Counter] = 5; Counter = Counter + 1; } else { noTone(Buzzer); // 디지털 2번 핀에 디지털 신호 미출력 } delay(100); // 연속적인 음계 개수가 6개면 실행 if (Counter == 6) { // 연속적인 음계 정보를 실수 자료형으로 변형 long Serial_Num = Note_Serial[0] * 100000 + Note_Serial[1] * 10000 + Note_Serial[2] * 1000 + Note_Serial[3] * 100 + Note_Serial[4] * 10 + Note_Serial[5] * 1; // 연속적인 음계 정보가 234234이면 사리아의 노래를 재생 if (Serial_Num == 234234) { Correct_Sound(Buzzer); // Correct_Sound 함수 실행 Sarias_Song(Buzzer); // Sarias_Song 함수 실행 // 연속적인 음계 정보 초기화 for (int i = 0; i < 6; i++) { Note_Serial[i] = 0; } Counter = 0; } // 연속적인 음계 정보가 125125이면 폭풍의 노래를 재생 else if (Serial_Num == 125125) { Correct_Sound(Buzzer); Song_of_Storm(Buzzer); for (int i = 0; i < 6; i++) { Note_Serial[i] = 0; } Counter = 0; } // 연속적인 음계 정보가 453453이면 젤다의 자장가를 재생 else if (Serial_Num == 453453) { Correct_Sound(Buzzer); Zeldas_Lullaby(Buzzer); for (int i = 0; i < 6; i++) { Note_Serial[i] = 0; } Counter = 0; } // 연속적인 음계 정보가 312312면 시간의 노래를 재생 else if (Serial_Num == 312312) { Correct_Sound(Buzzer); Song_of_Time(Buzzer); for (int i = 0; i < 6; i++) { Note_Serial[i] = 0; } Counter = 0; } // 연속적인 음계 정보가 543543이면 에포나의 노래를 재생 else if (Serial_Num == 543543) { Correct_Sound(Buzzer); Eponas_Song(Buzzer); for (int i = 0; i < 6; i++) { Note_Serial[i] = 0; } Counter = 0; } else { Wrong_Sound(Buzzer); // Wrong_Sound 함수 실행 Counter = 0; // 변수를 0으로 초기화 // 연속적인 음계 정보 초기화 for (int i = 0; i < 6; i++) { Note_Serial[i] = 0; } } } } // 사리아의 노래 void Sarias_Song(int Buzzer) { int Note[20] = { // 정수형 배열 선언 후 음계 정보를 저장 F4, A4, B4, F4, A4, B4, F4, A4, B4, E5, D5, B4, C5, B4, G4, E4, D4, E4, G4, E4 }; float Tempo[20] = { // 실수형 배열 선언 후 박자 정보를 저장 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 0.5, 0.5, 1, 0.5, 0.5, 0.5, 0.5, 2.5, 0.5, 0.5, 0.5, 3 }; int Size = sizeof(Note) / sizeof(int); // 배열의 길이 연산 // 사리아의 노래 재생 for (int i = 0; i < Size; i++) { float NoteDuration = 300 * Tempo[i]; // 실수형 변수 선언 후 초기화 // 디지털 2번 핀에 Note[i]에 해당하는 디지털 신호를 NoteDuration동안 출력 tone(Buzzer, Note[i], NoteDuration); float PauseBetweenNotes = NoteDuration * 1.30; // 실수형 변수 선언 후 초기화 delay(PauseBetweenNotes); // PauseBetweenNotes동안 대기 } } // 폭풍의 노래 void Song_of_Storm(int Buzzer) { int Note[23] = { D4, F4, D5, D4, F4, D5, E5, F5, E5, F5, E5, C5, A4, A4, D4, F4, G4, A4, A4, D4, F4, G4, E4 }; float Tempo[23] = { 0.5, 0.5, 2, 0.5, 0.5, 2, 1.5, 0.5, 0.5, 0.5, 0.5, 0.5, 2, 1, 1, 0.5, 0.5, 3, 1, 1, 0.5, 0.5, 3 }; int Size = sizeof(Note) / sizeof(int); for (int i = 0; i < Size; i++) { float NoteDuration = 250*Tempo[i]; tone(Buzzer, Note[i], NoteDuration); float PauseBetweenNotes = NoteDuration * 1.30; delay(PauseBetweenNotes); } } // 젤다의 자장가 void Zeldas_Lullaby(int Buzzer) { int Note[13] = { B4, D5, A4, G4, A4, B4, D5, A4, B4, D5, A5, G5, D5 }; float Tempo[13] = { 2, 1, 2, 0.5, 0.5, 2, 1, 3, 2, 1, 2, 1, 4 }; int Size = sizeof(Note) / sizeof(int); for (int i = 0; i < Size; i++) { float NoteDuration = 500 * Tempo[i]; tone(Buzzer, Note[i], NoteDuration); float PauseBetweenNotes = NoteDuration * 1.30; delay(PauseBetweenNotes); } } // 시간의 노래 void Song_of_Time(int Buzzer) { int Note[17] = { A4, D4, F4, A4, D4, F4, A4, C5, B4, G4, F4, G4, A4, D4, C4, E4, D4 }; float Tempo[17] = { 1, 2, 1, 1, 2, 1, 0.5, 0.5, 1, 1, 0.5, 0.5, 1, 1, 0.5, 0.5, 4 }; int Size = sizeof(Note) / sizeof(int); for (int i = 0; i < Size; i++) { float NoteDuration = 500 * Tempo[i]; tone(Buzzer, Note[i], NoteDuration); float PauseBetweenNotes = NoteDuration * 1.30; delay(PauseBetweenNotes); } } // 에포나의 노래 void Eponas_Song(int Buzzer) { int Note[11] = { D5, B4, A4, D5, B4, A4, D5, B4, A4, B4, A4 }; float Tempo[11] = { 0.5, 0.5, 2, 0.5, 0.5, 2, 0.5, 0.5, 1, 1, 2 }; int Size = sizeof(Note) / sizeof(int); for (int i = 0; i < Size; i++) { float NoteDuration = 500 * Tempo[i]; tone(Buzzer, Note[i], NoteDuration); float PauseBetweenNotes = NoteDuration * 1.30; delay(PauseBetweenNotes); } } // 정답 알림음 void Correct_Sound(int Buzzer) { int Note[5] = {C4, D4, E4, F4, F6}; delay(100); noTone(Buzzer); delay(500); for (int i = 0; i < 6; i++) { tone(Buzzer, Note[i]); delay(100); } noTone(Buzzer); delay(500); } // 오답 알림음 void Wrong_Sound(int Buzzer) { noTone(Buzzer); delay(500); tone(Buzzer, F4); delay(100); noTone(Buzzer); delay(100); tone(Buzzer, F4); delay(1000); noTone(Buzzer); delay(500); }
[함께 읽으면 좋은 페이지]
참고문헌
saskiot. (2017). Legend of Zelda electronic ocarina. YouTube. https://www.youtube.com/watch?v=2q0E0348nAI. 2023.10.22.
반응형'Technology > Arduino' 카테고리의 다른 글
아두이노 프로젝트 | 자동차 후방 감지기 (0) 2023.12.01 아두이노 | 초음파센서 모듈 HC-SR04 (1) 2023.11.24 아두이노 프로젝트 | 디지털 피아노 (0) 2023.11.10 아두이노 | 피에조 부저 (1) 2023.11.03 아두이노 프로젝트 | 밝기 조절이 가능한 스탠드 (0) 2023.09.01