For a new project with Arduino I need to generate an alarm tone that needs to increase in amplitude over time if the user doesn't take action. The output would be via a small speaker.

So when the alarm condition triggers I would generate a low volume beep in the audible range, give the user some time to react, then increase the volume, wait, increase again until the user reacts. This way I don't generate a loud alarm tone from the start, which can be disturbing in a quiet environment.

Generating pulses and using a transistor or IC amplifier to drive the spaker is no trouble.

--> The issue is: how to modulate the amplitude of the speaker sound?

My limitation is that while sounding the alarm, the Arduino still needs to to other stuff, so I can't stall it in a complicated routine to generate tones for example by doing some fancy PWM that then gets filtered to deliver a signal with different amplitudes.

I could use one pin to generate the base frequency signal, and have 3 pins available to steer some external circuit to modify the amplitude, like this: enter image description here

Do you guys have some ideas to share?


ADDENDUM: This is the solution I had tried out already, but the volume levels are not repeatable from one unit to the next, so I would like to avoid adding a trimmer pot. D13 generates a square wave with the audio tone. The other outputs pipe this tone through the resistor ladder via the AND gates.

enter image description here


2 Answers 2


Your question shows a PWM unit, followed by an adjustable gain stage. This isn't a very obvious form to use, but it might work.

Traditionally, you might use multiple PWM units with different output drive strengths (using resistors), in effect building a DAC.

What you have built should work if you combine the PWM (for switching) with a programmable current source (for amplitude). For the current source, you can use 3 current mirror circuits in paralell, switched by your 3 amplitude controls. Typically you might choose a log-scale for each switching step.

You PWM output can be used to sink current, the 3 current mirror stages source current (and control the amplitude).

  • \$\begingroup\$ Hi Sean, I had already built a simple solution with a resistor ladder, but the volume levels are not repeatable from one unit to the next. I added the circuit to the text above. \$\endgroup\$
    – kxtronic
    Jan 15, 2017 at 23:30

Arduino doesn't really say which microcontroller specifically, but I think all the Arduinos I'm aware of have a programmable PWM unit, so that you need to spend no CPU on generating the signal at all.

For details on different ways to use a PWM unit, please refer to this answer, but the gist is:

You can program the period of your PWM, that is, the frequency of the output signal.

To adjust the voltage you're feeding into the speaker, you can take different routes:

  1. use a second PWM unit + low pass filter with low cutoff to generate an adjustable DC voltage with which you operate the transistor you use to amplify the signal before it goes into the speaker
  2. instead of using an audio-frequency PWM, use a PWM that's much faster, and turn that on and off at the desired tone frequency. Add filtering so that the fast PWM is reduced to an offset, but the audio frequencies don't get cut off.

Another, and probably the easiest way, is not concerning your µC with generating an analog signal at all, but using an audio DAC for that. These things take serial data, typically through SPI/I2S, and often even have integrated amplifiers.

For example, the ST Discovery boards use the CS43L22 IC for that job. You just send in digital audio data – and it generates the sound. In fact, it even has a beep generation unit if you're too lazy to write the beep waveform via the I2S interface!

There's a plethora of other options, like voltage-to-frequency converter ICs, driving a tank/oscillator circuit periodically, etc., but I think these might be the most arduino-friendly approaches.

  • \$\begingroup\$ Hi Marcus, A DAC sounds a like a good idea. The CS43L22 is an overkill. I will see if I can find something simpler. After all, I just need to generate pulses of different amplitude and amplifying with a single transistor. \$\endgroup\$
    – kxtronic
    Jan 15, 2017 at 23:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.