You are on page 1of 4

1.0.

0 IMPLEMENTING PULSE WIDTH MODULATION FOR THE BUZZER

We decided to implement a buzzer in our system, where each key pressed on the keypad would cause a
different tone to sound. In order to use the buzzer, a technique called Pulse Width Modulation (PWM) would
be required. To drive a buzzer, a string of high and low voltages would be sent to the buzzer through a
digital pin. To vary the frequency, different proportions of high and low voltages (duty cycle) would be needed.

1.1.0 Using Loops and Delays to Vary Frequency

At first, we tried to vary the frequency by using loops and delays. We encountered a few major problems.
Below are the two attempts using loops and delay

Figure 1.1

1.1.1 Example 1
Here, the period of the PWM waveform is kept constant (x+y=255), where (x/255)*100%
would be the duty cycle. However, at higher duty cycles (>20%), the buzzer stops working
properly, producing a clicking sound.

This was probably due to the period being too long, being 10.2ms plus the delay
from using the FOR loop, thus an attempt was made to shorten the period, using two
methods.

The first being decreasing x+y. While this worked (x+y=100), this would grant us
very little resolution and thus very inaccurate frequencies for the tones generated.

Second being using shorter delays, which would allow us to shorten the period as
well as maintain resolution. Delay10TCYx() is a function where it delays for a multiple of 10
Nop(). Nop() means no-operation and is a delay of exactly one cycle. The header file had no
function where it delays for a multiple of Nop() and making our own function would require
an understanding of machine code and thus this attempt was abandoned.
1.1.2 Example 2
Here, we fixed the time high and varied low. This attempt worked much better, with a
much better resolution. However, when we varied the time for which the waveform is low
(through the use of delays), the time taken for each FOR loop also changes, meaning that for
a set amount of loops, higher frequencies would sound for a shorter time and vice versa.
Finding the amount of FOR loops needed for each tone would be tedious and impractical.

1.2.0 USING THE ECCP (ENCHANCED CAPTURE/COMPARE/PWM) MODULE

After some research, we found hat the PIC18F46K20 had an ECCP module, allowing us to generate the PWM
signals in a more efffecient and practical manner compared to using loops and delays. Belows is the code used
for initialisation and changing the duty cycle of the tone, as well as the description of what each line of code
does.

Figure 1.2

The tone_int function initialises the ECCP module, while the tone function toggles the PWM pin on
and off as well as changes the frequency and duration of the heard tone.

Notice that we are not exactly manipulating the duty cycle of the PWM waveform (done by setting
PR2 and manipulating CCPR1L. This is due to the problem mentioned in Example 1 where at higher duty cycles
(>20%), the buzzer stops working properly, producing a clicking sound.

We worked around it by setting CCPR1L instead and varying PR2, thus changing the frequency of the
PWM instead of its duty cycle. While this worked, it had an effect of causing a reduced degree of resolution in
the high frequencies with smaller changes in PR2 causing large changes in frequencies.

However, this was not really a problem due to:


For each consecutive tone or semitone, the change in sound frequency increases, which
matches what our PWM code was doing.
For the range of frequencies that we desired the buzzer to sound, resolution was still good.
Resolution only deteriorates significantly at very high frequencies, which isnt good for
hearing and thus impractical.

Then, to control the duration for which the desired frequency was heard, we toggle the pin putting
out the PWM waveform ON and OFF (by using the TRIS register) with a variable delay in between the toggles.
We also vary the tone when the pin is OFF so that no artefacts are heard while buzzer is in operation.
1.3.0 DETERMINING PR2 VALUES FOR DIFFERENT FREQUENCIES

From Figure 1.2, we see that:


CCPR1L =1
PR2 = variable

Since we are manipulating the frequency of the PWM waveform instead of directly manipulating its duty
cycle, we can assume that the frequency of sound being produced by the buzzer would be roughly equal to the
frequency of the PWM waveform being sent to the buzzer.

Also, since even after calculating the duty cycle for each individual signal, we would still have to find
the correlation between the duty cycle and sound frequency. So, we skip the calculation of duty cycles and
directly relate PR2 and sound frequency through the use of an oscilloscope to measure the PWM frequency
which, as assumes, roughly equal to sound frequency for varying amounts of PR2.

The following data was gathered with PR2 being varied, 1/PR2 being calculated, and PWM frequency
being measured.
Table 1.3.1
PR2 1/PR2 PWM frequency (Hz)
175 0.00571429 357
162 0.00617284 385
150 0.00666667 416
140 0.00714286 446
129 0.00775194 483
120 0.00833333 519
112 0.00892857 556
104 0.00961538 599
97 0.01030928 641
91 0.01098901 683
85 0.01176471 731
79 0.01265823 785.854
74 0.01351351 838.264

The data points is charted and a line of best fit (dotted) is also drawn and its equation shown.

Graph 1.3 - 1/PR2 vs PWM frequency


1000
PWM frequency (Hz)

y = 61740x + 4.4935
800

600

400

200

0
0 0.002 0.004 0.006 0.008 0.01 0.012 0.014
1/PR2
As can be seen, there is minimal margin of error and thus we can conclude that PR2 is inversely proportional to
PWM frequency. Thus, from the line of best fit, the following equation is derived:

61740
=
4.4935
Where y=PR2 and x=PWM frequency.

So, now we have the equation linking PR2 and frequency. Now we need to determine the values of PR2 for the
tones desired. With data gathered from a source(1), we can derive the following values of PR2 from tones and
their frequencies.

Table 1.3.2
Frequency PR2
Note PR2
(Hz) rounded
A4 440 141.7659668 142
b
B 4 466.16 133.7329003 134
B4 493.88 126.1579549 126
C5 523.25 119.0153762 119
b
D 5 554.37 112.2797574 112
D5 587.33 105.9302223 106
b
E 5 622.25 99.94229118 100
E5 659.25 94.29459654 94
F5 698.46 88.96683053 89
b
G 5 739.99 83.94329545 84
G5 783.99 79.20497398 79
b
A 5 830.61 74.73522197 75
A5 880 70.51917947 71
Bb5 932.33 66.54189612 67
B5 987.77 62.79006973 63
C6 1046.5 59.25106993 59

Now that we have the PR2 values, we use #define so that we can assign each PR2 values to each of their
respective tones to simplify generating specific tones for the user.

1.4.0 Conclusions for PWM and Buzzer

Implementing loops and delays were a bad idea, as they are very unwieldly to use effectively in a system,
especially one where timing is important and multiple tones are needed. The ECCP was much better though it
took a lot of time going through the data sheets for the register that were needed.

A better understanding of PWM implementation, buzzers, and the features of the PIC1846K20 was
gained from implementing this part of our system.

You might also like