Changing PWM duty cycle on BluePill produces wrong output

Post here all questions related to STM32 core if you can't find a relevant section!
Post Reply
Leviro
Posts: 11
Joined: Sat Aug 01, 2020 9:07 am

Changing PWM duty cycle on BluePill produces wrong output

Post by Leviro »

Hi everyone!
I am working with STM32F103C8T6-BluePill to control the speed of a motor through PID (feedback from rotary encoder connected to the same STM32 board).

The problem is, the PID generates output so often (about 50~200 outputs/sec) and the PWM needs to be set to this value. But calls to analogWrite and setPWM with such small intervals seems to break it and causes it to produce wrong output.

To reproduce the problem,
Simply call setPWM with any duty cycle in setup and measure the output using a voltmeter.
Update the sketch and move setPWM to loop with small delay and measure the output again.
The values won't be the same.
by ozcar » Tue Aug 04, 2020 10:19 pm
Leviro wrote: Tue Aug 04, 2020 6:28 pm I started with the example in the GitHub wiki, made the timer variable global, and used it to call setPWM in the loop:
They say that great minds think alike – that is exactly what I tried.

My equipment does not run to an AVOmeter, but I do have an old analog meter. With 5HZ, and 10% as in the example, I measure close to the expected 0.33V when not calling setPWM() in the loop (at that frequency, the pointer does shudder a little).

If I put the same setPWM() call into the loop, with no added delay, then the voltage as measure on the meter drops down to around 0.08V. The DSO shows there are so many of the 35 microsecond lows in the pulse, that this is not surprising. If, however, I add a 5ms delay into the loop (you said you could update up to 200 times per second), then the DSO show only four 35 microsecond lows per 20ms pulse, which is not enough to make a noticeable difference on the analog meter – the pointer is still hovering around 0.33V.

So, I don’t totally understand why you saw the problem originally, but changing to use setCaptureCompare() does make the problem go away.
Go to full post
stevestrong
Posts: 502
Joined: Fri Dec 27, 2019 4:53 pm
Answers: 8
Location: Munich, Germany
Contact:

Re: Changing PWM duty cycle on BluePill produces wrong output

Post by stevestrong »

viewtopic.php?f=2&t=301
Which core do you use?
Leviro
Posts: 11
Joined: Sat Aug 01, 2020 9:07 am

Re: Changing PWM duty cycle on BluePill produces wrong output

Post by Leviro »

This problem appears in the official core. But Roger Clark's core works fine and doesn't have this issue. However, the I2C is unstable in Roger Clark's core so I have to use the official core.
User avatar
fpiSTM
Posts: 1723
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: Changing PWM duty cycle on BluePill produces wrong output

Post by fpiSTM »

Hi @Leviro , could you share the code you used, please?
ABOSTM
Posts: 60
Joined: Wed Jan 08, 2020 8:40 am
Answers: 7

Re: Changing PWM duty cycle on BluePill produces wrong output

Post by ABOSTM »

Hi @Leviro,
Difficult to know what appends to PWM with a voltmeter, If you can observe signal with oscilloscope that would be better.
That said, setPWM() is made for simplicity to start a PWM, but it is not designed to update a running PWM because it performs a full initialisation of the timer, and I suspect you have transition step which disrupt your PWM.
setPWM() could be kept for the 1st time PWM is start.
But as far as PWM updates is concerned, I suggest you to use setCaptureCompare() and setOverflow() to respectively update dutycylce and period.
It will be more efficient (just update the necessary register witout a full initialisation) and I hope it will solve your issue
ozcar
Posts: 143
Joined: Wed Apr 29, 2020 9:07 pm
Answers: 5

Re: Changing PWM duty cycle on BluePill produces wrong output

Post by ozcar »

I tried it, repeatedly setting the frequency and duty cycle to the same value. If I happen to call setPWM() when the pulse is high, then it goes low for around 35 microseconds. It does not appear to disturb or reset the overall pulse though?? The time of this low glitch seems to be independent of the frequency or duty cycle, so if the frequency is low the glitches will not affect the average by very much, but for higher frequencies it could have a large effect.

I tried putting the call to setPWM() into the PeriodCallback function, and the low glitch is still there (but only once, around 6 microsecounds from the start of the pulse).
Leviro
Posts: 11
Joined: Sat Aug 01, 2020 9:07 am

Re: Changing PWM duty cycle on BluePill produces wrong output

Post by Leviro »

ABOSTM wrote: Tue Aug 04, 2020 9:14 am If you can observe signal with oscilloscope that would be better.
I don't have access to an oscilloscope right now thanks to COVID19. I will try using setCaptureCompare to change the duty cycle and see if it works.
Also, when I set my AVOmeter to measure "DC Voltage" and input a PWM signal, it seems to read the average correctly (or very approximately). That's what I meant by saying "measure using a voltmeter", sorry for the confusion.
Leviro
Posts: 11
Joined: Sat Aug 01, 2020 9:07 am

Re: Changing PWM duty cycle on BluePill produces wrong output

Post by Leviro »

fpiSTM wrote: Tue Aug 04, 2020 3:57 am Hi @Leviro , could you share the code you used, please?
I started with the example in the GitHub wiki, made the timer variable global, and used it to call setPWM in the loop:

Code: Select all

#define pin  PA3

TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(digitalPinToPinName(pin), PinMap_PWM);
uint32_t channel = STM_PIN_CHANNEL(pinmap_function(digitalPinToPinName(pin), PinMap_PWM));
HardwareTimer *MyTim = new HardwareTimer(Instance);

void setup()
{
  
}


void loop()
{
  MyTim->setPWM(channel, pin, 5, 100);
  // delay(50);
}
fredbox
Posts: 125
Joined: Thu Dec 19, 2019 3:05 am
Answers: 2

Re: Changing PWM duty cycle on BluePill produces wrong output

Post by fredbox »

Try this:

Move MyTim->setPWM() to setup.

Inside loop, call
MyTim->setCaptureCompare(channel, dutycycle, PERCENT_COMPARE_FORMAT)

I would keep dutycycle in the range of 1 to 99, avoiding 0 and 100.
ozcar
Posts: 143
Joined: Wed Apr 29, 2020 9:07 pm
Answers: 5

Re: Changing PWM duty cycle on BluePill produces wrong output

Post by ozcar »

Leviro wrote: Tue Aug 04, 2020 6:28 pm I started with the example in the GitHub wiki, made the timer variable global, and used it to call setPWM in the loop:
They say that great minds think alike – that is exactly what I tried.

My equipment does not run to an AVOmeter, but I do have an old analog meter. With 5HZ, and 10% as in the example, I measure close to the expected 0.33V when not calling setPWM() in the loop (at that frequency, the pointer does shudder a little).

If I put the same setPWM() call into the loop, with no added delay, then the voltage as measure on the meter drops down to around 0.08V. The DSO shows there are so many of the 35 microsecond lows in the pulse, that this is not surprising. If, however, I add a 5ms delay into the loop (you said you could update up to 200 times per second), then the DSO show only four 35 microsecond lows per 20ms pulse, which is not enough to make a noticeable difference on the analog meter – the pointer is still hovering around 0.33V.

So, I don’t totally understand why you saw the problem originally, but changing to use setCaptureCompare() does make the problem go away.
Post Reply

Return to “General discussion”