牛卧堂MCU技术交流
标题: 无感FOC代码: 调试简单,起转顺利 [打印本页]
作者: Angus 时间: 2016-8-10 16:46
标题: 无感FOC代码: 调试简单,起转顺利
本帖最后由 Angus 于 2025-5-13 15:29 编辑
参考原理图
M451_FOC.pdf
(39.23 KB, 下载次数: 4708)
, 图中第三相驱动和前两相一样,省略, 省一页图纸。
M451无感FOC吸尘器在10万转时,电流钳测的电流波形
每个PWM周期的计算耗时小于20us。如果 PWM=30KHz/周期33us,转速就可跑到 15万转。
启转快,同步快,代码精简到8K
顺风启转,直接同步
让电流设定值突变,电流响应快、并且无超调
有感FOC的IAR工程代码:
M451_SVPWM.zip
(1.57 MB, 下载次数: 5232)
运行此代码,不接电机,在PWM0_0, PWM0_2, PWM0_4 引脚接 10K/1uF 阻容后就可测到如下波形
无感 FOC 代码
M451_FOC_V26.zip
(829.57 KB, 下载次数: 2868)
,带详细中文注释,量产后可开放 M4_SVPWM.lib。
1>,在 DQ 坐标轴做的磁链观测器,并且用到了 M4 的 DSP 指令加快运算。
2>,有电流超前角,基速以下 MTPA 控制,基速以上弱磁控制。
3>,三闭环控制,有功率闭环控制。
4>,有加速度控制,可调节加减速的快慢。
5>,积分分离法 PI 抗饱和运算。
6>,有顺风起转功能。
7>,静止起转有两种方法可选:普通启动和快速启动。
每一行代码都反复检查并测试,我们精雕细琢,只为性能卓越
此代码效果的视频
M451_Video.zip
(32.33 MB, 下载次数: 754)
电机参数不同或电路不同时,代码修改说明
M451无感FOC 代码说明.pdf
(1.91 MB, 下载次数: 2588)
PWM 触发ADC中断代码流程: 读取电流 =>迭代运算、估算位置=>算三路PWM 占空比写入寄存器
过调制输出电压。 过调制可提高电压利用率
技术支持电话
新唐电子科技(上海)有限公司 021 - 62365999
-
-
M451_FOC基本原理.pdf
1.73 MB, 下载次数: 3755
作者: Uwen 时间: 2016-11-30 17:03
hello:
读了一下程序,发现有几个值没整清楚。
Voltage_dc = 100000 ; // PWM 周期是 4000, 母线数值太大无意义
Voltage_q = 40000 ; // Vd,Vq 范围 -65535 ~ 65535
Voltage_d = 1000 ; // Vq,Vd 的模超母线的 0.577 倍波形会消顶
这几个值,如果电机不一样,输入电压有变化,怎么选择?有怎么样的算法?有例程吗? 谢谢!!!
作者: Angus 时间: 2016-12-3 12:05
本帖最后由 Angus 于 2017-3-14 22:11 编辑
看一下 FOC 控制框图,系统控制的输入量是 Id,Iq 的设定值。Vd,Vq 是 PI 计算出来的理想值,再由 Vd,Vq算出 PWM 的占空比。
若想提高调节精度,一方面要增大 PWM 周期,PWM 周期为 4000 时,调节1,电压只调整了 1/4000。另一方面要提高由 Vd, Vq 计算 PWM 的精度。采用定点数,只能提高 Vd, Vq 的数值,而 Vd,Vq 的最大取值受限于母线的最大取值。
由此可见,母线数值选的越大,Vd,Vq 被允许的范围就越大,计算精度就越高。母线最大数值若超过 PWM 周期的四倍以上,电压的舍入误差已小于 PWM 所能达到的精度的 1/4,PWM 已无法完成如此精细的电压调节。
作者: rete0786 时间: 2017-3-14 13:32
哈哈,好东西,赞一个
作者: arm_nuedu 时间: 2017-7-27 20:39
PD->MODE = 0x00000400 ;
SYS->GPD_MFPL = SYS_GPD_MFPL_PD0MFP_UART0_RXD
| SYS_GPD_MFPL_PD1MFP_UART0_TXD ;
还有这个PD0 PD1,不是该0X0000 0004
作者: Angus 时间: 2017-7-27 21:46
代码中 PD->MODE = 0 ;
PD0 配置为 RXD 自动为输入,PD1 配置为 TXD 自动为 CMOS 输出, PD->MODE 的值已无效
作者: arm_nuedu 时间: 2017-7-28 11:48
哦哦,明白了,谢谢
作者: xiaoxiao2013 时间: 2018-11-20 13:57
请问,你启转那个图片是怎么启动的?是无感运行?看图上没有开环切闭环,是不是这样?你那个位置估算器是常用的,难实现这样的效果
作者: Angus 时间: 2020-5-29 14:09
本帖最后由 Angus 于 2020-5-29 14:12 编辑
电机中的三组线圈在圆周上呈120度安放,三相通电后,合成电压的方向可以是360度的任一方向,所以就用复数表示,Valpha + jVbeta
所以Valpha, Vbeta 是电压失量的实部和虚部,是计算的中间变量。
作者: 匿名 时间: 2022-1-10 21:39
调速旋钮刚好在最小启转值附近时,可能因数据抖动,造成启转、停转、启转、停转现像。为了防止这种现象,将调速旋钮值,做回差处理,如下图。
未转时,旋钮从0向上调,超过最小值的3/4, 到最小值之间,都算是最小值。
转动时,旅钮从上向下调,高于最小值的一半,到最小值之间,都算最小值。
未转时,旋钮调到3/4处,就会启转,这时,旋钮值上下抖动一点,转速设定值保持最小值不变。
实现代码,如下:
作者: a20084666 时间: 2022-1-15 14:40
最近出的都是干货
作者: Angus 时间: 2022-1-20 14:35
本帖最后由 Angus 于 2024-9-15 16:10 编辑
这里讲一下代码中的 PI 运算。
模拟 PID 运算公式 :
去掉微分运算,再把公式离散化,公式变为:
采用增量式算法:
下面是转速 PI 运算的代码
代码 733 行:增量 = Kp*[本次误差 - 上次误差] + Ki * 本次误差
代码 734 行,temp32 = U(n-1) + 增量。
736~739行是抗饱和运算
741 ~ 742行,计算结果 temp32 做限幅后,再赋值给电流设定值变量 Is_set_f12
作者: Angus 时间: 2022-1-23 21:36
本帖最后由 Angus 于 2024-9-12 13:41 编辑
这里讲一下 Clark 变换
求 I_alpha, I_beta, 就是求电流向量的实部和虚部。A相在0度,B相在120度,C相在-120度,三个电流写成复数形式分别为
求三个电流的“失量和” 。 三相电流的“标量和=0“,即Ia+Ib+Ic = 0,这个不用求。
因为在下MOS 导通时测电流,显然下MOS导通时间长时,电流ADC 受PWM 开关影响就小,值相对准确一些。
如果 C 相下 MOS 导通时间短、就用 Ia 和 Ib 计算电流向量, Ic = -Ia-Ib 代入向量求和公式,得到
消去 Ia 或 Ib 的公式,请读者自己推导
等幅变换中电流向量若是 I, 则对应相电流峰值是 I*2/3。所以上式求出的电流向量,乘2/3后才与控制量对应, 这样公式就变成了
上式这个电流向量的模,正好与相电流的峰值,数值上相等。
下面来看代码,
181~189行,按扇区,选择下MOS导通时间长的两相, 求I_alpha, I_beta,为了减小计算误差先增加小数,数值乘8
191行,1/3 的开方=0.57735 =18919/32768, 所以乘18919再右移15位就是乘1/3的开方,右移小了3位,等于是把结果乘了8
执行完191行后,就求出了 I_alpha,I_beta 。接下来坐标变换求出了有3位小数的 Id 和 Iq 电流
作者: 匿名 时间: 2022-10-27 10:15
请楼主再给讲解一下变量标幺值,看不懂
作者: Angus 时间: 2022-10-27 21:48
本帖最后由 Angus 于 2024-9-12 14:00 编辑
电压的基准值是 0.1V。最大值是 16383,若超过此值, 乘4后大于等于65536做坐标旋转会溢出,即最大工作电压是 1638.3V。 在ADC中断里, 读出母线电压ADC值,就换计算出0.1V 的数值,然后赋给变量 V_BUS_0v1
具体代码如下: 母线电压,电路上是俩220K 串4K1电阻分压后到ADC 引脚,所以分压比 (220*2+4.1)/4.1, 12位ADC 参考电压是5V, 所以 ADC值换算成电压公式是:
电压 = 5V * ADC值 / 4096 再乘分压比(444.1/4.1), 这个公式右边再乘10 就是0.1V数值,简化后 = ADC值*5416/4096 。代码中 355 行, 加1024是四舍五入,右移 11位是除 2048,少除了2后面补上。
把当前电压 ADC 值看作 X,
457行是求出了 2X。
458行是 2X + 2Y, 这是母线电压的4倍, 成了 25mV 的数值, 用25mV数值去做 SVPWM计算, 哪怕工作电压不到10V,也有足够的计算精度。最大电压 1638.3V 的数据乘4后得65532, 坐标变换也不会溢出。
459行是 (2X + 2Y)/4 = (X+Y)/2, 这是一阶低通滤波 Y(n) = [Y(n-1) + X(n)]/2。
SVPWM 能输出的无失真相电压,最大值是 0.577倍的母线电压,再大, 就是削顶的正弦电压了。 263行,选择一个相电压上限值。
265行, 增加17位小数后,赋值给 Vq_Limit_f17,Vd_Limit_f17 (后缀 _f17 表示17位小数) 用于电流PI 运算结果的上限值。 电流PI 运算结果有17位小数, 电压上限在这里先增加17 小数,比在PI 运算结果限幅时再增加17位小数,节省代码。
作者: Angus 时间: 2022-10-27 22:01
本帖最后由 Angus 于 2023-2-19 11:09 编辑
电流的基准是ADC 的值。一般电流ADC 数值较小,换算后会损失精度,所以不换算。ADC中断里,读出电流ADC 值乘 8 后再坐标旋转,求得 dq 轴电流赋给 Id_Measure_f3 ,Iq_Measure_f3 ,此处后缀 _f3,表示有 3 位小数。
在做电流PI 运算前,对直流量 Iq_Measure_f3 又做了一次滤波,并增加了一位小数赋值给 Iq_Meas_LPF_f4, 后缀 _f4 表示有 4位小数。
作者: 匿名 时间: 2022-10-28 15:00
十分感谢楼主解答,顺便请教一下这个代码有没有试过比较大的电感和电阻电机,如果一般冰箱压缩机的电阻有几欧姆到十几欧姆,电感几十到一百多mH,油烟机的风机电感和电阻也很大,惯量也大,可以试试效果。
作者: Angus 时间: 2022-10-28 21:26
本帖最后由 Angus 于 2022-10-29 12:44 编辑
下载代码后,不做改动,电感最大可到100mH,电阻最大可到500欧。
如果电感再大,可把电感除10后再赋值给Ld/Lq,然后把单位常量Unit_Magnify 也除10就可以。
目前我测试过的电机,电感最大的是220V的电机:50220/49220uH;电感最小的是航模电调用的一个小电机:11/9uH。
作者: 匿名 时间: 2022-10-29 20:00
谢谢!再请教一下,Angle_q是不是开环时候假定的转子Q轴角度,同步以后就是观测器算出来的真实转子Q轴角度?
作者: Angus 时间: 2022-10-29 20:57
是的。
另一角度看,Angle_q 总是是坐标旋转的角度。起转时软件控制角度,同步时用估算的角度。
作者: admin 时间: 2022-11-21 16:08
M451 可做 FOC + PFC 方案。 也可做 FOC + CAN通信 方案
七段式SVPWM 算法,一个PWM 周期有两次电流注入,所以电流频率是PWM 频率的两倍,PWM 频率若用10KHz(周期是 100us),电流频率主要是20KHz,所以噪音已比较小。
此M451 FOC 方案,PWM(ADC)中断耗时20us左右,所以另一组PWM 完全有时间做 PFC 控制。
我们推荐以下引脚配置, 同时留出CAN 通信引脚。PA2,PA3 可控制大功率 PFC 的主管和副管。
作者: Angus 时间: 2023-2-15 17:19
本帖最后由 Angus 于 2024-9-12 14:30 编辑
停转时一定关功率管吗? 停转后可以去状态0关功率管,也可去状态5 保持小电流锁定状态。这个由宏定义 MOTOR_STOP_STATUS 配置。
状态2输出0电压,若 RPM_Set >= RPM_STOP_VALUE, 上三管保持关断 , 下仨 MOS 输出使能,七段式SVPWM下管只导通50% 时间,所以不会刹车,可以给自举电容充电。
main()开头,外设初始化时,进状态2 等50ms,就是给自举电容充电 50ms(RPM_Set 初值= RPM_Stop_Value -1)。
状态2 代码见下面截图:
1> 397行,若 RPM_Set >= RPM_Stop_Value 时,PWM->MSKEN = 0x15。就是关上MOS, 只下MOS 输出使能。 否则哪路输出使能由中断外决定。
状态5锁定后,检测转速设定值 RPM_Set 是否大于0(301行),转速设定值大于0才起转,否则保持锁定状态,代码截图如下:
作者: Angus 时间: 2023-2-16 09:27
本帖最后由 Angus 于 2023-2-21 10:16 编辑
此代码起转方式,是 I/F 起动,还是V/F 起动?
这两种起动方式可以在代码中选配,由宏定义 __DO_CURRENT_PI_WHILE_ACTIVE 配置。
若选配了起动过程中做电流PI,就是I/F 起动,起动时,在状态2给自举电容充电后,变状态5磁体先吸到某个位置(这里耗费较长时间),再变状态4控制起转过程。整个过程电流是受控制的,对保护控制器比较有利。
若未定义__DO_CURRENT_PI_WHILE_ACTIVE ,就是起动过程不做电流PI控制, 起动时,在状态2给自举电容充电后,变状态3控制起转过程,起动过程稍快,但不做电流控制,电流波动较大。所以起动电压不要太大,防止电流冲太高对功率管不利
作者: Angus 时间: 2023-2-19 12:36
本帖最后由 Angus 于 2024-9-12 14:33 编辑
PWM 频率 15KHz 以上,用五段式 SVPWM, 可降低功率管开关次数,减小功率管发热量。
若 PWM 频率较低,10KHz 以下,就用七段式 SVPWM ,可降低 PWM 频率开关噪音,因为电流通断频率是 PWM 频率的两倍。
函数 M4_SVPWM() 是按五段式计算出的、三对PWM 的不供电时间。在本例中,就是PWM 低电平时间,是两边低电平时间和。把三个指针返回值,除2后写入占空比寄存器即可。
如果要用七段式,低电平最短的那路PWM, 低电平时间 temp16 要减半,另两相低电平时间,也减去 temp16/2
返回值 Section 的低16位,是 T1+T2, 即最大导通相的高电平时间。所以 temp16 = PWM周期 - Section 就是:低电平时间最短那相的、低电平时间。
五段式变七段式,只要三个指针返回值,都再减 temp16/2 就可以了,代码如下。
返回值 Section 低16位是 T1+T2 未修正值,如果它超过周期值了,就不必减了。
作者: Angus 时间: 2023-2-21 22:23
本帖最后由 Angus 于 2024-9-12 14:36 编辑
Vd_out_f17, Vq_out_f17 是电流 PI 计算出来的,有可能它俩的模大于母线电压,再计算 SVPWM 时,就会出现 T1+T2 > PWM 周期的情况。这时会修正 T1+T2 = PWM 周期,输出电压就比 Vd_out_f17, Vq_out_f17 小了,这时若用Vd_out_f17, Vq_out_f17做位置估算,比实际输出电压值大,位置估算数值就出错了。
因此 SVPWM 若 T1+T2 > PWM 周期,就要修正 Vd_out_f17 = Vd_out_f17 * PWM 周期/(T1+T2), Vq_out_f17 = Vq_out_f17 * PWM 周期/(T1+T2),如此 Vq/Vd 又等于实际输出电压了。
代码如下
在做 SVPWM 时,I_beta,I_alpha 二者已赋值去掉15位小数的电压值Vq_out_f17, Vd_out_f17, Section 的低16位是未修正的 T1+T2
把电压修正后,552,553行恢复小数位后,赋值给Vq_out_f17,Vd_out_f17
此处修正用的不是PWM 周期,而是 Pwm_Duty_Uplimit,因为这个值是计算 SVPWM 的上限,T1+T2 大于这个值,就会修正到这个值。
作者: Angus 时间: 2023-2-24 21:59
本帖最后由 Angus 于 2023-2-25 20:28 编辑
为什么 T1+T2 > Pwm_Duty_Uplimit 时,就要等比例减小T1,T2 呢, 这个上限本应该是 PWM 周期,为何可以比 PWM 周期小呢?
当 T1 + T2 = PWM 周期时,输出电压达到最大,电压向量就是下图中、最大的那个边长为(VDD*2/3)的六边形,这种情况,上管导通的占空比很大,下管导通时间很短。双电阻测电流方式,因不能轮换测电流相,可能会在某个时刻测不到电流,或因下管导通时间太短,测到的电流误差太大,影响角度估算。
在红蓝相输出电压最大时,红蓝相下管导通时间几乎=0。
如果 SVPWM 计算时,限制 T1+T2 最大= PWM*0.8,则输出电压向量的六边形大小,就减小到80%,限制了下管导通的时间 >= 20%. 这样在下管导通时测电流的时间就很宽裕了,当然,这样最大输出电压也低了一些。
作者: Angus 时间: 2023-3-2 22:00
本帖最后由 Angus 于 2023-3-3 16:00 编辑
观测器函数M451_FOC_Reckon()总在执行,只是在磁铁不转时,估算出的磁铁角度数值 Estimate_Q_Position 会大幅度跳动,数值是随机的。
电机转起来后,有了反电势,反正切估算出的角度Estimate_Q_Position 跳动幅度变小, 当数据跳动连续N 次小于某个值时(代码中可配置),就认定磁铁角度估值准确,就是估算已收敛,变量Position_Explicit 变非0。但这时电磁场与磁铁的位置不一定是90度,可能大于90度,也可能小于90度。
起转时,电流强托,电磁场角度逐增 Angle_q += Pull_Ommega >>16;
估算收敛后,启转函数Adjust_Pull_Ommega() 中会加快、或减慢电磁场的转速Pull_Ommega,向永磁体垂直方向靠近, 同时返回磁铁垂直方向(Q轴)与当前电磁场的角度差Estimate_Q_Position - Angle_q,做为调整电流的依据。
作者: Angus 时间: 2023-3-20 22:19
从黄色估算角度的曲线来看,角度很快就收敛了。
启动10ms 左右角度就收敛了。这个图一大格200ms,只有开头的一点点时间,角度不准确,几乎看不出来。
作者: Angus 时间: 2023-3-30 11:36
本帖最后由 Angus 于 2023-3-31 21:58 编辑
这里讲一下电流 PI 参数的取值问题
电机可以看成一个电感串一个电阻,其拉氏变换是 1/(sL+R), PI 控制的拉氏变换是 (Kp + Ki/s) , 这俩公式看不懂的,请去复习一下拉氏变换
电流的 PI 控制图如下,x是电流设定值,y是电机的实际电流。PI 控制的输出是电压V,电压加到电机(电阻+电感), 又调整了电流大小,控制的最终结果是 y=x 。因为有积分运算,所以只要 x-y >0, PI 运算的结果V 就会一直增加,所以电机电流y也一直增加,直到 y=x。
上图写成公式
公式化简
令 Ki = K*Kp, K是一个常数,公式变为
上式可变成 y 的二阶微分方程,求出 y 的解,用拉氏反变换的方法也可求出 y 的解。
当设定电流不变、即x=常数时,y 的解的形式是:
,
其中 x1,x2 是 S 的一元二次方程
的解。我们先不求解,讨论解的形式,比较简单。
S的一元二次方程有俩实数解时,y 的解中,e的指数是实数,y 的值指数变化(增加或衰减)趋于终值C0,没有振荡。
如果上述一元二次方程的解是复数,e的指数是复数,按欧拉公式,就是y的解是三角函数、乘e指数。y的解有三角函数,就是电流 y 有振荡。PI 控制效果、是振荡式趋于稳定值C0,这是我们不希望的。
上述S的二次方程有实根,必须满足:
上式可写成
,第二个括号内的值 >=0,就满足整个公式>=0。
从第二个括号内式子 4RKp - 4LkKp >=0 得出 R - LK >= 0,即 K <= R/L
所以,Ki 满足下式, 电流响应就不会有振荡:
这就是 Ki 取值的理论依据,实际上 PI 控制环路还有PWM 滞后一个周期等其它微小滞后因素,Ki 的这个临界值,比 R/L*Kp 还大一点,也就是只要Kp的取值不会引起振荡,Ki 取值 = R/L*Kp 也不会振荡。
作者: Angus 时间: 2023-4-10 11:00
本帖最后由 Angus 于 2023-4-10 13:27 编辑
Kp 如何取值呢?
楼上已推导出 Ki 取值 = RKp/L,我们重新推导楼上过程,
上式,是一阶低通滤波器的公式,低通的带宽(或转折频点)是
套用拉氏反变换公式,可求出冲激响应。或者把上式变成微分方程也可求出时域解为下式:
冲激响应的积分,是阶跃响应。对上式求积分,得到输入突变时的输出公式、和函数图形如下。
低通,除了用带宽描述,还有一种描述方法是: 阶跃上升时间,一般取“输出上升到1-1/e ”的时间,做为上升时间,如上图,t=L/Kp 时上升到 1-1/e。
电机的电流 PI 控制,电流上升时间一般取15个PWM周期以上,上升太快,输出容易振荡。
我们代码中的注释,建议取值 20~100个 PWM周期, 即低通带宽是 PWM 频率的 1/20~1/100
确定了低通带宽,就确定了Kp
这就是电流 PI 控制系数的计算方法。
作者: Angus 时间: 2023-4-11 11:22
本帖最后由 Angus 于 2023-4-11 11:26 编辑
前面推导可知,电流 PI 系数可按下式确定
L,R 是电机线圈的电感、电阻, N = 20~100
作者: Angus 时间: 2023-4-16 13:00
本帖最后由 Angus 于 2024-9-15 16:15 编辑
按前面所讲,令PWM 频率是 fp, 则比例系数 Kp = 2*3.14159*fp*L/N, N=20~100,为计算方便取值 10*3.14159=31.4159 ,变为 Kp = fp*L/5
推导 PI 系数,用的是标准单位,电压用伏特,电流用安培,电阻用欧姆,电感用亨利。 电流比例运算 V = Kp*I ,
M451 代码中,电流 PI 运算结果,是 0.1V 的数值再增17位小数的变量 Vq_out_f17,比例运算公式两边乘10* 2^17, 变为 (10*2^17)*V = (10*2^17*Kp) * I ,
电流用的是 ADC 值再增5位小数的数值 Iq_Meas_LPF_f5。假如电流采样电阻是 r, 运放倍数是A, 1安电流(5V参考电压,12bit)ADC值就是 Ar*4096/5。再增5位小数,就是再乘32。比例运算公式变成
(10*2^17)*V = (10*2^17*Kp) * I *( Ar*2^32/5)/ (Ar*2^32/5),
等号左边是Vq_out_f17,等号右边下划线部分是 Iq_Meas_LPF_f4(的误差), 公式变成
Vq_out_f17 = (10*2^17*Kp) / (Ar*2^32/5) * Iq_Meas_LPF_f5 。
所以比例系数 Kp_Current =(10*2^17*Kp) / (Ar*2^32/5) = 50Kp/(Ar)
再代入Kp = fp*L/5,得出比比例系数 Kp_Current = 10fp*L/(Ar) , 这里L,r 用亨利/欧姆,或者毫亨/毫欧
积分系数 Ki_Current = Ki*T = Ki/fp = Kp*R/L/fp, 所以 Ki_Current = Kp_Current *R/L/fp = 10R/(Ar), R是电机绕线电阻,r是电流采样电阻。
所以, M451 代码中,电流 PI 系数用以下公式求得:
A是运放倍数。 电机 L/R 和电流阻 r 用欧姆、亨利, 或者毫欧、毫亨。
上图 406 行求出电流误差,409行是用M4内核的饱和运算指令qadd加增量 ,即 Vq_out_f17 = Vq_out_f17 + I_beta ;
作者: 匿名 时间: 2023-4-25 11:58
标题: RE: 15万转无感弦波: 风机水泵吸尘器,航模电调压缩机
请楼主讲一讲,为何电压向量要乘2/3 ?
A 相接电源 BC 接地时,假如一相电阻是R, BC 相并联电阻是R/2,
所以 A 相分压是 VDD*2/3,BC 相分压是 VDD/3,
而 BC 相电压在 A 相方向的投影都是VDD/6, 如红色线。BC 相合成的向量是 VDD/3,
这样 ABC 相电压合成向量,应该是 A 相的 VDD*2/3 加 BC 相的 VDD/3,应 = VDD。
但所有资料里都说是 VDD*2/3 ? 而且没有解释
作者: Angus 时间: 2023-4-29 21:00
本帖最后由 Angus 于 2023-5-3 22:00 编辑
前面乘 2/3 是等幅变换。等幅变换是电压向量的模、等于相电压幅值的变换。
以下是推导:
假如 A,B,C 三相电压依次滞后120度,相电压幅度都是U, 就是如下图形和三个公式
三相线圈,空间上的位置是:A相在0度,B相在120度,C相在 240度(或-120度),所以三相电压的“向量和”就是下式
我们对此三相电压的向量和,化简一下
以上推导结果可知,三相电压的“相电压”幅度如果是U, 接到三相电机上,产生的电压向量:是模 U*3/2 的、均速转动的向量。
我们国家的三相电是220V, 有些国家的三相电是110V, 还有些国家用的是 240V,
假如你在国外见到一个用电器,用 ADC 测到某个时刻、此电器输入的三相电压的瞬时值是 ADC_a, ADC_b, ADC_c,此用电器接的电压是多少伏呢?显然只要求出此三个ADC 值的向量的模,然后再乘 2/3 就是三相电压的“相电压”幅值
所以,电机 FOC 控制,在求电压(或电流)向量时,乘系数 2/3 是等幅变换,求出的是方向不变、但 "模=相电压幅值" 的向量。
作者: 匿名 时间: 2023-5-11 22:26
作者: Angus 时间: 2023-5-29 21:03
本帖最后由 Angus 于 2023-6-1 09:15 编辑
以下起转函数,函数 Adjust_Pull_Ommega()可以重载,所以可直接用这个函数名,加到文件中
若有兴趣,可对此函数优化, 起转有很多方法
作者: 匿名 时间: 2023-6-7 21:43
角度很小时,角度值=正弦值=正切值,所以下图不求反正切,直接用 Vd/Vq 代替Theta_e 是否也可以?
作者: 匿名 时间: 2023-6-8 11:17
这部分调整思路本省就是有问题的,估算角度-实际角度,调整方法中很多地方用到了估算角度,前提条件是估算角度是准确可靠的,既然估算角度已经可靠了,还要什么if拖动?直接速度闭环启动不就行了?
作者: Angus 时间: 2023-6-8 17:25
本帖最后由 Angus 于 2023-9-4 09:59 编辑
能提出这个疑问,说明你用心思考了,先给你赞一个。
是“估计角度Estimate_Q_Position - 拖动角度Angle_q“
坐标变换函数用的 q 轴角度是 Angle_q,拖动时Angle_q 是代码控制值递增、没用估计角度,因为估计角度还不准。所以拖动时实际电流方向是Angle_q 。
拖动转起来后估计角度Estimate_Q_Position 慢慢准确了,即估算收敛了,但估计角度与 Angle_q 不一定重合,有个夹角,即:电流方向(Angle_q)与“磁铁垂直方向Estimate_Q_Position”有个夹角。
另外磁铁角度刚开始收敛时,估计位置若隐若现,角度时而准确、时而不准(角度数据跳动),电流方向若立即使用估计角度,效果并不好, 逐步接近效果反而更好。
作者: Angus 时间: 2023-6-12 10:58
本帖最后由 Angus 于 2023-9-4 10:58 编辑
正弦值 < 弧度值 < 正切值。 角度很小时,三者的值差不多,可以约等于。
理论上,我们需要减小实际角度与估计角度的偏差,所以计算出角度偏差做反馈量,引入的计算误差最小。
用正切值 Vd/Vq 虽然也可以,但实际角度偏差稍大,就会引入较大计算误差。现在的单片机计算能力很强,不必为了省一点点微不足道的计算量而损失精度。
思路打开,还有一种算法,就是用d轴反电势 Ed 做为后面 PLL 的输入,省掉了除法运算,但缺点是相同的实际角度偏差,反馈量受转速影响。
反正切+PLL ,角度校正量只与角度差成正比,与转速无关。
作者: 匿名 时间: 2023-6-25 16:59
我用的M453板子,220V交流供电,采样电阻0.1欧姆,放大倍数5倍,由于驱动电路原因,PWM频率只能用7K左右,家用油烟机变频风机,电机相电阻20欧姆,Ld=50mH,Lq=50mH,电机是4对极,请教一下我怎么设置参数才可以初步转起来?
作者: Angus 时间: 2023-6-25 18:05
本帖最后由 Angus 于 2023-7-1 22:03 编辑
这个贴子里有个 “M451无感FOC_V23.03代码说明” 文件。你先根据这个文件,把PWM 输出极性,电感参数,电流ADC常数,最大工作电流,等等参数配置正确。
转速PI 参数可以先小一点(加速度会小一点,容易起转),电流PI 参数按注释方法计算出具体值。
起转电流可取最大值的1/3~1/2,起转加速度设置可以小一点。就可以试着起转了。
你还可以电话或邮件向新唐技术人员咨寻细节,或带着实物到新唐办公室调试起转。
作者: Angus 时间: 2023-7-2 23:11
本帖最后由 Angus 于 2024-9-15 16:46 编辑
为简化代码逻辑,无论电机是转是停,都会估算角度并做SVPWM 计算,只是停转时关了功率管,起转时不用估算的角度(因角度还不准确)
状态机变量Motor_Status 的不同值,标识电机停转、起转、同步,等等各个状态,控制代码的执行分支。
无论电机在转、还是停,函数M451_FOC_Rekon() 每个PWM 周期都在执行完成以下三件事:
1>,更新角度偏差Theta_e
2>,估算磁体角度Estimation_Q_Position, 并计算出角度增量做函数返回值
3>,初步判断估算是否收敛:角度偏差(PLL的输入)Theta_e 若连续多次较小,就认为角度已收敛,变量Position_Explicit 写成非0值;若角度偏差较大就 Motor_Status &= ~0x30 清零 bit4/5
起转时,何时切同步转动,除了估算角度收敛之外,一般还有其它条件,比如转速超过某个最小值,已转过一定角度等等。
作者: Angus 时间: 2023-7-26 16:08
本帖最后由 Angus 于 2023-7-26 17:33 编辑
今天让一个电机反复改变转动方向,测试快速起转是否顺畅。无霍尔 FOC 控制,能做到这么快的改变转动方向,效果不错。上视频
Reverse.zip
(2.96 MB, 下载次数: 758)
作者: Angus 时间: 2023-9-15 15:31
本帖最后由 Angus 于 2023-12-28 14:38 编辑
我们测试过10万转吸尘器,测试过220V大风机,测试过不均匀转动的活塞压缩泵,测试过48V汽车空调压缩机,验证我们的观测器和起转方法的通用性,测试都没问题。
作者: Angus 时间: 2023-10-3 21:30
本帖最后由 Angus 于 2023-10-29 18:00 编辑
M451无感FOC方案特性:
1,磁链估计,比电流估计精度好。
2,dq轴估计,比静态坐标轴估计误差小,因为Ld,Lq是常量,而ab轴的电感是随角度变化的,静轴估计理论上就有误差。
3,反正切输入PLL, 比Ea*sin+Eb*cos 输入PLL好,因为前者的值只与角度偏差有关,而后者的值还受转速影响。
4,定点数运算比浮点运算快。电机最小电感仍可10uH以下。我们测试了电感9uH 的吸尘器,起转很好。
5,M4内核有除法指令,更有“抗饱和累加“指令,写代码方便,运算速度快。
6,M451工作电压范围2.5~5.5V, 宽工作电压范围,抗干扰能力强。
作者: Angus 时间: 2023-10-27 17:00
M451无感FOC方案,测试飞行器螺旋桨的视频,示波器上可看到电流波形正弦度很好
电调测试.zip
(2.38 MB, 下载次数: 712)
如果不固定住,就要起飞了
作者: a20084666 时间: 2023-10-27 17:39
的确不错
作者: Angus 时间: 2023-11-26 17:17
本帖最后由 Angus 于 2024-9-15 16:21 编辑
这里讲一下短路保护代码。 逻辑关系有点绕,但工作可靠。
短路信号接到 PWM 的 Brake 功能引脚,短路时,PWM 输出立即关闭功率管、然后产生 Brake 中断。
进 Brake 中断后 811 行写标志,表明执行过Brake中断,用于中断外检查。
812 行写标志,表示关了功率管。如果干扰较强,可采用 BrakeCount 计数的方式,两次或三次 Brake 信号确定是短路了,就保持关功率管关闭。 如果硬件做的好(比如用IPM)短路信号没有干扰,一次 Brake 信号就有效。
清除 Brake 中断标志 PWM0->INTSTS1 后 PWM 的输出就会恢复,不清除 Brake 中断标志退出中断后又会反复进 Brake 中断,所以 816行关了 Brake 中断再返回 ,这样即可保持功率管关闭,又不会反复进 Brake 中断了。
Brake 中断里不能改写状态机 Motor_Status = 0, 因为Brake 中断优先级高,后续可能返回 ADC 中断又被改写,可能打乱 ADC 里的状态机。在中断外、主循环里有“是否发生 Brake ”的检查和后续处理,如下 297 行在这里,改写Mortor_Status =0 才是可靠的。296行把 Stop_Runing 相应位写1,后面检查此标志,RPM_Set 会一直赋值为停转值,不再起转。
以后,只要 Stop_Runing 不清0,406行都会把转速设定值 RPM_Set 写成 <=0 的停转值,Motor_Status 会保持在0、电机自由停转,不会再重新启转。
执行到 343 行时,检查短路是否已解除。 若短路保护已解除,即 Brake_No_Resume =0 了,这里清除 Brake 中断标志PWM0->INTSTS1 、恢复 PWM 输出,重新使能 Brake 中断。Stop_Runing 的短路标志也清除,但此时 Motor_Status=0,因在ADC 中断里有 PWM0->MSKEN = 0 , PWM 引脚输出仍保持着关闭功率管。
功率管如果用的是 IPM , 短路时 Fo 输出几十 us 低脉冲,然后输出高。如果是15V 太低,Fo 会持续输出低,二者都会产生 Brake, 所以, 如果后续检测到是 15V 太低,不是短路,也解除短路保护。
如果没有其它错误,Stop_Runing=0, 后续转速设定值 RPM_Set 就可以正常赋值了。一切从新开始,由 RPM_Set 的值决定是否启转。
作者: Angus 时间: 2023-12-28 11:39
本帖最后由 Angus 于 2024-7-15 18:06 编辑
起转时,即可以线性加速,也可以指数加速。
线性加速的好处是,起转时,如果想让转速慢慢稳定增加,就采用线性加速。
起转开始时,位置不收敛,转速较低,执行63~64行代码,转速逐步增加。
转速低于上限时,64行是线性加速。63行,转速增加一个百分比,这是指数加速度。
然后83行Pull_Ommega_f16 去掉16位小数,加到“位置”角度值 Angle_q 上。
调用函数时,如果实参一用0值,63行转速增加百分比=0,就取消了指数加速,转速仅线性增加。
作者: a20084666 时间: 2024-1-2 14:07
上桥180欧姆的电阻,感觉很大
作者: Angus 时间: 2024-1-2 20:34
功率管栅极电阻,要根据功率管特性调整。开关慢了发热多,开关快了可能会振荡,发热也会多。
作者: Angus 时间: 2024-1-17 21:06
本帖最后由 Angus 于 2024-9-12 16:17 编辑
今天调试一个新板子,总结一下调试步骤:修改好电机Lq, Ld,绕线电阻RESISTER_COIL,以采样电阻及运放倍数CURRENT_Adc1000以后,核对以下事项
1,核对PWM, PWM024 驱动上MOS, PWM135 驱动下MOS。如果不是这样,代码改动稍大。
2,核对PWM 的输出极性,PWM 输出高时功率管导通,如果不是,在函数PWM_Init()中124~125行注释或放开反相函数。
3,核对电流运放的极性,电流流入电机时,运放输出电压增高。电流 ADC 的值为正。若正负反了,在ADC 中断里把Current_PWM01/PWM23/PWM45 数据取反。
4,核对电流 ADC 输入引脚与输出 PWM01/23/45 对应关系。
以上若没错,可以烧录代码,通电了。若转速旋钮=0,上电后在状态0,功率管关闭。这时可以在 ADC 中断代码中增加一个状态7(下面详述两处代码改动)。然后在仿真状态,依次写变量的值 Motor_Status=7, Angle_q=0,PWM->MSKEN=0(PWM输出), Id_set_f12 = CURRENT_Adc1000<<2 (电流值=1A), 这个时候,Current_PWM01的值刚好是1A电流对应的ADC 值。
调试电路,代码如下稍做修改。
ADC 中断里,349 行这里是增加的状态7,什么都不用做,这个状态用于仿真状态直接变量的值
main.c 中主循环这里,333行,增加if(Motor_Status != 7)排除状态7,即状态7也是什么都不做。
CURRENT_Adc1000 = 0xB333, 此值相当于0.25A电流值,设定电流1A, 就是把 Iq_Set_f12写成其4倍的值 = 0x0002CCCC
如下图,10毫欧电阻放大5.6倍相当于56毫欧。
电流1A时,5V 参考源,12位ADC 值是: (1A*56毫欧/5000毫伏)*4096 = 45.875, 仿真看到 Current_PWM01 = 45,
如果Current_PWM01的值若比45小,可能是A相电流有振荡或ADC转换时间窗太短。不过,在0度时,代码中是用Current_PWM23/PWM45计算Ia,Ib的, 所以,只要Current_PWM23/PWM45的电流和=45电流控制就是对的,不影响控制。
输出电压 Vq_out_f17 =1441344,右移17位得0.1V的数值是 : 1441344/131072 = 11, 即输出电压Vq是1.1V,电机电阻是1欧,这个电压值也是对的。
作者: Angus 时间: 2024-2-8 18:00
本帖最后由 Angus 于 2024-7-16 09:04 编辑
有这个宏定义是 I/F 起动,启转阶段从功率管开始工作,电流就在控制范围内。即使换一个型号的电机、电感电阻有较大变化,也不易烧功率管,这是优点。建议初学者先用这个方法试着让电机起转。
若把此句注释掉,就是 V/F 起转,好处是起转快。因起转阶段不做电流 PI 控制、电流波动大,所以需小心确定起转电压。若换个型号的电机、电感电阻参数差异较大,需调整起转电压,否则可能过流。
作者: 匿名 时间: 2024-2-23 14:39
楼主,每次都要采样母线电压的值吗?不太明白,母线电压不是固定不变的吗?请楼主解惑。另外,原理图对不上啊,能否分享一张实际的原理图,采样的是那个点,采样的是相线电压还是母线电压,谢谢!
作者: Angus 时间: 2024-2-23 18:44
如果是交流220V 整流得到的直流,有人为节省成本母线电容用的小,母线电压波动大,这时最好每次PWM 都测一次电压比较好。
此代码是三电阻或双电阻测电流,在PWM 计数起点测电流,即下MOS 导通中间。
我测试的板子,稍做了改动,只要测到母线电压和三相电流,就能转起来。ADC 引脚用哪个、就配置哪个就行。
作者: 匿名 时间: 2024-2-28 08:41
谢谢楼主。
作者: 匿名 时间: 2024-3-6 15:41
关于PARK变换,求出id,iq,我下载的代码如下:(无法发送图片,只能复制)
////===求Idq,前俩实参最大正负65535(可同时最大),否则计算溢出 ========
// *_I_alpha, 输入 I_alpha 返回 Id
// *_I_beta, 输入 I_beta 返回 Iq
// _q_Angle q 轴角度,[0 ~ 65536)表示[0~360)度
void Static_to_Dynamic(int32_t *_I_alpha, int32_t *_I_beta, int32_t _q_Angle)
{
int32_t C11, C21 ;
int32_t Ia = *_I_alpha, Ib = *_I_beta ;
C11 = _q_Angle ;
C21 = Get_cos(&C11) ;
// 65535*0x8000+16384= 0x7FFFC000
*_I_alpha = ((Ia*C11+16384)>>15)+((-Ib*C21+16384)>>15); // 65536 * 0x8000 = 0x80000000 溢出
*_I_beta = ((Ia*C21+16384)>>15)+ ((Ib*C11+16384)>>15); //-65536 *(-0x8000) = 0x80000000 溢出
} //-65535 *(-0x8000) = 0x7FFF8000
上面的的两个等式*_I_alpha和 *_I_beta =,和公式不一致,楼主能给讲讲吗?谢谢@
作者: Angus 时间: 2024-3-7 08:33
本帖最后由 Angus 于 2024-4-1 10:11 编辑
正余弦值 C11,C12,C21,C22有15位小数,所以Ia,Ib乘c11~C22后右移15位去掉小数, 加16384是四舍五入。
若不用浮点运算,整数除法,得到的只有整数的商和余数,比如 20~24 除10,=2.0~2.4, 商是整数部分2。25~29 除10,=2.5~2.9,商也是整数部分2,如何让整数部分是 3 呢?
整数运算没法加0.5,那就在被除数上,加除数的一半(等于加了0.5)。25~29, 加5后再除10 =3.0~3.4,整数部分刚好是3。而20~24 加5后除10 = 2.5~2.9,整数部分仍是 2。
也就是说,整数除法的四舍五入,是在除之前,先在被除数上加除数的一半,再做除法,结果就四舍五入了。
所以,右移15是除32768,四舍五入就在被除数上先加 16384。
作者: Angus 时间: 2024-3-24 11:16
本帖最后由 Angus 于 2024-9-15 16:28 编辑
在做位置估算时,要用到一个低通滤波器。低通带宽若太低,转速响应慢;若太高,起转时容易受干扰、同步慢。所以,可以启转成功后, 把带宽加倍,以加快转速的响应。
低通滤波器的带宽配置函数 Set_PWM_Frequency_LPF(72437760ul/gPWM_Period, 200); 参数一是数据采样频率, 即PWM 频率;参数二是低通滤波器的带宽“角频率”值 Ommega, 实参若用200,转折频点=200/3.14159/2 = 32Hz
此代码中,低通带宽在 main() 中配置后,未再配置。对于风机来说这样做没什么影响。
此低通带宽值在 ADC 中断里计算时用到,所以,可以在 ADC 中断里调用此函数、重新配置低通带宽。
作者: 匿名 时间: 2024-3-25 11:04
这里的低通滤波器,是为了得到一个比较平滑的反电动势是吗?能否详细讲讲。这个算法在启动和低速时和速度正常时的区别,以及如何切换的,谢谢!
作者: Angus 时间: 2024-3-26 09:07
我们是dq 轴估算,直接计算出 q 轴的电势,这个反电势直接与转速成正比。
刚启转时,电流容易受干扰 ADC 数据更容易跳动,计算出的反电势也会数据跳动,就是含有高频分量,由此计算出的转速值,也会有数据跳动。低通滤波,就是滤除数据跳动分量。实际机械转速几乎不跳动,就是频率较低,带宽较窄。
启转成功后,数据比较稳定,可以适当增大一点点带宽,加快转速响应,特别是转速会快速变化的应用。
作者: Angus 时间: 2024-4-1 12:40
本帖最后由 Angus 于 2024-9-15 16:30 编辑
电机公式是 V - Ri = Ldi/dt + E ; 位置估算输入的电压,一般先把电机绕线电阻的压降去掉,即先计算等式左边的 V-Ri
我们的代码是用电压的 25mV 数值计算的,可以保证电压不足10V的低压电机的计算精度。最大电压可到 1638.3V,380V 的电机也无需修改电压数据精度。
先计算 V- Ri, 187/188行是Vd/Vq电压的 25mV 数值。Ri 计算结果是 伏,就要乘 40 得 25mV 数值
R = 毫欧/1000 = RESISTER_COIL / 1000
i = 电流ADC值/1安电流的ADC 值
电流 Iq_Measure_f3,是电流ADC 值乘8的数值(乘8是为了后面位置估算提高精度),所以电流ADC值 = Iq_measure_f3/8
CURRENT_Adc1000 是1安电流的ADC值、再乘1000的数据,所以1安电流 ADC 值 = CURRENT_Adc1000 / 1000
所以电流 i = (Iq_Measure_f3/8) / (CURRENT_Adc1000/1000)
40*R*i = 40 * (RESISTER_COIL/1000)*【(Iq_Measure_f3/8) / (CURRENT_Adc1000/1000)】
上式简化后 40*Ri = 5*RESISTER_COIL * Iq_Measure_f3 / CURRENT_Adc1000
Iq_Measure_f3 有 15 位,如果电阻RESISTER_COIL 有17位,前面乘积就 32位了,就不能再乘5了,所以把乘5移到分母除5。
第208行代码本应除5,做四舍五入要加 2.5, 加不了小数,就变成加5除10。
作者: Angus 时间: 2024-4-17 17:12
本帖最后由 Angus 于 2024-4-17 22:11 编辑
新唐 M451 无感 FOC 是如何很快起转成功的?
无感 FOC 的起转,是先托动,就是电磁场吸引着转子永磁体转动。
刚开始,转子位置未知,用较大电流吸着磁铁转,所以磁铁跟得紧,电流方向与磁铁夹角小于90度,如下图。
转速稍快后,磁铁位置准确了。由于电流大转矩大,转速又慢,所以电流方向与转子夹角仍小于90度。若想让二者夹角到90度,有两个方法:
1>,加快电流转速。让电流方向,尽快转到 Q 轴位置——90度。 如果电流不减小,可能要转很多圈,电流方向才能赶上90度位置,切同步慢。
2>,减小电流降低转矩,永磁体转不动就会落后,直到落后电流方向 90度,就变同步转。 如果电流减太快、转矩降太快,重载时,还没变同步,就转不动而停转了。
所以,以上两个办法,同时使用,才能尽快变到同步转动。
这里再详细说一下电流加速度。
为了加快电流转速,我们采用了指数加速的方式。如下图
刚开始时,转速要慢,要让电流吸住磁铁转。转到磁铁位置准确了,就要尽快转到90度,这时指数加速,电流方向可很快转到90度
转速调整函数, Adjust_Pull_Ommega(Speed_Inc, PULL_Ommega_Inc_f16 , PULL_Ommega_Max_f16);
函数内这样实现
Pull_Ommega_f16 += Pull_Ommega_f16 * Speed_Inc >>14 ; // 指数加速
Pull_Ommega_f16 += PULL_Ommega_Inc_f16 ; // 线性加速
拖动刚开始,如果只想线性加速,可以让实参一 = 0,磁铁位置准确了,再用非0实参。
作者: Angus 时间: 2024-4-19 17:36
本帖最后由 Angus 于 2024-7-16 09:28 编辑
状态 4 起转流程图
锁定电流 CURRENT_MotorLock_f12 的取值:大小让重载时能转得动。
锁定时间 TIME_MotorLock 的取值: 反转最大角度时,能转到位。比如想逆时针转,电流在 12点锁定,此时磁铁若在8点会是最大反转角度,锁定时长要让磁铁转到12点差不多。先用电流半值驱动,是让轻载时减缓转速、减轻在 12 点左右的来回抖动。
线性加速度 PULL_Ommega_Inc_f16 的取值,重载起动时(起转较慢), 拖动最少的圈数能起转成功,一般两三圈, 或四五圈就能同步。
轻载时磁铁跟得紧,线性加速度若取值小,要到转速较高时、要转很多圈电流方向才能追上Q轴,就用指数加速度加快电流增速。逐步增加指数加速度值,让轻载能较快同步。
拖动转速上限 PULL_Ommega_Max_f16 :比最小能同步的转速高一点。比如在500 rpm 以下无法同步转,则拖动转速上限可取值700rpm 以上。
拖动转速下限 PULL_Ommega_Min_f16 : 一般比最小同步转速小一点。比如500rpm以下无法同步转动,则拖动转速下限可取值 300rpm以下。高于此转速才判断是否同步。
作者: Angus 时间: 2024-4-24 13:25
本帖最后由 Angus 于 2024-4-28 10:00 编辑
状态 4 起转波形
从上图可见,收敛速度很快,电流方向追赶估算角度的速度有点慢。若要加快起转,就要缩短这段时间。
作者: Angus 时间: 2024-4-26 23:03
本帖最后由 Angus 于 2024-4-27 11:00 编辑
24年4月26日以后更新的代码,完善了状态 3 起转。 下图可见,切同步较快。
压缩泵起转波形,50ms 内切同步,电流 PI 值可以稍大一点,以加快响应。
风机起转波形,0.2 秒切同步
作者: Angus 时间: 2024-5-30 11:33
高压电机控制的电源部分
作者: Angus 时间: 2024-5-30 11:35
高压电机控制的 AC/DC 部分。
作者: Angus 时间: 2024-5-30 12:31
高压电机控制的功率驱动部分。
R114 的阻值按保护电流选取,取值 75欧时,保护电流 10A
作者: Angus 时间: 2024-5-30 12:32
本帖最后由 Angus 于 2024-5-30 13:53 编辑
高压电机控制的 CPU 部分。
作者: Angus 时间: 2024-5-30 13:32
高压无感 FOC 代码执行后,用 PinView 查看引脚配置
作者: Angus 时间: 2024-6-2 17:07
本帖最后由 Angus 于 2024-6-3 18:06 编辑
用新唐 M451 做的一个 24V 的空气泵,无感 FOC 控制。
反复启动的视频
24V泵反复启动的视频.zip
(5.72 MB, 下载次数: 415)
示波器一大格是50ms, 可以看出,起动时间每次都不到 0.05秒。
作者: Angus 时间: 2024-7-1 11:00
本帖最后由 Angus 于 2024-7-15 13:35 编辑
积分饱和
假如输出电压最高时,电机达到最快的 5Krpm,电流稳定在3A。如果设定转速此时是 6Krpm, 转速误差仍有1K, 转速 PI 运算中的积分运算,仍会一次次增加电流设定值,一直加到控制器电流上限,假如是 20A 。
这时如果转速设定值突然变成 4Krpm,转速 PI 结果——设定电流,从20A慢慢往下降,在降到 3A 前,输出电压不会降,所以转速不会降、保持5Krpm。只有电流降到 3A 再降时,输出电压才开始降,转速也才开始从 5k 往下降。 转速控制会有一个长时间的滞后才反应过来。这就是积分饱和、造成的不良后果。
一个性能优良的电机控制代码,一定有积分抗饱和运算。
作者: Angus 时间: 2024-7-15 16:18
本帖最后由 Angus 于 2025-1-20 13:06 编辑
积分抗饱和的方法
网上查一下,有很多种抗积分饱和的方法,比如,积分分离法,输出限幅法,等等。
我们24年7月以后的代码,积分抗饱和方法是:每次做转速PI 前,检查若转速误差为负(表明指令要降速)并且输出饱和了,就先让电流设定值=电流测量值,这样接下来的转速PI 计算结果,一定是降电流设定值,下次电流PI 计算时,输出电压就降了,退出饱和了。
作者: Angus 时间: 2024-7-18 09:09
本帖最后由 Angus 于 2024-8-2 09:06 编辑
采用状态 3 起转,起转前不需要锁定
作者: Angus 时间: 2024-7-20 11:11
本帖最后由 Angus 于 2024-11-23 15:58 编辑
新唐M451 无感FOC 代码,做MTPA控制。
先介绍一下理论。文字中的符号, 要显示出来,必须单独上传图片,为了省事,我只好先写成 word 文件,再截成一个大图片上传了。
电流分量代入转矩公式,得
MTPA 控制就是给定电流Is,求角度等于多少时,转矩最大。求导=0得
解这个一元二次方程,得
不同Is对应的超前角可做一个折线。假如最大工作电流是32A,做32个点,1A一个点。算出N =Is (取整),则Is对应的超前角在点[ N], [N+1 ]之间,按下式做一个线性计算就可得到角度
M451的无感FOC 代码,起转时Id=0,起转成功能后,第277行代码,切同步前把超前角 Angle_Fai 写成 0,如果以后不再改这个超前角,就是 Id=0 控制。
若要做 MTPA 控制,就在 SysTick 中断里、转速 PI 运算得出 Is 后,再查表求出超前角 Angle_Fai就可以了,求 Iq,Id的代码已写好。
-
-
M451做MTPA 控制.pdf
332.75 KB, 下载次数: 917
作者: Angus 时间: 2024-8-13 11:39
本帖最后由 Angus 于 2024-11-30 19:26 编辑
MTPA 控制就是用最小的电流,获得最大转矩 。为什么要获得最大转矩,基础理论是什么 ?
牛顿第二定律
力矩 = 半径 叉乘 力,
把 "质量与半径平方的积" 定义为转动惯量 J 后,转矩与角速率的关系,和牛顿第二定律一样,称为转动的牛顿第二定律
上式可见,相同的转动惯量,转矩大,角速率的斜率大,即提速快。如果没有摩擦力,会一直加速。
实际的负载——被外力驱动的物体,转速与转矩的公式,是下式:B 是一个常量系数
这是个一阶微分方程,解这个微分方程,可得转速公式与转矩的关系式为:
此函数的形状是这样的。最终转速是 M/B
对于同一个负载,显然,若外加的转矩大,不仅最终的转速高,提速也快。
作者: Angus 时间: 2024-8-13 15:00
本帖最后由 Angus 于 2024-8-13 15:17 编辑
MTPA 控制为何比Id=0控制,消耗的电流会小
假定转矩 T 是个常数,电流 iq,id 就是反比关系,Te 公式的意义,见前面回帖。
Iq 与 Id 的函数图像,可以看成是 y= - 1/x 向右平移。如下图
控制器的输出功率,与电流的模有关,即 Is
以 Is 为半径的圆上,控制器的输出功率是相等的。
在电机基速以下,即未达到最快转速时,下图蓝色 Te 是等转矩线,可以理解为负载等转速线(确切来说,应是输出转矩曲线才是负载等速线)。其原理见楼上回帖的讲解。
如果采用 MTPA 控制,达到这个转速,所需电流是蓝色箭头 Is2 。
如果采用 Id=0 控制,达到这个转速,需要的电流是红色箭头 Is1,已超出以 Is2 为半径的圆圈 。
此图很明显得看出,相同转速, MTPA 控制所需的电流 Is2,比 Id=0控制所需的电流 Is1 小。
作者: Angus 时间: 2024-8-13 16:19
本帖最后由 Angus 于 2024-8-13 16:26 编辑
查表法 MTPA 控制,要先按下式计算出不同电流 Is 下的超前角,做成一个表格。
电机的电阻和电感,都好测量,但磁链常数怎么测量呢?
电机参数里,会给出反电势常数 Ke, 可以按下式求出磁链常数,这里频率 f 是每秒的转速,不是每分钟的转速。
如果不知道电机的参数, 测量磁链常数的最好办法是,用另一个电机拖动,用出示波器测出反势电压峰值,再按上式算出磁链常数。
如果找不到合适的方法用另一个电机拖动,可以让电机空载转起来,采用 Id=0 的控制方式。用下式求出磁链常数。
电机均速转时,Iq 是个常数,求导=0,第一个公式,等号右边前两项=0, 公式就成了下式:
上式等号右边是反电势。转速高时反电势高、计算误差小。
这样就可求出电机的磁链常数了。
在新唐 M451 无感 FOC 的代码中,反电势数值是变量 EMF_Multi_Unit_Magnify , 此变量每个PWM 周期估算位置时更新一次,对此变量低通滤波后,就得到一个稳定的反电势数值。
作者: Angus 时间: 2024-9-16 09:00
积分抗饱和运算
如果电机转速已到最大,而设定转速仍比实际转速大,转速 PI 的积分计算仍一直增加电流设定值,最终电流设定值加到上限,可能比电流实际值大很多倍。如下图电流设定值一直加到了高位 =0x0019,十进制的25,比电流实际值 Iq_Measure 的高位= 2,大了12倍多。
这时如果设定转速 RPM_Set 调到 4767 以下,电流设定值要很久才能降到电流实际值以下,而这期间转速不会下降,这就是积分饱和引起的调节滞后,不好的使用体验。
假如本次转速误差 Err_Spd =K,K>0,
下次 PI 运算时前 Err_Spd_Last = Err_Spd = K ; 到时候若转速设定值与转速实际值一样,即 Err_Spd = 0 ; 则转速 PI 运算就是
temp32 = (Err_Spd - Err_Spd_Last)*Kp_Speed +Err_Spd*Ki_Speed = -K * Kp_Speed ;
如果下次刚好能让“电流设定值 = 电流实际值”, 那么就不会积分饱和。
即本次转速 PI 计算的电流值若等于下式,下次转速 PI 运算就可以把增量减去,不会积分饱和
本次电流设定值 = K * Kp_Speed + 电流实际值 = Err_Spd * Kp_Speed + 电流实际值 ; // 这个是本次电流设定值的上限
K 值取多少呢? 因转速控制精度1%以下,可取转速最大值的 1/64。所以有以下积分抗饱和运算代码:
这段代码的执行效果如下图,电流设定值只增加到实际值的 2.7 倍,这是下次能一次把电流误差回调到 0 的值。
作者: Angus 时间: 2024-9-17 11:00
本帖最后由 Angus 于 2024-10-2 21:11 编辑
电机启动流程
更新转速设定值 RPM_Set ,不是一个很紧急的事件,在 main() 主循环中,按旋钮 ADC 值确定转速设定值 RPM_Set 是多少。
在main() 主循环代码中,电机可能在同步转,也可能未在同步转。分别做如下处理:
一,如果电机在同步转(Motor_Status 的 bit4 非0),下图318行,做以下事情:
如果 RPM_Set <= 0, 说明电机已在停转降速中,这时需判断一下,若转速已降到最小值以下,就去状态 1 刹车停转。
如果 RPM_Set >0, 这里不需要做什么。电流大小由SysTick 中断里、转速 PI 计算结果决定;电压角度和 PWM 输出占空比,由 ADC 中断里计算、输出。
二,如果电机未在同步转, 下图327 行,要么不需要起动(RPM_Set <= 0),要么需要启动(RPM_Set >0)。
1>,如果不需要起动(RPM_Set <= 0),又已在起动流程(状态3,4,5,6),则直接刹车停转(335行, 去状态1)、或关功率管(去状态0)就行了。
如果未在启动流程,未转、也未在启转,就判断是否取消故障状态,转向开关是否变了,等等。
2>,如果需要起动、又未在启动流程,执行到 362 行,先调用函数 Test_Period() 判断是否已顺风吹转,若是则跳转到状态6,顺风起转。若未顺风转,跳转到状态 2 先给自举电容充电,充电结束后,在状态 2,按宏定义决定跳转到状态 3 开始 V/F 起转、还是跳转到状态 5 ( 再跳转到状态4) 开始 I/F 起动。
若需要启动,又已在启动流程,这里就不需要做什么了,ADC 中断里、启动代码会变换状态。
作者: Angus 时间: 2024-9-23 11:33
本帖最后由 Angus 于 2024-10-2 21:09 编辑
代码的总体架构就是main() 里的主循环 + 两个中断,这里介绍一下这三部分之间的关系或相互之间的数据通信
每个PWM 周期产生一次 ADC 中断,转电机的代码主要在 ADC 中断里,包括电流 PI 计算。"电流 PI 运算"的电流设定值来至 SysTick 中断里"转速 PI 计算"的计算结果(同步转时), 或ADC 中断里自己决定电流设定值大小(启动时)。
SysTick 中断代码里,用转速设定值和实际值,做转速 PI 计算求出电流设定值 Iq_set_f12,Id_set_f12 由 ADC 中断代码用。既然这个全局变量,只有在同步转时 ADC 中断代码才用到,不同步时,就不做这个转速 PI 计算了,详见 SysTick 中断代码。
在 ADC 中断里,状态机的转变如下图,状态0(关功率管停转状态)不会变成其它状态,如果需要启动(转速设定值 RPM_Set >0) 要在 main() 主循环里判断,转变为状态2(静止状态启动)或状态6(顺风转时启动)
main() 主循环里,除了启动前判断一下是否已顺风转,还会做一件事:判断如果启动时出现 RPM_Set <=0, 就是又不想启动了,那就直接变状态1、立即停止启动,不必再等超时了。
作者: Angus 时间: 2025-1-13 11:18
作者: Angus 时间: 2025-3-5 15:02
本帖最后由 Angus 于 2025-3-17 22:11 编辑
转速控制 ,涉及到以下几个变量
RpmMechanical_Set : UART转速指令、或由旋钮获得的机械转速值
RPM_Command : 转速指令对应的电转速,但是,若Stop_Runing 非0(有异常)此值等0
RPM_Set_Target : 控制加减速的转速设定值,此变量慢慢增加或慢慢减小,直到等于RPM_Command,范围 0~Max
RPM_Set : 此变量基本= RPM_Set_Target, 只是范围 Min ~ Max,停转时此值是负值,是为了加快转速PI 运算结果的电流值下降
停转时,若想降速受控,慢慢降速,就让 RPM_Command =0,电流慢慢下降。降速过程保持着同步。
停转时,若让RPM_Set_Target=0,则电流立即=0,风机会自由降速,降速过程仍保持着同步。水泵降速很快。
若让状态变量 Motor_Status =0,下个PWM 周期就关功率管,电机自由停转,降速过程不保持同步。
作者: Angus 时间: 2025-3-12 16:58
缺相时,电流等于0,似乎缺相不难检测出,可做起来并不容易。
正常转动时,角度=0或180度时,相电流等于0,所以不能检测到电流=0就认为是缺相。如果检测到电流=0持续一段时间才认为是缺相,则在确定缺相前,电机已无法正常转动,可能已关功率管了。
启动期间三相的电流差异较大,缺相的条件很难确定。长时间电流较小, 检测多长时间合适也不容易确定。
实际测试还发现,断线的那相,电流ADC 数据异常波动,波动幅度已超过了轻载、低速转动的电流。 如果设置一个电流门限,低于此门限就认为是缺相,电流判断门限若设置高了,轻载低速时会误判为缺相。若门限低了,真缺相又会判断不出来。
我们最终确定的办法是,启动前在 240 度通电,通电时间参考 L/R,一般几个毫秒就可以。这时电流经 C 相流向 AB 相, 三相都有电流,AB 相电流是 C 相的一半。如果有一相电流比设定电流小一半以上, 置位一个标志,可能缺相了。 继续启动, 如果后面启动成功了,就不认为是缺相,清除标志(310行)。如果后面启动失败了,才确定是缺相(285行),这样就减少了误判。
作者: 匿名 时间: 2025-3-14 08:34
思路好。不过有另外的问题,假如没有缺相,启动失败也发生了,那这时怎么判断是什么故障?
作者: Angus 时间: 2025-3-14 09:16
本帖最后由 Angus 于 2025-5-14 22:00 编辑
如果没缺相,标志 TempFlag_Open 不会写成非0,一次启动失败,会停一秒左右,再次启动。如果电机卡住了根本转不动,FailCnt 失败计数,多次失败就不再启动了(上图中 286行),需人工干预,不会报缺相故障,报多次启动失败故障。
正常情况一次就能启动成功。若负载很重,偶尔会失败一次,第二次能启动成功。
作者: Angus 时间: 2025-4-12 14:30
本帖最后由 Angus 于 2025-4-29 15:00 编辑
V26版,优化了启动逻辑,提速逻辑和缺相检测,并且把ADC 限流改为周期性检测和阶梯性报警。
如何做到重载启动顺利,轻载启动转速又不上冲呢? 方法说出来其实很简单:限压。 说出这两个字有人立马就明白了,很多事就是一层窗户纸。
电机的转速与电压成正比,300V 电压轻载时若有一万转,启动时限压30V转速就不会高于一千转。重载时转速稍低一点,900转左右,不会太低。
以 V26 代码为例,启动时,在状态5 代码中。407行,设定限压值再跳转去状态3或状态4,开始电流拖动。一旦转起来,反电势会让实际电流下降。电流实际值可能远小于设定值,即控制处于输出饱和状态。变同步时再做调整。
作者: Angus 时间: 4 天前
本帖最后由 Angus 于 2025-5-17 19:52 编辑
转速的计算和控制一。
转速的计算: RPM 转速 = 转过的角度/一圈角度/时间,再换算成一分钟转过的圈数。
有些应用,转动是不均匀的,比如活塞式压缩机,压缩时转速变慢,回程时转速快, 计算转速要在一个机械周期内求平均。
如下图,一个机械周期有四个电周期。
为了加快转速控制的响应,每转过一个扇区,我们就对前面24个扇区求平均转速,所以要保存前面24个扇区边界的角度和时间,即至少25组数据。
代码中结构体数组 Section_data[SECTION_RPM_AVERAGE +2],保存跨过扇区边界时的角度的时间,SECTION_RPM_AVERAGE 是机械周期的扇区数 。
上图 N = 24 个扇区一个机械周期,如果转动在宏观上是平稳的,第 N 个扇区转动时间,将等于第 N+1个扇区的时间。这样可更快发现转速的变化,转速控制的响应将更快,这个留给有兴趣的人去测试。代码中保留了 N+1 个扇区的边界数据,即 N+2 组数据。
每次 PWM 检查一次角度是否跨过扇区边界,若是就记录一下角度,角度不会刚好是60度。时间用 PWM 周期个数再乘 PWM 一个周期的时间。
作者: Angus 时间: 3 天前
本帖最后由 Angus 于 2025-5-17 19:51 编辑
转速的计算和控制二
启动时,至少转过 N 个扇区,转速的计算才正确。在转速正确之前,不能做转速 PI 运算。每计算一次转速,变量 Do_Spd_PI 就加1。启动时赋值 Do_Spd_PI = -N-2; 转过一个扇区边界后 Do_Spd_PI = -N-1 ; 算是起点,再转过一个扇区Do_Spd_PI= -N; 就有了一个扇区前后两个边界的角度和时间,Do_Spd_PI= -1 时就有了 N 个扇区两边的角度和时间,就可计算出正确的转速了。
启动时不能做转速 PI 控制,也不能让转速设定值一直往上增加,所以代码中让转速设定值变量 RPM_Set_Target 一直等于测量转速。
启动后只有转到 Do_Spd_PI = -1 时,转速才正确,前面虽转速数据不对,让RPM_Set_Target = 测量转速,也无妨,因不做转速 PI 控制。 Do_Spd_PI = 0 以后就可以做转速 PI 控制了。
另一方面,启动阶段未变同步转动时 Motor_Status & 0x10) = 0,也不能做转速 PI 控制,也不能让设定转速一直往上增加。
启动时,是先 Do_Spd_PI 增加到0、还是先变同步转,不一定。
作者: Angus 时间: 3 天前
本帖最后由 Angus 于 2025-5-17 16:45 编辑
转速的计算和控制三。
同步转动时,测量转速值未更新也不做转速 PI 。在转一扇区时间、长于转速 PI 计算周期后,多次执行转速 PI 函数做一次 PI 运算,这相当于减小了积分系数,即随着转速降低,转速积分系数跟着降低。
如果不想让积分系数一直降低,就把变量 WaitCount 利用起来,当转速低到一定程度,Do_Spd_PI 一直不更新,而 WaitCount 已加到上限,也做一次转速 PI 运算。就得到了如下转速积分系数曲线:
作者: 匿名 时间: 前天 08:35
这里有个疑问,限压后,轻载能满足启动的电压电流要求,重载时,电压会不会不够用?毕竟负载不同,需要的电流不同,电压也相应不一定。
作者: Angus 时间: 前天 13:40
本帖最后由 Angus 于 2025-5-17 10:55 编辑
限压多少,应按重载测试的效果确定,轻载启动稍快一点,依然很平稳,转速不会冲到很快。
限压带来的最大好处,是启动代码变得简单了,调整启动特性容易了。
作者: Angus 时间: 昨天 15:55
本帖最后由 Angus 于 2025-5-17 19:39 编辑
转速计算和控制四
压缩机在停转时一般不能立即关功率管,立即关功率管机械结构会猛得回弹,时间长了会损伤机械结构,应有个减速的过程。
M451 无感 FOC 代码,有加减速控制。代码中每25ms 电转速增加 50,一个 3000RPM 两对磁极电机,3秒内达到最快转速。 减速时每次减200,快了四倍。
代码中可修改这个加减速度。
全速3000 rpm 的电机,如果转速加到2500 rpm ,功率已到最大,不能再增加转速,代码如何处理呢? 功率 PI 运算采用增量式算法就轻易解决了此问题。
假如转速设定3000 rpm, 转速已到 2500 rpm, 则25ms 后,转速再增加 50。
如果功率 PI 算出增量是 300,只能按转速控制增加50,不然加速度就太快了。如果功率 PI 算出必须减 10,那就减10,不然功率就超了。即,功率 PI 算出的增量,和转速控制的增减量,哪个小,就计入哪个。这样在功率不超的前提下,加速度或减速度,都是期望的值。
欢迎光临 牛卧堂MCU技术交流 (http://nuvoton-mcu.com/) |
Powered by Discuz! X3.2 |