Playing The Imperial March

From Texas Instruments Wiki
Jump to: navigation, search
The Launchpad board in action, playing the Imperial March!
In this tutorial we will learn how to generate sounds and tunes with the Texas Instruments MSP430 Launchpad.

Quick Start

  • Get a piezo speaker, like the ones that can be found in an old computer.
  • Get a 1KOhm resistor.
  • Download Code/Build the circuit.
  • Enjoy the John Williams' masterpiece!

Development

Schematic

The circuit is really simple to build. Solder the 1KOhm resistor to the positive lead of the speaker (red wire) and connect it to P1.2 on the Launchpad. Then connect the black wire to the GND pin on the board. You can even remove the R1, but the sound will be very loud and annoying, and the speaker may be damaged. You can add a 1K trimmer instead of the resistor to make the volume adjustable.

Schematic for driving the piezo speaker

Code

Here is the fully commented code for this tutorial. I have ported it to the MSP430G2231 from an Arduino example made by naneau.

File:Lauchpad Imperial March.zip

#include "msp430g2231.h"
 
//Definition of the notes' frequecies in Hertz.
#define c 261
#define d 294
#define e 329
#define f 349
#define g 391
#define gS 415
#define a 440
#define aS 455
#define b 466
#define cH 523
#define cSH 554
#define dH 587
#define dSH 622
#define eH 659
#define fH 698
#define fSH 740
#define gH 784
#define gSH 830
#define aH 880
 
/* This two functions stop the main thread for a certain number of milli -or- microseconds.
   They are based on trial and error, but they work fine for the out-of-the-box Launchpad board.
   TI should really add this types of functions as default, just like Arduino does :) .
*/
void delay_ms(unsigned int ms )
{
    unsigned int i;
    for (i = 0; i<= ms; i++)
       __delay_cycles(500); //Built-in function that suspends the execution for 500 cicles
}
 
void delay_us(unsigned int us )
{
    unsigned int i;
    for (i = 0; i<= us/2; i++) 
       __delay_cycles(1);
}
 
//This function generates the square wave that makes the piezo speaker sound at a determinated frequency.
void beep(unsigned int note, unsigned int duration)
{	
    int i;  
    long delay = (long)(10000/note);  //This is the semiperiod of each note. 
    long time = (long)((duration*100)/(delay*2));  //This is how much time we need to spend on the note.
    for (i=0;i<time;i++)    
    {    
        P1OUT |= BIT2;     //Set P1.2...
        delay_us(delay);   //...for a semiperiod...
        P1OUT &= ~BIT2;    //...then reset it...
        delay_us(delay);   //...for the other semiperiod.
    }  
    delay_ms(20); //Add a little delay to separate the single notes
}
 
//This is the Imperial March code. 
//As you can see, there are lots of beeps at different frequencies and durations, and some delays to separate the various bits of this wonderful song.
void play()
{
    beep(a, 500);
    beep(a, 500);
    beep(a, 500);
    beep(f, 350);
    beep(cH, 150);  
    beep(a, 500);
    beep(f, 350);
    beep(cH, 150);
    beep(a, 650);
 
    delay_ms(150);
    //end of first bit   
 
    beep(eH, 500);
    beep(eH, 500);
    beep(eH, 500);   
    beep(fH, 350);
    beep(cH, 150);
    beep(gS, 500);
    beep(f, 350);
    beep(cH, 150);
    beep(a, 650);
 
    delay_ms(150);
    //end of second bit...  
 
    beep(aH, 500);
    beep(a, 300);
    beep(a, 150);
    beep(aH, 400);
    beep(gSH, 200);
    beep(gH, 200); 
    beep(fSH, 125);
    beep(fH, 125);    
    beep(fSH, 250);
 
    delay_ms(250);
 
    beep(aS, 250); 
    beep(dSH, 400); 
    beep(dH, 200);  
    beep(cSH, 200);  
    beep(cH, 125);  
    beep(b, 125);  
    beep(cH, 250);  
 
    delay_ms(250);
 
    beep(f, 125);  
    beep(gS, 500);  
    beep(f, 375);  
    beep(a, 125);
    beep(cH, 500);
    beep(a, 375);  
    beep(cH, 125);
    beep(eH, 650);
 
    //end of third bit... (Though it doesn't play well)
    //let's repeat it
 
    beep(aH, 500);
    beep(a, 300);
    beep(a, 150);
    beep(aH, 400);
    beep(gSH, 200);
    beep(gH, 200);
    beep(fSH, 125);
    beep(fH, 125);    
    beep(fSH, 250);
 
    delay_ms(250);
 
    beep(aS, 250);  
    beep(dSH, 400);  
    beep(dH, 200);  
    beep(cSH, 200);  
    beep(cH, 125);  
    beep(b, 125);  
    beep(cH, 250);      
 
    delay_ms(250);
 
    beep(f, 250);  
    beep(gS, 500);  
    beep(f, 375);  
    beep(cH, 125);
    beep(a, 500);   
    beep(f, 375);   
    beep(cH, 125); 
    beep(a, 650);   
    //end of the song
 
}
 
int main( void )
{
    WDTCTL = WDTPW + WDTHOLD; //Disable Watchdog Timer
    P1DIR|=BIT2;              // P1.2 output
    while(1)
    {
	play();              
	delay_ms(2000);      //Add a 2 sec. delay to avoid replaying right after the end.
    }
}

Theoretical Background

A square wave.

A Pulse Width Modulation (PWM) output can be used to play tones on a piezo speaker. With this, musical scales and simple songs can be played on the piezo speaker.

Piezo speakers operate by the converse piezoelectric effect: when a voltage is applied across the terminals, the piezoelectric material in the speaker deflects in one direction. Applying an alternating voltage, such as a square wave, will cause the material to vibrate and create a sound. A constant voltage will not produce a sound. Also sine, triangle and sawtooth waves can be used to drive a piezo speaker, resulting in different pitches of the notes.

As you can see from the code, the beep() function was used to provide the alternating voltage to drive the speaker. The period (do you remember delay_us() ?) of the sqare wave determines the note that will be played.

You can have some problems about the clock and timings with this project, I'm still figuring out the MSP430 Clock System as it is the first time I use them.

Future Ideas

  • You might want to play sounds from an SD Card, like it has been done here. (I'm working on it, but the sound is really distorced, I'm still wondering why...)

References

  1. MSP430x2xx Family User Guide
  2. MSP430G2x31 Datasheet
  3. Naneau's Arduino Imperial March
  4. Make a talking MSP430 MCU

Related Projects