2018-03-31 01:59 PM
Hi guys!
I use HAL drivers and I would like to measure the duty cycle of 10 x 25 kHz (asynchronus) PWM signal, but I'm not sure which peripheral should I use:
- if I use timer with capture mode then I get 2 x 10 x 25000 interrupts a second (might be too much?)
- I could use RC elements to convert the signals to analog and use the ADC (converting from digital to analog then back to digital again, sounds like unnecessary tasks to me)
What would you do in my case?
Thank you in advance!
Greetings,
P�ter
#capture #pwm #signal #processing #timerSolved! Go to Solution.
2018-04-01 07:27 AM
I think the F051 has 4 capture channels on TIM1, TIM2 and TIM3 as well, which is already more than I need
While the timers' input circuit can be set so that capture occurs on both leading and trailing edge, if two edges happen close to each other and you won't succeed to read out the first from the capture register before the second arrives, you'll miss it. Note, that the interrupt latencies are relatively high, and significantly higher if multiple interrupts are active at the same times. In practice it means, you won't be able to measure PWM with small and large duty cycles.
This is why it's better to capture the two edges separately in two channels - the STM32 timers have a provision to connect one pin to two adjacent timer channels, so you don't even need to waste pins on that.
Note, that the two limit cases - 0% and 100% duty (more precisely, not only the DC case but also extremely short pulses with edges spaced closer to each other than is the period of timer input clock) won't fire an interrupt at all, and have to be handled as an exception in some other way.
How can I determine the duty cycle if I catch only one edge of the signal?
This works if you use the two-channel scheme outlined above. The other edge's time you read out simply from the other channel's capture register. Even if its readout is missed and you read out the next other-edge's occurence's time, it's easy to reveal by simple time comparison and you'd then simply wait until the next interrupt to determine the exact period relevant to that transition.
In the TIM chapter in RM you'll find also described a scheme with resetting the counter upon one edge, but I personally would be hesitant to use that (and it is unusable if both 2 couples of channels are to be used).
it might be enough to catch every 10th for example, that means that I could simply use an external multiplexer, right?
Yes, but if you multiplex all 10 channels into one, don't count on that you'll be able to determine the period/duty immediately after switching the multiplexer, i.e. it would be significantly more than every 10th period (I'd count more like 50th). Of course this approach can be tweaked with using several timers and lower multiplex ratio.
JW
2018-04-01 03:27 AM
You need to interrupt only on one edge, so that's 10x25k interrupts. At 48MHz system clock it's 192 clocks per ISR; depending on what sort of processing do you want to do, this may be viable running them from SRAM to avoid FLASH latency; you may also want to avoid the overhead of Cube/HAL 'drivers'.
Also, is it necessary to measure duty cycle in *every* period of the incoming signal? Can't you measure only one or a few of them at a time, and then switch to the next one, etc.?
JW
2018-04-01 03:30 AM
Looking at the DS of 'F051, I couldn't help noticing that there are only 3 timers with 4 channels (TIM1, TIM2, TIM3) which could handle 2 PWM inputs each; and one with 2-channel TIM (TIM15); so that's only 7 PWM channels that could be handled with one 'F051.
You may want to reconsider your choice of mcu.
JW
2018-04-01 05:53 AM
If you really only need to measure the duty cycle of PWM independently and now exactly at the same time, you may not need to worry too much (if you'd like to measure the skew between a reference edge, it would require more HW resource). My quick tought to this challenge would be to use a timer which has many alternate function pins on the chosen STM32. Select a pin and use the timer in freerun mode to capture with 2 interrupts the rise and fall timestamp (interrupt will stop itself and set a flag to tell main loop one capture is completed). Rince a repeat.
For more HW assisted, use 2 channels, one for rise and one for fall. Doesn't require the interrupt to check pin level when input capture occurs (sometime with delay if other peripheral interrupt prevail).
Going with RC filter is used when very few channels are present and not eough timers are available (beside alternates). It was used in VGA cables to check H Sync and V Sync polarity, in fact as digital input. Works with very high frequencies too....
2018-04-01 05:53 AM
How can I determine the duty cycle if I catch only one edge of the signal?
Actually it's not necessary to catch every period, it might be enough to catch every 10th for example, that means that I could simply use an external multiplexer, right? This is a really good idea!
I think the F051 has 4 capture channels on TIM1, TIM2 and TIM3 as well, which is already more than I need
2018-04-01 07:27 AM
I think the F051 has 4 capture channels on TIM1, TIM2 and TIM3 as well, which is already more than I need
While the timers' input circuit can be set so that capture occurs on both leading and trailing edge, if two edges happen close to each other and you won't succeed to read out the first from the capture register before the second arrives, you'll miss it. Note, that the interrupt latencies are relatively high, and significantly higher if multiple interrupts are active at the same times. In practice it means, you won't be able to measure PWM with small and large duty cycles.
This is why it's better to capture the two edges separately in two channels - the STM32 timers have a provision to connect one pin to two adjacent timer channels, so you don't even need to waste pins on that.
Note, that the two limit cases - 0% and 100% duty (more precisely, not only the DC case but also extremely short pulses with edges spaced closer to each other than is the period of timer input clock) won't fire an interrupt at all, and have to be handled as an exception in some other way.
How can I determine the duty cycle if I catch only one edge of the signal?
This works if you use the two-channel scheme outlined above. The other edge's time you read out simply from the other channel's capture register. Even if its readout is missed and you read out the next other-edge's occurence's time, it's easy to reveal by simple time comparison and you'd then simply wait until the next interrupt to determine the exact period relevant to that transition.
In the TIM chapter in RM you'll find also described a scheme with resetting the counter upon one edge, but I personally would be hesitant to use that (and it is unusable if both 2 couples of channels are to be used).
it might be enough to catch every 10th for example, that means that I could simply use an external multiplexer, right?
Yes, but if you multiplex all 10 channels into one, don't count on that you'll be able to determine the period/duty immediately after switching the multiplexer, i.e. it would be significantly more than every 10th period (I'd count more like 50th). Of course this approach can be tweaked with using several timers and lower multiplex ratio.
JW
2018-04-01 08:04 AM
use a timer which has many alternate function pins on the chosen STM32
I envy you came up with this idea!
JW
2018-04-01 09:37 AM
assuming that you don't need to measure all the channels at all times and at the same time.
I would route them all into one timer input capture pin and do your work there. each channel is isolated by a resistor + diode into that IC pin, shorted by a GPIO pin. turn that input pin as input while all other pins as output low, you measure the associated channel.
essentially it is a digital switch.
2018-04-01 11:28 AM
Thank you guys!
I've learned a lot today thanks to you!
Cheers!
Péter
2018-04-01 12:00 PM
Very smart idea! Thanks!