cancel
Showing results for 
Search instead for 
Did you mean: 

pwm duty cycle measurement for 0% duty cycle

saurabhkore
Associate

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)
  {

  }
}

 

 

1 ACCEPTED SOLUTION

Accepted Solutions

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

View solution in original post

3 REPLIES 3

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

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

@SofLit has edited it for you)

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
}
}
}