FOC无感开环启动排除掉高频注入这种直接识别当前转子dq轴的位置直接闭环启动,大部分的常规启动方式就是三段式启动,对齐-强拖-观测器介入-观测器误差稳定后平滑过渡-闭环。
这里就只写出I/F(V/F)启动的角度输出的代码,力矩就是一条y=kx+b的直线,没什么好说的。
这里的逻辑是我搭建的Simulink仿真的逻辑
simulink仿真如下图
相关参数
#define MOTOR_POLE_PAIRS 4 //4对极
#define OPEN_LOOP_END_SPEED 300 //RPM
#define OPEN_LOOP_END_TIME 20 //Second
#define OPEN_LOOP_FREQ 0.001f //1kHz
#define OPEN_LOOP_CURRENT 0.2f
#define OPEN_LOOP_CURRENT_END 1.1f
#define OPEN_LOOP_VOLTAGE 0.4f
#define OPEN_LOOP_VOLTAGE_END 1.1f
#define OPEN_LOOP_TORQUE_DURATION 500 //ms
开环启动控制头文件
struct OpenLoopControl
{
int8_t CloseLoopFlag; //指示是否可以切入闭环
float StartAngle; //初始角度,对齐的角度
float OpenLoopAngleAcc; //角加速度
float OpenLoopAngleSpeed; //角速度
float OpenLoopElecTheta; //电角度
uint16_t OpenLoopAccCount; //计数器
uint16_t OpenLoopAccTime; //时间
float OpenLoopOutAngle; //计算出的开环实际角度
float OpenLoopTorqueSlop; //开环力矩斜率
float OpenLoopOutTorque; //计算出的实际力矩,V/F是电压,I/F是电流
};
void OpenLoopSlopInit(void);
void OpenLoopCtrl(void);
相关实现
#define PI 3.11415926535f
#define PI_2 (2 * PI)
#define RadGain 2 * PI / 60.0f
static void OpenLoopTorqueCtrl(void);
static void OpenLoopAngleCtrl(void);
struct OpenLoopControl _sOpenLoopHandle;
//初始化
void OpenLoopSlopInit(void)
{
_sOpenLoopHandle.CloseLoopFlag = 0;
_sOpenLoopHandle.OpenLoopOutAngle = 0;
_sOpenLoopHandle.OpenLoopOutTorque = OPEN_LOOP_CURRENT;
_sOpenLoopHandle.StartAngle = 0;
_sOpenLoopHandle.OpenLoopAngleAcc = OPEN_LOOP_END_SPEED * MOTOR_POLE_PAIRS * RadGain / OPEN_LOOP_END_TIME;
_sOpenLoopHandle.OpenLoopAccCount = 0;
_sOpenLoopHandle.OpenLoopAccTime = (OPEN_LOOP_END_TIME / OPEN_LOOP_FREQ);
_sOpenLoopHandle.OpenLoopAngleSpeed = 0.0f;
_sOpenLoopHandle.OpenLoopElecTheta = 0.0f;
_sOpenLoopHandle.OpenLoopOutAngle = 0.0f;
_sOpenLoopHandle.OpenLoopTorqueSlop = (OPEN_LOOP_CURRENT_END - OPEN_LOOP_CURRENT) / OPEN_LOOP_TORQUE_DURATION;
}
//开环曲线计算
void OpenLoopCtrl(void)
{
OpenLoopTorqueCtrl();
OpenLoopAngleCtrl();
_sOpenLoopHandle.OpenLoopOutAngle = fmodf(_sOpenLoopHandle.OpenLoopElecTheta ,PI_2);
}
static void OpenLoopTorqueCtrl(void)
{
if(_sOpenLoopHandle.OpenLoopOutTorque < OPEN_LOOP_CURRENT_END)
{
_sOpenLoopHandle.OpenLoopOutTorque += _sOpenLoopHandle.OpenLoopTorqueSlop;
}
else
{
_sOpenLoopHandle.OpenLoopOutTorque = OPEN_LOOP_CURRENT_END;
}
}
static void OpenLoopAngleCtrl(void)
{
if(_sOpenLoopHandle.OpenLoopAccCount < _sOpenLoopHandle.OpenLoopAccTime)
{
_sOpenLoopHandle.OpenLoopAngleSpeed += _sOpenLoopHandle.OpenLoopAngleAcc * OPEN_LOOP_FREQ;
_sOpenLoopHandle.OpenLoopElecTheta += _sOpenLoopHandle.OpenLoopAngleSpeed * OPEN_LOOP_FREQ;
_sOpenLoopHandle.OpenLoopAccCount++;
}
else
{
_sOpenLoopHandle.OpenLoopElecTheta += _sOpenLoopHandle.OpenLoopAngleSpeed * OPEN_LOOP_FREQ;
}
}
该开环启动算法是在1ms的周期执行的实测如下