Tutorial 003: Making Sounds with Buzzer

Electromagnetic Buzzer

So far we’ve used a LED as output to produce light of different colors and intensity (Tutorial 001 and Tutorial 002) but we haven’t generated any sound yet.

In fact, that isn’t very difficult to do.

We will use a buzzer for output.

According to Wikipedia … the buzzer or beeper is an audio signaling device, which may be mechanical, electromechanical, or piezoelectric. Typical uses of buzzers and beepers include alarm devices, timers, and confirmation of user input such as a mouse click or keystroke.

Tinusaur Buzzer

We will use an electromechanical buzzer. When voltage is applied to it its membrane moves up (or down, depending on the particular device), and respectively when there is no voltage the membrane goes back to its normal position. Applying constantly changing voltage will generate audio waves perceived by us as a sound.

Let’s connect the buzzer to the PB2 of the ATtiny85 on the Tinusaur board.

The program should look very much like the one for blinking LED except that the delay between switching the port should be very short.

In the example below we have a delay 500 and since we’re using the _delay_us() function that means the delay is 500 uS (microseconds). That means the period of the signal will be 2 x 500 uS = 1000 uS (or 0.0001 sec.) and then the frequency is 1 / 0.0001 S = 10000. That means the sound will have a frequency of 10 KHz.

Here is the source code:

#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>
#define BUZZER_PORT     PB2     // Buzzer I/O Port
#define BUZZER_DELAY    500     // Delay for each tick
int main(void)
{
    DDRB |= (1 << BUZZER_PORT); // Set port as output
    while (1) {
        PORTB |= (1 << BUZZER_PORT);
        _delay_us(BUZZER_DELAY);
        PORTB &= ~(1 << BUZZER_PORT);
        _delay_us(BUZZER_DELAY);
    }
    return (0);
}

Full source code with more comments and the other necessary files such as Makefile is available at https://bitbucket.org/tinusaur/tutorials/src/default/tut003_buzzer/

Build the program:

$ make

Upload the code to the controller:

$ avrdude -c usbasp -p t85 -U flash:w:"main.hex":a

The buzzer should start making sounds immediately.

Let’s do some more experiments.

Let’s make the delay between the buzzer ticks change over time and see what sound it will produce.

This time instead of _delay_us() we will use the _delay_loop_2() function. According to the _delay_loop_2(int) documentation it produces 4 empty CPU cycles per iteration – in other words with parameter 100 it will produce a delay of 400 CPU cycles. That tells us that the maximum is 65536 x 4 = 262252 cycles. That, at 1MHz CPU clock, is approximately 262 mS (milliseconds) maximum delay, … or about 3.8 Hz minimum frequency – perfect for our experiments.

Below is the source code:

#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>
#define BUZZER_PORT     PB2     // Buzzer I/O Port
#define BUZZER_DELAY    200     // Delay for each tick
int main(void)
{
    DDRB |= (1 << BUZZER_PORT); // Set port as output
    int delay = 0;
    while (1) {
        if (delay < 1) delay = BUZZER_DELAY;
        PORTB |= (1 << BUZZER_PORT);
        _delay_loop_2(delay);
        PORTB &= ~(1 << BUZZER_PORT);
        _delay_loop_2(delay);
        delay--;
    }
    return (0);
}

After building and uploading this should start making sounds like a car alarm.

With similar techniques, a lot more complex sounds could be generated.

This post will eventually become Tutorial 003.

Leave a Comment