Skip to main content
Graduate II
December 3, 2024
Solved

pwm duty cycle measurement for 0% duty cycle

  • December 3, 2024
  • 7 replies
  • 3683 views

I am working on STM32L476RG mcu for duty cycle measurement of PWM signal. I share my code with you. it working fine but when i switch off pwm input coded stuck there and it shows previous reading .when i again given input then it measure the duty cycle correctly. so my question is that why code stuck at 0% duty cycle or when no PWM input provide to it. please check my code and share any solution .

 

 

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
 if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) // If the interrupt is triggered by channel 1
 {
 // Read the IC value
 ICValue = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
 if (ICValue != 0)
 {
 // calculate the Duty Cycle
 Duty = (HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2) *100)/ICValue;
 Frequency = 90000000/ICValue;
 }
 }

}

Int main(void)
{
 HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
 HAL_TIM_IC_Start(&htim2, TIM_CHANNEL_2);

 while(1)
 {

 }
}

 

 

    This topic has been closed for replies.
    Best answer by Andrew Neil

    Think of it like a "Watchdog" timer: each time you get a capture callback, you restart the "watchdog".

    Therefore it will only time-out after there have been no capture callbacks for the timeout time.

     

    7 replies

    Super User
    December 3, 2024

    If there are no edges in the input signal, there are no captures and thus no interrupts either. You have to work around it as an exception.

    One way to do it would be to have a periodic interrupt - either using the same interrupt or other - with a period longer than the longest expected PWM input period. In the periodic interrupt you set a (volatile) flag, and in the capture interrupt you clear it. If upon entering the periodic interrupt again you find out that the flag was not cleared, that means that there was no capture interrupt, and that would mean zero PWM duty cycle.

    JW

    Graduate II
    December 9, 2024

    sir i am trying to implement you're suggestion but i am unable to do it. can you edit your suggestion in code or can you share any data, document regarding to that.

    Super User
    December 3, 2024

    As @waclawek.jan says, 0% duty cycle isn't really PWM at all - there is no modulation - it's just steady-state OFF.

    Similarly for 100% - that's just steady-state ON.

     

    Please see the Posting Tips for how to properly post source code:

    https://community.st.com/t5/community-guidelines/how-to-write-your-question-to-maximize-your-chances-to-find-a/ta-p/575228

    @mƎALLEm has edited it for you)

    Graduate II
    December 4, 2024

    thankyou sir,

    According to you're suggestion i implement one more timer but it is still stuck at 0% input. please check my code once.

    volatile uint32_t ICValue = 0; // To store the input capture value
    volatile uint32_t Duty = 0; // To store duty cycle
    volatile uint32_t Frequency = 0; // To store frequency
    volatile uint8_t pwmCapturedFlag = 0; // Flag to check if PWM capture interrupt was triggered
    volatile uint8_t zeroDutyCycleFlag = 0; // Flag for zero duty cycle detection
    
    // Capture callback for PWM input signal (TIM2 Channel 1)
    void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
    {
    if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) // If interrupt triggered by channel 1
    {
    // Read the IC value (PWM period)
    ICValue = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
    
    if (ICValue != 0) // If the period is non-zero
    {
    // Calculate the duty cycle based on captured values
    Duty = (HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2) * 100) / ICValue;
    Frequency = 90000000 / ICValue; // Assuming clock speed of 90 MHz
    }
    
    // Clear the pwmCapturedFlag (PWM interrupt was triggered)
    pwmCapturedFlag = 0;
    }
    }
    
    // Periodic interrupt (TIM3 interrupt, e.g., every 1 ms)
    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    {
    if (htim->Instance == TIM3) // Check if the interrupt is from TIM3
    {
    // Check if pwmCapturedFlag is still set, indicating no PWM capture interrupt occurred
    if (pwmCapturedFlag == 1)
    {
    // No capture interrupt occurred, so the duty cycle is 0%
    zeroDutyCycleFlag = 1;
    Duty = 0; // Zero duty cycle detected
    }
    else
    {
    zeroDutyCycleFlag = 0; // Normal duty cycle
    }
    
    // Set the pwmCapturedFlag to indicate that the periodic interrupt occurred
    pwmCapturedFlag = 1; // The next period is waiting for capture
    }
    }
    
    int main(void)
    {
    // Initialize peripherals, HAL, and timers
    HAL_Init();
    
    // Start input capture interrupt for PWM signal (TIM2 Channel 1)
    HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
    
    // Start the regular timer for the second channel (TIM2 Channel 2)
    HAL_TIM_IC_Start(&htim2, TIM_CHANNEL_2);
    
    // Start a periodic timer (TIM3, for example, for 1ms interrupt)
    HAL_TIM_Base_Start_IT(&htim3); // TIM3 as periodic interrupt
    
    while(1)
    {
    // Here, you can process or use the Duty and Frequency values
    if (zeroDutyCycleFlag == 1)
    {
    // Zero duty cycle detected, you can take action here
    }
    else
    {
    // Non-zero duty cycle detected, use the duty and frequency values
    }
    }
    }

     

    Super User
    December 4, 2024

    @saurabhkore wrote:

    i implement one more timer but it is still stuck at 0% input. }


    So why have you marked this as solved?

    To unmark it, see: https://community.st.com/t5/community-guidelines/help-others-to-solve-their-issues/ta-p/575256#:~:text=If%20you%20accidentally%20chose%20the%20wrong%20post%20as%20solution%2C%20you%20can%20always%20revert%20this%20action%20by%20clicking%20%22Not%20the%20Solution%22

     

    Please see the Posting Tips for how to properly post source code:

    https://community.st.com/t5/community-guidelines/how-to-write-your-question-to-maximize-your-chances-to-find-a/ta-p/575228

     


    @saurabhkore wrote:

    please check my code once.


    Have you checked it ?

    What testing/debugging have you done to see what's happening?

    Super User
    December 4, 2024

    > it is still stuck at 0% input

    What does it mean, exactly? Where is it stuck?

    JW

    Graduate II
    December 4, 2024

    sir i simplify my statements.

    here we are try to measure duty cycle of pwm signal .existing code successfully measure the correct duty cycle but once pwm input is zero or duty cycle is zero ,in this case in live expression of cube ide it shows duty cycle value is previous one ,and it show that value only means stuck there. if i again given pwm input then again it measure proper value. i mention example with following sequence.

    pwm input duty cycle=49.88%

    measure duty cycle by stm=48.99%

    pwm input duty cycle=0%

    measure duty cycle by stm=48.99%

    pwm input duty cycle=55%

    measure duty cycle by stm=55%

    pwm input duty cycle=0%

    measure duty cycle by stm=55%

    In short i am fail to measure or fail to capture 0% duty cycle.

     

    Super User
    December 4, 2024

    So did you follow @waclawek.jan's suggestion - the first reply in this thread - to have a timer to detect the "no edges seen" case?

    Graduate II
    December 4, 2024

    yes sir.

    Graduate II
    December 4, 2024

    What I suggest is to add a flag as volatile unit8_t dutyCycleData = 0 ; make it 1 when you get a new calculation time, copy the duty cycle value to a volatile variable say back_dutycycle.  Read the backed duty cycle in the while(1) loop, clear the flag. only side effect is that you may get just the previous data, which many not be that bad since the duty cycle is measured in every cycle.

     

    Super User
    December 9, 2024

    I can't help you more than give the suggestion above.

    JW

    Super User
    December 10, 2024

    I don't use Cube/HAL, but in the above code - which to me looks to be AI-generated - I don't see how the Update interrupt to be enabled.

    Also, there would need to be some mechanism to reset the timeout-timer (which in this case is apparently the same TIM2), maybe using Reset mode of the slave-mode controller, as in the "PWM input" described in RM.

    JW

    Graduate II
    December 10, 2024

    I suggest op try to reset the pwm variable reset to zero in the while(1) loop which is protected by a flag