NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Sensors, Actuators, and Robotics » Real speakers

May 19, 2009
by palako
palako's Avatar

Hi,

I have one little puppet that sings a song (real song, not tones using a piezo) through an internal speaker. The speaker has two wires connecting it to the board, but I cannot see the chip that does the magic, seems to be covered under a black bubble that I haven't seen before. I guess the song is encoded somehow in a very tiny chip and it sends the right voltages to the speaker to reproduce the song.

Anyway, I was wondering, if I wanted to use this speaker with the nerdkit microcontroller to play realtones (as opposed to using the buzzer to make single tones), do you know if this is possible at all? I'm sure it is!. Do you know how could I get started searching info about the topic? How do I code the tune in my program? What kind of voltages changes do I have to send to the speaker to reproduce the song?

Thanks,

May 20, 2009
by wayward
wayward's Avatar

Hi palako,

unless I am grossly mistaken, the buzzer that comes with the NerdKit can be treated like a miniature speaker, which is what it is: it vibrates the membrane once when the current starts or stops going through it. Beepers, on the other hand, make a single tone of factory-fixed pitch; you don't have to worry about switching the power on and off, you simply supply the current for the desired duration of the sound. The big difference between buzzers and speakers is that the latter need more current to operate, and have much better sound characteristics -- a wider frequency response and much less deformation (when compared to buzzers) due to limitations in construction. I'm sure someone here will tell you a lot more about this.

As for controlling the buzzer: all you need is to know when to move the membrane. Knowing that any sound is actually a series of sound waves with varying amplitude (perceived "loudness") and frequency (perceived "pitch"), we can approximate those waves by kicking the membrane at certain times. If you imagine the wave passing through an imaginary plane, the wave will intersect the plane in one point at any given time. When that point of intersection reaches its peak (for the current segment of the wave), we switch the buzzer on (or off), and produce a wave. Repeat for the duration of the song, et voila. Kicking the membrane faster makes for a higher pitch. (I don't think that the buzzer gives us any control over the volume, though.)

Take a look at NerdKits' music project for the basic implementation of this principle using our AVRs. For more information, magic keyword is "PWM" (pulse-width modulation).

Have fun!

May 20, 2009
by palako
palako's Avatar

Hi wayward, and thanks for your answer,

...but I guess my question was probably not well formulated, will give it another try :)

I know how the speaker works (didn't know the buzzer was that similar), in a nutshell, there's a couple of magnets, one static and the other electric. The electric one gets polarized based on the current that it receives. The frecuency of the signal turns the magnet on/off, and when it's on one magnet goes away from the static one, carrying with him the membrane (that pushes the air, then soundwave, blah blah blah...). The amplitud of the signal indicates how far the magnet gets from the other, that is, how much the membrane gets moved. Well, that's how I think it works, if I'm wrong, it might also be that depending on how many time the magnet is on, it keeps pushing the membrane, but I'm more into the first theory, I think that the speed which which the membrane moves is important for the soundwave.

My question is, I have two wires that connect the speaker with the circuit. One is ground, the other will be connected to the microcontroller. As opposed to the buzzer, which is connected to a fixed voltage digital output which switches very quickly 1s and 0s, I'm guessing that I need to connect the speaker to a digital to analog converter so I can send different amplitudes. Am I wrong? On the contrary, if I'm wrong, my second theory is that the amplitud will only control the volume, and EVERYTHING that we listen in a song are just frecuency changes.

In case I'm right, I wonder what kind of program could I write that sends the approriate signal, with the appropriate amplitudes and frecuency changes to the speaker. In case I'm wrong, even better, I'd only need to take care of frecuencies, but then my question is, how can I codify a song in such a way that I can send those frecuency changes to the speaker.

I did the music project, it was actually very interesting the calculations that you need to play the exact tone that you want. But this one is pretty different. No matter if I use a speaker, or, as you said is possible, the piezo buzzer, what I want are not single tones of a fixed duration, one after the other, like the happy birthday on the music project. I want to be able to reproduce the song with the drums, guitars, bass, vocals... well, you get the point... Maybe is it frecuency multiplexion? I have no clue.

So those are my questions: 1) Do I need digital to analog output? 2) How do I encode the song to send the right signal to the speaker?

Thanks so much! I love learning about all this stuff, and learning by doing, even better!!

(Makers faire in two weeks, BTW, I'm flying there all the way from London!)

May 20, 2009
by palako
palako's Avatar

After reading a bit and asking some in some other forums (http://stackoverflow.com/questions/890414/how-to-send-sound-to-a-speaker), seems that actually the frecuency is constant and the amplitude changes. Given an 8-bit WAV files that codifies every sample from 0x00 to 0xFF, I just need to convert those to the voltage range of the speaker with a digital to analog converter. If the file is 22.1KHz encoded, I will send 22.1K voltage samples per second.

Now I need to explore the limits of the chip that comes with the Nerdkit for this, what is the maximum frecuency that I can use, etc...

Will keep you posted :)

May 20, 2009
by palako
palako's Avatar

It might be easier that what I thought....

Page 90 of the ATMega168 manual:

  1. 8-bit Timer/Counter0 with PWM:

"Timer/Counter0 is a general purpose 8-bit Timer/Counter module, with two independent Output Compare Units, and with PWM support. It allows accurate program execution timing (event management) and wave generation."

May 20, 2009
by wayward
wayward's Avatar

You may also want to look at pulse-code modulation. I think you will have to use some sort of D-A converter to drive the speaker.

(throws crumbs to attract resident audio gurus)

May 21, 2009
by palako
palako's Avatar

I don't think so, that's the beauty of the PWM you suggested, you can have an D2A converter with a timer using the AVR.

take a look at this link:

http://extremeelectronics.co.in/avr-tutorials/pwm-signal-generation-by-using-avr-timers-part-ii/

and linked from that one is a previous article on PWM using timers, really good:

http://extremeelectronics.co.in/avr-tutorials/pwm-signal-generation-by-using-avr-timers/

May 21, 2009
by wayward
wayward's Avatar

Great,

I'll need this when I finally figure out why I can't talk to the RTC chip in my VAC project. Thanks!

May 25, 2009
by palako
palako's Avatar

I've been playing with this a bit again, and I feel I almost have it, but it doesn't work as I expect yet.

I'm doing PWM with two timers. Timer0 will do the PWM itself, counting up to 255 without prescaling and reseting when it gets to OCR0A. The output at OC0A will be my desired signal.

With timer1 I change the value of OCR0A 19200 times per second. I do that with prescaling /256 and clearing on compare with OCR1A=2 (every three steps). I capture an interrupt (SIG_OUTPUT_COMPARE1A) when the timer is 2.

What I would like to do is to change the value of OCR0A on each interruption, but OCR0A=something doesn't seem to have any effect inside the SIGNAL routine. I guess for some reason I cannot access OCR0A when running interruption code.

If I keep a volatile uint8_t and change the value of this one inside the interruption code, then I can have OCR0A=the volatile variable inside a while(1) in my main(), but that is not exactly what I want, as the loop code will not be syncronized with the interruptions.

Any tip on how to change that OCR0A exactly every time the interruption happens?

Thanks,

May 25, 2009
by wayward
wayward's Avatar

palako,

I wonder if you're being haunted by the fact that the OCR registers are double-buffered. I didn't read this in detail, but do check the datasheet, page 96, close to the bottom. It seems like double-buffering depends on the timer's mode of operation.

May 25, 2009
by palako
palako's Avatar

That's an interesting point, as I actually thought that double-buffering was an aly in this case, allowing me to change the NEXT comparation value before the current one has been reached. Is good to know that depending on the mode, for low values of the counter this might me a problem.

However, I don't think this is what is causing the problem. When I try to give a value to OCR0A inside the SIGNAL() {} code, it is simply ignored.

May 26, 2009
by wayward
wayward's Avatar

Maybe this?

May 26, 2009
by palako
palako's Avatar

I hate when this happen.... I misstyped (1<CS12) instead of (1<<CS12) when setting the timer!

Anyway, I still don't have it. I have noise now in my speaker, like very fast tics, not constant frecuency, but not the song that is supposed to be codified in my array. Possible causes:

1) I'm sending the wrong voltage range to the speaker.

2) I have some codification problem and the values that I have in my array are incorrect.

3) ideas?

How would you guys go now for debugging?

FYI, I discovered the typo by starting all over again with something that I could actually see, so I made a very simple changing bright led with timer0 for PWM changing the value in a for loop with a delay, and then a second version with timer1 for interrupts, meaning that I am now 100% sure that both timers and the interrupt routine are correct. It must be something else.

Thanks!

May 26, 2009
by palako
palako's Avatar

Some more info. As in your first coment you said that the buzzer should behave similar to the speaker, I tried it and it makes exactly the same kind of fast tics. I'm sending PWM between 0 and 5V, and those are correct values for the buzzer, aren't they? Or perhaps even if the voltages are in the range of the speaker, the 255 possible values corresponding to an 8-bit sample should not be mapped from 0V to 5V, but in a much smaller range? maybe 0V to 1V? or 4V to 5V? does that make sense?

May 26, 2009
by wayward
wayward's Avatar

I actually have no idea how those audio components work :) I suspect that varying the current through a speaker would produce stronger or weaker motion of the membrane ( = sound intensity), but as for the buzzer, I am clueless. All I know is that the buzzer clicks once when I connect it to 5V, and clicks again when I disconnect it. I am actually going to get a 555 and test the buzzer from the kit to see if it acts discretely or can be used across a range of voltages.

Also, 'nother thing to keep in mind is that the membrane might not recoil fast enough if you're sending it signal outside of its mechanically acceptable frequency range. Just a thought...

Post a Reply

Please log in to post a reply.

Did you know that you can generate hundreds of volts AC from your microcontroller with a little bit of circuitry? Learn more...