FOC(空間矢量控制)算法在永磁同步電機驅動中應用十分廣泛,在家電行業中無感FOC控制算法的應用更加廣發,通過軟件算法估算壓機轉速和位置,實現無感FOC的控制。
我會以產品開發的角度,將軟件開發過程進行拆分,從系統架構、軟件流程圖、狀態機、中斷處理、算法實現、異常操作和判斷一一和大家進行探討。
一、系統架構
本方案采用DSP28035作為主控芯片,PWM1A-PWM5B作為三個橋臂的驅動輸出端,本方案采用雙電阻采樣,電阻采樣的信號通過ADC給到DSP芯片,另外母線電壓DC-Bus通過電阻分壓采樣也送入ADC端口。預留HOST端口,用232信號作為通信端口,接收上位機發送的數據進行電機驅動的頻率和力矩控制,具體如下:
無傳感器矢量控制的控制算法框圖如下,無感FOC最重要的就是觀察器,本方案采用滑膜觀測器,用于觀測電機的角度和速度。觀測器的設計好壞直接關系到系統的好壞。
二、軟件流程圖
系統初始化流程圖如下,初始化主要就是對DSP芯片的端口進行配置,比如PWM端口,配置成PWM觸發ADC采樣。ADC端口配置對相電流、母線電壓等進行采樣、IO端口配置輸入輸出功能、UART配置波特率等信息。開啟中斷功能。
系統中斷流程圖如下,PWM觸發ADC中斷,中斷頻率設置為10K,即PWM的驅動頻率也為10K。中間也就是這個程序的重點,FOC算法。
三、狀態機
我這里提出的狀態機,是指程序運行的狀態機,我們常規的程序是在一個while循環里把除了中斷以為的所有的程序都在里面實現。然后再分為多個中斷,比如有的函數需要1ms、有的函數需要10ms,寫成中斷的方式進行處理,然后控制算法在一個ADC中斷。
我這里采用的方案是利用定時器實現狀態機,狀態機的處理時間就可以固定成1ms、或者10ms的處理時間,狀態機還可以延時出很多子函數。相當于一個簡易的操作系統。
1)初始化函數:
void A0(void); //state A0
void B0(void); //state B0
void C0(void); //state C0
// A branch states
void A1(void); //state A1
void A2(void); //state A2
void A3(void); //state A3
void A4(void); //state A4
void (*Alpha_State_Ptr)(void); // Base States pointer
void (*A_Task_Ptr)(void); // State pointer A branch
void (*B_Task_Ptr)(void); // State pointer B branch
void (*C_Task_Ptr)(void); // State pointer C branch
2)主循環:
for(;;) //infinite loop
{ // State machine entry & exit point
//==================================================
(*Alpha_State_Ptr)(); // jump to an Alpha state (A0,B0,...)
//===================================================
}
狀態機函數
//A1狀態機主要執行的就是電機的運行的控制過程,從空閑→啟動→運行→停止→等待→錯誤狀態幾個狀態機之間循環。
void A1(void) // SPARE (not used)//--------------------------------------------------------{
switch(SystemState)
{
case STATE_IDLE:
StateIdle();
break;
case STATE_STARTUP:
StateStartUp();
break;
case STATE_RUN:
StateRun();
break;
case STATE_STOP:
StateStop();
break;
case STATE_WAITMIN:
StateWaitMin(N_MIN);
break;
case STATE_FAULT:
StateFault();
break;
default:
SystemState = STATE_FAULT;
break;
}
//-------------------
//the next time CpuTimer0 'counter' reaches Period value go to A2
A_Task_Ptr = &A2;
//-------------------
}
四、中斷處理&算法實現
本文的控制算法實現就是在中斷函數中進行的,參考第2點的軟件流程圖,簡單的來說就是ADC中斷(一般是PWM觸發,也可以是定時器觸發)→清除中斷標志→算法→產生PWM驅動→退出中斷。
算法部分也就是我系統款圖的里面的算法款圖,之前的文章有對具體CLARK變換、PARK變換以及滑膜觀測器的算法的具體實現代碼,感興趣的也可以再去看看。
算法的重點過程也就是先對采樣的相電流進行CLARK和PARK變換,得到d軸和q軸的電流。d軸和q軸的電流再和參考的d軸和q軸的電流(也有說法叫給定的電流)做比較經過PID控制器得到d軸和q軸的電壓,最后再經過iPARK變換給到SVPWM軟件模塊輸出PWM驅動信號,對三相橋臂進行驅動,實現電機的驅動,其中有兩個重點就是,給點電流Id和Iq的是根據什么來的,是根據速度PID環得到的,而速度PID環又是通過角度觀測器得到的。也就是我之前文章提到的滑膜觀察器(只是觀察器中的一種),同時PARK變化和iPARK需要的角度也是通過觀測器計算出來的。
//中斷函數關于算法部分的簡單示例
interrupt void MainISR(void)
{
CLARKE_MACRO(clarke1); //clarke變換
park1.Alpha = clarke1.Alpha;
park1.Beta = clarke1.Beta;
park1.Sine = _IQsinPU(park1.Angle);
park1.Cosine = _IQcosPU(park1.Angle);
PARK_MACRO(park1); //PARK變換
PI_MACRO(pi_iq);//iq的PID控制器
PI_MACRO(pi_id);//id的PID控制器
ipark1.Ds = pi_id.Out;
ipark1.Qs = pi_iq.Out;
ipark1.Sine=park1.Sine;
ipark1.Cosine=park1.Cosine;
IPARK_MACRO(ipark1);//iPARK變換
volt1.MfuncV1 = svgen1.Ta;
volt1.MfuncV2 = svgen1.Tb;
volt1.MfuncV3 = svgen1.Tc;
PHASEVOLT_MACRO(volt1);
esmo1.Ialpha = clarke1.Alpha;
esmo1.Ibeta = clarke1.Beta;
esmo1.Valpha = volt1.Valpha;
esmo1.Vbeta = volt1.Vbeta;
esmo1.runSpeed = rc_spd.SetpointValue; // Suggestion from Igor
esmo1.cmdSpeed = rc_spd.SetpointValue;
eSMO_MODULE(&esmo1);
esmo1.Theta = angleFilter(&pi_smo, &esmo1); // optional - uncomment to include
speed3.EstimatedTheta = esmo1.Theta;
SE_MACRO(speed3);//速度
svgen1.Ualpha = ipark1.Alpha;
svgen1.Ubeta = ipark1.Beta;
SVGENDQ_MACRO(svgen1);//SVPWM輸出
}// MainISR Ends Here
五、異常操作和判斷
異常操作就相對簡單了,主要就是判斷電機的過流(軟件、硬件)、缺相、母線電壓過壓、欠壓、功率器件過溫、電機啟動失敗、電機堵住等。這些保護操作我一般是用一個1ms的狀態機里面進行判斷。然后硬件過流和母線電壓過壓是直接在中斷里面去判斷,硬件過流是硬件完成的,一旦觸發過流就立馬關斷PWM,在中斷里面只是一個判斷是否有硬件過流的狀態。
申明:由于本人水平一般,分享的知識有誤,或者采用的方案不夠好的,歡迎各路大神指正批評,給大家帶來的不便,敬請諒解,本文觀點僅供參考。