PwmOut missing a pulse

06 Sep 2009 . Edited: 06 Sep 2009

Hi,

I am updating a PWM signal's period & duty-cycle every 25 ms. The PWM signal drives a buzzer to generate sound. The problem is that the update frequency interferes with the generated sound. I put a scope on the PWM signal and noticed that it misses a pulse every time the period is updated, which would explain the interference observed. I don't see anything in the ARM datasheet that would explain such behaviour. What am I doing wrong? This simple program shows the behaviour:

#include "mbed.h"

PwmOut buzzer(p21);

int main()
{
buzzer.period_us(2000);
buzzer.write(0.5);

while (1)
{
buzzer.period_us(2000);
wait(0.025);
}
}

Another thing I noticed, but that may be intended, is that the duty-cycle changes when you change the period, meaning that you have to update the duty-cycle when you change the period (50% at 1kHz becomes say 25% at 2 kHz) if you want it to stay the same (what I would expect).

Thanks,

Clemens

07 Sep 2009

Hi Clemens,

Clemens Valens wrote:
I am updating a PWM signal's period & duty-cycle every 25 ms. ... I put a scope on the PWM signal and noticed that it misses a pulse every time the period is updated, which would explain the interference observed.

This behaviour is caused by the fact that whenever the period is updated, the counters are reset. This is to avoid race condidtions (e.g. the period counter becoming smaller than the pulsewidth counter), but your use case shows this is not ideal. I'll have a think about whether this could be tackled in a better way.

Clemens Valens wrote:
Another thing I noticed, but that may be intended, is that the duty-cycle changes when you change the period, meaning that you have to update the duty-cycle when you change the period (50% at 1kHz becomes say 25% at 2 kHz) if you want it to stay the same (what I would expect).

Yes, that is the expected behaviour. The two (sane) ways of doing it are the duty-cycle stays the same, or the pulse-width stays the same. I chose the later, but I agree the former would be more attractive for your use case.

I think therefore I prefer the duty-cycle staying the same, so will look at trying a modified version of this and see if there is a way to avoid the unwanted behaviour at the same time.

Thanks for the feedback. Just what we want!

Simon

02 Sep 2010

Hello,

I have also found that when I update the period sometimes a pulse is missing (high state).

I am reading the RPM engine speed on a car-CAN-bus and produce a proportional frequency with the PWMout.

For me it is important not to miss any pulses.

Could it be possible to "update" the period only when the PWM output pin is in low state mode ?

I think that you can minimize the "error" in this way.

/Hans

02 Sep 2010

We'll take a look. Thanks for the report.

Simon

22 Aug 2011

Hello,

I think the LPC1768 misses a pulse when the match register is updated to a lower value when the timer counter is at a position between the new value and the old value. The match then has not yet occured for the old value, but it will also not occur for the new value before the timer counter is reset to 0 again and reaches the new value, with the output staying high for one period plus the duty cycle of the new value. I was able to work around this issue by adding the while loop in the code below:

int set_pwm_d(float a) {
    while(LPC_PWM1->TC < LPC_PWM1->MR3); // wait until PWM goes into low state
    if (a > A_MAX) {
        LPC_PWM1->MR3 = A_MAX * LPC_PWM1->MR0;
        LPC_PWM1->LER |= (1 << 3);
        return 1;
    } else if (a < A_MIN) {
        LPC_PWM1->MR3 = 0;
        LPC_PWM1->LER |= (1 << 3);
        return 1;
    } else {
        LPC_PWM1->MR3 = a * LPC_PWM1->MR0;
        LPC_PWM1->LER |= (1 << 3);
    }
    return 0;
}

For low PWM frequencies this slows down your code significantly, though.

I think this is an error of the LPC1768, as the behavior is contradictory to what is written about the latch enable register in the manual.

Tilman