Pages: [1]   Go Down
Author Topic: Interfacing with Piezo Buzzer  (Read 2554 times)
0 Members and 1 Guest are viewing this topic.
GA
Offline Offline
Newbie
*
Karma: 0
Posts: 43
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've read a few posts on this topic already...  and it seems like the answer is "NO"...  but just in case I've misinterpreted things...  I'll ask bluntly:

Considering that a square wave (at a specific frequency) is needed to get a piezo buzzer to make a sound...  Is it possible for the microcontroller to emit a sound (uninterrupted) through the piezo buzzer, then move on to another task (like, reading an analog value) -- all while the buzzer is still going... AND without the use of an external circuit (i.e., 555 timer)?  Just checking.

What I'd like is to make the buzzer go off, then read an analog value, and when the desired value is reached, make the buzzer stop.

One post mentioned using a 555 timer, but I'm just checking to see if this can be done without this...  even the "Tone" library implies that it's a sequential process, but I'm not 100% sure.

Can you please advice?  Thanks.
Logged

B0100111001000011, USA
Offline Offline
Edison Member
*
Karma: 0
Posts: 1503
I'm confused.  Wait, maybe not..
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The tone library uses the same timer used for millis and PWM to generate the tone, and it can continue whilst other things are happening.

Using
Code:
[toneInstance].begin(NOTE_A1)
will start the tone A1 and will continue indefinitely until
Code:
[toneInstance].stop()
is called.
Logged

GA
Offline Offline
Newbie
*
Karma: 0
Posts: 43
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks, TchnclFl.  That's good news.

One last question...  At the Arduino Tone Project website, it states that: "The number of tones that can be played simultaneously depends on the number of hardware timers (with CTC capability) available on the microcontroller.

    * ATmega168/328: 3"


It also states that "Using this library will affect usage of the PWM outputs, so be aware."

I won't be playing 3 different notes simultaneously, but I'd like one additional PWM output do drive the speed of a motor.   If I understand this library correcly, it seems like this would be possible.  Can you confirm?  Thanks, again!
Logged

B0100111001000011, USA
Offline Offline
Edison Member
*
Karma: 0
Posts: 1503
I'm confused.  Wait, maybe not..
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Umm, I don't think so.  I'm pretty sure that no matter how many tones you're generating, it still messes up PWM, sorry smiley-sad.
Logged

GA
Offline Offline
Newbie
*
Karma: 0
Posts: 43
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Oh, well...  I tried.  I may still go this route (and maybe omit the motor for now; or run it at full speed using digitalWrite).  Thanks for the input, though.  I really appreciate it.
Logged

B0100111001000011, USA
Offline Offline
Edison Member
*
Karma: 0
Posts: 1503
I'm confused.  Wait, maybe not..
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Happy to help.  There's probably a way to do a similar thing using a different timer, but that would involve some complicated (at least to me) code.  Keep your eyes open for something like that, but I can't help with it.
Logged

Plano, TX
Offline Offline
Full Member
***
Karma: 0
Posts: 101
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This bit of code directly programs timer 1 and digital pin 9 to generate a tone.  I haven't checked the frequency for accuracy but it does generate sound.

My problem is making it loud enough to work as an alarm clock.  I'm using a TDK PS1240P02BT that I think is supposed to produce 70 dB when driven with a 3V square wave at 4KHz.  That's either not as loud as I expected or my drive circuit needs work.

Code:
#define BuzzerPin 9

void setup()
{
  pinMode(BuzzerPin, OUTPUT);
  TCCR1B = 0;                                    // Stop timer1
  TCNT1 = 0;                                     // Clear timer1 counter
  TCCR1B = _BV(WGM13);                           // Phase & freq correct mode, TOP = OCR1A
  TCCR1A = _BV(WGM10);
  TCCR1A |= _BV(COM1A0);                         // Toggle OC1A on Compare Match
}

void loop()
{
  buzzerOn(2000);                                // This should generate 4KHz
  delay(1000);
  buzzerOff();
  delay(1000);
}

void buzzerOn(unsigned int value)
{
  OCR1A = value;                                 // Set timer1 TOP value
  TCCR1B |= _BV(CS10);                           // Enable timer1, divide-by-1 prescale
}

void buzzerOff()
{
  TCCR1B &= ~_BV(CS10);                          // Stop timer1
  TCNT1 = 0;                                     // Clear timer1 counter
}
Logged

Sussex UK / CT USA
Offline Offline
Edison Member
*
Karma: 0
Posts: 1028
Forums forever
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

If you just need two constant-spec pulse streams, which can each be turned on or off by your Arduino, a 556 timer, a few resistors and a few capacitors will be well worth the small effort of learning to connect up.
Logged

Plano, TX
Offline Offline
Full Member
***
Karma: 0
Posts: 101
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
If you just need two constant-spec pulse streams, which can each be turned on or off by your Arduino, a 556 timer, a few resistors and a few capacitors will be well worth the small effort of learning to connect up.

Hi tkbyd,

Note sure who your reply was intended for -- I agree that a 555 is pretty simple to use but the OP was looking for a way to drive a piezo buzzer without one.  I should have elaborated on that point.  The example code I posted was to show how to use timer 1 to produce a square wave signal on a PWM output that can be used to drive a piezo buzzer without tying up the processor.  The main loop simply calls my buzzer "on" and "off" functions at 1 second intervals.  The value provided to the buzzer "on" function determines the frequency of the tone.  How to actually drive the buzzer depends on the buzzer specs (e.g., may need to use a transistor).

For anyone interested in the gory details:  The code works by putting timer 1 in "phase & frequency correct" PWM mode and selects the OCR1A register as the "top" value for the timer 1 counter (set bits WGM13 & WGM10 for Wave Generation Mode 9).  Putting the OC1A PWM output in "toggle" mode (set bit COM1A0 for Compare Output Match mode Toggle on Match) generates a 50% duty cycle signal on Arduino pin 9.  The frequency of the signal depends on the value loaded in the OCR1A register:

f = fio / (2*N*TOP)

where fio is 16MHz for most Arduinos, N is the timer pre-scale value (I used "1" in my example code) and TOP is the value loaded in the OCR1A register.  So loading 2000 into OCR1A should yield a 4 KHz output frequency.

I'm using this approach with a piezo buzzer for an alarm clock project.  I'm finding that the apparent loudness varies significantly with frequency and the peak is NOT with the "2000" value I think should hit the 4KHz resonant frequency of my buzzer.  Still trying to get to the bottom of that.
Logged

Pages: [1]   Go Up
Jump to: