cancel
Showing results for 
Search instead for 
Did you mean: 

Changing the period values of all timers in high-resolution timer

BSale.1
Associate II

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


 

1 ACCEPTED SOLUTION

Accepted Solutions
nouirakh
ST Employee

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
}

 

View solution in original post

5 REPLIES 5
SHs
ST Employee

Hello @BSale.1 ,

Could you pls specify which STM32 product you are currently working with? 

Regards,

 

Please close this topic by clicking on “Accept as solution" button if it fully answered your question.
nouirakh
ST Employee

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
}

 

stm32g474

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?

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:

  • Use interrupts and DMA to offload the update process from the CPU. This can help the update function run faster and the main control loop more efficiently.
  • Prioritize Critical Updates, If some timers or compare values are more important than others, make sure you update them first. This can help keep the most critical parts of your system running smoothly.
  • Optimize Calculation Functions, ensure that the functions used to calculate new periods and compare values are optimized for performance. Avoid unnecessary calculations and use efficient algorithms.