1. 程式人生 > >基於stm32f427實現SVPWM控制永磁同步開環轉動

基於stm32f427實現SVPWM控制永磁同步開環轉動

1、SVPWM原理簡介

PWM(Pulse Width Modulation)脈寬調整,這是一種利用面積等效原理實現的控制技術。SVPWM(Space Vector PWM)空間向量PWM控制,因為控制電動機內部的圓形旋轉磁場,最終需要控制的是電壓空間向量。一般控制電機的三相電壓相互成120度,以正弦的形式變換。我們需要控制的就是這三相電壓呈現這種形式來最終控制到電磁轉矩。主電路圖如下所示:

將三相電壓向量以等幅計算方式轉換為兩相向量得:

 

由於逆變器三相橋臂共有6個開關管,為了研究各相上下橋臂不同開關組合時逆變器輸出的空間電壓向量,特定義開關函式Sx(x=a、b、c) 為:

                                                       

(Sa、Sb、Sc)的全部可能組合共有八個,包括6個非零向量 Ul(001)、U2(010)、U3(011)、U4(100)、U5(101)、U6(110)、和兩個零向量  U0(000)、U7(111),下面以其中一種開關組合為例分析,假設Sx(x=a、b、c)=(100),此時

 

求解上述方程可得:UaN=2Ud/3、UbN=-Ud/3、UcN=-Ud/3。同理可計算出其它各種組合下的空間電壓向量,列表如下:

表 1-1  開關狀態與相電壓和線電壓的對應關係

Sa

Sb

Sc

向量符號

線電壓

相電壓

Uab

Ubc

Uca

UaN

UbN

UcN

0

0

0

U0

0

0

0

0

0

0

1

0

0

U4

Udc

0

-Udc

 2/3*Udc  -1/3*Udc  -1/3*Udc

1

1

0

U6

0

Udc

-Udc

 1/3*Udc  1/3*Udc  -2/3*Udc

0

1

0

U2

-Udc

Udc

0

  -1/3*Udc  2/3*Udc  -1/3*Udc

0

1

1

U3

-Udc

0

0

 -2/3*Udc  1/3*Udc  1/3*Udc

0

0

1

U1

0

-Udc

Udc

 -1/3*Udc  -1/3*Udc   2/3*Udc

1

0

1

U5

Udc

-Udc

0

 1/3*Udc  -2/3*Udc  1/3*Udc

1

1

1

U7

0

0

0

0

0

0

八個基本電壓空間向量的大小和位置入下圖所示:

如果某一瞬間要求的電壓控制鍵向量在第一扇區,那麼可以根據第一扇區的向量U4以及U6以及零向量U0或U7合成所要求的向量U。經過計算,可以得到各向量的狀態保持時間為:

式中 m 為 SVPWM 調製係數(調製比):若要求Uref的模保持恆定,則Uref的軌跡為一圓形;若要求三相電壓波形不失真(即不飽和),則Uref的軌跡應在正六邊形內部;結合此兩點可知Uref的模取最大值時的軌跡為正六邊形的內切圓,此時m=1,故m<=1。

我們以減少開關次數為目標,將基本向量作用順序的分配原則選定為:在每次開關狀態轉換時,只改變其中一相的開關狀態。並且對零向量在時間上進行了平均分配,以使產生的 PWM對稱,從而有效地降低PWM的諧波分量。當 U4(100)切換至 U0(000)時,只需改變 A 相上下一對切換開關,若由 U4(100)切換至 U7(111)則需改變 B、C 相上下兩對切換開關,增加了一倍的切換損失。因此要改變電壓向量U4(100)、U2(010)、U1(001)的大小,需配合零電壓向量U0(000),而要改變U6(110)、U3(011)、U5(101),需配合零電壓向量U7(111)。這樣通過在不同區間內安排不同的開關切換順序, 就可以獲得對稱的輸出波形,其它各扇區的開關切換順序如表 所示:

Uref 所在的位置

開關切換順序

三相波形圖

Ⅰ區(0°≤θ≤60°)

…0-4-6-7-7-6-4-0…

 

Ⅱ區(60°≤θ≤120°)

…0-2-6-7-7-6-2-0…

 

Ⅲ區(120°≤θ≤180°)

…0-2-3-7-7-3-2-0…

 

Ⅳ區(180°≤θ≤240°)

…0-1-3-7-7-3-1-0…

 

Ⅴ區(240°≤θ≤300°)

…0-1-5-7-7-5-1-0…

 

Ⅵ區(300°≤θ≤360°)

…0-4-5-7-7-5-4-0…

 

以第Ⅰ扇區為例,其所產生的三相波調製波形在時間 Ts 時段中如圖所示,圖中電壓矢量出現的先後順序為 U0、U4、U6、U7、U6、U4、U0,各電壓向量的三相波形則與表 1-2 中的開關表示符號相對應。再下一個 TS 時段,Uref 的角度增加一個γ,利用式(1-8)可以重新計算新的 T0、T4、T6 及 T7 值,得到新的合成三相類似表(1-2)所示的三相波形;這樣每一個載波週期TS就會合成一個新的向量,隨著θ的逐漸增大,Uref 將依序進入第Ⅰ、Ⅱ、Ⅲ、Ⅳ、Ⅴ、Ⅵ區。在電壓向量旋轉一週期後,就會產生 R 個合成向量。

通過以上 SVPWM 的法則推導分析可知要實現SVPWM訊號的實時調製,首先需要知道參考電壓向量 Uref 所在的區間位置,然後利用所在扇區的相鄰兩電壓向量和適當的零向量來合成參考電壓向量。圖1-4是在靜止座標系(α,β)中描述的電壓空間向量圖,電壓向量調製的控制指令是向量控制系統給出的向量訊號 Uref,它以某一角頻率ω在空間逆時針旋轉,當旋轉到向量圖的某個 60°扇區中時,系統計算該區間所需的基本電壓空間向量,並以此向量所對應的狀態去驅動功率開關元件動作。當控制向量在空間旋轉 360°後,逆變器就能輸出一個週期的正弦波電壓。

    空間向量調製的第一步是判斷由 Uα 和 Uβ所決定的空間電壓向量所處的扇區。假定合成的電壓向量落在第 I 扇區,可知其等價條件如下:

以上等價條件再結合向量圖幾何關係分析,可以判斷出合成電壓向量 Uref 落在第 X扇區的充分必要條件,得出下表:

扇區

落在此扇區的充要條件

I

Uα>0 ,Uβ>0 且Uβ/ Uα<sqrt(3)

Uα>0 , 且Uβ/ |Uα|>sqrt(3)

Uα<0 ,Uβ>0 且-Uβ/ Uα<sqrt(3)

Uα<0 ,Uβ<0 且Uβ/ Uα<sqrt(3)

Uβ<0 且-Uβ/|Uα|>sqrt(3)

Uα>0 ,Uβ<0 且-Uβ/Uα<sqrt(3)

    若進一步分析以上的條件,有可看出參考電壓向量Uref 所在的扇區完全由Uβ, sqrt(3)Uα-Uβ, -sqrt(3)Uα- Uβ 三式決定,因此令:

                                           

 

再定義,若U1>0 ,則 A=1,否則 A=0; 若U 2>0 ,則 B=1,否則 B=0;若U3>0 ,則 C=1,否則 C=0。可以看出 A,B,C 之間共有八種組合,但由判斷扇區的公式可知 A,B,C 不會同時為 1 或同時為 0,所以實際的組合是六種,A,B,C 組合取不同的值對 應著不同的扇區,並且是一一對應的,因此完全可以由 A,B,C 的組合判斷所在的扇區。為區別六種狀態,令 N=4*C+2*B+A,則可以通過下表計算參考電壓 向量 Uref 所在的扇區。

N值與扇區對應關係

N

3

1

5

4

6

2

扇區號

採用上述方法,只需經過簡單的加減及邏輯運算即可確定所在的扇區,對於提高系統的響應速度和進行模擬都是很有意義的。

最後因為程式中控制的是沒相電壓的佔空比,佔空比經過計算得到如下表格

表 1-4 各扇區基本空間向量的作用時間

扇區

時間

 

I

   

 

   

   

 

   

 

   

 

在扇區1中時間圖如下:

 

 

2、stm32f427資源簡介

a、 stm32f427帶有FPU,它有硬體的浮點計算器,所以執行SVPWM演算法大致需要15us左右的時間

b、stm32f427的定時器1有7路PWM埠,其中6路是互補的PWM可以實現對三相橋式電路的控制,另外一路PWM埠,用來指示取樣電流的時間。

c、stm32f427有多路ADC轉換,並且分為注入組與規則組,注入組的優先順序高於規則組。SPWM演算法就是在取樣相電流完成後處理的。

d、取樣相電流的時間:這裡採用的是雙電阻取樣法,取樣的時間是三相PWM都為0的時候,這時候的電流狀態如圖所示,這時候取樣電阻上的電流就是相電流。現在的關鍵點是怎麼知道是處於零向量的狀態,其實設定定時器1的PWM4佔空是4路PWM中最高的就可以了,當然還需要考慮ADC的轉換時間,這有個壞處就是PWM佔空比將不能達到最大。

 

3、SVPWM演算法程式實現

需要用到的結構體如下

struct CLARK
{
    long Ia;     //輸入,A相定子電流
    long Ib;     //輸入,B相定子電流
    long Ic;     //輸入,C相定子電流
    long IAlpha;  //輸出,靜止座標系Alpha軸定子電流
    long IBeta;   //輸出,靜止座標系Beta軸定子電流
    void (*calcClark)();    
    void (*calcAntiClark)();
};
struct PARK
{
    long Id;     //輸出,旋轉座標系下的D座標值電流
    long Iq;         //輸出,旋轉座標系下的Q座標值電流
    long IAlpha;  //輸入,靜止座標系Alpha軸定子電流
    long IBeta;   //輸入,靜止座標系Beta軸定子電流
    float Ud;     //輸出,旋轉座標系下的D座標值電壓
    float Uq;          //輸出,旋轉座標系下的Q座標值電壓
    float UAlpha;  //輸入,靜止座標系Alpha軸定子電壓
    float UBeta;   //輸入,靜止座標系Beta軸定子電壓
    long Theta;    //旋轉座標角度
    float ActId;  //實際D軸電流
    float ActIq;  //實際Q軸電流
    void (*calcPark)();      
    void (*calcAntiPark)();  
};
struct SVPWM
{
    float UAlpha; //輸入,靜止座標系Alpha軸定子電壓
    float UBeta;  //輸入,靜止座標系Beta軸定子電壓
    long Ua;      //
    long Ub;      /
    long Uc;      //
    long Tx;        //
    long Ty;        //
    long Tz;        //
    long taOn;    //A相時間
    long tbOn;      //B相時間
    long tcOn;      //C相時間
};

 1、clark變換模組程式,clark變換既將三相座標系轉換成二相固定座標系的變換。

static void Clark_calc(struct CLARK *v)
{
    float sqrt_3 = SQRT_3;//新增浮點變數為了編譯器優化呼叫硬體浮點指令
    v->IAlpha = v->Ia;
    v->IBeta  = (sqrt_3/3)*(v->Ia+(v->Ib*2));
}

 2、park變換模快程式,park變換既二相固定座標系轉換成二相旋轉座標系的變換。存在旋轉座標系是為了將永磁同步電機的勵磁電流與轉矩電流剝離。

#define SinPointNum  3600
extern const int Sin_Table[SinPointNum];//正弦表
static void Park_Calc(struct PARK *v)
{
    long Sinthe,Costhe;
    UINT16 Point;
    Point  = v->Theta;
    if(Point<2700)
        Costhe = Sin_Table[Point+900];     
    else
        Costhe = Sin_Table[Point-2700];  // Ualpha = Ucos(the)  UpmMax = 2/3Udc
    Sinthe  = Sin_Table[Point];         // Ubeta  = Usin(the)
    v->Id = v->IAlpha*Costhe+v->IBeta*Sinthe;
    v->Iq = -v->IAlpha*Sinthe+v->IBeta*Costhe;
    v->Id = v->Id/0x8000;
    v->Iq = v->Iq/0x8000;
    v->ActId = (float)(v->Id)*7.15*3.3/4096;//最大采樣實際電流11.8a
    v->ActIq = (float)(v->Iq)*7.15*3.3/4096;//最大采樣實際電流11.8a
}

3、反park變換,反park變換既二相旋轉座標系轉換成二相固定座標系的變換

static void Anti_Park_Calc(struct PARK *v)
{
    int Sinthe,Costhe;
    UINT16 Point;
    Point  = v->Theta;
    if(Point<2700)
        Costhe = Sin_Table[Point+900];     
    else
        Costhe = Sin_Table[Point-2700];  // Ualpha = Ucos(the)  UpmMax = 2/3Udc
    Sinthe  = Sin_Table[Point];         // Ubeta  = Usin(the)
    v->UAlpha = v->Ud*(float)Costhe - v->Uq*(float)Sinthe;//範圍是-sqrt(2)μ?+sqrt(2)
    v->UBeta  = v->Ud*(float)Sinthe + v->Uq*(float)Costhe;//範圍是-sqrt(2)μ?+sqrt(2)
}

 4、SVPWM模組實現

static void Svpwm_Module(struct SVPWM *pstrSvpwm)
{
    UINT8 u8Sector=0;
    UINT8 a,b,c;
    int t1,t2;
    int temp;
    float sqrt_3 = SQRT_3;//新增浮點變數為了編譯器優化呼叫硬體浮點指令
    float m = K;
    UINT8 Udc = MOTOR_POWER;
    /* 利用以下公式確定扇區 */
//         iClarkBeta_calc(&strSvpwm.v);
//         pstrSvpwm->v.Va = pstrSvpwm->v.Beta;                                           // beta
//         pstrSvpwm->v.Vb = (AMP1000_SQRT_3*pstrSvpwm->v.Alpha/2 - pstrSvpwm->v.Beta*AMP1000/2)/AMP1000;  // alpha*sqrt(3/4)-0.5*beta
//         pstrSvpwm->v.Vc = (-AMP1000_SQRT_3*pstrSvpwm->v.Alpha/2 - pstrSvpwm->v.Beta*AMP1000/2)/AMP1000; // -alpha*sqrt(3/4)-beta*0.5
        pstrSvpwm->Ua = pstrSvpwm->UBeta;                                           // beta
        pstrSvpwm->Ub = (sqrt_3*pstrSvpwm->UAlpha/2 - pstrSvpwm->UBeta/2);  // alpha*sqrt(3)-beta
        pstrSvpwm->Uc = (-sqrt_3*pstrSvpwm->UAlpha/2 - pstrSvpwm->UBeta/2); // -alpha*sqrt(3)-beta
        if(pstrSvpwm->Ua>0)
            a = 1;
        else
            a = 0;
        if(pstrSvpwm->Ub>0)
            b = 1;
        else
            b = 0;
        if(pstrSvpwm->Uc>0)
            c = 1;
        else
            c = 0;
        u8Sector = 4*c + 2*b + a;
        
        //*24/MOTOR_POWER
        /* 利用下面公式計算出X、Y、Z 其中Ts為Timer1_Period,Udc為MOTOR_POWER*/
        pstrSvpwm->Ua = sqrt_3*pstrSvpwm->Ua/Udc*Ts/(0x8000);//X=sqrt(3)*beta*Ts/Udc
        pstrSvpwm->Ub = sqrt_3*pstrSvpwm->Ub/Udc*Ts/(0x8000);//Y=(sqrt(3)/2*beta+3/2*alpha)*Ts/Udc
        pstrSvpwm->Uc = sqrt_3*pstrSvpwm->Uc/Udc*Ts/(0x8000);//Z=(sqrt(3)/2*beta-3/2*alpha)*Ts/Udc
//         pstrSvpwm->v.Va = SQRT_3*pstrSvpwm->v.Va*Ts/(0x8000)*K;//X=sqrt(3)*beta*Ts/Udc
//         pstrSvpwm->v.Vb = SQRT_3*pstrSvpwm->v.Vb*Ts/(0x8000)*K;//Y=(sqrt(3)/2*beta+3/2*alpha)*Ts/Udc
//         pstrSvpwm->v.Vc = SQRT_3*pstrSvpwm->v.Vc*Ts/(0x8000)*K;//Z=(sqrt(3)/2*beta-3/2*alpha)*Ts/Udc
        /* 計算SVPWM佔空比 */
        switch(u8Sector)
        {
            case 0:
                        pstrSvpwm->taOn = Time1_Period / 2;
                        pstrSvpwm->tbOn = Time1_Period / 2;
                        pstrSvpwm->tcOn = Time1_Period / 2;
                        break;
            case 1:
//                         if(Ts>(t1+t2))
                        {
//                             t1 = -pstrSvpwm->v.Vc;
//                             t2 = -pstrSvpwm->v.Vb;
                              t1 = -pstrSvpwm->Ub;//U2t  //這個U2向量先發生,所以在前
                                t2 = -pstrSvpwm->Uc;//U6t
                        }
                        if(Ts<(t1+t2))
                        {
                            t1 = t1*Ts/(t1+t2);
                            t2 = t2*Ts/(t1+t2);
                        }
                        pstrSvpwm->tbOn = ((Ts)- t1 - t2)/4;          //Tbon = (1-t1-t2)/4
                        pstrSvpwm->taOn = pstrSvpwm->tbOn + t1/2;     //Taon = Tbon + t1/2
                        pstrSvpwm->tcOn = pstrSvpwm->taOn + t2/2;     //Tcon = Taon + t2/2
                        break; //2號扇區
            case 2:
//                         t1 = -pstrSvpwm->v.Va;
//                         t2 = -pstrSvpwm->v.Vc;
                        t1 = -pstrSvpwm->Uc;//Ut4
                        t2 = -pstrSvpwm->Ua;//Ut5
                        if(Ts<(t1+t2))
                        {
                            t1 = t1*Ts/(t1+t2);
                            t2 = t2*Ts/(t1+t2);
                        }
                        pstrSvpwm->taOn = ((Ts)-t1 - t2)/4;//Taon = (1-t1-t2)/4
                        pstrSvpwm->tcOn = pstrSvpwm->taOn + t1/2;              //Tcon = Taon + t1/2
                        pstrSvpwm->tbOn = pstrSvpwm->tcOn + t2/2;              //Tbon = Tcon + t2/2
                        break;//6號扇區
            case 3:
                        t1 = pstrSvpwm->Ub;//Ut4
                        t2 = pstrSvpwm->Ua;//Ut6
                        if(Ts<(t1+t2))
                        {
                            t1 = t1*Ts/(t1+t2);
                            t2 = t2*Ts/(t1+t2);
                        }
                        pstrSvpwm->taOn = ((Ts)-t1 - t2)/4;//Taon = (1-t1-t2)/4
                        pstrSvpwm->tbOn = pstrSvpwm->taOn + t1/2;              //Tbon = Taon + t1/2
                        pstrSvpwm->tcOn = pstrSvpwm->tbOn + t2/2;              //Tcon = Tbon + t2/2
                        break;//1號扇區
            case 4:
//                         t1 = -pstrSvpwm->v.Vb;
//                         t2 = -pstrSvpwm->v.Va;
                        t1 = -pstrSvpwm->Ua;//Ut1
                        t2 = -pstrSvpwm->Ub;//Ut3
                        if(Ts<(t1+t2))
                        {
                            t1 = t1*Ts/(t1+t2);
                            t2 = t2*Ts/(t1+t2);
                        }
                        pstrSvpwm->tcOn = ((Ts)-t1 - t2)/4;             //Tcon = (1-t1-t2)/4
                        pstrSvpwm->tbOn = pstrSvpwm->tcOn + t1/2;         //Tbon = Tcon + t1/2
                        pstrSvpwm->taOn = pstrSvpwm->tbOn + t2/2;         //Taon = Tbon + t2/2
                        break;//4號扇區
            case 5:
                        t1 = pstrSvpwm->Ua;//Ut2
                        t2 = pstrSvpwm->Uc;//Ut3
                        if(Ts<(t1+t2))//·防止發生過調整導致圓形電壓向量失真,所以採取比列縮小
                        {
                            t1 = t1*Ts/(t1+t2);
                            t2 = t2*Ts/(t1+t2);
                        }
                        pstrSvpwm->tbOn = ((Ts)- t1 - t2)/4;//Tbon = (1-t1-t2)/4
                        pstrSvpwm->tcOn = pstrSvpwm->tbOn + t1/2;              //Tcon = Tbon + t1/2
                        pstrSvpwm->taOn = pstrSvpwm->tcOn + t2/2;              //Taon = Tcon + t2/2
                        break;//3號扇區
            case 6:
//                         t1 = pstrSvpwm->v.Vc;
//                         t2 = pstrSvpwm->v.Vb;
                        t1 = pstrSvpwm->Uc;//Ut1
                        t2 = pstrSvpwm->Ub;//Ut5
                        if(Ts<(t1+t2))
                        {
                            t1 = t1*Ts/(t1+t2);
                            t2 = t2*Ts/(t1+t2);
                        }
                        pstrSvpwm->tcOn = ((Ts) - t1 - t2)/4;//Tcon = (1-t1-t2)/4
                        pstrSvpwm->taOn = pstrSvpwm->tcOn + t1/2;              //Taon = Tcon + t1/2
                        pstrSvpwm->tbOn = pstrSvpwm->taOn + t2/2;              //Tbon = Taon + t2/2
                        break;//5號扇區
            default:break;
        }
        
                
        /* stm32的中間對齊模式為倒三角,所以重新計算佔空比 */
        u16TimeAon = Time1_Period - (UINT16)pstrSvpwm->taOn;
        u16TimeBon = Time1_Period - (UINT16)pstrSvpwm->tbOn;
        u16TimeCon = Time1_Period - (UINT16)pstrSvpwm->tcOn;
        if(t1==0 && t2==0)
        {
            u16TimeAon = Time1_Period;
            u16TimeBon = Time1_Period;
            u16TimeCon = Time1_Period;
        }
        if(u16TimeAon>=(Limit_Pluse_Max_Value))
            u16TimeAon = Limit_Pluse_Max_Value;
        if(u16TimeBon>=(Limit_Pluse_Max_Value))
            u16TimeBon = Limit_Pluse_Max_Value;
        if(u16TimeCon>=(Limit_Pluse_Max_Value))
            u16TimeCon = Limit_Pluse_Max_Value;
        TIM1->CCR1 = u16TimeAon;//Time1_Period/4;//u16TimeAon;//Time1_Period/4*3;////u16TimeAon;//下一個週期生效
        TIM1->CCR2 = u16TimeBon;//0;//u16TimeBon;//Time1_Period/4;////u16TimeBon;//下一個週期生效
        TIM1->CCR3 = u16TimeCon;//0;//u16TimeCon;//Time1_Period/4*3;////u16TimeCon;//下一個週期生效
}

開環控制的方式為設定Ud=0,Uq=20.可以看到電機轉動起來了。相電流的波形與轉速如圖所示:

紅色為Ia相電流,綠色為Ib相電流,在旋轉轉過程中轉速相差為8r/min