0 前言
今天獲知了,電機FOC包含了SVPWM、坐标轉換、信号采集回報、PID閉環控制等,這個控制政策,統稱為FOC控制。一般SVPWM算法的實作是在靜止的αβ坐标系上實作。而PID控制器由于是對直流參考信号的跟蹤效果較好,是以三相交流電會經過坐标變換,在旋轉的dq坐标軸上,可以用直流量描述電樞繞組的合成矢量。
FOC控制中,有兩種坐标轉換需要注意的,分别是clark變換,和park變換。clark變換将abc坐标系轉換為αβ坐标系,而park變換将靜止的αβ坐标系轉換為旋轉的dq坐标系。
1 clark變換
其實直接可以把轉換公式列出。
寫成轉換矩陣,就是:
clark變換的逆變換:
寫成轉換矩陣,就是:
将兩個轉換矩陣相乘,應該是一個機關矩陣,系數K的作用是可以将轉換變為等幅值轉換或者等功率轉換。
當
,是等幅值轉換;當
,是等功率轉換。
1.1 matlab仿真
在matlab/simulink中搭建仿真模型:
abcToAlphabeta中的代碼:
function y = fcn(a,b,c)
%#eml
alpha = a - b/2 - c/2;
beta = sqrt(3)/2 * (b - c);
y = (2/3)*[alpha;beta];
alphabetaToABC中的代碼:
function y = fcn(alpha,beta)
%#eml
a = alpha;
b = -1/2 * alpha + sqrt(3)/2 * beta;
c = -1/2 * alpha - sqrt(3)/2 * beta;
y = [a;b;c];
仿真波形:
我在這裡使用的是等幅值變換。因為這裡調制系數為1,各個正弦波的幅值都是1。假如使用等功率變換,alphabeta坐标系上的幅值會超過1,此時若直接經過SVPWM算法,會變成過調制。
2 park變換
通過幾何變換,可以直接得到
圖中
就是d軸和α軸之間的夾角。我們也可以用q軸和α軸之間的夾角進行轉換,但是會影響矩陣的參數。故還是采用d軸和α軸之間的夾角。因為我參考了wikipedia的alphabeta transformation和TI的controlSuite裡面的資料,都是使用這個夾角去推轉換矩陣的。是以不轉牛角尖了。
寫成矩陣的形式:
那麼逆變換就是:
2.1 仿真
搭建仿真模型:
alphabetaToDQ代碼:
function y = fcn(alpha,beta, c)
%#eml
d = cos(c)* alpha + sin(c)*beta;
q = -sin(c)* alpha + cos(c)*beta;
y=[d;q];
DQToAlphabeta代碼:
function y = fcn(d,q, c)
%#eml
alpha = cos(c) * d - sin(c)*q;
beta = sin(c) * d + cos(c)*q;
y=[alpha;beta];
波形:
此時注意到:
現在三相abc的波形函數是:
假如需要反轉,那麼把輸入改為:
同時把仿真模型中的constant改為 -2*pi*10
可以得到:
3 C語言
以下代碼來自TI的controlSUITE。在此特别鳴謝TI。
3.1 clarke.h
/* =================================================================================
File name: CLARKE.H
===================================================================================*/
#ifndef __CLARKE_H__
#define __CLARKE_H__
typedef struct { _iq As; // Input: phase-a stator variable
_iq Bs; // Input: phase-b stator variable
_iq Cs; // Input: phase-c stator variable
_iq Alpha; // Output: stationary d-axis stator variable
_iq Beta; // Output: stationary q-axis stator variable
} CLARKE;
/*-----------------------------------------------------------------------------
Default initalizer for the CLARKE object.
-----------------------------------------------------------------------------*/
#define CLARKE_DEFAULTS { 0, \
0, \
0, \
0, \
0, \
}
/*------------------------------------------------------------------------------
CLARKE Transformation Macro Definition
------------------------------------------------------------------------------*/
// 1/sqrt(3) = 0.57735026918963
#define ONEbySQRT3 0.57735026918963 /* 1/sqrt(3) */
// Clarke transform macro (with 2 currents)
//==========================================
#define CLARKE_MACRO(v) \
v.Alpha = v.As; \
v.Beta = _IQmpy((v.As +_IQmpy2(v.Bs)),_IQ(ONEbySQRT3));
// Clarke transform macro (with 3 currents)
//==========================================
#define CLARKE1_MACRO(v) \
v.Alpha = v.As; \
v.Beta = _IQmpy((v.Bs - v.Cs),_IQ(ONEbySQRT3));
#endif // __CLARKE_H__
3.2 park.h
/* =================================================================================
File name: PARK.H
===================================================================================*/
#ifndef __PARK_H__
#define __PARK_H__
typedef struct { _iq Alpha; // Input: stationary d-axis stator variable
_iq Beta; // Input: stationary q-axis stator variable
_iq Angle; // Input: rotating angle (pu)
_iq Ds; // Output: rotating d-axis stator variable
_iq Qs; // Output: rotating q-axis stator variable
_iq Sine;
_iq Cosine;
} PARK;
/*-----------------------------------------------------------------------------
Default initalizer for the PARK object.
-----------------------------------------------------------------------------*/
#define PARK_DEFAULTS { 0, \
0, \
0, \
0, \
0, \
0, \
0, \
}
/*------------------------------------------------------------------------------
PARK Transformation Macro Definition
------------------------------------------------------------------------------*/
#define PARK_MACRO(v) \
\
v.Ds = _IQmpy(v.Alpha,v.Cosine) + _IQmpy(v.Beta,v.Sine); \
v.Qs = _IQmpy(v.Beta,v.Cosine) - _IQmpy(v.Alpha,v.Sine);
#endif // __PARK_H__
3.3 ipark.h
/* =================================================================================
File name: IPARK.H
===================================================================================*/
#ifndef __IPARK_H__
#define __IPARK_H__
typedef struct { _iq Alpha; // Output: stationary d-axis stator variable
_iq Beta; // Output: stationary q-axis stator variable
_iq Angle; // Input: rotating angle (pu)
_iq Ds; // Input: rotating d-axis stator variable
_iq Qs; // Input: rotating q-axis stator variable
_iq Sine; // Input: Sine term
_iq Cosine; // Input: Cosine term
} IPARK;
/*-----------------------------------------------------------------------------
Default initalizer for the IPARK object.
-----------------------------------------------------------------------------*/
#define IPARK_DEFAULTS { 0, \
0, \
0, \
0, \
0, \
0, \
0, \
}
/*------------------------------------------------------------------------------
Inverse PARK Transformation Macro Definition
------------------------------------------------------------------------------*/
#define IPARK_MACRO(v) \
\
v.Alpha = _IQmpy(v.Ds,v.Cosine) - _IQmpy(v.Qs,v.Sine); \
v.Beta = _IQmpy(v.Qs,v.Cosine) + _IQmpy(v.Ds,v.Sine);
#endif // __IPARK_H__
小結
坐标變換在FOC中也是重要的部分。本文介紹了clark變換和park變換。這兩種變換其實在網上資料十分豐富了。但在這裡還是寫了一遍。一方面是貢獻自己的能力,另一方面是滿足自己的收藏癖。假如需要重新程式設計,那麼我還是會重新找出資料。但是目前TI的資料也很豐富,我往下在實物上實作FOC的話,估計會從現有的代碼上修改。
現在幹活都做LED了,看維基上面的clarke變換,讓我想起了以前的日子。以前沒搞懂的坐标公式和PID公式,多推幾遍,現在也越來越熟悉了。
參考資料1:https://en.wikipedia.org/wiki/Alpha%E2%80%93beta_transformation
參考資料2:http://www.ti.com/controlsuite