STMF303 phase shifted PWM - Page 1
Forum section: electronics / projects

author: uer166
author_rank: Super Contributor
timestamp: May 30, 2020, 03:18:45 am
content: I'm making a 2-phase boost with peak current mode control with an STM32F303. I'm having a hard time generating the 180-degree phase shifted, cycle-by-cycle current limited PWM for Timer1 channel1 and Timer1 channel3. I put them on the same advanced timer thinking I could use the Asymmetric PWM mode, or perhaps the Combined PWM mode.I'm having a hard time finding a mode that does what I want.. I also tried synchronizing Timer 4 with Timer 1, thinking I can just use separate timers and sync their counters 180 degrees apart? Still nada, a bit stuck.. Knew I should have just used a STM32G4 from the beginning, but this seemed like an easy task.Another problem is I can't figure out how to clear the 2 different PWM channels separately, Timer1 seems to have only one clear source for the whole thing.

author: Siwastaja
author_rank: Super Contributor
timestamp: May 30, 2020, 08:52:47 am
content: Shouldbe trivial, maybe you are missing something?Some copy-pasta which works for me, giving 180 deg phase shift, on STM32F7 advanced control timer. I think these timers are pretty much the same between the products?Code:// TIM8:// Create a 50% duty square wave on CH2&CH2N, and another one 180deg apart on CH3&CH3NTIM8->CR1 = 0UL<<7 /*Auto-reload ARR register is NOT buffered*/ |0b00UL<<5 /*Edge-aligned mode*/ |1UL<<4 /*downcounter*/;// PHA = CH2, PHB = CH3 Positive channel = Hi-side FET, Negative channel = Lo-side FET// PWM mode 1 "0110": active when CNT<CCR// PWM mode 2 "0111": inactive when CNT<CCR// WARNING: Highest mode bit is elsewhere in the registerTIM8->CCMR1 = 0UL<<11 /*CH2 Pre-load OFF*/ |0b110UL<<12 /*CH2 PWM mode 1*/;TIM8->CCMR2 = 0UL<<3 /*CH3 Pre-load OFF*/ |0b111UL<<4 /*CH3 PWM mode 2*/;TIM8->CCER = 1UL<<4 /*CH2 enable*/ |1UL<<6 /*CH2N enable*/ |1UL<<8 /*CH3 enable*/ |1UL<<10 /*CH3N enable*/;TIM8->BDTR = 1UL<<15 /*Main Output Enable*/ |1UL<<11 /*OSSR, In off-state, the idle states are driven*/ |1UL<<10 /*OSSI, same thing*/ |10UL /*Deadtime, 8-bit value must begin with 0, max 127*/;TIM8->ARR = 10000;TIM8->CCR2 = 5000;TIM8->CCR3 = 5000;TIM8->BDTR |= 1UL<<15; // Main Output EnableTIM8->CNT = 0;TIM8->EGR = 1UL; // Generate update eventTIM8->CR1 |= 1UL; // Enable counter

author: uer166
author_rank: Super Contributor
timestamp: May 30, 2020, 08:07:59 pm
content: I think it's trivial for 50% duty cycle, in your case you're making one PWM mode 1 and the other mode 2, not quite sure if that works for, say 20% duty PWM or 80% duty PWM while maintaining 180-degree phase shift, I will certainly try. I think I finally found a way to synchronize different timer counters, turns out the trigger connections between timers are hard-wired and need to look at the interconnect matrix to figure it out..

author: fourtytwo42
author_rank: Super Contributor
timestamp: May 31, 2020, 09:04:57 am
content: I also failed with this series of chips, it seems the apparently Arm IP doesn't have the concept of push-pull operation.If your sold on Arm either find some rare part somewhere that doesn't use the same IP block (I failed on that too), use a PLD to implement a proper PWM externally or give up on Arm and use Microchip PIC24EP/DSPIC33 motor control series (MC) like I did, warts and all but at least Microchip understand the concepts required.

author: capt bullshot
author_rank: Super Contributor
timestamp: May 31, 2020, 09:34:33 am
content: Quote from: uer166 on May 30, 2020, 03:18:45 amOne tip: If you want to do phase shifted PWM on STM32 timers, you must use different timers for the different phases. So e.g. TIM1 for the first phase, TIM2 for the second (or TIM8 if you need the dead time generation capabilities). The timer counters can be preloaded to achieve the phase shift, then the timers can be started synchronously - read the manuals for details. You can't generate multi-phase PWM using one timer only. Might be different with the high resolution timers from other derivatives of that family, but I'm not familiar enough with those to give you a simple answer.

author: mbless
author_rank: Regular Contributor
timestamp: May 31, 2020, 04:26:42 pm
content: I did this about 2 weeks ago but with variable phase shift. The gist of it:Set timer A trigger output event to Compare Pulse 1Set timer A channel 1 to 50% duty cycle. The falling edge of this channel is the trigger for timer B to create the phase shift.Set timer A channel 2, 3 or 4 as your output 1Set timer B slave mode to triggerSet timer B trigger source to timer A trigger output. You'll have to look this up in the reference manual.Set timer B channel x as your output 2Enable timer B to arm phase-shifted outputEnable timer A to start outputFor my use case with variable phase-shift, I change timer A channel 1 duty cycle to change the phase shift of output 2. You'll also likely want to make timer B an advanced timer so you can set the TIMx.CR2.CCPC and CCUS bits. The reason being that once you enable timer B, it's output will go high (for high polarity) before it receives the trigger signal. Setting the CCPC and CCUS bits allows the capture compare enable (CCxE) to be preloaded, so it will enable the output when it receives the trigger.I attached scope images of this setup. Magenta is my timer A channel 1, cyan is timer A channel 2, and blue is timer B channel 1. In the "500ms" image the blue trace is initially high on the very first output cycle when it shouldn't go high until the falling edge of the magenta trace. The subsequent cycles shows it doing the correct thing. In the "50pc" image, the blue trace is correct from the beginning because I set the CCPC and CCUS bits.

author: uer166
author_rank: Super Contributor
timestamp: June 01, 2020, 04:29:37 am
content: This was certainly not trivial to figure out. Eventually I put the two PWMs in different timebases, it is true that you couldn't achieve proper phase shift with only one timer. For TIM1 I set trigger as OC2REF, and setup the channel 2 PWM to be 50% duty cycle mode 2, such that it generates a rising edge at 50% of the timer1 count (this is the 180 deg phase shift), and allows it to be easily adjustable.TIM2 was set-up with ITR0 (which maps to TIM1 trigger output), and is set up in reset mode. So that the TIM2 counter is reset at 50% count of TIM1. I'm still not clear why TIM1 has 2 triggers: TRGO and TRGO2, the reference manual is not clear at all how they are mapped.In any case the pics attached show the result that I was after with a low and high duty cycles.

author: fourtytwo42
author_rank: Super Contributor
timestamp: June 04, 2020, 09:17:20 am
content: Quote from: uer166 on June 01, 2020, 04:29:37 amAre you able to change the duty cycle with a single instruction ?As far as I could see when I looked at this long ago that was the issue with using multiple timers.

author: uer166
author_rank: Super Contributor
timestamp: June 05, 2020, 03:04:55 am
content: I'm not changing the duty cycle at all, I'm changing the DAC comparator reference value that runs the cycle-by-cycle current limit for peak current control. I could change the maximum duty cycle in 2 instructions though, not sure why you'd want it to be in 1, the HAL functions take many 10s of instructions anyway..

author: Siwastaja
author_rank: Super Contributor
timestamp: June 05, 2020, 05:49:11 am
content: Quote from: fourtytwo42 on June 04, 2020, 09:17:20 amChange the duty cycle in the timer ISR so that the change happens during a time window guaranteeing no glitch.You usually adjust duty cycle in a timer interrupt, synchronously per cycle, anyway, not asynchronously somewhere else.

author: uer166
author_rank: Super Contributor
timestamp: June 05, 2020, 05:53:41 am
content: Quote from: Siwastaja on June 05, 2020, 05:49:11 amThe timers have shadow registers that synchronize the compare value write to the timer period. No glitches should happen even with async writes. I want to have cooperative/hybrid scheduler architecture with no interrupts anyway..

author: Siwastaja
author_rank: Super Contributor
timestamp: June 05, 2020, 06:08:09 am
content: Quote from: uer166 on June 05, 2020, 05:53:41 amYes, but I think fourtytwo42's point was that these shadow registers won't help with two separate timers, even if they have some synchronization mechanisms. Even if the synchronization makes the timer counters run in sync, the shadow register to working register transfer would happen separately at each timers overflow, possibly causing one of the two timers changing its duty cycle one cycle later, sometimes.I think this issue is easy to sidestep - if you have a phase offset, you can just write the duty registers in the correct order in a small interrupt-disabled block, even asynchronously - but you can't just ignore it, you need to think about it.

author: uer166
author_rank: Super Contributor
timestamp: June 05, 2020, 06:39:13 am
content: I guess I don't understand what the problem is, if I update one PWM after the other, so what? Each individual PWM won't glitch thanks to the shadow register copy, so what's the issue? Each timer has its' own clear inputs an timebases, they basically are independent in every way except a phase relationship that happens to minimize output capacitor ripple.

author: Siwastaja
author_rank: Super Contributor
timestamp: June 05, 2020, 08:29:10 am
content: Yes, I agree that in a standard two-phase converter as you explain it, it wouldn't matter if the phases change their duty cycles with unpredictable order and latency.fourtytwo42 must be thinking some very specific case. I don't see what he has in mind, either, but I understand there might be something to it.

author: fourtytwo42
author_rank: Super Contributor
timestamp: June 05, 2020, 09:57:38 am
content: Hi everybody thank you for your clarification, I don't want to hijack the thread but I was concerned about transformer saturation in a large hard switched high frequency bridge converter where the duty cycle is part of the regulation loop and hence updated frequently. Unfortunately the same as sub-harmonic oscillation the inability to change the duty cycle of both halves of the bridge simultaneously could have bad results, I was not convinced sufficiently to risk it and stuck with the PIC solution instead (where a divider flip-flop is part of the pwm). The synchronous with the pwm update is also a feature of the PIC but here it applies to both halves of the waveform simultaneously as the counter source is the same.I would have preferred to use the STM32 for lots of other reasons. I may be old fashioned but I would never consider using anything like HAL where as the poster mentioned an untold number of instructions are taken to do something poorly documented IMOP.Once again I apologies for deviating the thread as I realize my concern would probably not affect the OP.