Driving a piezo speaker with a PIC

From Mech
Revision as of 21:53, 7 February 2009 by Bobby By (talk | contribs) (→‎Circuit)
Jump to navigationJump to search

Original Assignment

In this project you will use a PWM output of the PIC microcontroller to play tones on a piezo speaker. Document frequencies that play the basic notes in the musical scale and demonstrate a simple song.

Overview

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

Piezoelectric speakers operate by the converse piezoelectric effect: when a voltage is applied across the terminals, the piezoelectric material in the speaker to deflect in one direction. Applying an alternating voltage, such as a square wave, will cause the material to vibrate and create a sound.

PWM was used to provide the alternating voltage to drive the speaker (Parallax 900-00001). The period of the PWM determines the tone that will be played; the duty cycle changes the volume. The frequency range of the speaker was limited by the timer used by the PIC to control PWM, which is timer 2. First, we determined the PWM frequencies that we could use, which was 2kHz to 10kHz. Setting the lowest frequency as our first note (C), a set of timer scaling values that correspond to frequencies that would play the basic notes of an octave of the diatonic scale was found. The period of the PWM is defined in the following equation:

   Period = 4 * (1/clock speed) * 16 * (scaling value + 1)  This is for a T2_DIV_BY_16.

Frequency can be calculated by inversing the period. The table below displays the basic musical notes, their timer scaling value and their frequencies in hertz.

Note Timer Scaling Value Frequency (Hz)
C 255 2441
D 227 2741
E 204 3048
F 191 3255
G 170 3654
A 153 4058
B 136 4562
C2 127 4882

Circuit

Circuit Diagram
Circuit

To the right is a simple circuit diagram showing the PIC connected to a piezo speaker. The circuit consists of two main components, the PIC 18F4520 and the piezo speaker. The piezo speaker is driven by the PWM output of the PIC (Pin 17, RC2/CCP1). A 1K ohm resistor was added between the PIC and the speaker because the piezo speaker has very low impedance and connecting the speaker directly to the PIC effectively created a short circuit, pulling the PWM output down to zero.

Code

#include <18f4520.h>
#fuses HS,NOLVP,NOWDT,NOPROTECT
#use delay(clock=40000000)
//define timer scaling value for each note
#define C 255 
#define D 227
#define E 204
#define F 191
#define G 170
#define A 153
#define B 136
#define C2 127
//

#define x 14 //total number of notes in song to be played - modify for specific song

//the song to be played is "Twinkle Twinkle Little Star" in this demonstration
int i;
int song[x]={C, C, G, G, A, A, G, F, F, E, E, D, D, C}; //insert notes of song in array
int length[x]={1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2}; //relative length of each note

void main() {

      setup_ccp1(CCP_PWM); // PWM output on pin 17, RC2/CCP1 
      set_pwm1_duty(30); // the number changes the volume of the piezo speaker, demonstrate the use of both PWMs independently


      for (i=0; i<x; i++) { //play x notes inside song array
      
      setup_timer_2(T2_DIV_BY_16, song[i], 16); //set PWM frequency according to entries in song array
      delay_ms(400*length[i]); //each note is played for 400ms*relative length
      setup_timer_2(T2_DIV_BY_16, 1, 16); //the PWM frequency set beyond audible range in order to create a short break between notes
      delay_ms(50); //the break is played for 50 ms                  
      }
}

Bonus Songs

To play these songs, copy and paste the lines into the appropiate location in the code above.

Mary Had a Little Lamb

#define x 26
int song[x] = {B, A, G, A, B, B, B, A, A, A, B, B, B, B, A, G, A, B, B, B, A, A, B, A, G, G};
int length[x] = {1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 2};

Jingle Bells

#define x 25
int song[x] = {E, E, E, E, E, E, E, G, C, D, E, F, F, F, F, F, E, E, E, E, D, D, E, D, G};
int length[x] = {1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2};

Further Reading

Parallax Piezo Speaker