接上篇文章:FOC算法(笔记一)_马鞍波和三角波调制合成-****博客
前面已经对FOC的开环控制进行了介绍,下面对FOC的闭环控制进行介绍。
本次使用的电机参数如下图所示:
一、HALL传感器
1.1、霍尔传感器的角度、速度计算
因为本次使用的是120°安装的三相霍尔编码器,所以霍尔德精度是非常低的,如下图所示的,每圈只能检测6次,对角度的精度是比较低的,所以较低速度情况下如无法获得电机的角度和角速度信息的。
所以通过计算上一个60°的电机的转速,作为下一个60°来临之前的速度,乘以ADC检测时间就可以算出中间检测时间。
(1) 如下图所示的,通过判断霍尔三相GPIO的电平可以判断当前霍尔的角度在第几个60°。
(2)一般电机三相的0角度为Ud=1、Uq=0电平的时候转子所在位置,所以转子的0°和霍尔德0°,也即是如下图所示0x50位置所示的0°,两个是不一样的,所以需要对角度进行补偿,具体补偿如下代码所示:
#define PHASE_SHIFT_ANGLE (float)(220.0f/360.0f*2.0f*PI)
(3)只知道是多少个60°,精度太低,所以通过定时器对三相霍尔德编码器进行霍尔(HALL)模式的检测,当有上升沿、下降沿的时候就触发定时器的中断,之后通过中断的时间和60°角度计算出来电机的转速,后面在ADC检测中使用角度自增的时候,直接用速度乘以ADC检测时间就可以计算出来每次ADC检测角度的增量。从而平滑的获得角度递增的锯齿波结果。
(4)上面(3)中计算出来的速度是电机的角速度,在速度闭环控制的时候,使用的机械速度,并且两者都是弧度制的,所以应该将角速度转化为机械速度(转/min、r/min):角速度(°/s)/360°/60s*极对数.
2.2、霍尔编码器嵌入式程序
如下面代码所示的是TIM4定时器的编码器模式,在检测到三相上有电平变化的时候产生中断,中断中调用下面的回调函数,回调函数中计算速度(机械角度频率,转/分钟,rmp/min),ADC一个检测周期角度增加值。
(1)HallTemp = HAL_TIM_ReadCapturedValue(&htim4,TIM_CHANNEL_1);
(2)HallThetaAdd = (PI/3)/(HallTemp/3200000)/10000;
(3)HallSpeed = (PI/3)*2/(HallTemp/3200000)*60/(2*PI);
(1)获得触发定时器中断的时间。
(2)计算ADC一个检测周期的角度增加值HallThetaAdd,PI/3表示一个编码器触发周期的角度;HallTemp/3200000表示定时器的计时时间,单位秒,(计数次数/TIM时钟频率);10000标志ADC检测的频率,除以频率等于乘以ADC检测一次时间。
(3)计算电机的速度(rmp/min),2表示电机的极对数,将电角度转化为机械角度;60是将秒转化为分钟;(2*PI)标志一圈的弧度,将弧度转化为圈。
//转子0角度和霍尔零角度的差值补偿
#define PHASE_SHIFT_ANGLE (float)(220.0f/360.0f*2.0f*PI)
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(htim);
if(htim == &htim4)
{
HallTemp = HAL_TIM_ReadCapturedValue(&htim4,TIM_CHANNEL_1);
HallThetaAdd = (PI/3)/(HallTemp/3200000)/10000; //电角度的速度增量,除以10000是为了提前乘以ADC采样时间。
HallSpeed = (PI/3)/(HallTemp/3200000)*30/(2*PI); //角度的计算,60/计数时间,然后将电角度转化为机械角度
// /* 一介低通滤波器,对于高频噪声滤波效果好,运算量小 */
// HallSpeed_filter = HallSpeed;
// HallSpeed_filter = (1-(HallTemp/16000))*HallSpeed_last+(HallTemp/16000)*HallSpeed_filter;
// HallSpeed_last = HallSpeed_filter;
/* 角度的判断,只能60增加的判断 */
HallReadTemp = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_8);
HallReadTemp |= HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7)<<1;
HallReadTemp |= HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_6)<<2;
if(HallReadTemp==0x05)
{
HallTheta = 0.0f+PHASE_SHIFT_ANGLE;
}
else if(HallReadTemp==0x04)
{
HallTheta = (PI/3.0f)+PHASE_SHIFT_ANGLE;
}
else if(HallReadTemp==0x06)
{
HallTheta = (PI*2.0f/3.0f)+PHASE_SHIFT_ANGLE;
}
else if(HallReadTemp==0x02)
{
HallTheta = PI+PHASE_SHIFT_ANGLE;
}
else if(HallReadTemp==0x03)
{
HallTheta = (PI*4.0f/3.0f)+PHASE_SHIFT_ANGLE;
}
else if(HallReadTemp==0x01)
{
HallTheta = (PI*5.0f/3.0f)+PHASE_SHIFT_ANGLE;
}
if(HallTheta<0.0f)
{
HallTheta += 2.0f*PI;
}
else if(HallTheta>(2.0f*PI))
{
HallTheta -= 2.0f*PI;
}
}
}
下面是对上面回调函数中计算的数据的使用。
HallTheta = HallTheta + HallThetaAdd; //区间角度+角度变化值
if(HallTheta < 0.0f)
{
HallTheta += 2.0f*PI;
}
else if(HallTheta > (2.0f*PI))
{
HallTheta -= 2.0f*PI;
}
g_SC.theta = HallTheta; //当前的角度值
g_SpPI.Speed_now = HallSpeed; //当前编码器速度
二、电流环闭环
2.1、电流闭环整体框架