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,在中断里面只是一个判断是否有硬件过流的状态。
申明:由于本人水平一般,分享的知识有误,或者采用的方案不够好的,欢迎各路大神指正批评,给大家带来的不便,敬请谅解,本文观点仅供参考。