cancel
Showing results for 
Search instead for 
Did you mean: 

How to read PWM signal amplitude-wise and its timestamp?

NBin .1
Associate II

Hello,

I am trying to compare the PWM-signal with some sensor data, I want to investigate the correlation between these two signal. But I am having problem to read the amplitude of the PWM signal. Most of the example that I found explain how to get the duty cycle or frequency of the PWM signal. Which mean the input capture data are timestamp but I am also interested to know the what the amplitude of the PWM signal at this particular timestamp.

Amplitude=f(t1)

Amplitude=f(t2)

Because I want to build a real time graph comparing the pwm signal and the sensor data. Could anyone help and guide me to achieve this.

The following is my current code, the bottom of the code is the implemention for PWM input capture, but I want to extend it to include capturing Amplitude with its respective timestamp. I am using STM32L476RG MCU.

/**
  * @brief TIM3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM3_Init(void)
{
 
  /* USER CODE BEGIN TIM3_Init 0 */
 
  /* USER CODE END TIM3_Init 0 */
 
  TIM_SlaveConfigTypeDef sSlaveConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_IC_InitTypeDef sConfigIC = {0};
 
  /* USER CODE BEGIN TIM3_Init 1 */
 
  /* USER CODE END TIM3_Init 1 */
  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 0;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 65535;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_IC_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;
  sSlaveConfig.InputTrigger = TIM_TS_TI2FP2;
  sSlaveConfig.TriggerPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
  sSlaveConfig.TriggerFilter = 0;
  if (HAL_TIM_SlaveConfigSynchro(&htim3, &sSlaveConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;
  sConfigIC.ICSelection = TIM_ICSELECTION_INDIRECTTI;
  sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
  sConfigIC.ICFilter = 0;
  if (HAL_TIM_IC_ConfigChannel(&htim3, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
  sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
  if (HAL_TIM_IC_ConfigChannel(&htim3, &sConfigIC, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM3_Init 2 */
 
  /* USER CODE END TIM3_Init 2 */
 
}
 
 
/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
 
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
 
}
 
/* USER CODE BEGIN 4 */
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
	{
		/* Get the Input Capture value */
		uwIC2Value = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
 
		if (uwIC2Value != 0)
		{
			/* Duty cycle computation */
			uwDutyCycle = ((HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1)) * 100) / uwIC2Value;
 
			/* uwFrequency computation
	      TIM3 counter clock = (RCC_Clocks.HCLK_Frequency) */
			uwFrequency = (HAL_RCC_GetHCLKFreq())  / uwIC2Value;
		}
		else
		{
			uwDutyCycle = 0;
			uwFrequency = 0;
		}
	}
}
/* USER CODE END 4 */

9 REPLIES 9
NSR
Associate III

I may be wrong but I think the only way you would be able to do this is by setting the input pin to analog and buffering the original signal to another pin set up as input. Measuring the duty-cycle is typically a timing exercise with a digital signal; how long of the cycle is 'on' over the entire period. I wouldn't have thought that you'd be able to do both tasks on the same pin.

TDK
Guru

The timer input capture is a digital function. If you want to see signal amplitude, you'll need to capture analog data with the ADC.

If you feel a post has answered your question, please click "Accept as Solution".
selcukozb
Associate III

I understand that sensor signal is coming in PWM form, isn't it ? If so, you can calculate its effective amplitude as : Vcc*(dutyCycle%). But I can not see the second PWM that you want to compare ? Would it be an internally generated PWM by another TIM ? Then such a comparison shall be just comparing their duty cycles, no need to calculate their amplitudes. A bit confused.

BR

Thank you for your reply. I thought it is somehow possible to capture the amplitude by using timer input capture.

Thank for your suggestion. I will consider this idea.

It's possible to capture the duty cycle of a digital signal, as selcukozb notes below, but not amplitude.

If you feel a post has answered your question, please click "Accept as Solution".
NBin .1
Associate II

Nevermind, I think already figure out how to get around this after discsussing wih my colleague. Thank you everyone for the reply.

It is not exactly like that, but I kind of get some idea from your answer. Thank you.

​Hello @Community member​,

Please share the way that solved your problem, it may be helpful for other community users.

Then, please mark your post which answered the question as the Best, so that this thread is marked as solved.  

Best Regards,

Imen

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen