SVPWM and sinf() slow calculation.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2016-06-19 7:46 AM
Hello to everyone, i am building an old project with STM32F107 now.
I am trying to calculate the SVPWM values on the fly but seems like compiler's code is so long.I am running on 72MHz.The fuction below needs around 60-65 usec,which is too much to fit on 20Khz timing.I am using KEIL uvision 5 and 3lvl optimization.float THETA;int SECTOR=0;float Ua=0;float Ub=0;float Uc=0;float PI=3.14;float T=0.0000625; // 16kHzfloat MAXMODINDEX = 2250;volatile float n=0;volatile float i=0;float FREF =50;int MAXn;//--------------------------------//void SVPWM(int count){__disable_irq(); THETA= 2*PI*FREF*count*T;SECTOR = THETA/(PI/3); Ua = (FREF/50)*sinf((PI/3)-(THETA-SECTOR*(PI/3)));Ub = (FREF/50)*sinf(THETA-SECTOR*(PI/3));Uc = 1.0-Ua-Ub;switch(SECTOR) { case 0: TIM3->CCR1 = MAXMODINDEX*(Ua + Ub + 0.5*Uc); TIM3->CCR2 = MAXMODINDEX*(Ub + 0.5*Uc); TIM3->CCR3 = MAXMODINDEX*(0.5*Uc); break; case 1: TIM3->CCR1 = MAXMODINDEX*(Ua + 0.5*Uc); TIM3->CCR2 = MAXMODINDEX*(Ua + Ub + 0.5*Uc); TIM3->CCR3 = MAXMODINDEX*(0.5*Uc); break; case 2: TIM3->CCR1 = MAXMODINDEX*(0.5*Uc); TIM3->CCR2 = MAXMODINDEX*(Ua + Ub + 0.5*Uc); TIM3->CCR3 = MAXMODINDEX*(Ub + 0.5*Uc); break; case 3: TIM3->CCR1 = MAXMODINDEX*(0.5*Uc); TIM3->CCR2 = MAXMODINDEX*(Ua + 0.5*Uc); TIM3->CCR3 = MAXMODINDEX*(Ua + Ub + 0.5*Uc); break; case 4: TIM3->CCR1 = MAXMODINDEX*(Ub + 0.5*Uc); TIM3->CCR2 = MAXMODINDEX*(0.5*Uc); TIM3->CCR3 = MAXMODINDEX*(Ua + Ub + 0.5*Uc); break; case 5: TIM3->CCR1 = MAXMODINDEX*(Ua + Ub + 0.5*Uc); TIM3->CCR2 = MAXMODINDEX*(0.5*Uc); TIM3->CCR3 = MAXMODINDEX*(Ua + 0.5*Uc); break; default: break; } __enable_irq(); }- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2016-06-19 7:59 AM
The F107 is a Cortex M3, without FPU , so every floating point operation needs to be emulated.
Even the FPU (in the F3/F4/F7 parts) does not support trigonometric functions (sinf(), cosf() ...). Better use scaled math, and integer variables.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2016-06-19 8:17 AM
Yeah i know F107 doesnt support FPU but 60-65usec is still too much.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2016-06-19 9:12 AM
Try measure the timing for sinf() calls, and for mult./div. operations.
You can also step through the disassembly code ... I used a integer-based approach with a sin/cos table (also integer) to create a realtime modulation of two frequencies (output via DAC). That took about 10us per cycle on a F100 (24MHz).- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2016-06-19 10:37 AM
There are likely a number of significant ways to optimize your code, Keil doesn't understand the algorithms, and especially where you have variables with global scope rather than constants. Multiplication is faster than division.
The F1 series also has no caching, prefetching, or optimization of the very slow Flash memory. Consider also using a proper version of PI, and using methods where you are not constantly rehashing the same math.Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2016-06-19 10:53 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2016-06-19 11:03 AM
If i use constants i see time being increased.
Could other compiler has much more optimized code;- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2016-06-19 1:19 PM
Take a look at this book ''Math Toolkit for Real-Time Programming'' might be useful.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2016-06-19 1:51 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2016-06-19 5:27 PM
something like this should be faster
#define PI 3.141592654f
// ...
Ua = (FREF * (1.0f/0f))*sinf((PI/3.0f) - (THETA - (float)SECTOR * (PI/3.0f)));
Ub = (FREF * (1.0f/0f))*sinf(THETA - (float)SECTOR * (PI/3.0f));
Up vote any posts that you find helpful, it shows what's working..
