cancel
Showing results for 
Search instead for 
Did you mean: 

Timer, motor _speed

bendkhilarwa
Associate III
Posted on April 09, 2016 at 16:45

Hello,

I wanna calculate the motor speed using timer of STM32F4. I wanna know the time spended in one revolution.  So , who would  explain for me how can I do that . thanks a lot.
11 REPLIES 11
Posted on April 09, 2016 at 18:12

The timer counts at a fixed rate, you use the counter to time-stamp the two time separated events A and B, subtracting them (B - A) will give you the clock ticks of the interval. So if the timer counts at 1 MHz, and the motor rotates at 50 times a second (3000 rpm), then the counter will indicate 20000 ticks have passed. ie 1,000,000 / 50

There have been several threads covering the measurement of frequency, review them.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
bendkhilarwa
Associate III
Posted on April 09, 2016 at 21:35

thanks a lot for your response, But this is exactly my problem. I have no idea how can I measure the time separing the two event A( the begining of revoultion) and B (the end of revolution). Can you explain me more how to use the timer to measure this time? 

mark239955_stm1
Associate II
Posted on April 10, 2016 at 02:24

The most accurate and efficient way to measure the time between two pulses using a microcontroller is a technique called ''Input Capture'', or ''IC''.  Read the sections of the STM32F407's reference manual that describe its Timer peripherals, most of which are capable of IC.

Posted on April 10, 2016 at 02:34

The mechanics here are not inherently complicated,

// STM32F4-Discovery TIM2 32-bit Input Capture (PA.01 TIM2_CH2) - sourcer32@gmail.com

#include ''stm32f4_discovery.h''

/**************************************************************************/

void RCC_Configuration(void)

{

  /* GPIOA  clock enable */

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

  /* TIM2 clock enable */

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

}

/**************************************************************************/

void NVIC_Configuration(void)

{

  NVIC_InitTypeDef NVIC_InitStructure;

  /* Enable the TIM2 gloabal Interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

}

/**************************************************************************/

void GPIO_Configuration(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

  /* GPIOA Configuration: TIM2 CH2 (PA1) */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Connect TIM2 pins to AF */

  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_TIM2);

}

/**************************************************************************/

void TIM2_Configuration(void)

{

  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

  TIM_ICInitTypeDef TIM_ICInitStructure;

  /* Time base configuration */

  TIM_TimeBaseStructure.TIM_Period = 0xFFFFFFFF; // 32-bit maximal

  TIM_TimeBaseStructure.TIM_Prescaler = ((SystemCoreClock / 2) / 1000000) - 1; // 1 MHz

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseStructure.TIM_ClockDivision = 0;

  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

  /* Input capture configuration */

  TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;

  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;

  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;

  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;

  TIM_ICInitStructure.TIM_ICFilter = 0x0;

  TIM_ICInit(TIM2, &TIM_ICInitStructure);

  /* TIM2 enable counter */

  TIM_Cmd(TIM2, ENABLE);

  /* TIM Interrupts enable */

  TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);

}

/**************************************************************************/

void TIM2_IRQHandler(void)

{

  if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)

  {

    static uint32_t A, B;

    uint32_t DeltaTicks;

    TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);

    B = TIM2->CCR2;

    DeltaTicks = B - A; // Ticks of 1 MHz clock, ie 1us per tick

    // Do something with the measurement of time

    A = B;

  }

}

/**************************************************************************/

int main(void)

{

  RCC_Configuration();

  NVIC_Configuration();

  GPIO_Configuration();

  TIM2_Configuration();

  while(1); // Do not exit

}

/**************************************************************************/

#ifdef  USE_FULL_ASSERT

/**

  * @brief  Reports the name of the source file and the source line number

  *         where the assert_param error has occurred.

  * @param  file: pointer to the source file name

  * @param  line: assert_param error line source number

  * @retval None

  */

void assert_failed(uint8_t* file, uint32_t line)

{

  /* User can add his own implementation to report the file name and line number,

     ex: printf(''Wrong parameters value: file %s on line %d\r\n'', file, line) */

  while (1)

  {}

}

#endif

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
bendkhilarwa
Associate III
Posted on April 10, 2016 at 20:14

thanks a lot clive1, but I need more help please.

So this code is used to trriger the timer then each input signal received on PA1,

the counter will be start from 0 on each signal reception? 

Posted on April 10, 2016 at 21:49

No in this case the timer keeps ticking, which is why you keep a running total from interrupt to interrupt, and look at the *difference*

Now if you used PWM Input mode, then the timer would get reset, and you'd use two of the channels to hold the period and duty. These modes are covered in the Reference Manual

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
bendkhilarwa
Associate III
Posted on April 11, 2016 at 17:30

So, I have used this code , I want  that the interruption will be excuted when PA1 goes from 0 to VDD. how can I do that please

/**************************************************************************/

void RCC_Configuration(void)

{

  /* GPIOA  clock enable */

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

  /* TIM2 clock enable */

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

}

/**************************************************************************/

void NVIC_Configuration(void)

{

  NVIC_InitTypeDef NVIC_InitStructure;

  /* Enable the TIM2 gloabal Interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

}

/**************************************************************************/

void GPIO_Configuration(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

  /* GPIOA Configuration: TIM2 CH2 (PA1) */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Connect TIM2 pins to AF */

  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_TIM2);

}

/**************************************************************************/

void TIM2_Configuration(void)

{

  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

  TIM_ICInitTypeDef TIM_ICInitStructure;

  /* Time base configuration */

  TIM_TimeBaseStructure.TIM_Period = 0xFFFFFFFF; // 32-bit maximal

  TIM_TimeBaseStructure.TIM_Prescaler = ((SystemCoreClock / 2) / 1000000) - 1;;////Horloge Timer = sysclock / (TIM_Prescaler + 1) = 2M

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseStructure.TIM_ClockDivision = 0;

  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

    /* Input capture configuration */

  TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;

  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;

  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;

  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;

  TIM_ICInitStructure.TIM_ICFilter = 0x0;

  TIM_ICInit(TIM2, &TIM_ICInitStructure);

  /* TIM2 enable counter */

  TIM_Cmd(TIM2, ENABLE);

  /* TIM Interrupts enable */

  TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);

  TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

}

/**************************************************************************/

void TIM2_IRQHandler(void)

{

 if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)

  {

   if(CaptureNumber == 0)

{

    counter = TIM_GetCapture2(TIM2); //The first capture

    CaptureNumber = 1;

}

else if(CaptureNumber == 1)  //Treatment of second capture

{

   if(TIM_GetFlagStatus(TIM2,TIM_FLAG_Update) != SET)//Treatment of two capture no overflow occurs

   {

     Time = TIM_GetCapture2(TIM2);

      Time2 = TIM_GetCapture2(TIM2);

      Time = Time - counter;

    

     }

    else

    {

        nmbr = nmbr+ 1;

       

       TIM_ClearFlag(TIM2,TIM_FLAG_Update); //The update event

       Time3=TIM_GetCapture2(TIM2);

     

       Time = (0xFFFFFFFF - counter) + TIM_GetCapture2(TIM2)+1; //If the calculation mode update events

    

    }

   

CaptureNumber = 0;

    }

}

}

/**************************************************************************/

int main(void)

{

  RCC_Configuration();

  NVIC_Configuration();

  GPIO_Configuration();

  TIM2_Configuration();

  

  while(1); // Do not exit

}

/**************************************************************************/

#ifdef  USE_FULL_ASSERT

/**

  * @brief  Reports the name of the source file and the source line number

  *         where the assert_param error has occurred.

  * @param  file: pointer to the source file name

  * @param  line: assert_param error line source number

  * @retval None

  */

void assert_failed(uint8_t* file, uint32_t line)

{

  /* User can add his own implementation to report the file name and line number,

     ex: printf(''Wrong parameters value: file %s on line %d\r\n'', file, line) */

  while (1)

  {}

}

#endif 

bendkhilarwa
Associate III
Posted on April 12, 2016 at 17:54

hello, please I really need help,

when I'm using this code, the variable b was incremented several time when I have just done one interrption  ( I put PA1 on 5v ). I don't understand what is it the problem. I think that TIM2_IRQHandler(void) must be excuted just one time for each interruption. please who can help me to resolve this problem 

#include ''stm32f4xx.h''

uint64_t Time;

int b=0;

uint32_t a;

uint32_t Time3;

uint32_t Time2;

uint32_t Time1;

uint32_t counter;

int nmbr = -1;

int CaptureNumber=0;

/**************************************************************************/

void RCC_Configuration(void)

{

  /* GPIOA  clock enable */

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

  /* TIM2 clock enable */

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

}

/**************************************************************************/

void NVIC_Configuration(void)

{

  NVIC_InitTypeDef NVIC_InitStructure;

  /* Enable the TIM2 gloabal Interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

}

/**************************************************************************/

void GPIO_Configuration(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

  /* GPIOA Configuration: TIM2 CH2 (PA1) */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Connect TIM2 pins to AF */

  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_TIM2);

}

/**************************************************************************/

void TIM2_Configuration(void)

{

  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

  TIM_ICInitTypeDef TIM_ICInitStructure;

  /* Time base configuration */

  TIM_TimeBaseStructure.TIM_Period = 0xFFFFFFFF; // 32-bit maximal

  TIM_TimeBaseStructure.TIM_Prescaler = ((SystemCoreClock / 2) / 1000000) - 1;//1mhz

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseStructure.TIM_ClockDivision = 0;

  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

    /* Input capture configuration */

  TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;

  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;

  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;

  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;

  TIM_ICInitStructure.TIM_ICFilter = 0x0;

  TIM_ICInit(TIM2, &TIM_ICInitStructure);

  /* TIM2 enable counter */

  TIM_Cmd(TIM2, ENABLE);

  /* TIM Interrupts enable */

  TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);

  TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

}

/**************************************************************************/

 void TIM2_IRQHandler(void)

{

 if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)

  { b=b+1;

     TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);

     if(CaptureNumber == 0)

{

    counter = TIM_GetCapture2(TIM2); //The first capture

    CaptureNumber = 1;

}

else if(CaptureNumber == 1)  //Treatment of second capture

{

   Time1 = TIM_GetCapture2(TIM2);

      Time1 = Time1 - counter;

   if(TIM_GetFlagStatus(TIM2,TIM_FLAG_Update) != SET)//Treatment of two capture no overflow occurs

   {

   

      Time1 = TIM_GetCapture2(TIM2);

      Time1 = Time1 - counter;

      

     

         }

    else

    {

              

       TIM_ClearFlag(TIM2,TIM_FLAG_Update); //The update event

       a=0xFFFFFFFF - counter;

       Time = a + TIM_GetCapture2(TIM2)+1; //If the calculation mode update events

   

    }

   

CaptureNumber = 0;

    }

}

}

/**************************************************************************/

int main(void)

{

  RCC_Configuration();

  NVIC_Configuration();

  GPIO_Configuration();

  TIM2_Configuration();

  

  while(1); // Do not exit

}

/**************************************************************************/

#ifdef  USE_FULL_ASSERT

/**

  * @brief  Reports the name of the source file and the source line number

  *         where the assert_param error has occurred.

  * @param  file: pointer to the source file name

  * @param  line: assert_param error line source number

  * @retval None

  */

void assert_failed(uint8_t* file, uint32_t line)

{

  /* User can add his own implementation to report the file name and line number,

     ex: printf(''Wrong parameters value: file %s on line %d\r\n'', file, line) */

  while (1)

  {}

}

#endif 

Posted on April 12, 2016 at 19:18

I'm afraid I don't have any resources to apply to your problem.

If you are using a switch to generate the pulses, perhaps there is some noise/bouncing coming from that. Look at the options related to filtering the input.

I would suggest using another timer to generate periodic pulses, and wire those pins externally, and use that to measure and evaluate the code you have.

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