cancel
Showing results for 
Search instead for 
Did you mean: 

STM8S PWM jitter

klaasdc
Associate II
Posted on October 16, 2010 at 18:09

STM8S PWM jitter

12 REPLIES 12
klaasdc
Associate II
Posted on May 17, 2011 at 15:11

Okay, this is getting weird.

I have reimplemented everything without interrupts, just to be sure. And guess what, the servo is shaking again at exactly the same frequency...

Then I switched from TIMER1 to TIMER3 to count the time between pulses. Again, the problem persists.

With everything I tried I can only come to one logical conclusion, and that is that the reading of input ports cannot be timed consistently...

Code below:

while (1){

        //Check photoinput

        if (GPIO_ReadInputPin(GPIOE, GPIO_PIN_5)){

            // Now begin counting until pin is active again

            TIM3_SetCounter(0);

            while (GPIO_ReadInputPin(GPIOE, GPIO_PIN_5)){

                //Wait as long as pin is high

            }

            while ( !(GPIO_ReadInputPin(GPIOE, GPIO_PIN_5)) && (TIM3_GetCounter() < 10000)){

                //Now wait as long as pin is low

            }

            time = 10000 / ((double)TIM3_GetCounter());//revolutions per second

            pwm = (u16) 56 * time + 1120;

           

            if (pwm < 3000)

                pwm = 3000;

            if (pwm >4200)

                pwm = 4200;

           

            TIM2_SetCompare1( pwm );

        }

}

klaasdc
Associate II
Posted on May 17, 2011 at 15:11

I have a little bit more information. The problem seems to lie with the timing between the pulses that are sometimes not correctly timed.

On the scope, the pulses are perfect, but then I added a line to blink a led whenever the measured time is really wrong (<10ms or >300ms for example). The led blinks frequently.... This explains the pwm problem.

I then increased TIMER1's speed and adapted the calculation accordingly. The problem persists, but the speeds at which it happens has changed.

So, what exactly I am doing wrong that I get false/bogus timer values? Could there be some interrupts that I have no control of that mess up with the timing?

lowpowermcu
Associate II
Posted on May 17, 2011 at 15:11

Hi klaas,

I have make a little bit overview of your code below and I have one comment:Are you aware about enabling the preload registers using the two functions below ?

  TIM2_OC1PreloadConfig(ENABLE);

  TIM2_ARRPreloadConfig(ENABLE);

In my understanding when preload register is enabled, setting counter will not be immediately: you will need an update event to get your new counter value.

Hope that helps.

Herzlich,

MCU Lüfter

klaasdc
Associate II
Posted on May 17, 2011 at 15:11

Thanks for your reply!

You mean I should add

TIM2_GenerateEvent(TIM2_EVENTSOURCE_UPDATE);

every time I set a new capture-compare value for TIMER2? Or do you mean when setting the counter value of TIMER1?

I will try that, but I don't think anymore the problem is related to the PWM generator itself. I have tested it by incrementing the CC value on every interrupt and that works fine.

My view at the moment is the following: Interrupts from the input pin are generated at the right time (checked by toggling output pin on interrupt call and a scope. Input pulse and output pin are an exact match).

However, what happens with the measured time ends up as a wrong pwm value. This can be due to TIMER1 not correctly reporting the time

OR

the calculation from time-between-pulses to a pwm setting is unstable.

The latter would mean that using doubles/floats and divisions with the STM8S and the COSMIC compiler does not lead to a correct outcome of the calculations. I could check this by using an LUT instead of calculating the pwm every time.

klaasdc
Associate II
Posted on May 17, 2011 at 15:11

I have tested your suggestion about

TIM2_GenerateEvent(TIM2_EVENTSOURCE_UPDATE);

but it completely messes up the generation of PWM signals. I can also confirm that the COSMIC compiler handles floats and doubles fine.

I have now reimplemented everything without timers (just counting clock cycles). It works perfectly fine!

So the culprit must be the timers which behave erratically when (re)setting them at at certain frequency. Their next reported value is then incorrect. I will try to find more proof.

lowpowermcu
Associate II
Posted on May 17, 2011 at 15:11

Hi klaas,

If you use ''TIM2_ARRPreloadConfig(ENABLE);'' you should generate an update event using ''TIM2_GenerateEvent(TIM2_EVENTSOURCE_UPDATE);''

 

 

If you use ''TIM2_OC1PreloadConfig(ENABLE);'' you should genarate an update event using ''TIM2_GenerateEvent(TIM2_EVENTSOURCE_UPDATE);''

 

 

In your case, since you are using both, you should generate an update event when setting a new capture-compare value for TIMER2 or when setting the counter value of TIMER1.

Hope that helps.

good luck,

Herzlich,

MCU Lüfter

klaasdc
Associate II
Posted on May 17, 2011 at 15:11

lowpowermcu, I have tested what you say but it is not correct.

If you use the preload register, it means the compare value is cached and refreshed only when the CC value is reached. This is already an update event in itself. If you add TIM2_GenerateEvent(TIM2_EVENTSOURCE_UPDATE), then another update event will be generated that will reinitialize the PWM generation.

You will not notice the effect as long as you update the CC value at the same frequency as TIM2. But if you generate the event asynchronously then one will see on a scope that the PWM frequency becomes dependent on the calling of the update event.

So, my problem lies elsewhere :(

lowpowermcu
Associate II
Posted on May 17, 2011 at 15:11

Hi Klaas,

I have understood from your code that you are measuring the time betwwen two consecutive rising edges and you set the pwm duty cycle depending on the measured time.

If I don't miss-understand your code, why you aren't using the capture feature ? It is used to measure time between programmed edges. So you need to set your timer in capture mode and at each capture event you will find the captured value (timer counter) in CCRx register. I think it is better than using timer counter and EXTI interrupt. That doesn't mean that what you are doing is wrong.

Thanks to clarify this for me.

Good luck.

Regards,

MCU Lufter

klaasdc
Associate II
Posted on May 17, 2011 at 15:11

Hi lowpowermcu,

You understand the code correctly. I'm implementing a digital tachometer that controls an analog needle attached to a servo.

The suggestion you made is a very good idea. I had not considered that before. I will try it now 🙂

However, I'm still a bit worried by the fact that I can consistenly make the next timer's output a rubbish value by calling TIMx_SetCounter(0) at a certain frequency. I'm beginning to fear it might be some sort of bug. When I have some time I might verify this with a pulse generator as I can't believe it.