Experiment 9:

Finally some Music

In this experiment we are going to learn how to make a speaker or buzzer click. Now a click may not sound like much :-) but when we put clicks together we can make more interesting sounds. For example, if we have 440 clicks in a second we have the note ‘A’. If we have 3 short periods of it clicking at 392 clicks per second followed by a period of it clicking at 261 clicks per second we have the opening four notes of Beethoven’s Fifth Symphony (albeit in a musical greeting card quality). Let’s get clicking.

Parts Needed

You will need:

  • 1x buzzer or speaker
  • a Few Jumper Wires

Hardware Hookup

Link to larger image

The basic code

int speaker = 3;

// We'll set up an array with the notes we want to play
// change these values to make different songs!

// Length must equal the total number of notes and spaces

   //
  //
 // SONG 1
//
void song1(){
   const int songLength = 17;
   String notes[] = {"C4", "D4", "F4", "D4", "A4", " ",  "A4", "G4", " ",
                     "C4", "D4", "F4", "D4", "G4", " ", "G4", "F4"};
   //a space represents a rest

   // Beats is an array of values for each note and rest.
   // A 1 represents the shortest note in the song. If it is an eighth note, then 1 = an eighth note,
   // if the shortest note is a 16th note, then 1 represents a 16th note
   // Don't forget that the rests (spaces) need a length as well.
   int beats[] = {1,1,1,1,1,1,4,4,2,1,1,1,1,1,1,4,4,2};

   // the notes and beats array are aligned meaning the first note C4 has a beat of 1.

   int tempo = 150;

   int i, duration;

   // step through the song array
   for (i = 0; i < songLength; i++){
      duration = beats[i] * tempo;   // length of note/rest in ms
      if (notes[i] == " ") {         // is this a rest?
        delay(duration);             // then pause for a moment
      }
      else {                         // otherwise, play the note
        tone(speaker, frequency(notes[i]), duration);
        delay(duration);             // wait for tone to finish
      }
      delay(tempo/10);              // brief pause between notes
   }
}

   //
  //
 // SETUP
//
void setup() {
  pinMode(speaker, OUTPUT);
}

   //
  //
 // LOOP
//
void loop() {
    song1();
    delay(2000);
}

   //
  //
 // FREQUENCY
//
int frequency(String note) {
  // This function takes a note string (for example C4), and returns the
  // corresponding frequency in Hz for the tone() function.

  int i;
  int numNotes = 8;  // number of notes we're storing

  String names[] = { "C4", "D4", "E4", "F4", "G4", "A4", "B4", "C5" };
  int frequencies[] = {262, 294, 330, 349, 392, 440, 494, 523};

  for (i = 0; i < numNotes; i++) {
    if (names[i] == note) {        // Is this the one?
      return(frequencies[i]);     // Yes! Return the frequency
    }
  }
  return(0);
}

When you upload the code you should hear a song that annoyingly repeats over, and over and over again.

Comments

The Frequency Procedure

Note that the frequency procedure is similar to the lookup procedure in our array experiment. In the lookup procedure we gave the procedure a name, Addie as an example, and it returned the person’s age. In the frequency procedure, we give the procedure the name of a note, F4 as an example, and it returns that note’s frequency, 349 in this case.

Let’s say we want to write our own song and it requires a new note, say C#4. We look up its frequency on the frequencies for the equal temperament scale and see that the frequency is 277.18. We round that to 277 and add the name of the note (C#4) to the names array and its frequency to the frequencies array …

  String names[] = { "C4", "C#4", "D4", "E4", "F4", "G4", "A4", "B4", "C5" };
  int frequencies[] = {262, 277, 294, 330, 349, 392, 440, 494, 523};

The song1 procedure

Within the song1 procedure a song is represented by the variables, songLength, notes and beats. songLength is simply the number of entries in the notes array. The notes array contains the names of the notes to play and the beats array represents how long to play each note. Let’s say we want to play a new song. Perhaps this one …

We are only going to encode the top line of notes and for now let’s just look at the first measure:

The notes of that measure are

C4, B3, A3, B3, C4, B3, A3.

So the notes array will be

String notes[] = {"C4", "B3", "A3", "B3", "C4", "B3", "A3"}'

The shortest notes of the songs are eighth notes so those will get 1 beat. The first 6 notes of the song are eighth notes and the 7th note is a quarter note so the beats array will be

int beats[] = {1,1,1,1,1,1, 2};

Remix 1: The Song

Can you write code to have the buzzer play a recognizable (and correct) tune that spans an octave and a half?

Don’t know music? This remix is a great opportunity to have a conversation with someone that does.


Previous section:
Next section: