Go Down

Topic: PWM as Analog Audio Gain Control (Read 867 times) previous topic - next topic


I'd like to meter the level of "beep" sounds the board produces and think I can if I use a PWM output. My board is an Uno R3. How would one filter out the PWM waveform? Capacitors? That variable near-DC would go to base of a transistor that is fed the audio signal at emitter.

Another obvious approach would be to gang up a few resistors and have a selection of output powers. That uses a lot of pins though, even if I would use a MUX.

Am I FoS? :)
Hate myself


Hmm. Can that even output a PWM at same time as tone? I know it only does one tone per time.
Hate myself


Here is a shematic I hashed out in Multisim.

Multism Schematic
Hate myself


Jun 19, 2018, 12:04 am Last Edit: Jun 19, 2018, 12:15 am by Southpark
I'd like to meter the level of "beep" sounds the board produces and think I can if I use a PWM output. My board is an Uno R3. How would one filter out the PWM waveform? Capacitors? That variable near-DC would go to base of a transistor that is fed the audio signal at emitter.
When describing something, make sure to read over it a few times to make sure it is coherent...... ie. is clear and makes sense.

First, you mention beep sounds a board produces. And then you mention using PWM output.

There is no link (or clear link) between 'beep sounds' and 'using PWM output'.

Also, 'filter out' generally means 'to remove by filtering'.

In any case, it will be necessary to describe the situations clearly in order for others to understand the situation clearly.

And...... for discussions on pwm filtering, take a look at this link here:

pwm filtering


Jun 19, 2018, 12:14 am Last Edit: Jun 19, 2018, 12:16 am by DVDdoug
Actually, PWM can sort-of do that automatically.   A PWM value of 0 or 255 (0V or 5VDC) is silence.   PWM of 1 or 254 (a narrow pulse) is quiet and a value of 127 or 128 (a square wave) is the loudest.   

If you're using a piezo, you'll probably want to change the PWM frequency (it's about 500Hz by default and that's low for a piezo).   Off-hand, I don't know how to do that.

As you deviate from a square wave, you'll get relatively more harmonics so the character of the tone will change and you'll probably hear a higher-pitch as the volume goes down.


Thanks. I'm using speakers which produce a variety of tones, including a paging horn located outside. It will be used as an alarm of sorts.

I wanted to control the amplitude of the square wave (tone) of any given frequency, since the PWM (analogWrite) is 490 or 890Hz about, i'd have to filter that out with a RC network. I think I got it figured out after a hour or so tinkering with it and watching the scope.

See the above link to a JPG schematic. It works surprisingly.

Hate myself




Jun 20, 2018, 01:39 am Last Edit: Jun 20, 2018, 01:44 am by Southpark
For the OP.....

Graphically ..... it is hypothetically something like this. Not all the details are provided though. It's just hypothetical..... but shows the basic idea. The PWM frequency is chosen to be high enough so that the speakers can't respond to it. And then this 'PWM' signal is basically switched on and off like a flash light.....so that the high frequency PWM signal appears for 1.136 millisec, then disappears for 1.136 millisec, then reappears etc etc.


You know, the tone() function also works. For little piezos, the output volume perceived changes drastically with pitch, so you can get different levels by using different pitches.

For more advanced audio output from your Arduino, you need more hardware. Maybe an MP3 shield with various pre-recorded beeps.
"The problem is in the code you didn't post."


My students expressed interest in variable volume on tones, so while I'm otherwise interested in manipulating the PWM frequency, I tried to make a variable volume circuit with a transistor so they could see the transistor working as a switch. I used PWM to control the volume, and tone to control the pitch. It's alive!
There is horrible aliasing, or FM, because the PWM frequency is near the middle of the audio spectrum. If you want it to be more harmonious, you might select tones that are in harmony with the PWM frequency.
So, here's how I do it:
I use non-interfering pins for tone() and analogWrite(). On my Leonardo, I choose 6 and 9. See the tone() reference, https://www.arduino.cc/reference/en/language/functions/advanced-io/tone/ , for more info.
I use a cheap PNP transistor, a small 8Ω speaker, a 10µF capacitor, two 2kΩ resistors and a 1kΩ resistor.
The main current path is 5V>emitter, collector>speaker>10µF>GND. There is a 1kΩ between the tone pin and the base of the PNP, a 2kΩ between the analogWrite() pin and the point where the speaker and capacitor meet, and a 2kΩ between that point and GND. Those last two resistors are for charging and discharging the capacitor with analogWrite(). I find that I need to revise the circuit to get the capacitor to discharge more quickly, even though I need it to be larger for less ripple from analogWrite().
I test with the following code
Code: [Select]
/* From Reference:
* Use of the tone() function will interfere
* with PWM output on pins 3 and 11
* (on boards other than the Mega).
const int tonePin=6;
const int volumePin=9;
void setup() {
 digitalWrite(tonePin,HIGH);//default to make PNP off when not making a tone
void loop() {
 for(int volume=255;volume>0;volume-=10){//sweep the volume
   for(float pitch=600.0;pitch<900.0;pitch*=1.1){//sweep the pitch

Go Up