2016-10-25 03:52 PM
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-again2016-10-25 05:14 PM
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
2016-10-26 09:45 AM
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. } }2016-10-26 09:50 AM
The forum doesn't like mobile devices, and you should top-post responses