Driving a piezo speaker with a PIC

From Mech
Jump to: navigation, search






PWM Period


   Period = 4 * (1/clock speed) * 16 * (scaling value + 1)  This is for 1:16 prescaled Timer 2.


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

Duty Cycle

To set the duty cycle of the PWM signal you use the following line of code:

set_pwm1_duty(scaling value);

This duty cycle does not refer to the pulse width ratio = \begin{matrix}\frac{t_{on}}{t_{period}}\end{matrix} but rather the length of time that the pulse is held high (ton). This time is given by:

      Duty Cycle = 4 * (1/40MHz) * 16 * (scaling value)   for 40MHz clock and 1:16 Timer 2.



Completed Circuit

Below 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 to limit the current being drawn by the speaker. A potentiometer may be used instead of a fixed resistor, which can act as a volume control. To the right is an example of how to wire the circuit. The piezo speaker is the black circular object.

Circuit Diagram


Code written by Bobby By, Agatha Lee, Dan Niecestro 02-2009
This code uses a PWM signal from PIC 18F4520 to define the frequencies 
that produce the basic notes in one octave of the musical scale, 
and plays a simple song on a piezo speaker.
The volume of the speaker can be set by changing the duty cycle value (1~125)

#include <18f4520.h>
#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 in this demonstration is "Twinkle Twinkle Little Star" 
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
int i;

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

      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 silence between notes
      delay_ms(50);   //the silence 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};

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};

Further Reading

Parallax Piezo Speaker

Personal tools