Atmega88 buzzer speed.

Go To Last Post
5 posts / 0 new
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello, i want to control a buzzer frequency using a distance calculated with HC-SR04 (ultrasonic sensor).

I have only the timer1 free, i need to blink led at 1Hz, and at same time need to blink buzzer at vaiavel frequency.


The program works fine but the buzzer dont blink every time, and i think its because the distance its to fast.

I add a delay between the calculus of fbuzz and the buzz compare (doesnt work and everything get late like LCD ).


Any one can help how to put the buzzer blinking with fbuzz ticks without stop for a while and come back?



So a ll give a part importante of code:



TCCR1A = (1 << COM1B0)  |(1<<WGM10)  ;        //PWM phase and frequency with ocr1a  

TCCR1B = (1 << ICNC1  )  |(1 << ICES1 )  |(1 <<CS12  ); //PSC256

TIMSK1 |= (1 << OCIE1A);

OCR1A=194;                                                //Calculated to prescaled of 256 and to 50ms frequency

TCCR2A = (1 <<COM2A1 )  | (1 << WGM22 )  | (1 << WGM20 ) ; 




int fbuzz=0;


if (distancia<1){ fbuzz=1;} // if distance=0, buzzer stills


if(contaled==10){ contaled=0;  PORTC ^= 0b00100000; }  // Led blink 10 * 50ms 




       if (buzzer==fbuzz) // how many tick ll make 








OCR2A its PINB3 with buzzer.

Led works fine and its on PIND5

Last Edited: Wed. Dec 6, 2017 - 11:21 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Welcome to the Forum.


The M88 has three Timer/Counters, IIRC.


I've not done the math to check on the pre-scaler value, but perhaps you could do something along these lines:


1 T/C for input capture mode to measure the sensor's ping pulse width.


1 T/C, in CTC mode, to generate a 2 KHz output frequency, (or whatever), to drive the piezo.

By changing the "TOP" value, you easily change the output frequency, (i.e. the tone of the piezo).


1 T/C, in CTC mode, generating a one every 1 or 2 or 5 or whatever mSec system "Tic", for other timing purposes.


The piezo is likely to have a rather limited range of usable frequencies.

Too low and it won't make much sound, likewise too high and it won't make much sound.

You should write a small test program to test the reasonable range of frequencies for your piezo.


When your Main Loop generates a ping, and gets either a valid echo pulse duration or times out, you need to test for a valid number.

"0" is not a valid number.

There is a minimal range for the sensor to work, which might be a few cm.

There is a maximal range, also, or more accurately, a time limit.

If you waited X mSec, with not echo, then the return signal to too small to be detected, (no object, or the object was too small at too far a distance to give a good enough echo to be detected).

No valid reading, turn off the LED and piezo from the last reading and loop again, taking another measurement.


Have a valid reading?

Then set the TOP value for the T/C for the piezo and turn it on, to make the beep.

You could use an equation to calculate the TOP value based upon the distance, but you need to map your distance reading to the valid tone range.

You could also have a look up table of range < 10 cm, 10-20 cm, 20-30 cm...  and the tone (TOP) value, for each range.


When you get a valid reading, you use the system "TIC" to turn on the piezo for 1 sec, or whatever, and to flash the LED.

The flash rate of the LED can also be made to vary with the ping distance, but get it working with a simple on/off first.

One counter counts the Tic's to determine how long, ( 1 Sec, 2 Sec, or whatever), the piezo and LED are on for, after a valid reading.

One counter can be used to flash the LED on and off during that 1 second interval.


The Main Loop controls all of the activity.

You will benefit, perhaps, from drawing out a flow chart of how you want it to operate.


A third Tic counter might decide when it is time to take a new distance measurement, perhaps once every 1/2 second.


The Main Loop, then, goes roughly like this, (after first clearing the variables, etc.):


Time for a ping?

If not, continue through loop.

If so, send a ping.


Is the flag for LED on still set?

Time to adjust the flashing LED, based upon its on/off counter?

If so turn the LED on or off and set its state flag

Continue in the loop.


Have a ping reading?

If not, continue on.

If yes, then validate the range (reading).


If have a valid reading, set a flag to turn on the piezo and the LED.

Continue on.


Manage the output device, piezo and LED.

If the valid ping flag was set, then turn on the piezo, using its TOP value to set is tone.

Turn on the flashing LED.

If they have been on for 1 Sec, or what ever, then turn them off.




Once you have working subroutines to initiate a ping, read the echo pulse width, and make the piezo beep at a desired frequency, you have the key components for the program.


The Main Loop then orchestrates the overall actions and what needs to take place next.


Once it basically works, then go back and modify it to take several distance readings for each reading, eliminate the high and low, and average the remaining readings.

Use that value in the above processing loop.








Last Edited: Wed. Dec 6, 2017 - 03:42 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello DocJC, thank you for answer.


I have the ultrasonic working fine and the value of distance is the really distance already calculated.

That value is called distancia and i want my timer1 blink buzzer faster while distance going 0.

its a car parking system. All program works, i have a LCD, two ultrasonic sensors and a blinking led at 1HZ. All works.

As i have one timer to eash sensor, just have 1 free, and im using that free to blink led and blink buzzer. i have that timer configurate to 50ms.

On LED i have cycle of 10 to counter 500ms ON and 500ms OFF. I want do the same to the buzzer in the same ISR. But instead of 10 i want to vareate this number while distance changes too.

This number needs to be   10 * distance / 50

Whene i build the program the buzzer works but if distance valuer variate many times, the buzzer stops for 6 or 7 seconds to have other stabilize value, but i want continuouse and not stop, whatever is the number of distance.



Thanks you, i thing i explain better now ;)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How often does the system send a ping?

(If more than 4 / Sec, then slow it down, at least to get it working.)


Are variables used in the Main and in the ISR declared volatile, (or whatever it is for you C programmers...)?


Do you reset ALL of the piezo and LED variables every time you make a new measurement?

Are you correctly resetting them to their maximum count down value, (re-triggering), if needed?


6 or 7 seconds is a long time for the micro to "get lost".


Do you flash the LED in a particular manner on start up so you see if / when the micro is re-setting?


Do you have an adequate power supply to power the micro, the LED, and the piezo, etc., without the voltage dropping?




  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0



The variable are declared unsigned char because i want to compare a counter (buzzer++) with a number that cames from the formula with distance (fbuzz=(distancia*10)/50; ), i try put both volatile but still unworking.

I think the slow its because im reseting buzzer every whene buzzer = fbuzz. That way the counter is in fast loop so should work.


The solution ll be create a few intervals of comaprations, its not the best but should work.


Thanks for all.