hello-boy
认证:优质创作者
作者动态
分享一个使用C语言实现锁相环(PLL)以跟踪输入电压(正弦波)的例程代码
10-30 17:18
一文读懂几种永磁同步电机(PMSM)的区别
04-10 16:23
SJ/T 11893-2023《便携式锂离子电池储能电源技术规范》解读
01-29 15:44
#征文#基于DSP的无感FOC驱动嵌入式软件设计
01-17 21:15
电机V/F、开环矢量SVC、闭环矢量FVC控制的区别与应用
01-03 17:22

#征文#基于DSP的无感FOC驱动嵌入式软件设计

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,...)       

//===================================================

  }

状态机函数

void A0(void)
{
//GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1;    // Turn on/off LD3 on the controlCARD every 1ms
// loop rate synchronizer for A-tasks
if(CpuTimer0Regs.TCR.bit.TIF == 1)
{
CpuTimer0Regs.TCR.bit.TIF = 1; // clear flag
//-----------------------------------------------------------
(*A_Task_Ptr)(); // jump to an A Task (A1,A2,A3,...)
//-----------------------------------------------------------
}
Alpha_State_Ptr = &B0; // Comment out to allow only A tasks
}
void B0(void)
{
   // loop rate synchronizer for B-tasks
   if(CpuTimer1Regs.TCR.bit.TIF == 1)
   {
      CpuTimer1Regs.TCR.bit.TIF = 1; // clear flag
   //-----------------------------------------------------------
   (*B_Task_Ptr)(); // jump to a B Task (B1,B2,B3,...)
   //-----------------------------------------------------------
}
Alpha_State_Ptr = &A0; // Allow C state tasks
}

//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,在中断里面只是一个判断是否有硬件过流的状态。

申明:由于本人水平一般,分享的知识有误,或者采用的方案不够好的,欢迎各路大神指正批评,给大家带来的不便,敬请谅解,本文观点仅供参考。

声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
觉得内容不错的朋友,别忘了一键三连哦!
赞 3
收藏 4
关注 154
成为作者 赚取收益
全部留言
0/200
成为第一个和作者交流的人吧