# Control PWM Volume

I am using Arduino's tone() function to produce some basic tunes. However, tone() does not have volume control.

I did post about this in the Arduino Stack Exchange web site as well. User Majenko said that

The tone() function generates a 50% duty cycle square wave using a timer and interrupts. 50% duty cycle is basically full volume. An alternative is to do it in hardware. You can use an op-amp as buffer (or speaker driver) and a couple of resistors (or a potentiometer) as an "attenuator" before it to change the voltate of the signal going to the op-amp. You need the op-amp as a buffer because the speaker will mess with the potentiometer otherwise.

I am not so experienced in electronics and i do not understand what he means. I want to try this. Can anyone help me out with the schematic of this configuration?

There is one digital pin going to the positive end of the speaker. The negative end of the speaker goes to Arduino's GND. Can someone explain how this topology should be?

I believe what the author is trying to say is this:

simulate this circuit – Schematic created using CircuitLab

The potentiometer is used as a voltage divider, to provide a signal at node X with amplitude variable between 0% and 100% of the full 5V/0V digital output from the Arduino.

If you were to connect a low-impedance speaker to X, it would seriously mess with the nice proportionality between potentiometer position and signal amplitude. He is suggesting using an op-amp voltage follower to drive the speaker, and isolate it from X.

You could achieve a similar result with a single transistor "emitter follower" instead:

simulate this circuit

If you don't need manually variable volume control, then a simpler solution would be:

simulate this circuit

The value you choose for R1 would depend on the impedance of the speaker, and the volume you desire. Without more information about the speaker, all I can suggest is that you experiment with different values until you get what you want.

If you are trying to control volume in software, that's a very different problem to solve, and none of these ideas are appropriate.

• if the audio signal comes out at a DC level of Vcc/2, you definitely need DC block caps here. Jun 30 at 6:56
• Thank you so much for this beautiful and detailed answer! I will try these methods when i buy the necessary components and i will report my findings. BTW, i am using this speaker: visaton.de/en/products/drivers/fullrange-systems/k-50-8-ohm. This is an 8 Ohm speaker, so how exactly the resistance should vary based on the speaker impedance? Thank you very much! Jul 4 at 8:07
• @danmcb Thank you very much! Where exactly should they be placed in the circuit? BTW, i have another problem, that there is heavy clicking involved. (Question is here: electronics.stackexchange.com/questions/625147/…). Can this DC blocking capacitor help me with the mitigation of this problem as well? From comments i read, i got the impression that a capacitor can help me. Thank again! Jul 4 at 8:09
• @user1584421 You can't drive an 8&Omega; speaker directly from the Arduino, or an op-amp, that's far too low, and may cause damage to the IC. You must put at least 390&Omega; in series with the speaker, which will heavily attenuate the volume, or consider an LM386 circuit, for such a low impedance speaker. Jul 4 at 15:01
• @SimonFitch What exactly are 8&Omega and 390&Omega? that's far too low.. What is low exactly? Is there a speaker that works great with the arduino? I thought about it as well, that the speaker selection might be wrong. I didn't put any thought to this (not experienced with audio electronics), i just got whatever i found. Jul 4 at 21:48