cancel
Showing results for 
Search instead for 
Did you mean: 

SVPWM and sinf() slow calculation.

SProg
Associate III
Posted on June 19, 2016 at 16:46

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;  // 16kHz

float 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();

}

10 REPLIES 10
SProg
Associate III
Posted on June 21, 2016 at 06:18

I made some changes and now the calculation times is about 40usec.I think next step is to caclulate only Ub with sinf() and use it to calculate Ua,cause theere been an trigonometric connection between them.

Thats the 40usec code:

#define F 10000.0f // 10kHz

#define T 1.0f/F  

#define PI_2_T  2.0f*PI*T

#define PI 3.141592f

float MAXMODINDEX = 3600;

float THETA;

float SECTOR=0;

float Ua=0;

float Ub=0;

float Uc=0;

float  FREF =50.0f;

void SVPWM(int count)

{

__disable_irq();

THETA= PI_2_T*FREF*count;

SECTOR = THETA/(PI/3.0f);

Ua = (FREF * (1.0f/50.0f))*sinf((PI/3.0f) - (THETA - (float)SECTOR * (PI/3.0f)));

 

Ub = (FREF * (1.0f/50.0f))*sinf(THETA - (float)SECTOR * (PI/3.0f));

Uc= 1.0f-Ua-Ub;

switch((int)SECTOR)

{

case 0:       TIM3->CCR1 = MAXMODINDEX*(Ua + Ub + (float)0.5*Uc);

             TIM3->CCR2 = MAXMODINDEX*(Ub + (float)0.5*Uc);

             TIM3->CCR3 = MAXMODINDEX*((float)0.5*Uc);

break;

case 1:

         TIM3->CCR1 = MAXMODINDEX*(Ua + (float)0.5*Uc);

TIM3->CCR2 = MAXMODINDEX*(Ua + Ub + (float)0.5*Uc);

TIM3->CCR3 = MAXMODINDEX*((float)0.5*Uc);

break;

case 2:       TIM3->CCR1 = MAXMODINDEX*((float)0.5*Uc);

                TIM3->CCR2 = MAXMODINDEX*(Ua + Ub + (float)0.5*Uc);

                 TIM3->CCR3 = MAXMODINDEX*(Ub + (float)0.5*Uc);

break;

case 3:       TIM3->CCR1 = MAXMODINDEX*((float)0.5*Uc);

                TIM3->CCR2 = MAXMODINDEX*(Ua + (float)0.5*Uc);

                TIM3->CCR3 = MAXMODINDEX*(Ua + Ub + (float)0.5*Uc);

break;

case 4:      TIM3->CCR1 = MAXMODINDEX*(Ub + (float)0.5*Uc);

               TIM3->CCR2 = MAXMODINDEX*((float)0.5*Uc);

               TIM3->CCR3 = MAXMODINDEX*(Ua + Ub + (float)0.5*Uc);

break;

case 5:       TIM3->CCR1 = MAXMODINDEX*(Ua + Ub + (float)0.5*Uc);

                TIM3->CCR2 = MAXMODINDEX*((float)0.5*Uc);

                TIM3->CCR3 = MAXMODINDEX*(Ua + (float)0.5*Uc);

break;

default: break;

        }

__enable_irq();

}