Driving a buzzer

To connect it to the ATMEGA168, I followed the suggestion from the datasheet: the buzzer if driven by a 2N3904 NPN transistor and a diode protects the transistor from reverse currents from the magnetic inductance. /* Setup PB1 as an output */ DDRB = _BV(PB1); /* Initial period */ period = 1600; /* Main loop */ for(;) { PORTB |= _BV(DDB1); delay
Driving a buzzer - schematic

_us(period / 2); PORTB &= ~_BV(DDB1); delay_us(period / 2); counter+; if (counter = 200) { /* Reset the counter */ counter = 0; /* Update the toggling period */ if (period = 1600) period = 2000; else period = 1600; } } The period variable contains the period in us of the generated square wave. The counter toggles the period from 2000us (500Hz) to 1600us (625Hz) every 200 periods. Toggling an output in a loop is the easiest way to control the buzzer but it doesn`t allow the main program to do much else at the same time. To achieve this you can delegate the square wave generation to a hardware timer. An hardware timer is a counter that is constantly incremented by the CPU clock. Actions can be triggered when the counter reaches a predefined value. It is useful to measure time intervals or generate signals either for the software with an interrupt or for the hardware by toggling a pin. To generate a square wave I will use timer1 from the ATMEGA168 in CTC mode (Clear Timer on Compare). The 16-bit resolution of timer1 offers the greatest precision for selecting an output frequency. The timer is setup to toggle the OC1A/PB1 pin when it reaches the OCR1A value. By changing the OCR1A value, I can control the period of the OC1A signal. The following schema diagram excerpted from the ATMEGA168 datasheet illustrate the expected behavior: I choose a clk/8 prescaler to obtain a 2MHz counter from my 16MHz main clock. So each 0. 5us...

Leave Comment

characters left:

New Circuits