2024-08-12 04:01 AM - edited 2024-08-12 07:15 AM
I have a high-resolution timer configured at some frequency. This master timer has three other timers associated to it, where each timer also runs at the same frequency. But the trigger events of these timers are compare values from the master timer, that generate update event to trigger the reset of these timers.
This works and all and I am using LL APIs but I need now at some point to change the period of these timers to a lower frequency. I know I can change the period using LL APIs while running. But can I do so without causing any glitches?
I have 6 outputs (2 for each timer) set to 50% duty cycle.
My approach would be to use the functions as follows, but instead of doing a jump in the period, I do in a ramped fashion. Which means each run of the mainLoop I changed the period and then apply the code shown for all timers.
Then after 10 mainLoop runs, the change of frequency is completed
LL_HRTIM_TIM_SetPeriod(HRTIM1, LL_HRTIM_TIMER_MASTER, NEW_PERIOD);
LL_HRTIM_TIM_SetPeriod(HRTIM1, LL_HRTIM_TIMER_A, NEW_PERIOD);
uint32_t newCompareValue = __calculateCompareValue(NEW_PERIOD);
LL_HRTIM_TIM_SetCompare1(HRTIM1, LL_HRTIM_TIMER_MASTER, newCompareValue); // Compare value 1 used for timer A
Solved! Go to Solution.
2024-08-16 03:02 AM
Hello @BSale.1 ,
It can be tricky to change the period of high-resolution timers without causing glitches, especially when you have multiple timers synchronised and generating outputs. Your approach of ramping the period change gradually over multiple iterations of the main loop is a great way to minimise glitches, by breaking the period change into smaller steps, you reduce the risk of glitches. Also, you need to ensure that the updates to the period and compare values are synchronized. For the Duty Cycle Calculation: Adjust the compare values based on the new period to maintain the desired duty cycle.
Example of
#define NUM_STEPS 10
void updateTimerPeriods(uint32_t currentPeriod, uint32_t newPeriod) {
uint32_t stepPeriod;
uint32_t stepCompareValue;
uint32_t periodIncrement = (newPeriod - currentPeriod) / NUM_STEPS;
for (int i = 0; i < NUM_STEPS; i++) {
stepPeriod = currentPeriod + (i * periodIncrement);
stepCompareValue = __calculateCompareValue(stepPeriod);
// Update the master timer period
LL_HRTIM_TIM_SetPeriod(HRTIM1, LL_HRTIM_TIMER_MASTER, stepPeriod);
// Update the associated timers' periods
LL_HRTIM_TIM_SetPeriod(HRTIM1, LL_HRTIM_TIMER_A, stepPeriod);
LL_HRTIM_TIM_SetPeriod(HRTIM1, LL_HRTIM_TIMER_B, stepPeriod);
LL_HRTIM_TIM_SetPeriod(HRTIM1, LL_HRTIM_TIMER_C, stepPeriod);
// Update the compare values
LL_HRTIM_TIM_SetCompare1(HRTIM1, LL_HRTIM_TIMER_MASTER, stepCompareValue);
LL_HRTIM_TIM_SetCompare1(HRTIM1, LL_HRTIM_TIMER_A, stepCompareValue);
LL_HRTIM_TIM_SetCompare1(HRTIM1, LL_HRTIM_TIMER_B, stepCompareValue);
LL_HRTIM_TIM_SetCompare1(HRTIM1, LL_HRTIM_TIMER_C, stepCompareValue);
// Wait for the next main loop iteration
// This could be a delay or a synchronization point in your main loop
waitForNextIteration();
}
}
uint32_t __calculateCompareValue(uint32_t period) {
// Calculate the compare value based on the new period
return period / 2; // Example for 50% duty cycle
}
void waitForNextIteration() {
// Implement a delay or synchronization mechanism
// This could be a simple delay or a more complex event-driven wait
HAL_Delay(10); // Example delay of 10ms
}
2024-08-14 02:53 AM
Hello @BSale.1 ,
Could you pls specify which STM32 product you are currently working with?
Regards,
2024-08-16 03:02 AM
Hello @BSale.1 ,
It can be tricky to change the period of high-resolution timers without causing glitches, especially when you have multiple timers synchronised and generating outputs. Your approach of ramping the period change gradually over multiple iterations of the main loop is a great way to minimise glitches, by breaking the period change into smaller steps, you reduce the risk of glitches. Also, you need to ensure that the updates to the period and compare values are synchronized. For the Duty Cycle Calculation: Adjust the compare values based on the new period to maintain the desired duty cycle.
Example of
#define NUM_STEPS 10
void updateTimerPeriods(uint32_t currentPeriod, uint32_t newPeriod) {
uint32_t stepPeriod;
uint32_t stepCompareValue;
uint32_t periodIncrement = (newPeriod - currentPeriod) / NUM_STEPS;
for (int i = 0; i < NUM_STEPS; i++) {
stepPeriod = currentPeriod + (i * periodIncrement);
stepCompareValue = __calculateCompareValue(stepPeriod);
// Update the master timer period
LL_HRTIM_TIM_SetPeriod(HRTIM1, LL_HRTIM_TIMER_MASTER, stepPeriod);
// Update the associated timers' periods
LL_HRTIM_TIM_SetPeriod(HRTIM1, LL_HRTIM_TIMER_A, stepPeriod);
LL_HRTIM_TIM_SetPeriod(HRTIM1, LL_HRTIM_TIMER_B, stepPeriod);
LL_HRTIM_TIM_SetPeriod(HRTIM1, LL_HRTIM_TIMER_C, stepPeriod);
// Update the compare values
LL_HRTIM_TIM_SetCompare1(HRTIM1, LL_HRTIM_TIMER_MASTER, stepCompareValue);
LL_HRTIM_TIM_SetCompare1(HRTIM1, LL_HRTIM_TIMER_A, stepCompareValue);
LL_HRTIM_TIM_SetCompare1(HRTIM1, LL_HRTIM_TIMER_B, stepCompareValue);
LL_HRTIM_TIM_SetCompare1(HRTIM1, LL_HRTIM_TIMER_C, stepCompareValue);
// Wait for the next main loop iteration
// This could be a delay or a synchronization point in your main loop
waitForNextIteration();
}
}
uint32_t __calculateCompareValue(uint32_t period) {
// Calculate the compare value based on the new period
return period / 2; // Example for 50% duty cycle
}
void waitForNextIteration() {
// Implement a delay or synchronization mechanism
// This could be a simple delay or a more complex event-driven wait
HAL_Delay(10); // Example delay of 10ms
}
2024-08-16 03:03 AM
stm32g474
2024-08-16 03:10 AM - edited 2024-08-16 03:12 AM
Thank you very much for your reply.
I tested the idea against the glitches, a glitch cannot be detected only a constant slow increase in the period until the desired new period is reached.
This was only a dry test, the next step would be testing this with power.
I am facing now a different problem, since my system consists of a lot timers (actually 6 + master) and a lot of compare values, the update function takes a lot to execute. This is messing with my frequency of the whole system and I can see that my main control frequency is affected due to the fact that HRTIMER runs at a 5 times higher frequency than the control frequency. I can work around the implementation and try to optimize it. But do you see any other idea this can be optimized?
2024-08-16 04:05 AM
It's really important to make sure that your high-resolution timers are working as well as they can be, so you don't end up slowing down the whole system. Here are some ways to make updates more efficient: