经过一段时间对FOC的深度学习,我也是终于写出来了自己的一套FOC代码了。有了这一套代码之后,也就有了我的第一个基于FOC的项目----力反馈旋钮。
这个套着黄色外壳的无刷电机就是力反馈旋钮,我用的主控是STM32F407ZGT6,无刷驱动板是立创开源里自己打出来的。
力反馈旋钮所利用的原理:利用FOC,我们可以很轻松的控制无刷电机的力矩环(也就是电流环),既然力矩可控,我们自然就可以控制转动旋钮的难易程度,想要轻松且顺滑的转动电机,就把电流环的电流的目标初始值设置为一个小的正值乘以编码器得到的速度值。;不想要电机那么轻易被转动,也就是让旋钮转起来感觉有阻尼感,我们就把电流环的初始目标电流值设置为一个小的负值乘以编码器得到的速度值。这么做的话,只要你转动电机,电机就会有速度,就会有相应的阻尼感。
我做的这个力反馈旋钮共有4种模式,直接上代码,结合代码来讲解每一种模式的原理:
1.棘轮模式,这个模式就是模拟机械旋钮转起来一卡一卡的感觉
float jilun(float target)
{
float attractor_distance = 45.0f * 3.1415926f / 180.0f;
return roundf(getAngle()/attractor_distance)*attractor_distance;
}
void jilun_xuanniu(void)
{
serial_targrt = jilun(serial_targrt);
FOC_setCurrent_velocity_angle(serial_targrt );
}
其实非常简单,45.0就是我把一圈360°分成八等份,然后转化为弧度制。第二行中的roundf就是一个四舍五入函数,对当前从AS5600获取的角度/45°对应的弧度值就可以得到一个小数,对这一个小数做四舍五入(大于0.5进一,小于0.5的保持原来的整数),再将得到的这一个数乘以45°的弧度值,就可以得到目标角度了。这样做的思路就是使电机转一圈,感觉卡了八次。
2.有界模式,也就是电机在某个角度范围内旋转是顺滑的,超过这个范围电机就会自动进行纠正。同样的,拿代码出来讲解:
void youjie_xuanniu(void)
{
float angle = getAngle();
float angle_range2 = 45.0f;
float limit_range = angle_range2 / 360.0f * 6.2831853f;
float L1 = zero_angle + limit_range;
float L2 = zero_angle - limit_range;
//angle_range 范围内
if (angle > L2 && angle < L1) {
FOC_setCurrent_alone(0);
} else { //angle_range 范围外
if (angle < L2)
FOC_setCurrent_velocity_angle(L2);
if (angle > L1)
FOC_setCurrent_velocity_angle(L1);
}
}
其实上面的代码只要是会FOC的都能看懂我在写什么,FOC_setCurrent_alone(0);这个就是只有单独一个电流环函数,只要你旋转旋钮,由于产生了电流,由于有电流环的PID作用(我的目标电流值是0),你会感到一丝阻力,而当旋转超过我设定的边界后,马上就会切换成角度,速度,电流的串级PID环,会强制纠正到指定的角度的,这就是这个有界旋钮的实现思路。
3.阻尼模式和顺滑模式。阻尼模式其实就是使电机转起来阻力感更强,而顺滑模式就是使电机转起来好像有一种惯性,还会再往前转一下。
void zuni_xuanniu(void)
{
FOC_setCurrent_alone(-0.52f*getVelocity_Fillter());
}
void shunhua_xuanniu(void)
{
FOC_setCurrent_alone(0.04f*getVelocity_Fillter());
}
受上面有界函数的一点影响,单独电流环时,如果目标电流值是0,而你用手去旋转从而产生反电动势和电流的话,电机就会产生相反的电流也就是力矩与你给电机的力相互抵消,而如果你想要这个抵消的力更加明显的话,就直接把编码器测得的速度给作为输入的目标值再乘以一个系数即可。当你转动电机,而前面系数又是负的就会形成负反馈,旋转电机就会有阻尼感;当前面的系数是正的时候就会形成正反馈,只不过这个系数不能太大,否则你轻轻一旋转电机,电机就会直接满转速而停不下来了。
总结,其实这个项目就是小菜一碟,主要就是让自己深化一下对FOC程序里每个函数的理解,为后续做更难的项目做铺垫。