Introduction: Christmas Song Player

This experiment shows a piezo buzzer playing Christmas songs pressing the push button.  It has two songs who alternates every time you press the button.  In order to play the other song, you have to wait until the song that is playing ends and press the button. 

Also, it has a potentiometer that allows you to change the speed of the song.

In the code, it uses an h file for the mapping of notes with its frequency. Its name is pitches.h, it can be find here arduino.cc/en/Tutorial/Tone3.

Step 1: Parts

Hardware Required
- Arduino Board
- RGB-Led
- Push Button
- Piezo speaker
- Rotary potentiometer
- 100 Ω Resistor (brown-black-brown)
- 270 Ω x 3 Resistor (red-purple-brown)
- 10k Ω Resistor (brown-black-orange)

PIEZO SPEAKER
- It produces notes with a certain frequency.
- It has two pins, one pin we are going to connect to GND and the other to a resistor of 100 Ohms

RGB-LED(common Anode)
- This Led allows you to light up it with 3 differents colors Red, Green and blue. Basically is a box with 3 leds inside.
- It is called common anode because the three leds share its anode (see the schematic below).
- We will combine the colors in order to generate other colors that will be synchronized with the song played.
- The long pin of the led is connected to +5v , and the others are connected to a resistor of 270 Ohms each one.
- In the flat part of the led we found the red pin, then the common anode, blue pin () and the green pin.  They should be connected as the schematic shows.

ROTARY POTENTIOMETER
- This will allow us to control the speed of the music just rotating it.
- It gives values between 0-1023.  We will see how to map them to the range that we want.

Arduino UNO and Arduino IDE
- It is an open source electronics prototyping platform, easy to use hardware and software.
- Its environment allows us to program the microcontroller ATMEGA of the Arduino UNO. For more information go to http://www.arduino.cc/






Step 2: Piezo - Speaker Component

Description
This component will allow us to produce our Christmas songs :).

How to wire it?
-As you will see in the datasheet of the Piezo speaker, it requires 8mA, so for this case, we will use a resistor of 100Ohms (brown-black-brown) in order to reduce the current that is flowing through this component.
-We are going to use the pin 8 of the Arduino to send the specified frequency that will allow us to produce tones.
-Follow the schematic in order to connect each pin of the Piezo speaker correctly.

Code
Here I will explain which parts of the code will allow us to produce these tones.

First we import the file "pitches.h".  It defines the frequency mapped with a name that represent our notes. 
E.g.  NOTE_D3 = 147


#include "pitches.h"

This to constants represent the number of notes that have our songs.  Since we have two songs, one has 24 notes and the other have 14

#define SONG1_SIZE 24
#define SONG2_SIZE 14

This array is just an array of frequency that was given by the file pitches.h

// notes in the melody 1:
int melody1[] = {
  NOTE_D3, NOTE_B3, NOTE_A3, NOTE_G3, NOTE_D3,
  NOTE_D3, NOTE_D3, NOTE_D3, NOTE_B3, NOTE_A3, NOTE_G3, NOTE_E3, 0,
  NOTE_E3, NOTE_C4, NOTE_B3, NOTE_A3, NOTE_FS3, 0 ,
  NOTE_D4, NOTE_D4, NOTE_C4, NOTE_A3, NOTE_B3
};

// notes in the melody 2:
int melody2[] = {
NOTE_F4, NOTE_E4, NOTE_D4, NOTE_C3, NOTE_AS3, NOTE_A3, NOTE_G3, NOTE_F3,
  NOTE_C4, NOTE_D4, NOTE_D4, NOTE_E4, NOTE_E4, NOTE_F4
};


The durations of each note is specified in the following arrays for each song (1 -> 1sec ,4  -> quaver ...etc)

// note durations of melody 1: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations1[] = {
  4, 4, 4, 4, 2.5,
  8, 8, 4, 4, 4, 4, 2.5, 2,
  4, 4, 4, 4, 2.5, 2,
4, 4, 4, 4, 1};
// note durations of melody 2: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations2[] = {
  2, 2.5, 8, 1.5, 4, 2, 2 ,1.5,
  4, 1.8, 4, 1.8, 4, 1};

Inside of the loop() method, we will find a loop-for. This will go through  each note of our melody1 or melody2

for (int thisNote = 0; thisNote < songSizeS ; thisNote++) {
    .....
      // to calculate the note duration, take one second

     // divided by the note type.

     //e.g. quarter note = 1000 / 4, eighth note =     1000/8, etc.
     i
nt noteDuration =  1000/noteDurationS[thisNote];
    
     //tone function will produce the tone and send it trough pin 8 with its duration
tone(pin, frequency,duration)
     tone(8, melodyS[thisNote],noteDuration);
      ....
      // to distinguish the notes, set a minimum time between them.
      // the note's duration will be handel by the tempo variable which is variable depending of the potentiometer (step 5)
     
int pauseBetweenNotes = noteDuration * tempo;
      delay(pauseBetweenNotes);
      // stop the tone playing:
     
noTone(8);
      .....
}

Step 3: Light Component

Description
The RGB-led component will allow us to light up our Christmas song.

How to wire it?
-In this experiment we are using RGB-led common anode, this means that it should be connected to +5v (otherwise GND).  
-Also we will limit the current to ~20mA using the resistor of 270Ohms (red-purple-brown).
-Follow the schematic as it is shown in the picture.

Code
We are going to use the pin11, pin10 and pin9 to send the Red-Green-Blue values to the RGB-led as it is shown:

int redPin = 11;
int greenPin = 10;
int bluePin = 9;

In the setup() function we are going to specify the mode of the pins:

void setup() {
  //setup pins
 
pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
  pinMode(button, INPUT);
  //light up to green at the beginning
 
  mapColor(-1);
  .....
}

The mapColor() function is the main function that allow us to light up our RGB-LED with an specific color.  The idea is to combine intensities of RGB in order to produce other colors rather than red, green and blue.

void mapColor(int note)
{
  //The switch will maps the note to a certain color
 
switch(note)
  {
  case NOTE_C3:
  case NOTE_C4:
    //combine colors to produce a new one :)
    analogWrite(redPin, 0);
    analogWrite(greenPin, 255 );
    analogWrite(bluePin,   255);
    break;
  .......
  .......
   }
}





Step 4: Switch Between Songs

Description
Using a button, we are going to switch between songs.

How to wire it?
-As the same of the other components, we are going to limit its current to 20mA using a resistor of 10kOhms(brown-black-orange).
-Follow the schematic to know which pin to use.

Code
We are going to control the button in the way that, each time it is pressed it will alternate the song.

First we declare some variables to control it:

//pin number
int button = 2;
//control variables
int counter = 0;

int pressed = 0;

boolean playsong =false;
//song temp variables to point the song to play
int songSizeS;
int *noteDurationS = 0;
int *melodyS=0;

In the loop() function we are going to verify that the button should be pushed and released in order to play the song:

void loop() {
  //detect when the button was pressed
  if(digitalRead(button)  ==LOW)
  {
     pressed = 1;
  }
  //detect when the button was released
 
if(digitalRead(button)  ==HIGH && pressed == 1)
  {
    counter++;
    pressed = 0;
    playsong =true;//variable to control when to start the song
    //decide which song plays

    if( counter % 2 == 0 )
{
      songSizeS = SONG1_SIZE;
      noteDurationS = noteDurations1;
      melodyS = melody1;
    } 
    else
    {
      songSizeS = SONG2_SIZE;
      noteDurationS = noteDurations2;
      melodyS = melody2;
     }
}
  //start the song if the button was pressed:
 
if(playsong)
  {
       playsong =false; 
       ....
       //play the song and the light up the led
     
 ....
  }
}


Step 5: Speed Variator

Description
Using the potentiometer, we are going to variate the speed of the song.

How to wire it?
- As the potentiometer has 3 pins, the middle will be connected to pin A0 of the Arduino, the others two will go to 5vc and GND respectively (follow the schematic). While we turn the potentiometer, it will give us values which we are going to use in order to control the speed of the song.

Code
First we are going to declare some variables of control:

//speed control variables
int sensorValue = 0;
float tempo = 0;

Then, during the for-loop we are going to sense the values given by the potentiometer using the pinA0. We are going to limit those values to 3. 

loop()
{
  ....
  for(....)
  {
     .....
    //sensor value from the potentiometer mapped to range until 3 
    sensorValue =analogRead(A0);

    tempo = sensorValue * (3.0 / 1023.0);
    ....
    // to distinguish the notes, set a minimum time between them.
    // the note's duration * tempo speed given by the potentiometer:
   
int pauseBetweenNotes = noteDuration * tempo;
    ....
  }
}




Step 6: Time to Run It !!!

After we have connected all the hardware and analyzed the code we are ready to run it!.

Video
http://youtu.be/lV9WurONtV0


As summary
The program will have 3 main parts:


-The first part consists of variables declaration, constants and  imports of other files.  It imports the file "pitches.h", there you will find the constant of the notes with their frequencies. You can download it from arduino page:  http://arduino.cc/en/Tutorial/Tone3
-The second part is the setup() which basically is the initialization of the program.  Here we will define input/output pins and other stuff. The setup part will only run once, at the beginning of the program.
-The third part is the loop(). This will always until you turn off the arduino. There you will find the code of the main program which plays the song and light up the led with different colors.  Also it sense the value of the potentiometer to define the speed (tempo) which it will play.



All the complete code:

/* Melody
Plays a melody
circuit:
* 8-ohm speaker on digital pin 8
Base on the example of http://arduino.cc/en/Tutorial/Tone by Tom Igoe
Modified by: Irene Meiying Cheung Ruiz
*/

#include "pitches.h"
#define SONG1_SIZE 24
#define SONG2_SIZE 14

// notes in the melody 1:
int melody1[] = {
  NOTE_D3, NOTE_B3, NOTE_A3, NOTE_G3, NOTE_D3,
  NOTE_D3, NOTE_D3, NOTE_D3, NOTE_B3, NOTE_A3, NOTE_G3, NOTE_E3, 0,
  NOTE_E3, NOTE_C4, NOTE_B3, NOTE_A3, NOTE_FS3, 0 ,
  NOTE_D4, NOTE_D4, NOTE_C4, NOTE_A3, NOTE_B3
};

// notes in the melody 2:
int melody2[] = {
NOTE_F4, NOTE_E4, NOTE_D4, NOTE_C3, NOTE_AS3, NOTE_A3, NOTE_G3, NOTE_F3,
  NOTE_C4, NOTE_D4, NOTE_D4, NOTE_E4, NOTE_E4, NOTE_F4
};

// note durations of melody 1: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations1[] = {
  4, 4, 4, 4, 2.5,
  8, 8, 4, 4, 4, 4, 2.5, 2,
  4, 4, 4, 4, 2.5, 2,
4, 4, 4, 4, 1};

// note durations of melody 2: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations2[] = {
  2, 2.5, 8, 1.5, 4, 2, 2 ,1.5,
  4, 1.8, 4, 1.8, 4, 1};

//Pins
int redPin = 11;
int greenPin = 10;
int bluePin = 9;
int button = 2;

//control variables
int counter = 0;
int pressed = 0;
boolean playsong =false;

//song temp variables
int songSizeS;
int *noteDurationS = 0;
int *melodyS=0;

//speed control variables
int sensorValue = 0;
float tempo = 0;


// initialization
void setup() {
  //setup pins
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
  pinMode(button, INPUT);

  //light up to green at the beginning
   mapColor(-1);
  //debug purposes
  Serial.begin( 9600 ); // optional
}

// main program
void loop() {
  //detect when the button was pressed
  if(digitalRead(button)  ==LOW)
  {
     pressed = 1;
  }

  //detect when the button was realesed
  if(digitalRead(button)  ==HIGH && pressed == 1)
  {
    counter++;
    pressed = 0;
    playsong =true;
//variable to control when to start the song

//decide which song plays
  if( counter % 2 == 0 )
  {
      songSizeS = SONG1_SIZE;
      noteDurationS = noteDurations1;
      melodyS = melody1;
   }
  else
    {
      songSizeS = SONG2_SIZE;
      noteDurationS = noteDurations2;
      melodyS = melody2;
     }
   }

  //start the song if the button was pressed:
  if(playsong)
  {

      playsong =false;
     
// iterate over the notes of the melody
      for (int thisNote = 0; thisNote < songSizeS ; thisNote++)
      {
         
//sensor value from the potentiometer mapped to range of 1 - 3 speed values
         sensorValue =analogRead(A0);
         tempo = sensorValue * (3.0 / 1023.0); Serial.println(tempo);

         // to calculate the note duration, take one second
        // divided by the note type.
        //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc. int noteDuration = 1000/noteDurationS[thisNote];
        tone(8, melodyS[thisNote],noteDuration);
        //light up the rgb-led depending of the note
        mapColor( melodyS[thisNote] );
        // to distinguish the notes, set a minimum time between them.
        // the note's duration * tempo
        int pauseBetweenNotes = noteDuration * tempo;
        delay(pauseBetweenNotes);

        // stop the tone playing:
        noTone(8);
        //light up the led to initial state (green color)
        mapColor(-1);
     }
  }
}


//function that maps the note to a certain color
// it combines the color of RGB to produce a different one
void mapColor(int note)
{
  switch(note)
  {
  case NOTE_C3:
  case NOTE_C4:
    analogWrite(redPin, 0);
    analogWrite(greenPin, 255 );
    analogWrite(bluePin,   255);
    break;
  case NOTE_D3:
  case NOTE_D4:
    analogWrite(redPin, 0);
    analogWrite(greenPin, 0 );
    analogWrite(bluePin,   255);
    break;
  case NOTE_E3:
  case NOTE_E4:
    analogWrite(redPin, 255);
    analogWrite(greenPin, 0 );
    analogWrite(bluePin,   0);
    break;
  case NOTE_F3:
  case NOTE_F4:
    analogWrite(redPin, 0);
    analogWrite(greenPin, 255 );
    analogWrite(bluePin,   0);
    break;
  case NOTE_G3:
  case NOTE_G4:
    analogWrite(redPin, 255);
    analogWrite(greenPin, 0);
    analogWrite(bluePin,   255);
    break;
  case NOTE_A3:
  case NOTE_A4:
    analogWrite(redPin, 255);
    analogWrite(greenPin, 255 );
    analogWrite(bluePin,   0);
    break;
  case NOTE_B3:
  case NOTE_B4:
    analogWrite(redPin, 0);
    analogWrite(greenPin, 0 );
    analogWrite(bluePin,   0);
    break;
  case  0:
//it represents end state or silence
    analogWrite(redPin, 255);
    analogWrite(greenPin, 255 );
    analogWrite(bluePin,   255);
    break;

  case -1:// it represents initial state
    analogWrite(redPin, 255);
    analogWrite(greenPin, 0);
    analogWrite(bluePin,   255);
    break;
  default:
//other notes
    analogWrite(redPin, 105);
    analogWrite(greenPin, 255 );
    analogWrite(bluePin,   100);
    break;
  }
}