SimpleFOC的基本操作在前几节都已经演示过了,虽然还有很多没演示的例程,但是触类旁通,仔细琢磨下难度不大。
网上关于FOC和SVPWM的文章很多,但大都偏理论,最多用matlab验证下,本文通过程序演示验证SVPWM算法,有助于对理论的理解。对理论没兴趣的同学可以跳过。
1、测量电机三相定子电流,可得到Ia 和Ib。将三相电流通过Clark变换至两相电流Iα和Iβ ,
2、按照控制环上一次迭代计算出的电机角度, 通过Park变换得到旋转坐标系下相互正交的电流Id和Iq,
3、Id、Iq与设定值进行比较得到电流环PI控制器的输入。调节PI控制器的参数,得到Vd 和Vq ,即要施加到电机上的电压矢量,
4、通过位置传感器得到新的电机位置,从而得到新的角度和转速。新的电机角度可告知 FOC算法下一个电压矢量在何处,
5、通过使用新的电机角度,Vd 和Vq经过Park逆变换产生下一个正交电压值Vα、Vβ,
6、采用SVPWM算法判定其合成的电压矢量位于哪个扇区,计算出三相各桥臂开关管的导通时间,最后经过三相逆变器驱动模块输出电机所需的三相电压。
由三相功率逆变器的六个功率开关元件组成的特定开关模式产生的脉宽调制波,能够使电机电流波形尽可能接近于理想的正弦波形。
请看下面这两片文章:
《SVPWM算法原理及详解》https://blog.csdn.net/qlexcel/article/details/74787619,
《SVPWM分析、各个扇区详细计算以及Matlab仿真》https://blog.csdn.net/michaelf/article/details/94013805,
推导的结果是一样的,
实际上大部分文章的SVPWM的算法结果都是这样。我觉得这个结果主要是针对无感FOC的算法,无感FOC需要根据Vα和Vβ来确定扇区和角度,但是对于有位置传感器,特别是有编码器的电机来说可以直接获取角度,上面的推导计算过头了。
首先去掉了电流采样,所以简单了很多,有位置传感器,所以不用观测器估算位置。对空间矢量作用时间可以直接利用下面的公式(这些公式来自《SVPWM分析、各个扇区详细计算以及Matlab仿真》算法推导的中间状态,《SVPWM算法原理及详解》只写了第一个扇区):
对照矢量图,可以总结如下:
Udc表示电源电压(在代码中是voltage_limit),Uref表示设置的力矩大小(在代码中是target_voltage),Ts表示PWM周期(代码中没有把Ts体现出来,代码中的T1、T2是周期的百分比)。
在simpleFOC工程中,先来看下被创作者称之为核心的代码(代码路径: …\Arduino-FOC-minimal\library_source\ BLDCMotor.cpp)
输入变量Uq、Ud和角度θ,计算出3路PWM占空比。对照上面的SimpleFOC原理框图,一个函数基本就把主要工作做完了,确实是核心。
通过设置不同的Ud和θ角度实现不同的波形输出,并将三相输出波形与SVPWM的理论波形做对比。
本实验分两个阶段来完成,第一阶段先直观感受下SVPWM参数对电机运转的影响,第二阶段电机三相输出波形与理论做对比。
序号 | 名称 | 数量 |
---|---|---|
1 | Arduino UNO | 1 |
2 | simpleFOCShield V2.0.3 | 1 |
3 | 云台电机 | 1 |
4 | 12V电源 | 1 |
5 | 方口USB线 | 1 |
simpleFOC工程以库的形式安装到Arduino中,不能修改底层代码,所以只能把代码复制出来,以子程序的形式放到当前程序中。之所以选择standalone例程,是因为这个例程比较简单,而且本身就是演示矢量控制的。
①、增加SVPWM算法的子程序
②、loop循环中调用子程序
例程为只读文件,可以验证上传,如需保存要“另存为”。
SVPWM子程序(为了让代码看起来更简洁,所以程序中没有约束条件,参数设置一定要按要求范围输入):
void setPhaseVoltage(float Uq, float Ud, float angle_el) {
int sector = (angle_el / _PI_3) + 1; // find the sector we are in currently
float T1 = _SQRT3*_sin(sector*_PI_3 - angle_el) * Uq/driver.voltage_limit;
float T2 = _SQRT3*_sin(angle_el - (sector-1)*_PI_3) * Uq/driver.voltage_limit;
float T0 = 1 - T1 - T2;
float Ta,Tb,Tc;
switch(sector){
case 1:
Ta = T1 + T2 + T0/2;
Tb = T2 + T0/2;
Tc = T0/2;
break;
case 2:
Ta = T1 + T0/2;
Tb = T1 + T2 + T0/2;
Tc = T0/2;
break;
case 3:
Ta = T0/2;
Tb = T1 + T2 + T0/2;
Tc = T2 + T0/2;
break;
case 4:
Ta = T0/2;
Tb = T1+ T0/2;
Tc = T1 + T2 + T0/2;
break;
case 5:
Ta = T2 + T0/2;
Tb = T0/2;
Tc = T1 + T2 + T0/2;
break;
case 6:
Ta = T1 + T2 + T0/2;
Tb = T0/2;
Tc = T1 + T0/2;
break;
default: // possible error state
Ta = 0;
Tb = 0;
Tc = 0;
}
// calculate the phase voltages and center
float Ua = Ta*driver.voltage_limit;
float Ub = Tb*driver.voltage_limit;
float Uc = Tc*driver.voltage_limit;
driver.setPwm(Ua,Ub,Uc);
}
上电后电机开始转动,当前的转动方式其实就是开环速度模式。
修改Uq值(范围0—6.928),重新验证上传,会发现电机的力矩改变了,如果有万用表会发现电机的工作电流随Uq等比例改变。
注意:Uq值设置越大,力矩越大,电流越大,电机发热越严重。
修改角度增量,重新验证上传,会发现电机的转速改变了,
注意:增量越大电机转速越快,增量太大电机会因失步变振动。
在第一阶段程序的基础上,
①、增加了串口通信子程序,实现通过串口设置电机的电角度,
②、通信程序放入主循环
③、角度值由上一节的循环增加变为串口设置。注意为了更加直观,串口设置的角度单位为“度”,所以会有“度”转换为“弧度”的计算。
串口通信子程序:
void serialReceiveUserCommand() {
// a string to hold incoming data
static String received_chars;
while (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the string buffer:
received_chars += inChar;
// end of user input
if (inChar == '\n') {
// change the motor target
theta = received_chars.toFloat();
Serial.print("Target Angle:");
Serial.println(theta);
// reset the command buffer
received_chars = "";
}
}
}
程序运行后,电机固定在0度位置,类似开环位置模式。
通过串口发送角度值(直接发送数字,范围0—359),电机运动到指定的角度。(此时的角度为电角度,所以电机在一个很小的范围内运动。比如当前用的电机为7对极,电机从0转动到360度,转过了电机的1/7圈。电角度和机械角度的概念请自行百度。)
串口输入角度,示波器查看三相输出波形,并与理论做对比。(示波器只有两个通道,所以三相波形只能通过拼接得到)
①、30度
⑥、330度
顺便说下,Arduino UNO 的PWM频率是31.25KHz。16MHz晶振,时钟不分频,PWM模式为相位校正模式(Phase Correct PWM Mode,在STM32中称之为 中央对齐模式),16000/256/2=31.25KHz。
下面是PWM的配置代码(代码路径:…\Arduino-FOC-minimal\library_source\drivers\hardware_specific\atmega328_mcu)
本文涉及理论的部分写的很笼统,存在用词不准确,语句不通顺的问题,请大家不要太纠结,做为一名合格的工程师就是要把科研人员的理论转变为可以落地的代码,理论不是我的强项也不是我的目标。
(完)
欢迎加入simpleFOC技术交流群:923734429 (入群申请写:CSDN)
请继续阅读相关文章:
SimpleFOC(一)—— 简介(附有文件下载链接)
SimpleFOC(二)—— 快速入门 (开环控制)
SimpleFOC(三)—— AS5600角度读取
SimpleFOC(四)—— 闭环控制
SimpleFOC(五)—— 双电机控制
SimpleFOC(六)—— PowerShield和AS5047P
SimpleFOC(七)——STM32(Bluepill)的应用
SimpleFOC(八)—— 理论+实践 深度分析SVPWM
SimpleFOC(九)—— 霍尔电机控制