Skip to main content
bendkhilarwa
Associate III
Apr 9, 2016 2:45 PM UTC
Question

Timer, motor _speed

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.
    This topic has been closed for replies.

    11 replies

    Tesla DeLorean
    Guru
    Apr 9, 2016 4:12 PM UTC
    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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
    bendkhilarwa
    Associate III
    Apr 9, 2016 7:35 PM UTC
    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
    Visitor II
    Apr 10, 2016 12:24 AM UTC
    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.

    Tesla DeLorean
    Guru
    Apr 10, 2016 12:34 AM UTC
    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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
    bendkhilarwa
    Associate III
    Apr 10, 2016 6:14 PM UTC
    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? 

    Tesla DeLorean
    Guru
    Apr 10, 2016 7:49 PM UTC
    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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
    bendkhilarwa
    Associate III
    Apr 11, 2016 3:30 PM UTC
    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
    Apr 12, 2016 3:54 PM UTC
    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 

    Tesla DeLorean
    Guru
    Apr 12, 2016 5:18 PM UTC
    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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
    bendkhilarwa
    Associate III
    Apr 15, 2016 7:26 PM UTC
    Posted on April 15, 2016 at 21:26

    hello, 

     I want to count the input signal (PA1) in a period  of 10 second. 

    The PA1 can have two state:

    state1 :-connected to 5v

    state2: not connected to anything.

    So I want that the variable impulsion be incremented (+1) for each translation from state 2 to state 1.

    So I use the sysTick to configure a period of 10 second, in each I incremente the varibale impulsion. But this variable it's not well incremented. can you help me to solve this problem please.

    #include ''stm32f4xx.h''

    __IO uint32_t TimmingDelay;

    uint64_t revolution_period;

    int impulsion=0;

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

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

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

    void GPIO_Configuration(void)

    {

      GPIO_InitTypeDef GpioConfiguration;

      GpioConfiguration.GPIO_Pin =GPIO_Pin_1;

      GpioConfiguration.GPIO_Mode = GPIO_Mode_IN;

      GpioConfiguration.GPIO_OType = GPIO_OType_PP;

      GpioConfiguration.GPIO_Speed = GPIO_Speed_50MHz;

      GpioConfiguration.GPIO_PuPd = GPIO_PuPd_UP;

      GPIO_Init(GPIOA,&GpioConfiguration);

      

    }

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

    void SysTick_Handler(void)

    {

      if(TimmingDelay !=0)

      {

        TimmingDelay --;

       }

    }  

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

     

    void count_pulse(__IO uint32_t time)

    {

      TimmingDelay = time;

      while(TimmingDelay !=0)

      {

        if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1)==Bit_SET)

        {

          impulsion=impulsion + 1;

        }

      }

    }

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

    int main(void)

    {

         

    //Enable the GPIOD Clock

      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);

    // GPIOA Configuration

      GPIO_Configuration();

      //Systick Configuration

      NVIC_SetPriority (SysTick_IRQn, 0);

      SysTick_Config(SystemCoreClock/1000);

      while(1)

      {

    // insert a delay of 10s 

        count_pulse(10000);

        revolution_period= 10000/impulsion;

        }

       

     

    }

     

          

     

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

    #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