Introduction: Arduino Ocarina

About: Game Design Student at HKU

In this tutorial I'll be showing you how to make your own ocarina like in Zelda!

Supplies

Necessities for this project:

  • Piezo Buzzer
  • 5 buttons of your choosing 
  • Arduino Uno (Nano if you want to make a smaller Ocarina) 
  • Circuit board 
  • LDR Sensor 
  • Arduino IDE (free program Windows & Mac) 
  • USB A to USB B Cable (usually comes with Arduino) 
  • Wires for the Arduino of your choosing (Jumper Wires or normal Copper cables for example, coloured cables are helpful ( Black, White, Red, Blue, Yellow) The final project has 18 wires but make sure to keep extra at hand
  • Soldering Kit 
  • 6 Resistors 10K Ohm
  • A breadboard (if you want to test)



Further necessities:

I made the Ocarina out of wood so you can use wood for this project. I used sprucewood. First make the circuit board and the arduino part and then you can measure how much space you will need inside your Ocarina and thus be able to get a piece of wood accordingly, I think you can make this with clay as well 

Wood / Wood workshop

Step 1: Breadboard Testing(skip to Step Three If You Are Not Testing)

Here you will remake the setup in the added picture (left side) Test out your material so you are certain everything is working.

Get the following:

  • Wire
  • Breadboard
  • Piezo Buzzer
  • LDR
  • 5 buttons
  • Arduino
  • Resistors


Then put in your buttons, resistors and buzzer first as shown in the picture.

Then grab a white, black, yellow, blue, red and cyan wires.

put one side of each cable on the right side of the buttons and the LDR.


Connect them as followed on the Arduino:

white:12

black:10

yellow:9

blue:8

red:7

cyan:A2


Yes we skipped 11!


Because 11 is the Piezo Buzzer, connect the negative (usually black) side to the 11 on the Arduino.

Then on the right side corner of the picture you can see a red and black cable, we are using this to show the positive and the negative positive being red negative being black. Connect the red cable to the 5v and the black wire to the GRND.

Now to connect all the buttons and the LDR to the positive. Get red wires and connect them to the left side of the buttons now and add them all to the row of positive as shown in the picture

Now that's everything is connected it's time for step 2!

Make sure to check the picture to know you did everything right.




Step 2: Setting Up Arduino Files

Download Arduino IDE here:

https://www.arduino.cc/en/software


Then download my files make sure pitches.h and Zelda Ocarina.ino are in a folder together.


Open Zelda Ocarina.ino

It should look like the second screenshot.


Connect your Arduino to the PC with the USB cable, the program should automatically read that you connected it.


Upload the code to the Arduino by pressing the " Upload" button it is depicted as an arrow facing right


You can now test your buttons and play some songs!

Step 3: Circuit Board + Soldering

Now that you've tested everything and it's all working its time to do this on the circuit board. Since the buttons will have to go through the wood we aren't going to connect those to the circuit board just yet. You can however add the coloured wire to the right side of the button and a red wire to the left one. Do the same for the LDR, Piezo and the buttons.

Now for the circuit board.

See it as a street, houses an island.

We're going to make an island where we attach all red wires from the buttons and the LDR (the lefts), to this we'll add the 'positive' , the wire that will go to the 5v. This can be a cluster or a line as long as all islands touch. Then we'll make a negative (or ground line) this will be the street, the street will be connected by one side of the resistors to this street you attach the black wire going to the grnd.

Then we have the houses these are on the other side of the resistor the houses should not touch they all have their own yard and electricity. To this side you will add the coloured wires from de LDR and the buttons. Each house (resistor) will have a coloured wire and the same coloured wire that leads from the resistor to the Arduino. (make sure to do this step after you build your housing(the wood or clay or etc.)

The Piezo buzzer will be connected to the 11 with the negative and the positive will be connected to the ground.

And that's it! make sure to look at the drawing if things aren't working. Also a tip is to make the button have long wires so you have the ease of space when soldering then through the wood.


Step 4: The Woodworking

As this isn't the main point of this tutorial I am going to make a short list of steps with not a lot of explanation and I'll add the pictures of the process.

  1. Make sure to measure your Arduino and circuit board together and leave a bit of space measure the height, depth and length.
  2. Take 2 pieces of wood that are exactly the same, take your measurement and make a hole in both pieces of wood. for example if your Arduino measure ten cm make sure to have 5cm depth in both and add a cm on both sides to be sure.
  3. Make a mold to keep both side exactly the same.
  4. Draw out your mold and make stripes to indicated the parts that will go
  5. Before we go any further, check if your Arduino fits in the hole you made.
  6. After cutting out your mold, you'll have two blocks that are exactly the same
  7. you can put in a precise piece of wood to hold both sides together. sand them together to make them the same.
  8. Round them till you are happy with the shape, make sure to not make them too small or you'll break into the hole.
  9. Make a hole for the Piezo speaker, on the bottom
  10. Make a hole for the LDR, on the mouth piece
  11. Make a hole for the USB cable
  12. Make the holes for the buttons, pre drill them so the wood doesn't break, put your buttons through the hole and solder the cables.
  13. Put the LDR in place and the speaker too
  14. I made these little magnet holes so that it can close and open, on the other side I put screws that are magnetic.

And that's it! you've made your Arduino Ocarina!


Step 5: Cheat Sheet

Song Cheat Sheet: 


Saria's Song: 

Blue - Red - Yellow - Blue - Red - Yellow 


Zelda’s Lullaby: 

Yellow - Black -  Red - Yellow - Black -  Red 


Sun Song: 

Red - Blue - Black - Red - Blue - Black


Song Of Storms:

White - Blue - Black - White - Blue - Black


Song of Time:

Red - White - Blue - Red - White - Blue


Epona’s Song: 

Black - Yellow - Red - Black - Yellow - Red



Step 6: Code

//this version of pitches.h is modified, so don't use the default arduino pitches.h
#include "pitches.h"

boolean isPlay1 = false;
boolean isPlay2 = false;
boolean isPlay3 = false;
boolean isPlay4 = false;
boolean isPlay5 = false;
boolean isPlay6 = false;
char note1;
char note2;
char note3;
char note4;
char note5;
char note6;

const int LIGHT_SENSOR_PIN = A2; // Arduino pin connected to light sensor's pin
const int ANALOG_THRESHOLD = 10;
int analogValue;


int read[] = { 8, 9, 12, 10, 7 };
char logicChars[] = { 'z', 'g', 'r', 'b', 'w' };


int tones[] = { _D5, _B4, _A4, _F4, _D4 };


int logic(char note) {
if (isPlay1) {
if (isPlay2) {
if (isPlay3) {
if (isPlay4) {
if (isPlay5) {
note6 = note;
isPlay6 = true;
Serial.print("6");
} else {
note5 = note;
isPlay5 = true;
Serial.print("5");
}
} else {
note4 = note;
isPlay4 = true;
Serial.print("4");
}
} else {
note3 = note;
isPlay3 = true;
Serial.print("3");
}
} else {
note2 = note;
isPlay2 = true;
Serial.print("2");
}
} else {
note1 = note;
isPlay1 = true;
Serial.print("1");
}
}

//this song plays after a correct song combination is played
int correctSong() {
noTone(11);

int correctSongArray[5] = { _D5, _F5, _A5, _C6, _D6 };
for (int i = 0; i < sizeof(correctSongArray); i++) {
tone(11, correctSongArray[i], 325);
delay(100);
}
}

int playSariaSong() {
//play correct sound effect
correctSong();
delay(500);

//play song
int sariaSongArray[] = { _F4, _A4, _B4, _F4, _A4, _B4, _F4, _A4, _B4, _E5, _D5, _B4, _C5, _B4, _G4, _E4, _D4, _E4, _G4 };
int sariaSongDelay[] = { 250, 250, 500, 250, 250, 500, 250, 250, 250, 250, 500, 250, 250, 250, 250, 625, 250, 250, 250 };
for (int i = 0; i < sizeof(sariaSongArray); i++) {
tone(11, sariaSongArray[i]);
delay(sariaSongDelay[i]);
}
tone(11, _E4, 750);
delay(750);
}

int playZeldaLullaby() {
//play correct sound effect
correctSong();
delay(500);

//play song
int zeldaLullabyArray[] = { _B4, _D5, _A4, _B4, _D5, _A4, _B4, _D5, _A5, _G5, _D5, _C5, _B4 };
int zeldaLullabyDelay[] = { 875, 500, 1000, 875, 500, 1000, 875, 500, 1000, 500, 750, 250, 250 };
for (int i = 0; i < sizeof(zeldaLullabyArray); i++) {
tone(11, zeldaLullabyArray[i]);
delay(zeldaLullabyDelay[i]);
}
tone(11, _E4, 750);
delay(750);
}

int playSunSong() {
//play correct sound effect
correctSong();
delay(500);

//play song
int sunSongArray[] = { _A4, _F4, _D5, _A4, _F4, _D5, _A4, _B4, _C5, _D5, _E5, _F5 };
int sunSongDelay[] = { 250, 250, 625, 250, 125, 500, 125, 125, 125, 125, 125, 125 };
for (int i = 0; i < sizeof(sunSongArray); i++) {
tone(11, sunSongArray[i]);
delay(sunSongDelay[i]);
}
tone(11, _G5, 750);
delay(750);
}

int playSongOfStorms() {
//play correct sound effect
correctSong();
delay(500);

//play song
int songOfStromArray[] = { _D4, _F4, _D5, _D4, _F4, _D5, _E5, _F5, _E5, _F5, _E5, _C5, _A4, _A4, _D4, _F4, _G4, _A4, _A4, _D4, _F4, _G4 };
int songOfStormDelay[] = { 250, 125, 600, 250, 125, 600, 500, 125, 125, 125, 125, 125, 625, 250, 250, 125, 125, 625, 250, 375, 125, 250 };
for (int i = 0; i < sizeof(songOfStromArray); i++) {
tone(11, songOfStromArray[i]);
delay(songOfStormDelay[i]);
if (i == 12 || i == 17) {
noTone(11);
}
}
tone(11, _E4, 750);
delay(750);
}

int playSongOfTime() {
//play correct sound effect
correctSong();
delay(500);

//play song
int songOfTimeArray[] = { _A4, _D4, _F4, _A4, _D4, _F4, _A4, _C5, _B4, _G4, _F4, _G4, _A4, _D4, _C4, _E4 };
int songOfTimeDelay[] = { 500, 1000, 500, 500, 1000, 500, 250, 250, 500, 500, 250, 250, 500, 500, 250, 250 };
for (int i = 0; i < sizeof(songOfTimeArray); i++) {
tone(11, songOfTimeArray[i]);
delay(songOfTimeDelay[i]);
}
tone(11, _D4, 750);
delay(750);
}

int playEponaSong() {
//play correct sound effect
correctSong();
delay(500);

//play song
int EponaSongArray[] = { _D5, _B4, _A4, _D5, _B4, _A4, _D5, _B4, _A4, _B4 };
int EponaSongDelay[] = { 250, 250, 1125, 250, 250, 1125, 250, 250, 625, 625 };
for (int i = 0; i < sizeof(EponaSongArray); i++) {
tone(11, EponaSongArray[i]);
delay(EponaSongDelay[i]);
}
tone(11, _A4, 750);
delay(750);
}

int songChecker() {
//check for Saria's Song


if (note1 == 'b' && note2 == 'r' && note3 == 'g' && note4 == 'b' && note5 == 'r' && note6 == 'g') {
playSariaSong();
}
//check for Zelda's Lullaby
else if ((note1 == 'g') && (note2 == 'z') && (note3 == 'r') && (note4 == 'g') && (note5 == 'z') && (note6 == 'r')) {
playZeldaLullaby();
}
//check for the Sun's Song
else if ((note1 == 'r') && (note2 == 'b') && (note3 == 'z') && (note4 == 'r') && (note5 == 'b') && (note6 == 'z')) {
playSunSong();
}
//check for the Song of Storms
else if ((note1 == 'w') && (note2 == 'b') && (note3 == 'z') && (note4 == 'w') && (note5 == 'b') && (note6 == 'z')) {
playSongOfStorms();
}
//check for the Song of Time
else if ((note1 == 'r') && (note2 == 'w') && (note3 == 'b') && (note4 == 'r') && (note5 == 'w') && (note6 == 'b')) {
playSongOfStorms();
}
//check for Epona's Song
else if ((note1 == 'z') && (note2 == 'g') && (note3 == 'r') && (note4 == 'z') && (note5 == 'g') && (note6 == 'r')) {
playEponaSong();
} else {
//plays error tone if no correct song combo is played
tone(11, _D2, 750);
delay(500);
}
isPlay1 = false;
isPlay2 = false;
isPlay3 = false;
isPlay4 = false;
isPlay5 = false;
isPlay6 = false;
}

void setup() {
Serial.begin(9600);
//Speaker pin
pinMode(3, OUTPUT); // IS ACTUALLY 11 don't know why

//Light sensor
pinMode(LIGHT_SENSOR_PIN, OUTPUT);

//Button Pins
pinMode(8, INPUT);
pinMode(9, INPUT);
pinMode(12, INPUT);
pinMode(7, INPUT);
pinMode(10, INPUT);
}

void loop() {
//code you always run here; you can leave this section blank if you want the entire program to stop and start, or add code here if you want it to always run
//D,F,A,C,D


analogValue = analogRead(LIGHT_SENSOR_PIN); // read the input on analog pin


Serial.print("Analog reading: ");
Serial.println(analogValue); // the raw analog reading

if (analogValue < ANALOG_THRESHOLD) {
for (int i = 0; i < 5; i++) {
if (digitalRead(read[i]) != 0) {
logic(logicChars[i]);
while (digitalRead(read[i]) != 0) {
tone(11, tones[i], 50);
}
}
}
if (isPlay6) {
songChecker();
}
}
}