- 代码的基本逻辑:目前只是使用了电流环,我们设定目标
Iq_set = 0.3
,然后调用PID控制函数,返回值传给Uq
- 目前存在的问题:肉眼观察下电机可以正常的转动,但是高负载的情况下转不动。目前通过调试观察 Iq 的值,发现Iq根本无法稳定在 0.3 附近,而且无规律的跳动。使用上位机观察UWV其中两项的电流值,电流曲线有点正弦波的样子,但是很杂。搞了很长时间找不出问题在哪里,求指导。
typedef struct
{
float error; // 当前误差
float errorLast; // 上一次误差
float feedforward; // 前馈
float integral; // 积分
float saturation; // 饱和
float differ; // 差值
float kp; // 比例增益
float ki; // 积分增益
float kd; // 微分增益
float ns; // 速度限制
float ka; // 加速度限制
float limit; // 限制
} PID_LocTypeDef;
/* 初始化PID参数 */
PID_Init(&PID_Iq, 0.65, 0.12, 0, 10, 0.01);foc.Uq = PID_Loc(0.3, cur.Iq, &PID_Iq);
void PID_Init(PID_LocTypeDef* pidHandle, float kp, float ki, float kd, float limit, float ns)
{
pidHandle->kp = kp;
pidHandle->ki = ki;
pidHandle->kd = kd;
pidHandle->limit = limit;
pidHandle->ns = ns;
}
foc.Uq = PID_Loc(0.3, cur.Iq, &PID_Iq);
setPhaseVoltage(&foc, angle.Eangle);
这是foc的SVPWM代码
// FOC核心函数:输入Ud、Uq和电角度,输出PWM
void setPhaseVoltage(sfoc *foc, float angle)
{
foc->angle_el = angle;
foc->angle_el = _normalizeAngle(foc->angle_el);
float cos_angle = arm_cos_f32(foc->angle_el);
float sin_angle = arm_sin_f32(foc->angle_el);
// 反park变换
foc->U_alpha = foc->Ud * cos_angle - foc->Uq * sin_angle;
foc->U_beta = foc->Ud * sin_angle + foc->Uq * cos_angle;
foc->Uref = _sqrtf(foc->U_alpha * foc->U_alpha + foc->U_beta * foc->U_beta) / voltage_power_supply;
// 限制最大参考电压
if (foc->Uref > 0.577f)
foc->Uref = 0.577f;
if (foc->Uref < -0.577f)
foc->Uref = -0.577f;
// 标准化电角度值,并根据Uq确定扇区
if (foc->Uq > 0)
foc->angle_el = _normalizeAngle(foc->angle_el + _PI_2);
else
foc->angle_el = _normalizeAngle(foc->angle_el - _PI_2);
foc->sector = (foc->angle_el / _PI_3) + 1;
// 计算作用时间
foc->T1 = SQRT_3 * arm_sin_f32(foc->sector * _PI_3 - foc->angle_el) * foc->Uref;
foc->T2 = SQRT_3 * arm_sin_f32(foc->angle_el - (foc->sector - 1.0f) * _PI_3) * foc->Uref;
foc->T0 = 1 - foc->T1 - foc->T2;
// 根据扇区计算占空比
switch (foc->sector) {
case 1:
foc->Ta = foc->T1 + foc->T2 + foc->T0 / 2;
foc->Tb = foc->T2 + foc->T0 / 2;
foc->Tc = foc->T0 / 2;
break;
case 2:
foc->Ta = foc->T1 + foc->T0 / 2;
foc->Tb = foc->T1 + foc->T2 + foc->T0 / 2;
foc->Tc = foc->T0 / 2;
break;
case 3:
foc->Ta = foc->T0 / 2;
foc->Tb = foc->T1 + foc->T2 + foc->T0 / 2;
foc->Tc = foc->T2 + foc->T0 / 2;
break;
case 4:
foc->Ta = foc->T0 / 2;
foc->Tb = foc->T1 + foc->T0 / 2;
foc->Tc = foc->T1 + foc->T2 + foc->T0 / 2;
break;
case 5:
foc->Ta = foc->T2 + foc->T0 / 2;
foc->Tb = foc->T0 / 2;
foc->Tc = foc->T1 + foc->T2 + foc->T0 / 2;
break;
case 6:
foc->Ta = foc->T1 + foc->T2 + foc->T0 / 2;
foc->Tb = foc->T0 / 2;
foc->Tc = foc->T1 + foc->T0 / 2;
break;
default: // 错误情况
foc->Ta = 0;
foc->Tb = 0;
foc->Tc = 0;
break;
}
// 输出PWM信号
TIM1->CCR1 = foc->Ta * PWM_PERIOD;
TIM1->CCR2 = foc->Tb * PWM_PERIOD;
TIM1->CCR3 = foc->Tc * PWM_PERIOD;
}
这是PID控制的代码
float PID_Loc(float SetValue, float ActualValue, PID_LocTypeDef* pidHandle)
{
pidHandle->error = SetValue - ActualValue;
/* Proportional Item */
float p = pidHandle->kp * pidHandle->error;
/* Integral Item */
float i = pidHandle->ki * (pidHandle->error - pidHandle->ka * pidHandle->saturation) + pidHandle->integral;
// i = _constrain(i, MIN(0.f, -pidHandle->limit), MAX(0.f, pidHandle->limit));
i = _constrain(i, -pidHandle->limit, pidHandle->limit);
pidHandle->integral = i;
/* Differential Item */
float d = pidHandle->kd * pidHandle->ns * (pidHandle->error - pidHandle->errorLast) -
pidHandle->differ * (pidHandle->ns - 1.0f);
pidHandle->errorLast = pidHandle->error;
pidHandle->differ = d;
/* Output value update and saturation value calculation */
float val = p + i + d + pidHandle->feedforward;
float out = _constrain(val, -pidHandle->limit, pidHandle->limit);
pidHandle->saturation = val - out;
return out;
}
这是计算Iq和Id的值部分
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *hadc)
{
GetCurrent(&cur);
float I_alpha = cur.CurA;
float I_beta = (cur.CurB - cur.CurC) * SQRT_3 / 2;
cur.Id = I_alpha * arm_cos_f32(foc.angle_el) + I_beta * arm_sin_f32(foc.angle_el);
cur.Iq = I_beta * arm_cos_f32(foc.angle_el) - I_alpha * arm_sin_f32(foc.angle_el);
/* 低通滤波 */
cur.Id = LowPassFilter_Update(&LPF_Id, cur.Id);
cur.Iq = LowPassFilter_Update(&LPF_Iq, cur.Iq);
}
这是使用上位机观察到了UV两项的电流波形。
在调试中观察的数值变化
目前我感觉是PID函数没有在正常的工作
1.检测电流环PI参数是否合适;
2.电流环控制是否只控制了Q轴,而没有控制D轴电流,如果是话,请把D轴也加上;
3、检查采样电流是否正确;
4.可以参考ST的 MCSDK的相关代码;
好的我会继续尝试不同的PI参数。目前只控制Q轴,d周我直接赋值
Ud = 0
,电流采样部分应该是没什么问提。