9 years, 10 months ago.

Smoothly varying PWM period

I am using a PWM output to drive a speaker via an audio amplifier. Works quite well but when I alter the PWM period using the PwmOut class's period_us method there is a very audible break in the sound being generated. Is there any way to avoid this?

Eventually what I want to do is sample an analogue input at regular intervals (say every 10ms) and then use the voltage at the analogue input to vary the PWM frequency so the speaker makes noises like a swanee whistle or theremin. If you get a break in the audio every 10ms then it is going to sound more like a buzzer.

Question relating to:

Which device are you using?

posted by Erik - 29 Jun 2014

1 Answer

9 years, 10 months ago.

Looked for the fun of it what happened with the LPC1768 and the application board. Never knew before that a potmeter to frequency program would be so much fun :P.

Anyway, first of all, take into account you get a square wave, if you want good quality you probably want a sine, and you will need to use AnalogOut. If you are using the LPC11u24: Not gonna work. It lacks proper PWM hardware, the LPC1768 (and IIRC the KL25Z that you have also) will automatically make sure to only update the period at the start of a new period, the LPC11u24 doesn't do that, which means software must reset the counter to prevent bad things from happening, which you will hear when connected to a speaker.

Now the LPC1768 doesn't need to do this, but just by listening to it I guess the standard code does it anyway. Since my random test program still had FastPWM there, I tried that one too, and that one did give good sound (as good as you can get it with a square wave):

#include "mbed.h"
#include "FastPWM.h"
 
AnalogIn input(p19);
FastPWM pwm(p26);
int main() {
 
    pwm.write(0.5);
    
    while (1){
        pwm.period(1/(100 + 5000 * input));
        pwm.write(0.5);
        wait_ms(10);
    }
}

Since it doesn't keep the duty cycle constant with changing periods, it needs to be written back to 50% everytime. It could happen that when a new period start right between the period and the write line, one period is done with a wrong duty cycle, but effects of that should be negligible. The documentation of the mbed PwmOut claims that they keep duty cycle constant with different period, but I think that is still bugged on the LPC1768, so even with regular PwmOut you would need to do the same.

I don't have a potmeter for my KL25 (and the only speaker I got would be a 40kHz piezo element), so can't see what that one does. But it should work too. Just the LPC11u24 can't do it.

Accepted Answer

Thanks. That works like a dream - no clicks!

I'm using the LPC1768. Actually the square wave output doesn't sound too bad but I plan to put some sort of simple filter on the output to round the edges of the square wave so I can get something approaching a sine. Might even allow it to be switched in and out of circuit.

posted by Richard Ellingworth 29 Jun 2014