Arduino Sketch That Plays Melodies

This is a simple Arduino sketch that can play various melodies . It can be used for fun as a toy. The melodies are changed by pressing a pushbutton. You can easily add new melodies, if you know the notes.

In all examples that I found, while a note is playing, the Arduino waits and does nothing else, so a switch would not work. In this sketch the note is played asynchronously so that the Arduino is able to read the switch.

 
sound.ino

/*
* Melodies
* 
* ---------
*
* A program that plays various melodies and changes them when you press a switch. 
* Press the switch once to start the first melody. Press again to change the melody.
* You can add more melodies.
*
* CIRCUIT: 
* 32ohm SPEAKER or a piezo on digital pin 2 with the other end connected to ground (in sequence with a resistor from 90ohm to 500ohm to limit the current)
* PUSHBUTTON on digital pin 4 with the other end connected to +5V
* 10KOhm or bigger pullldown RESISTOR from digirtal pin 4 to ground (to make pin 4 read zero when the button is unpressed)
*
* Author: Boyan Yankov
*/

#include "pitches.h"

//the pin that the speaker is attached to
const int speakerPin = 2;
const int buttonPin = 4;    // the number of the pushbutton pin

int buttonState = 0;        // variable for reading the pushbutton status
int lastState = 0;          // the previous switch state
int effectMode = 1;          // the mode of the sound effect
const int effectModeMax = 3;       // the number of supported effects
int thisNote = 0;            // the current note playing
int noteDuration = 0;       // duration of the current note
int pauseBetweenNotes = 0;  // pause between the current and the next note to distinguish them
unsigned long time = 0;        // the time passed since the start of the script
unsigned long timeLastNoteStart = 0;// the time that the last note started playing

//define the sound effects (melodies) here:

//Melody 1 - Marry Had a Little Lamb
// notes in the melody (see notes.h)
int melody1[] = {
  NOTE_E3, NOTE_D3, NOTE_C3, NOTE_D3, NOTE_E3, NOTE_E3, NOTE_E3, 
  NOTE_D3, NOTE_D3, NOTE_D3, NOTE_E3, NOTE_E3, NOTE_E3, 
  NOTE_E3, NOTE_D3, NOTE_C3, NOTE_D3, NOTE_E3, NOTE_E3, NOTE_E3, 
  NOTE_D3, NOTE_D3, NOTE_D3, NOTE_E3, NOTE_D3, NOTE_C3,
};
// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations1[] = {
  4, 4, 4, 4, 4, 4, 2, 
  4, 4, 2, 4, 4, 2, 
  4, 4, 4, 4, 4, 4, 2, 
  4, 4, 2, 4, 4, 2,
};

//Melody 2 - The Itsy Bitsy Spider
// notes in the melody (see notes.h)
int melody2[] = {
  NOTE_G2, NOTE_C3, NOTE_C3, NOTE_C3, NOTE_D3, NOTE_E3, NOTE_E3, 
  NOTE_E3, NOTE_D3, NOTE_C3, NOTE_D3, NOTE_E3, NOTE_C3, 0,
  NOTE_E3, NOTE_E3, NOTE_F3, NOTE_G3,
  NOTE_G3, NOTE_F3, NOTE_E3, NOTE_F3, NOTE_G3, NOTE_E3, 0,
  NOTE_C3, NOTE_C3, NOTE_D3, NOTE_E3,
  NOTE_E3, NOTE_D3, NOTE_C3, NOTE_D3, NOTE_E3, NOTE_C3, 0,
  NOTE_G2, NOTE_G2, NOTE_C3, NOTE_C3, NOTE_C3, NOTE_D3, NOTE_E3, NOTE_E3, 
  NOTE_E3, NOTE_D3, NOTE_C3, NOTE_D3, NOTE_E3, NOTE_C3, 0,
};
// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations2[] = {
  4, 4, 4, 4, 4, 2, 2, 
  4, 4, 4, 4, 4, 4, 2,
  2, 4, 4, 2,
  2, 4, 4, 4, 4, 4, 2,
  2, 4, 4, 2,
  2, 4, 4, 4, 4, 4, 2,
  4, 4, 4, 4, 4, 4, 2, 2,
  4, 4, 4, 4, 4, 2, 2,
};

void setup() {
  // initialize the speaker pin as an output:
  pinMode(speakerPin, OUTPUT); 
  
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT); 
}

void loop() {
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);
  
  // handle pushbutton press
  if (buttonState != lastState) {
    if (buttonState == HIGH){
      //change the effect
      effectMode ++;
      
      //reset the sound effect
      thisNote = 0;
      noteDuration = 0;
      
      if (effectMode > effectModeMax)
        effectMode = 1;
    }
    
    //remember the switch state
    lastState = buttonState; 
    
    //pause for button switching stability
    delay(100);
  }
  
  //play and change the melodies
  switch (effectMode){
    case 1:
      // default, no melody
      // stop the tone playing:
      noTone(speakerPin);
    break;
    case 2:    
      // melody 1
      playMelody(melody1, noteDurations1, sizeof(melody1)/sizeof(int));     
    break;
    case 3:    
      // melody 2
      playMelody(melody2, noteDurations2, sizeof(melody2)/sizeof(int));     
    break;
  }
}

void playMelody(int melody[], int noteDurations[], int melodyLength){ 
  //get the current time
  time = millis();
  
  //check if this is the first note or if we have to change the note
  if (timeLastNoteStart == 0 || time >= timeLastNoteStart + noteDuration){
    //stop playing the last note
    noTone(speakerPin);
    
    //change to the next note if the pause between the notes has ended
    if (time >= timeLastNoteStart + noteDuration + pauseBetweenNotes){
      //set the duration of the current note
      noteDuration = calculateNoteDuration(noteDurations[thisNote]);
      
      // to distinguish the notes, set a minimum time between them.
      // 20% of the note's duration seems to work well:
      pauseBetweenNotes = noteDuration * 0.2;

      //set the time for the current note
      timeLastNoteStart = time;
      
      //start playing the note
      if (melody[thisNote] != 0){
        //play an actual the note
        tone(speakerPin, melody[thisNote]);
      } else {
        //play a pause
        noTone(speakerPin);
      }
      
      //continue to the next note
      thisNote++; 
      if (thisNote > (melodyLength)-1){
        //end of melody reached - replay
        thisNote = 0;
      }
    }
  }
}

int calculateNoteDuration(int noteType){
  // to calculate the note duration, take one second 
  // divided by the note type.
  //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
  return 1000/noteType; 
}

pitches.h:

/*************************************************
 * Public Constants
 *************************************************/

#define NOTE_B0  31
#define NOTE_C1  33
#define NOTE_CS1 35
#define NOTE_D1  37
#define NOTE_DS1 39
#define NOTE_E1  41
#define NOTE_F1  44
#define NOTE_FS1 46
#define NOTE_G1  49
#define NOTE_GS1 52
#define NOTE_A1  55
#define NOTE_AS1 58
#define NOTE_B1  62
#define NOTE_C2  65
#define NOTE_CS2 69
#define NOTE_D2  73
#define NOTE_DS2 78
#define NOTE_E2  82
#define NOTE_F2  87
#define NOTE_FS2 93
#define NOTE_G2  98
#define NOTE_GS2 104
#define NOTE_A2  110
#define NOTE_AS2 117
#define NOTE_B2  123
#define NOTE_C3  131
#define NOTE_CS3 139
#define NOTE_D3  147
#define NOTE_DS3 156
#define NOTE_E3  165
#define NOTE_F3  175
#define NOTE_FS3 185
#define NOTE_G3  196
#define NOTE_GS3 208
#define NOTE_A3  220
#define NOTE_AS3 233
#define NOTE_B3  247
#define NOTE_C4  262
#define NOTE_CS4 277
#define NOTE_D4  294
#define NOTE_DS4 311
#define NOTE_E4  330
#define NOTE_F4  349
#define NOTE_FS4 370
#define NOTE_G4  392
#define NOTE_GS4 415
#define NOTE_A4  440
#define NOTE_AS4 466
#define NOTE_B4  494
#define NOTE_C5  523
#define NOTE_CS5 554
#define NOTE_D5  587
#define NOTE_DS5 622
#define NOTE_E5  659
#define NOTE_F5  698
#define NOTE_FS5 740
#define NOTE_G5  784
#define NOTE_GS5 831
#define NOTE_A5  880
#define NOTE_AS5 932
#define NOTE_B5  988
#define NOTE_C6  1047
#define NOTE_CS6 1109
#define NOTE_D6  1175
#define NOTE_DS6 1245
#define NOTE_E6  1319
#define NOTE_F6  1397
#define NOTE_FS6 1480
#define NOTE_G6  1568
#define NOTE_GS6 1661
#define NOTE_A6  1760
#define NOTE_AS6 1865
#define NOTE_B6  1976
#define NOTE_C7  2093
#define NOTE_CS7 2217
#define NOTE_D7  2349
#define NOTE_DS7 2489
#define NOTE_E7  2637
#define NOTE_F7  2794
#define NOTE_FS7 2960
#define NOTE_G7  3136
#define NOTE_GS7 3322
#define NOTE_A7  3520
#define NOTE_AS7 3729
#define NOTE_B7  3951
#define NOTE_C8  4186
#define NOTE_CS8 4435
#define NOTE_D8  4699
#define NOTE_DS8 4978

This sketch is based on the official example for playing a single simple melody. Read it and give it a try it first, if you have troubles running the code or assembling the scheme.

Leave a Reply

Your email address will not be published. Required fields are marked *