header
Back to Tutorials Page
  

 
 
PWM SOUND TUTORIAL::

Here we demonstrate the use of an Arduino PWM output pin to generate sound. The output pin can be toggled very quickly from LOW to HIGH generating a square wave. If the frequency of this square wave is within the range of 20-20,00Hz and sent directly into a Piezo Speaker, an audible tone will be produced (in reality, the range of output is limited by the specs of the speaker and does not cover the entire audible frequency range.) This tutorial covers three sound output schemes: first is the method with the Piezo Speaker connected directly to the Arduino output pin. The second uses a low pass filter to transform the square wave to a line level signal that can be used with standard audio equipment. The third output scheme uses a TDA7052 amplifier (8-DIP) chip with volume control and sends the audio signal into a small 8 OHM speaker.

Click HERE for audio sample.

CODE:

int PiezoPin = 9; // piezo output pin

//delay values in microseconds to produce standard octave of tones (C2 to B2)

int C = 7644;
int CS = 7216;
int D = 6811;
int DS = 6428;
int E = 6067;
int F = 5727;
int FS = 5406;
int G = 5102;
int GS = 4816;
int A = 4545;
int AS = 4290;
int B = 4050;
int rest = 0;
int period = 0;

//array holding one octave of notes + rest
int noteArray[13] = {C, CS, D, DS, E, F, FS, G, GS, A, AS, B, rest};

int noteValue = 50; //length of note to be played (100ms)

float note = 0; //value to hold note value

//these 2 variables are used to select the octave of the note to be played
int octave = 0;
int multiplier = 0;

//time counting variables (for note length)
long time = 0;
long newtime = 0;

void setup() {
pinMode(PiezoPin, OUTPUT); //piezo speaker connected to this pin

}

////////////////////////////////////////////////////////////////////////////
//function to measure time - compare current time with previous time value
int CompareTime()
{
newtime = millis();
newtime = newtime - time;
}

////////////////////////////////////////////////////////////////////////////
//function to play note selected (or rest) for a determined length of time
int PlayNote(float delaytime, float notelength)
{
time = millis(); //read current time and store for reference
newtime = millis(); //read new current time - for comparison
if (delaytime < 1) //this is true only if a rest value has been selected
{
do
{
CompareTime();
//wait, generate no sound until the duration of rest has been met
} while (newtime < notelength);
}
else
{
do
// This will toggle the output pin HIGH and LOW at a frequency to produce
// the selected note for the note duration.
// Turning on for a portion of the period(duty cycle) and then off for the
// remainder of the period produces pulse width modulation.
{
digitalWrite (PiezoPin, HIGH);
delayMicroseconds (delaytime);
digitalWrite (PiezoPin, LOW);
delayMicroseconds (period-delaytime);
CompareTime();
} while (newtime < notelength); //do this until reaching note duration
}
}

////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
void loop()
{
//following determines the octave of the note to be played
//using random function
octave = 1;
multiplier = (random(1,8));
for (int i=0; i<multiplier; i++){
octave = octave * 2;
}
//random choice of note value
note = (noteArray[(random(0,12))]/octave);
//max delay: 7644/2 = 3822 microseconds so we will say the period is 4000ms
period = 4000;
PlayNote (note, noteValue); //play note (50ms long)
PlayNote (rest, noteValue); //rest for same time
}

 

PIEZO SPEAKER CONNECTED TO OUTPUT

 

LOW PASS FILTER SCHEMATIC

 

LOW PASS FILTER TO AUDIO OUTPUT BREADBOARD CIRCUIT

 

LOW PASS FILTER / AMPLIFIER SCHEMATIC

 

LOW PASS FILTER, AUDIO AMPLIFIER TO SPEAKER CIRCUIT

 

TDA7052 AMPLIFIER PIN LAYOUT