本帖最后由 王昱顺 于 2023-10-25 20:32 编辑
新的Fast-SVPWM算法,这次通过查阅了一些论文,发现了有一个可以降低硬件消耗实现SVPWM算法的文章。
现在通过代码实现了一下,这里输出的值是串口绘图得到的。可以看出来是非常标准的马鞍波。
等下午实机运行一下试试。
电机与控制学报_一种低硬件资源消耗快速SVPWM算法.pdf
(1.25 MB, 下载次数: 149)
核心代码部分:
- #define voltage_power_supply 12.0 // 最高电压限制
- #define _constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))
- #define PI 3.14159265358979323846
-
- // 归一化角度到 [0,2PI]
- float _normalizeAngle(float angle)
- {
- float a = fmod(angle, 2 * PI); // 取余运算可以用于归一化,列出特殊值例子算便知
- return a >= 0 ? a : (a + 2 * PI);
- // 三目运算符。格式:condition ? expr1 : expr2
- // 其中,condition 是要求值的条件表达式,如果条件成立,则返回 expr1 的值,否则返回 expr2 的值。可以将三目运算符视为 if-else 语句的简化形式。
- // fmod 函数的余数的符号与除数相同。因此,当 angle 的值为负数时,余数的符号将与 _2PI 的符号相反。也就是说,如果 angle 的值小于 0 且 _2PI 的值为正数,则 fmod(angle, _2PI) 的余数将为负数。
- // 例如,当 angle 的值为 -PI/2,_2PI 的值为 2PI 时,fmod(angle, _2PI) 将返回一个负数。在这种情况下,可以通过将负数的余数加上 _2PI 来将角度归一化到 [0, 2PI] 的范围内,以确保角度的值始终为正数。
- }
-
- // 快速判断返回所在扇区
- u8 Fast_Sector(float Ua, float Ub)
- {
- return (fabs(Ub) >= fabs(Ua)) ? 2 : (((Ua * Ub) >= 0) ? 1 : 3); // 直接判断返回扇区信息
- }
-
- // 执行快速SVPWM算法,填入相应的占空比延时
- float Duty_A, Duty_B, Duty_C;
- void Fast_SVPWM(float Ua, float Ub)
- {
- switch (Fast_Sector(Ua, Ub))
- {
- case 1:
- Duty_A = (1 - Ua - Ub) / 2, Duty_B = (1 + Ua - 3 * Ub) / 2, Duty_C = (1 + Ua + Ub) / 2;
- break;
- case 2:
- Duty_A = (1 - 2 * Ua) / 2, Duty_B = (1 - 2 * Ub) / 2, Duty_C = (1 + 2 * Ub) / 2;
- break;
- case 3:
- Duty_A = (1 - Ua + Ub) / 2, Duty_B = (1 + Ua - Ub) / 2, Duty_C = (1 + Ua + 3 * Ub) / 2;
- break;
- default:
- break;
- }
- printf("%f,%f,%f\r\n",Duty_A-0.5,Duty_B-0.5,Duty_C-0.5);
- }
-
- // 常见数值
- #define SQART3_2 0.86602540378
- #define SQART3_3 0.57735026919
-
- // 执行压缩算法,进行SVPWM
- float _Ua, _Ub;
- void Transform_To_SVPWM(float Ua, float Ub)
- {
- _Ua = Ua * 1 * SQART3_2;
- _Ub = Ub * SQART3_3 * SQART3_2;
- Fast_SVPWM(_Ua, _Ub);
- }
-
- // 2023年9月20日11点35分添加Ud内容
- // 2023年9月22日添加SVPWM
- // 2023年10月25日改进SVPWM
- float Ualpha, Ubeta;
- //Uq是q轴电压设定,也就是期望电压(包括上半部分和下半部分)。Ud是d轴电压设定,angle_el是当前电机的实际角度
- void setTorque(float Uq, float Ud, float angle_el)
- {
- // 幅值限位
- Uq = (Uq*2)/voltage_power_supply;
- Uq = _constrain(Uq, -2, 2);
- Ud = (Ud*2)/voltage_power_supply;
- Ud = _constrain(Ud, -2, 2);
- angle_el = _normalizeAngle(angle_el);
- // 帕克逆变换
- Ualpha = (Ud * cos(angle_el)) - (Uq * sin(angle_el));
- Ubeta = (Uq * cos(angle_el)) + (Ud * sin(angle_el));
-
- Transform_To_SVPWM(Ualpha, Ubeta);
- }
复制代码
实机测试视频:
|