PDA

View Full Version : Piezo speaker question



Greg LaPolla
07-13-2009, 03:16 AM
I am using a piezo speaker and I can't seem to get it loud enough to hear it from inside a project box.

here is the code and the diagram is attached






CON

_clkmode = xtal1 + pll16x ' set clock mode
_xinfreq = 5_000_000 ' set external crystal freq



OBJ

PUB Main
warn
PRI warn
ctra[30..26] := %00100
ctra[8..0] := 27
frqa := 224_734

repeat 3
repeat 30
!dira[27]
waitcnt(clkfreq/30 + cnt)
waitcnt(clkfreq + cnt)

PRI alarm

ctra[30..26] := %00100
ctra[8..0] := 27
frqa := 224_734
repeat 5
!dira[27]
waitcnt(clkfreq + cnt)





Am I asking to much from the piezo ?


Greg

Leon
07-13-2009, 03:41 AM
Is it a plain piezo element or a piezo unit with a built-in driver? The schematic doesn't look right, anyway. The 1k resistor is shorted.

Leon

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Amateur radio callsign: G1HSM
Suzuki SV1000S motorcycle

Greg LaPolla
07-13-2009, 03:54 AM
It's the piezo that parallax sell. Your right about the resistor it should be between the piezo pins.

Greg LaPolla
07-13-2009, 03:58 AM
@Leon good catch. I moved the resistor across the piezo pins and now it is so much louder. Sometime it just takes another set of eyes!


Thanks


Greg

Erik Friesen
07-13-2009, 04:13 AM
You need to catch the resonant frequency for best results on a piezo.

Beau Schwabe (Parallax)
07-14-2009, 03:49 AM
Greg LaPolla,

In addition to finding a resonant frequency of the piezo (<- there can be more than one that will work), you can also increase the volume by driving the piezo element differentially rather than single ended. See this thread... although it was written for a BS2, it will still apply here.
http://forums.parallax.com/showthread.php?p=464410



If you can't provide a solution in software by sacrificing two pins that you can drive 180 Deg out of phase
to supply a piezo, then the below circuit may be of some use to you. It is basically a two transistor inverter
designed to be able to handle a floating input. Note for use from a Propeller pin, substitute the 4.7K resistors with 3.3K resistors.
http://forums.parallax.com/attachment.php?attachmentid=36227

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe (mailto:bschwabe@parallax.com)

IC Layout Engineer
Parallax, Inc.

Post Edited (Beau Schwabe (Parallax)) : 7/15/2009 6:00:07 AM GMT

Greg LaPolla
07-14-2009, 08:01 AM
@Beau,

I read through several spec sheets for various piezo's. One of them suggested placing a 1k resistor across the pins, (Resistor to do charging and discharging to a piezoelectric element - Value of about 1kΩ is good efficiency).
Does that achieve sorta what you were referring to? It did get significantly louder once I did that (Correctly as Leon noted).



Greg

Peter Jakacki
07-14-2009, 08:12 AM
I have driven piezos differentially using 2 I/O and that makes a big difference to the volume for a few reasons. Alternatively I have also connected the piezo from collector to ground and used an inductor + some series resistance in the collector to VCC to provide that punch. The resistor across the piezo is the most basic way to drive it but then you don't need that transistor there for that do you?

*Peter*

P.S. I read your original post and you mentioned that you had the piezo inside the box. Bear in mind that this will muffle the sound a lot unless you mount the piezo against the inside of the box with a small hole of around 1 to 5mm for the sound. This is how it is done in all commercial projects, the hole may be very small but it makes a difference.

Post Edited (Peter Jakacki) : 7/14/2009 1:36:09 AM GMT

Beau Schwabe (Parallax)
07-14-2009, 10:32 AM
Greg LaPolla,

The circuit that you provided will only drive the piezo in a single ended mode, and using a 1K bias resistor works fine for this. If you do however find that you need even more volume, the differential drive approach that I provided a link to can help. Even if you have one I/O pin there is an inverter that will work perfectly with the piezo that I also provided a link to that will drive the piezo element differentially.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe (mailto:bschwabe@parallax.com)

IC Layout Engineer
Parallax, Inc.

Greg LaPolla
07-14-2009, 11:40 AM
@Beau

Is there an inverter specifically that you would recommend or is it best to just build one as you have diagrammed.


Greg

Beau Schwabe (Parallax)
07-14-2009, 12:40 PM
Greg LaPolla,

I have always just built one in this situation... A CMOS inverter would probably work just fine. The unique property of the inverter that I posted is that it can accept a floating or hi-Z input.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe (mailto:bschwabe@parallax.com)

IC Layout Engineer
Parallax, Inc.

Greg LaPolla
07-15-2009, 06:36 AM
@Beau,

I don't have any 2n3906 transistors, I only have 2n3904's. I thought I would attack the 2 pin method. I have been going over the Counter Modules and Circuit applications lab in the PE kit. I can't seem to find anything that would help. I understand the methodology, but I can seem to wrap my head around it completely.

Would you just alternate the pins back and forth between input and output ? using the code I originally posted using ctra and frqa I am not sure it will work. Do those counters get reset when you change the pin direction?


Greg

Peter Jakacki
07-15-2009, 10:14 AM
Greg, if you use the counters you have a mode whereby you can nominate another pin as the complement so you don't have to worry about switching the I/O and direction. Try this on the "Synth" object that CHip and Beau did.




PUB Synth(CTR_AB, Pin, Freq) | s, d, ctr, frq

Freq := Freq #> 0 <# 128_000_000 'limit frequency range

if Freq < 500_000 'if 0 to 499_999 Hz,
ctr := constant(%00100 << 26) '..set NCO mode change this to 00101 for differential
s := 1 '..shift = 1
else 'if 500_000 to 128_000_000 Hz,
ctr := constant(%00010 << 26) '..set PLL mode change this to 00011 for differential
d := >|((Freq - 1) / 1_000_000) 'determine PLLDIV
s := 4 - d 'determine shift
ctr |= d << 23 'set PLLDIV

frq := fraction(Freq, CLKFREQ, s) 'Compute FRQA/FRQB value
ctr |= Pin 'set PINA to complete CTRA/CTRB value
ctr |= ++Pin<<9 add this line to select the differential pin (assuming here that you are using next pin up)

if CTR_AB == "A"
CTRA := ctr 'set CTRA
FRQA := frq 'set FRQA
DIRA[Pin]~~ 'make pin output change to DIRA{Pin..Pin+1]~~

if CTR_AB == "B"
CTRB := ctr 'set CTRB
FRQB := frq 'set FRQB
DIRA[Pin]~~ 'make pin output change to DIRA{Pin..Pin+1]~~




*Peter*

Greg LaPolla
07-15-2009, 10:59 AM
@peter


Thanks for the info. I am trying to get your example to work but It hangs here:

frq := fraction(Freq, CLKFREQ, s) 'Compute FRQA/FRQB value

What should that do ? I assume fraction is something you wrote.

I modified my code like this:




PUB warn
ctra[30..26] := %00101
ctra[8..0] := 18
ctrb[8..0] := 19
frqa := 224_734

repeat 3
repeat 30
!dira[18..19]
waitcnt(clkfreq/30 + cnt)
waitcnt(clkfreq + cnt)





this works but doesn't seem any louder so I assume my code is not correct.


Greg

Phil Pilgrim (PhiPi)
07-15-2009, 11:06 AM
Greg,

You need to set the destination field of CTRA to 19, not the source field of CTRB. The latter doesn't do anything, since you're not using CTRB.

-Phil

Greg LaPolla
07-15-2009, 11:15 AM
OK maybe I am totally missing the concept here, based on what Beau said to push both sides beyond the center it can be done using 2 pins.

My line of thinking is to drive pins high and low and alternate input and output respectfully on the 2 pins.

Changing ctra to differential mode I understand, but what about the second pin ?


Greg

Peter Jakacki
07-15-2009, 11:34 AM
In my example I have left the parameters Synth(CTR_AB, Pin, Freq) as they are but simply made the extra pin as +1 so therefore if you specify pin 10 for your piezo then pin 11 will be the complement of pin 10 automatically.
Basically all that happens is that one pin will be at 3.3V while the other will be at 0V, then it alternates (AC) so that it becomes 0V while the other will be at 3.3V. The piezo will with only two pins see a strong AC signal imposed across it which is ideal for this type of element as it is mostly capacitive in nature. Leaving a DC voltage on the piezo will have no effect at all or draw any current, it needs to be AC (in respect to the piezo).

3.3V -------PIEZO--------0V
0V----------PIEZO--------3.3V
3.3V-------PIEZO---------0V


If you want to specify a completely different complementary pin then you should add an extra parameter to the function and change the bits that write to the counter and direction register.


*Peter*

Peter Jakacki
07-15-2009, 11:38 AM
I just read Phil's post and I see you are getting confused with CTRA and CTRB. They are completely separate counters with the only thing in common being that they are accessed by the one cog. The destination field starts at bit 9 vs bit 0 for the source field in a 32-bit word. This is standard Propeller assembly convention for 9-bit source and destination fields and the counters are setup the same way.

*Peter*

Greg LaPolla
07-15-2009, 11:55 AM
@Peter,

I have tried your code and I can't seem to make it work.

Here is what I have done:





count = "A"

Synth(count,18,224_734)

PUB Synth(CTR_AB, Pin, Freq) | s, d, ctr, frq

Freq := Freq #> 0 <# 128_000_000 'limit frequency range

if Freq < 500_000 'if 0 to 499_999 Hz,
ctr := constant(%00101 << 26) '..set NCO mode change this to 00101 for differential
s := 1 '..shift = 1
else 'if 500_000 to 128_000_000 Hz,
ctr := constant(%00011 << 26) '..set PLL mode change this to 00011 for differential
d := >|((Freq - 1) / 1_000_000) 'determine PLLDIV
s := 4 - d 'determine shift
ctr |= d << 23 'set PLLDIV

'frq := fraction(Freq, CLKFREQ, s) 'Compute FRQA/FRQB value
frq := Freq
ctr |= Pin 'set PINA to complete CTRA/CTRB value
ctr |= ++Pin<<9 ' add this line to select the differential pin (assuming here that you are using next pin up)

if CTR_AB == "A"
CTRA := ctr 'set CTRA
FRQA := frq 'set FRQA
DIRA[Pin..Pin+1]~~ 'make pin output change to DIRA{Pin..Pin+1]~~

if CTR_AB == "B"
CTRB := ctr 'set CTRB
FRQB := frq 'set FRQB
DIRA[Pin..Pin+1]~~ 'make pin output change to DIRA{Pin..Pin+1]~~




I can seem to get anything out of the peizo with this. I even tried a repeat calling synth.


Greg

Peter Jakacki
07-15-2009, 12:03 PM
What is that frequency you are running it at. Even bat ears won't pick that up!

Try 1500 for starters


*Peter*

Phil Pilgrim (PhiPi)
07-15-2009, 12:04 PM
Greg,

You need to add a repeat to your main code to keep the cog alive. Your program is dying right after the call to synth since Spin is doing an automatic cogstop. Repeatedly calling synth is only going to make it keep reinitializing.

-Phil

Peter Jakacki
07-15-2009, 12:11 PM
Yes Phil, and that too but it looked like he had clipped the listing as there was no pub method defined there.

Posters, if you are going to post code then post the exact code otherwise we have no idea what really is going on.

*Peter*

Greg LaPolla
07-15-2009, 12:11 PM
@Peter

that is c8. It plays fine with my code.

I changed it to 84_181 which is G6 still no go.


@Phil

I did use a repeat as I stated at the bottom neither worked.

Peter Jakacki
07-15-2009, 12:14 PM
Sorry Greg, but aren't you using the Synth object which expects frequency in Hertz, not in timing cycles?

*Peter*

Greg LaPolla
07-15-2009, 12:17 PM
ok, I made a change to it because some code was missing. I thought the change I made would work. What does the fraction method do? that was missing.


Greg

Peter Jakacki
07-15-2009, 12:25 PM
I think that fraction part is only working out what to load the counters with to get that frequency. If you notice the code checks the frequency to see if it is less than 500,000Hz so it uses 0 and 499_999 as the underscore is simply for readability and nothing else.

*Peter*

Phil Pilgrim (PhiPi)
07-15-2009, 01:08 PM
Greg,

You said you "even tried a repeat calling synth", which is different from what I suggested: namely, a naked repeat at the end of your main method, which serves to keep the cog alive. As I explained before, calling synth in a repeat loop just keeps reinitializing the counters, rather than letting them produce any sound.

-Phil

Beau Schwabe (Parallax)
07-15-2009, 01:22 PM
Here is a modified FreqSynth object that will create a differential signal.


For your application, you might try something like this to generate a 3kHz signal...

Freq.Synth("A",PinA,PinB, 3000)

Where PinA and PinB would be your output pins connecting to the piezo.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe (mailto:bschwabe@parallax.com)

IC Layout Engineer
Parallax, Inc.

Greg LaPolla
07-15-2009, 01:25 PM
OK, I read the prop manual again and I had one of those ah hah moments.

here is the final working copy





CON

_clkmode = xtal1 + pll16x ' set clock mode
_xinfreq = 5_000_000 ' set external crystal freq

PUB Main
warn
alarm

PRI warn
ctra[30..26] := %00101
ctra[5..0] := 18
ctra[14..9] := 19
frqa := 224_734

repeat 1
repeat 30
!dira[18..19]
waitcnt(clkfreq/30 + cnt)
waitcnt(clkfreq + cnt)

PRI alarm

ctra[30..26] := %00101
ctra[5..0] := 18
ctra[14..9] := 19
frqa := 224_734
repeat 5
!dira[18..19]
waitcnt(clkfreq + cnt)




After running this I about blew my ear drums out. It will definitely be able to be heard outside the project box.

Thanks to Phil & Peter especially for being on the board late at night! You guys were a great help.

Greg LaPolla
07-15-2009, 01:34 PM
@Beau

Thanks for the code. I was just re-reading the ctra section in the prop manual. What was confusing me was the BPIN reference for diff mode. I was looking at the ctra register map and discovered that bpin was 9 - 14. Once I realized that I found the error of my ways.


Greg