cancel
Showing results for 
Search instead for 
Did you mean: 

Input capture not consistent

Richard Cooke
Associate II
Posted on April 09, 2018 at 19:55

Hi Folks,

I'm struggling with getting a stable value for the input capture using the example from the latest STM32Cube_FW_L0_V1.10 download.  I'm using the STM32L031K6-Nucleo board and the Atollic TrueStudio 9.0. 

My input signal is a stable 100Hz signal,  2ms high and 8ms low.  Looking at the signal with my scope the signal is well behaved and stable.  The input is connected to PA1 which is TIM2 channel 2.

Here is my TIM2 setup:

/*♯♯-1- Configure the TIM peripheral ♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯*/

  /* Set TIMx instance */

  TimHandle.Instance = TIM2;

 

  /* Initialize TIMx peripheral as follow:

       + Period = 0xFFFF

       + Prescaler = 0

       + ClockDivision = 0

       + Counter direction = Up

  */

  TimHandle.Init.Period        = 0xFFFF;

  TimHandle.Init.Prescaler     = 3;

  TimHandle.Init.ClockDivision = 0;

  TimHandle.Init.CounterMode   = TIM_COUNTERMODE_UP;  

  if(HAL_TIM_IC_Init(&TimHandle) != HAL_OK)

  {

    /* Initialization Error */

    ErrorHandler();

  }

 

  /*♯♯-2- Configure the Input Capture channel ♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯*/

  /* Configure the Input Capture of channel 2 */

  sICConfig.ICPolarity  = TIM_ICPOLARITY_RISING;

  sICConfig.ICSelection = TIM_ICSELECTION_DIRECTTI;

  sICConfig.ICPrescaler = TIM_ICPSC_DIV1;

  sICConfig.ICFilter    = 0;   

  if(HAL_TIM_IC_ConfigChannel(&TimHandle, &sICConfig, TIM_CHANNEL_2) != HAL_OK)

  {

    /* Configuration Error */

    ErrorHandler();

  }

 

  /*♯♯-3- Start the Input Capture in interrupt mode ♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯*/

  if(HAL_TIM_IC_Start_IT(&TimHandle, TIM_CHANNEL_2) != HAL_OK)

  {

    /* Starting Error */

    ErrorHandler();

  }

My callback():

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)

{

  if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)

  {

    if(uhCaptureIndex == 0)

    {

      /* Get the 1st Input Capture value */

      uwIC2Value1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);

      uhCaptureIndex = 1;

    }

    else if(uhCaptureIndex == 1)

    {

      /* Get the 2nd Input Capture value */

      uwIC2Value2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);

      

      /* Capture computation */

      if (uwIC2Value2 > uwIC2Value1)

      {

        uwDiffCapture = (uwIC2Value2 - uwIC2Value1);

      }

      else if (uwIC2Value2 < uwIC2Value1)

      {

        uwDiffCapture = ((0xFFFF - uwIC2Value1) + uwIC2Value2) + 1;

      }

      else

      {

        uwDiffCapture = 0;

      }

      /* uwFrequency computation

      TIM2 counter clock = RCC_Clocks.HCLK_Frequency */      

      uwFrequency = HAL_RCC_GetHCLKFreq()/ (uwDiffCapture + 1);

      uhCaptureIndex = 0;

    }

  }

HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);   // to make sure the intr is being called

}

The uwlC2Value1, uwlC2Value2, uwDiffCapture and uwFrequency are all not stable.  They seem to be all over the place.  For example, the uwFrequency values: 1899, 1281, 6241, 1441, 932, 645, 4136, 58254, 8738, 696.

Any ideas what I might be doing wrong?

Thanks in advance,

Richard Cooke

#input-capture
17 REPLIES 17
Posted on April 09, 2018 at 20:44

The math is unnecessarily complicated, a simple delta with uint16_t variables should suffice.

The TIM clock is also being divided by 4, so clearly not HCLK

You'd want a prescaler so 10ms wouldn't exceed 65535 ticks, but not clear what speed system is clocking at. At 32 MHz I'd think you'd need to divide down by at least 5.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on April 09, 2018 at 20:52

Is your system clock below some 2.6MHz? If not, your timer overflows several times between the captures.

TIM2 is a 32-bit timer, btw.

JW

Richard Cooke
Associate II
Posted on April 09, 2018 at 21:47

I'm still stumped.  I've changed the prescaler to 127 and it still gives the same unstable values. DiffCapture values: 71, 1, 4, 100, 69, 1, 57, 51, 1.

Any other things I could try?

Thanks,

Richard

Posted on April 09, 2018 at 22:33

- check that the toggled pin toggles in the expected rhythm of input changes

- read out the relevant GPIO and timer registers' content and check/post

- tell us the set system frequency and the calculation for the expected differences values

JW

henry.dick
Senior II
Posted on April 09, 2018 at 23:13

You count 4 x 65k cycles over 10ms, or max of frequency of 26Mhz. If you are running your mcu faster than that, your code will fail.

You can increase the prevalent to see if the error goes away.

Richard Cooke
Associate II
Posted on April 09, 2018 at 23:34

I'm using the HAL and STM32CubeMX to setup my chip.  I've changed the APBxCLKs to be only 1Mhz and I still get the unstable count values.  This should allow me to measure a 100Hz signal shouldn't it? It should be only 1000 counts.

I've tried prescaler values of 3, 15, 63, and 127 all with the same crazy results.  Is there anything esle I can try.  This is driving me crazy.  It should be simple but I guess my computer didn't get that memo.

Richard Cooke
Associate II
Posted on April 10, 2018 at 00:17

You're correct Clive.  Don't know what I was thinking.  But with a prescaler of 3 it should be 10000/4 = 2500 counts right?

Posted on April 09, 2018 at 22:39

>>TIM2 is a 32-bit timer, btw.

Not on the L031

>>Is your system clock below some 2.6MHz?

1 / ((1 / 100) / 65536) = 6553600, so below 6.5 MHz for a timebase should be able to measure 10 ms intervals

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on April 09, 2018 at 22:55

 ,

 ,

uint16_t Prescaler = 8,

 ,

uint32_t uwFrequency = 0,

/* ♯ ♯ -1- Configure the TIM peripheral ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ */

 ,

 , /* Set TIMx instance */

 ,

 , TimHandle.Instance = TIM2,

 ,

 ,

 ,

 , /* Initialize TIMx peripheral as follow:

 ,

 , , , , , , + Period = 0xFFFF

 ,

 , , , , , , + Prescaler = 0

 ,

 , , , , , , + ClockDivision = 0

 ,

 , , , , , , + Counter direction = Up

 ,

 , */

 ,

 , TimHandle.Init.Period , , , , , , , = 0xFFFF,

 ,

 , TimHandle.Init.Prescaler , , , , = Prescaler - 1,

 ,

 , TimHandle.Init.ClockDivision = 0,

 ,

 , TimHandle.Init.CounterMode , , = TIM_COUNTERMODE_UP,  ,

 ,

 , if(HAL_TIM_IC_Init(&,TimHandle) != HAL_OK)

 ,

 , {

 ,

 , , , /* Initialization Error */

 ,

 , , , ErrorHandler(),

 ,

 , }

 ,

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)

 ,

{

 ,

 , static uint16_t uwIC2Value1, uwIC2Value2,

 ,

 , static int uhCaptureIndex = 0,

 ,

 , uint16_t uwDiffCapture,

 , if (htim->,Channel == HAL_TIM_ACTIVE_CHANNEL_2)

 ,

 , {

 ,

 , , , if (uhCaptureIndex == 0)

 ,

 , , , {

 ,

 , , , , , /* Get the 1st Input Capture value */

 ,

 , , , , , uwIC2Value1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2),

 ,

 , , , , , uhCaptureIndex = 1,

 ,

 , , , }

 ,

 , , , else if (uhCaptureIndex == 1)

 ,

 , , , {

 ,

 , , , , , /* Get the 2nd Input Capture value */

 ,

 , , , , , uwIC2Value2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2),

 ,

 , , , ,  ,

 ,

 , , , , , uwDiffCapture = (uwIC2Value2 - uwIC2Value1), // Delta

 , , , , , uwIC2Value1 = uwIC2Value2,

 , , , , , /* uwFrequency computation

 ,

 , , , , , TIM2 counter clock = RCC_Clocks.HCLK_Frequency */ , , , ,  ,

 , , , , , if (uwDiffCapture) // Perhaps ways to do with better precision

 ,

 , , , ,  , , ,  ,uwFrequency = (HAL_RCC_GetHCLKFreq() / (uint32_t)uwDiffCapture) / (uint32_t)Prescaler,

 ,

 , , , , , else

 ,

 , , , , , , , uwFrequency = 0,

 ,

 , , , }

 ,

 , }

 , HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin), , , // to make sure the intr is being called

 ,

}
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..