Skip to main content
marzouk_najeh92
Associate
October 25, 2016
Question

stm32f3 discovery how to fix loop periode !!

  • October 25, 2016
  • 3 replies
  • 885 views
Posted on October 26, 2016 at 00:52

Hi all, i use stm32f3 discovery and i develop a project with IAR but i have faced a problem in fixing my loop periode

to be more clear :

i use the accelerometer and the gyroscope of th stm32f3 discovery , however after filtring the acc and gyro data i have to know how much time my loop take longer , sorry for my beginner english ;) i need some help please thank you ..!

i think this post discribe clearly what i want to do

''''''''''''''''''''''''''''''''''''''

The gyro tracking will not be accurate if you can not run a well timed loop. The code includes the mymillis() function for the timing.

At the start of each loop, we get the current time;

1

startInt = mymillis();

then at the end of the loop, we make sure that at least 20ms has passed before continuing;

1 2 3 4 5

//Each loop should be at least 20ms.
while

(mymillis() - startInt < 20)
{
usleep(100);
}

If your loop takes longer than 20ms to run, 45ms for example. Jut update the above value to make sure that every loop cycle runs at the same speed and set this value in DT for the gyro tracking.

#please-try-again
    This topic has been closed for replies.

    3 replies

    Tesla DeLorean
    Guru
    October 26, 2016
    Posted on October 26, 2016 at 02:14

    So use a free running 32-bit TIM at a granularity you want to either a) time stamp the measurement epochs, or b) manage the loop iterations.

    You could also use the DWT_CYCCNT to get into the sub-microsecond realm for loop iterations. Covered this here multiple times, review other posts

    //******************************************************************************
    // sourcer32@gmail.com
    volatile unsigned int *DWT_CYCCNT = (volatile unsigned int *)0xE0001004; //address of the register
    volatile unsigned int *DWT_CONTROL = (volatile unsigned int *)0xE0001000; //address of the register
    volatile unsigned int *SCB_DEMCR = (volatile unsigned int *)0xE000EDFC; //address of the register
    //******************************************************************************
    void EnableTiming(void)
    {
    static int enabled = 0;
    if (!enabled)
    {
    RCC_ClocksTypeDef RCC_Clocks;
    RCC_GetClocksFreq(&RCC_Clocks);
    *SCB_DEMCR |= 0x01000000;
    *DWT_CYCCNT = 0; // reset the counter
    *DWT_CONTROL |= 1 ; // enable the counter
    enabled = 1;
    }
    }
    //******************************************************************************
    void TimingDelay(unsigned int tick)
    {
    unsigned int start, current;
    start = *DWT_CYCCNT;
    do
    {
    current = *DWT_CYCCNT;
    } while((current - start) < tick);
    }
    //******************************************************************************
    TimingDelay(SystemCoreClock); // One Second of ticks
    TimingDelay(SystemCoreClock / 1000000); // One Microsecond of ticks

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    marzouk_najeh92
    Associate
    October 26, 2016
    Posted on October 26, 2016 at 18:45

    thank you so much for your answer , i think it will help me a lot ;)

    this is my code and what i  want to do i written inside the code ( the main function )

     

    int main(void)

    {  

      /* SysTick end of count event each 10ms */

      RCC_GetClocksFreq(&RCC_Clocks);

      SysTick_Config(RCC_Clocks.HCLK_Frequency / 100);

     

      /* Configure the USB */

         Demo_USB();

      /* Configure the gyroscope */  

         Demo_GyroConfig();

      /* Configure the accelerometer */

         Demo_CompassConfig();

      /* Infinite loop */

      while (1)

      {

               *********At the start of each loop, I get the current time*******************

                     exemple --->        ---- current_time() = start_time ----

                       

                       

        //read ACC and GYR data

        Demo_CompassReadAcc(acc_raw);

        Demo_GyroReadAngRate(gyr_raw);

        //Convert Gyro raw to degrees per second

        rate_gyr_x = (float) *gyr_raw * G_GAIN;

        rate_gyr_y = (float) *(gyr_raw+1) * G_GAIN;

        rate_gyr_z = (float) *(gyr_raw+2) * G_GAIN;

        //Calculate the angles from the gyro

        gyroXangle+=rate_gyr_x*DT;

        gyroYangle+=rate_gyr_y*DT;

        gyroZangle+=rate_gyr_z*DT;

        //Convert Accelerometer values to degrees

        AccXangle = (float) (atan2(*(acc_raw+1),*(acc_raw+2))+M_PI)*RAD_TO_DEG;

        AccYangle = (float) (atan2(*(acc_raw+2),*acc_raw)+M_PI)*RAD_TO_DEG;

            AccZangle = (float) (atan2(*(acc_raw),*acc_raw+1)+M_PI)*RAD_TO_DEG;

        //Change the rotation value of the accelerometer to -/+ 180

        if (AccXangle >180)

        {

            AccXangle -= (float)360.0;

        }

        if (AccYangle >180)

            {

            AccYangle -= (float)360.0;

            }

        if (AccZangle >180)

            AccZangle -= (float)360.0;

            // Complementary filter used to combine the accelerometer and gyro values.

        CFangleX=AA*(CFangleX+rate_gyr_x*DT) +(1 - AA) * AccXangle;

        CFangleY=AA*(CFangleY+rate_gyr_y*DT) +(1 - AA) * AccYangle;

            CFangleZ=AA*(CFangleZ+rate_gyr_z*DT) +(1 - AA) * AccZangle;

        

            filter_xterm[0] = (AccXangle - CFangleX) * timeConstant * timeConstant;

        filter_yterm[0] = (AccYangle - CFangleY) * timeConstant * timeConstant;

            filter_zterm[0] = (AccZangle - CFangleZ) * timeConstant * timeConstant;

          filter_xterm[2] = (DT * filter_xterm[0]) + filter_xterm[2];

          filter_yterm[2] = (DT * filter_yterm[0]) + filter_yterm[2];

            filter_zterm[2] = (DT * filter_zterm[0]) + filter_zterm[2];

          filter_xterm[1] = filter_xterm[2] + (AccXangle - CFangleX) * 2 * timeConstant + rate_gyr_x;

          filter_yterm[1] = filter_yterm[2] + (AccYangle - CFangleY) * 2 * timeConstant + rate_gyr_y;

            filter_zterm[1] = filter_zterm[2] + (AccZangle - CFangleZ) * 2 * timeConstant + rate_gyr_z;

          CFangleX2 = (DT * filter_xterm[1]) + CFangleX2;

          CFangleY2 = (DT * filter_yterm[1]) + CFangleY2;

            CFangleZ2 = (DT * filter_zterm[1]) + CFangleZ2;

            

     --------------- ******* current_time()- start_time= DT

                             while

                                  (DT < 20 )

          ***exemple                  delay(10) ;

           

            //Each loop should be at least 20ms.

          

        }

    }
    Tesla DeLorean
    Guru
    October 26, 2016
    Posted on October 26, 2016 at 18:50

    The forum doesn't like mobile devices, and you should top-post responses

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