目录
前言
本文主要介绍SPWM原理及C语言单片机的实现
一、PWM简介
PWM是Pulse Width Modulation的缩写,也称为脉冲宽度调制。PWM信号主要用于控制半导体通电/断电的占空比(ON/OFF时间的比率)。如下图所示
其本质就是不停的开关电路状态,其中
T
T
T为周期,频率
f
=
1
T
f= \frac{1}{T}
f=T1,
T
w
T_w
Tw为开启时间,占空比是指周期性方波中导通周期(幅度不为零的周期)的百分比
占空比(
D
)
=
T
w
T
占空比(D)= \frac {T_w}{T}
占空比(D)=TTw
那PWM有什么用?以下图电路为例,假设的系统正常开启为
V
i
V_{i}
Vi,输入为PWM,那么实际电压有
V
o
=
D
∗
V
i
V_o = D * V_{i}
Vo=D∗Vi
其输出电压是个有效值,如果系统负载有个LED灯,那么通过改变PWM的占空比就可以改变
V
o
V_o
Vo,从而可以改变LED灯的亮度。那PWM在电机里有什么用呢?先看下图,我们使用PWM控制一个开关电路,忽略MOS的管压降有
- 当PWM输出为1时,MOS管打开,负载电流 I = 5 / R 3 I=5/R3 I=5/R3
- 当PWM输出为0时,MOS管关闭,负载电流为0
那么电路输入PWM信号的时候,有 I = D ∗ 5 / R 3 I=D*5/R3 I=D∗5/R3,从而实现了控制电流。如果负载R3为电机,是不是就可以通过控制PWM占空比,就可以控制电机工作电流,从而控制电机转速了,如下
注意:电力电子器件工作的开关频率越高,低次谐波越小,但开关器件的开关损耗也越大,带来散热问题同时也会使电能变换效率降低。高压大功率电力电子器件工作频率一般不高于1kHz
二、SPWM基本原理
2.1 SPWM简介
SPWM的全称是Sinusoidal Pulse Width Modulation,又称正弦脉冲宽度调制。简单来说就是占空比按照正弦波来调制,此时电流就会成正弦波的形式
上面我们发现PWM就可以调速,那么我们为什么还要使用SPWM,既增加代码复杂度,又增加运算量的事情呢?实际上对于有刷电机,PWM已经够用了,但是如果放在无刷电机、变频器、逆变器等系统里,我们就可能需要用到SPWM,甚至更复杂的控制算法。
如上图所示一个控制系统,具体无刷电机的6步方波控制原理这边就不细讲了,可以参考文末补充链接
如上图所示,我们主要关心的是无刷电机换相的问题。从之前的方波控制,我们知道使用PWM的原因主要是防止电机转速过快,实际上在6步方波控制里使用的是PWM+PID的方式,此时如果我们测量单相上的电流大致会呈现如下图所示波形,你会发现电流波形成阶梯形式
第首先一个问题是为什么会形成这样的波形?主要是无刷电机在旋转过程中经历下面几步:
1、开始在没有换相的时候由于PID的反馈几乎为0,此时电流达到最小值假设为 I 1 I_1 I1
2、当需要换相的时候,部分电能转化为动能,此时由于PID的滞后性,他开始补偿增大电流,达到电流最大值为 I 2 I_2 I2
3、当换相结束之后,没有了动能损耗,此时电流过大,PID又开始降低电流,最后又回到 I 1 I_1 I1
所以这样的电流波形是因为换相的动能损耗,以及PID补偿的滞后性导致的。那么第二个问题是这样的波形在现实生活中会带来什么问题?主要会带来下面的问题
1、电机转速有波动,就是一会快一会慢
2、由于转速的波动,导致电机在运转过程中噪声比较大
3、由于PID调节的滞后性,导致电机在运转过程中功率增大,效率降低
此时再回到SPWM调制思想,他是利用宽窄不等的方波来等效正弦波,保证宽窄不等的方波所对应的基波与所需要等效的正弦波的幅值、相位和频率均相等。所以你会发现SPWM相比于1.1小节的PWM在不同的占空比之间过度更加自然,加入SPWM控制后,电流波形会优化成如下所示
2.2 SPWM控制方法
SPWM控制的关键是如何确定脉冲宽度,及SPWM波产生方法。
2.2.1 直接计算法
- 方法:根据正弦波频率、幅值和半周期脉冲数,准确计算PWM波各脉冲宽度和间隔,据此控制逆变电路开关器件的通断,就可得到所需PWM波形
- 缺点:本法较繁琐,当输出正弦波的频率、幅值或相位变化时,结果都要变化
如按照等面积原则计算开关时刻
对于不同极性有
2.2.2 自然采样法
自然采样法就是取正弦波(调制波)与三角波(载波)的交点确定脉冲宽度,如下图所示
其缺点是交点求解涉及到多次三角函数计算和迭代多次,计算量很大
与之相类似的还有规则采样法:载波周期中点与正弦波(调制波)的交点所作的水平线与三角波(载波)的交点确定脉冲宽度,如下图所示,其得到的SPWM波与自然采样法接近,谐波会略微大一点
如果是单相逆变器系统,如下所示
有单极性调制法(单相)
和双极性调制法(单相)
对于三相系统有
2.2.3 谐波法
- 谐波的概念
谐波法是计算法中一种较有代表性的方法,首先理解什么是谐波。根据傅里叶级数,任意周期信号可以表示为
f ( t ) = a 0 + a 1 cos ω t + a 1 sin ω t + a 2 cos 2 ω t + a 2 sin 2 ω t + ⋯ = a 0 + ∑ n = 1 ∞ ( a n cos n ω t + b n sin n ω t ) \begin{split} f(t) &= a_0 + a_1\cos ωt + a_1\sin ωt + a_2\cos 2ωt + a_2\sin 2ωt + \cdots \\ &= a_0 + \sum_{n=1}^{\infty}(a_n\cos nωt + b_n \sin nωt) \end{split} f(t)=a0+a1cosωt+a1sinωt+a2cos2ωt+a2sin2ωt+⋯=a0+n=1∑∞(ancosnωt+bnsinnωt)
其中 a 0 a_0 a0就是 f ( t ) f(t) f(t)在一个周期内的平均值,即
a 0 = 1 T ∫ 0 T f ( t ) d t a_0 = \frac{1}{T}\int_0^T f(t) \,{\rm d}t a0=T1∫0Tf(t)dt
经过三角变换可以变成
f ( t ) = a 0 + ∑ n = 1 ∞ A n ( cos n ω 0 t + φ n ) f(t) = a_0 + \sum_{n=1}^{\infty} A_n(\cos nω_0t + φ_n) f(t)=a0+n=1∑∞An(cosnω0t+φn)
其中
A n = a n 2 + b n 2 A_n = \sqrt{a_n^2 + b_n^2} An=an2+bn2
余弦分量
a n = A n cos φ n a_n = A_n \cosφ_n an=Ancosφn
正弦分量
b n = − A n sin φ n b_n = -A_n \sinφ_n bn=−Ansinφn
相位
φ n = − arctan b n a n φ_n = - \arctan \frac{b_n}{a_n} φn=−arctananbn
而谐波分量就是指
- 当n=0时, F 0 = a 0 F_0=a_0 F0=a0称为直流分量
- 当n=1时, F 1 = A 1 F_1=A_1 F1=A1称为基波分量
- 当n=2时, F 2 = A 2 F_2=A_2 F2=A2称为二次谐波分量
……- 当n=k时, F k = A k F_k=A_k Fk=Ak称为k次谐波分量
-
谐波消去法
谐波消去法是为减少谐波并简化控制,那么如何消去谐波呢?首先尽量使波形对称,为消除偶次谐波,使波形正负两半周期镜对称,即
u ( ω t ) = − u ( ω t + π ) u(ωt) = -u(ωt + π) u(ωt)=−u(ωt+π)
其次,为消除谐波中余弦项,应使波形在正半周期内前后1/4周期以π/2为轴线对称
u ( ω t ) = u ( π − ω t ) u(ωt) = u(π - ωt) u(ωt)=u(π−ωt)
同时满足上两式的波形称为四分之一周期对称波形,用傅里叶级数表示为
u ( ω t ) = ∑ n = 1 , 3 , 5 , ⋯ ∞ a n sin n ω t u(ωt) = \sum_{n=1,3,5,\cdots}^{\infty} a_n \sin nωt u(ωt)=n=1,3,5,⋯∑∞ansinnωt
式中
a n = 4 π ∫ 0 π 2 u ( ω t ) sin n ω t d ω t \begin{split} a_n &= \frac 4 π \int_0^{\frac π2 } u(ωt)\sin nωt \,{\rm d}ωt \end{split} an=π4∫02πu(ωt)sinnωtdωt
假设一个系统可以独立控制 a 1 a_1 a1、 a 2 a_2 a2和 a 3 a_3 a3共3个时刻。则波形 a n a_n an为
a n = 4 π [ ∫ 0 α 1 U d 2 sin n ω t d ω t + ∫ α 1 α 2 ( − U d 2 sin n ω t ) d ω t + ∫ a 2 α 3 U d 2 sin n ω t d ω t + ∫ α 3 π 2 ( − U d 2 sin n ω t ) d ω t ] = 2 U d n π ( 1 − 2 cos n α 1 + 2 cos n α 2 − 2 cos n α 3 ) \begin{split} a_n &= \frac 4 π \left [\int_0^{α_1 } \frac {U_d}{2}\sin nωt \,{\rm d}ωt +\int_{α_1}^{α_2} (-\frac {U_d}{2}\sin nωt) \,{\rm d}ωt + \int_{a_2}^{α_3} \frac {U_d}{2}\sin nωt \,{\rm d}ωt +\int_{α_3}^{\frac π 2} (-\frac {U_d}{2}\sin nωt) \,{\rm d}ωt\right]\\ & =\frac{2U_d}{nπ} (1-2\cos nα_1 +2\cos nα_2 - 2\cos nα_3) \end{split} an=π4[∫0α12Udsinnωtdωt+∫α1α2(−2Udsinnωt)dωt+∫a2α32Udsinnωtdωt+∫α32π(−2Udsinnωt)dωt]=nπ2Ud(1−2cosnα1+2cosnα2−2cosnα3)
此时再令两个不同的 a n = 0 ( n = 1 , 3 , 5 , ⋯ ) a_n=0 (n= 1, 3, 5, \cdots) an=0(n=1,3,5,⋯),就可建三个方程,求得a1、a2和a3,这边选择消去5次和7次谐波,得如下联立方程:
a 1 = 2 U d π ( 1 − 2 cos α 1 + 2 cos α 2 − 2 cos α 3 ) a 5 = 2 U d 5 π ( 1 − 2 cos 5 α 1 + 2 cos 5 α 2 − 2 cos 5 α 3 ) = 0 a 7 = 2 U d 7 π ( 1 − 2 cos 7 α 1 + 2 cos 7 α 2 − 2 cos 7 α 3 ) = 0 \begin{split} a_1 &= \frac{2U_d}{π} (1-2\cos α_1 +2\cos α_2 - 2\cos α_3) \\ a_5 &= \frac{2U_d}{5π} (1-2\cos 5α_1 +2\cos 5α_2 - 2\cos 5α_3) = 0 \\ a_7 &= \frac{2U_d}{7π} (1-2\cos 7α_1 +2\cos 7α_2 - 2\cos 7α_3) = 0 \\ \end{split} a1a5a7=π2Ud(1−2cosα1+2cosα2−2cosα3)=5π2Ud(1−2cos5α1+2cos5α2−2cos5α3)=0=7π2Ud(1−2cos7α1+2cos7α2−2cos7α3)=0
给定 a 1 a_1 a1,解方程可得 α 1 α_1 α1、 α 2 α_2 α2和 α 3 α_3 α3。 α 1 α_1 α1变, α 2 α_2 α2和 α 3 α_3 α3也相应改变。一般在输出电压半周期内,器件通、断各k次,考虑到PWM波四分之一周期对称,k个开关时刻可控,除用一个自由度控制基波幅值外,可消去k-1个频率的特定谐波k的取值越大,开关时刻的计算越复杂 -
谐波电流法
我们假设双极性PWM逆变器系统,其直流环节电压为 V D V_D VD,基波角频率为 ω 0 ω_0 ω0。在一个 2 π 2π 2π周期内,其PWM波形开关点相对应的角度分别为 α 1 , α 2 , ⋯ , α M , π − α M , ⋯ , π − α 2 , π − α 1 , π , π + α 1 , π + α 2 , ⋯ , π + α M , 2 π − α M , ⋯ , 2 π − α 1 , 2 π α_1,α_2,\cdots,α_M,π-α_M,\cdots,π-α_2,π-α_1,π,π+α_1,π+α_2,\cdots,π+α_M,2π-α_M,\cdots,2π-α_1,2π α1,α2,⋯,αM,π−αM,⋯,π−α2,π−α1,π,π+α1,π+α2,⋯,π+αM,2π−αM,⋯,2π−α1,2π,开关角度满足
0 ⩽ α 1 ⩽ α 2 ⩽ ⋯ ⩽ α M ⩽ π 2 0 \leqslant α_1 \leqslant α_2 \leqslant \cdots \leqslant α_M \leqslant \frac π 2 0⩽α1⩽α2⩽⋯⩽αM⩽2π
然后对 a n a_n an进行变换得到
a n m = 4 π ∫ 0 π 2 V D 2 sin n ω t d ω t = 2 π ∫ 0 π V D 2 sin n ω t d ω t = 2 π [ ∫ 0 α 1 V D 2 sin n ω t d ω t − ∫ α 1 α 2 V D 2 sin n ω t d ω t + ∫ a 2 α 3 V D 2 sin n ω t d ω t − ⋯ − ∫ α M π − α M V D 2 sin n ω t d ω t + ⋯ − ∫ π − α 2 π − α 1 V D 2 sin n ω t d ω t + ∫ π − α 1 π V D 2 sin n ω t d ω t \begin{split} a_{nm} = &\frac 4 π \int_0^{\frac π2 } \frac {V_D}{2}\sin nωt \,{\rm d}ωt \\ = &\frac 2 π \int_0^{π} \frac {V_D}{2}\sin nωt \,{\rm d}ωt \\ = &\frac 2 π [\int_0^{α_1 } \frac {V_D}{2}\sin nωt \,{\rm d}ωt \\ &-\int_{α_1}^{α_2} \frac {V_D}{2}\sin nωt \,{\rm d}ωt \\ &+ \int_{a_2}^{α_3} \frac {V_D}{2}\sin nωt \,{\rm d}ωt - \cdots \\ &-\int_{α_M}^{π - α_M} \frac {V_D}{2}\sin nωt \,{\rm d}ωt + \cdots\\ &-\int_{π- α_2}^{π- α_1} \frac {V_D}{2}\sin nωt \,{\rm d}ωt \\ &+ \int_{π-α_1}^{π} \frac {V_D}{2}\sin nωt \,{\rm d}ωt \\ \end{split} anm===π4∫02π2VDsinnωtdωtπ2∫0π2VDsinnωtdωtπ2[∫0α12VDsinnωtdωt−∫α1α22VDsinnωtdωt+∫a2α32VDsinnωtdωt−⋯−∫αMπ−αM2VDsinnωtdωt+⋯−∫π−α2π−α12VDsinnωtdωt+∫π−α1π2VDsinnωtdωt
整理一下得到
a n m = S ( − 1 ) M 2 V D n π [ 1 − 2 ∑ i = 1 M ( − 1 ) i + 1 cos n ω 0 t i ] a_{nm} = S(-1)^M\frac{2V_D}{nπ}\left[1- 2\sum_{i=1}^{M}(-1)^{i+1} \cos nω_0t_i \right] anm=S(−1)Mnπ2VD[1−2i=1∑M(−1)i+1cosnω0ti]
式中 , S 值采用 + 1,称为正调制;S 值采用 - 1,称为负调制。开关点的 α i α_i αi角等于 ω 0 t i ω_0 t_i ω0ti 。假定谐波电流仅仅由漏抗决定,且认为是线性的,谐波电流的均方根值表达为:
I = 1 2 ∑ n = 3 ∞ ( a n m n ω 0 L ) 2 = 1 ω 0 L 1 2 ∑ n = 3 ∞ ( a n m n ) 2 \begin{split} I &= \sqrt{\frac 12\sum_{n=3}^{\infty}(\frac {a_{nm}}{nω_0L})^2} \\ &= \frac 1 {ω_0L}\sqrt{\frac 12\sum_{n=3}^{\infty}(\frac {a_{nm}}{n})^2} \end{split} I=21n=3∑∞(nω0Lanm)2=ω0L121n=3∑∞(nanm)2
式中:
- a n m a_{nm} anm:输出电压n次谐波的幅值
- L:电动机的漏抗
- ω 0 ω_0 ω0:基波角频率
对于三相系统,线电压
u
A
B
u_{AB}
uAB与相电压
u
A
u_A
uA 和
u
B
u_B
uB的关系如下 :
u
A
B
(
t
)
=
u
A
(
ω
0
t
)
−
u
A
(
ω
0
t
−
120
°
)
=
∑
n
=
1
∞
2
a
n
m
sin
60
°
⋅
n
⋅
cos
n
(
ω
0
t
−
60
°
)
\begin{split} u_{AB}(t) &= u_A(ω_0t) - u_A(ω_0t - 120°) \\ & = \sum_{n=1}^{\infty}2a_{nm}\sin60° ⋅ n⋅\cos n(ω_0t - 60°) \end{split}
uAB(t)=uA(ω0t)−uA(ω0t−120°)=n=1∑∞2anmsin60°⋅n⋅cosn(ω0t−60°)
线电压
u
A
B
u_{AB}
uAB的 n 次谐波幅值
a
A
B
n
m
a_{ABnm}
aABnm为:
a
A
B
n
m
=
2
n
a
n
m
sin
60
°
a_{ABnm} = 2n a_{nm}\sin60°
aABnm=2nanmsin60°
流过电动机的 n 次谐波电流
I
n
I_n
In表达为:
I
n
=
a
A
B
n
m
6
n
ω
0
L
I_n = \frac {a_{ABnm}}{\sqrt{6}nω_0L}
In=6nω0LaABnm
三相系统的谐波电流均方根值
I
δ
I_δ
Iδ:
I
δ
=
∑
n
=
3
∞
I
n
2
=
1
6
ω
0
L
∑
n
=
3
∞
(
a
A
B
n
m
n
)
2
I_δ = \sqrt{\sum_{n=3}^{\infty}I_n^2} = \frac 1 {\sqrt{6}ω_0L}\sqrt{\sum_{n=3}^{\infty}(\frac {a_{ABnm}}n)^2}
Iδ=n=3∑∞In2=6ω0L1n=3∑∞(naABnm)2
对所给出的每一对M和
a
A
B
1
m
a_{AB1m}
aAB1m ,以
I
δ
=
min
I_δ = \min
Iδ=min为条件 ,寻求一组
α
1
,
α
2
,
α
3
,
α
4
,
⋯
,
α
M
α_1,α_2 ,α_3 ,α_4,\cdots,α_M
α1,α2,α3,α4,⋯,αM的值,从而获得在谐波电流均方根值最小的性能指标下的开关模式。
2.3 SPWM的注意点
2.3.1 死区效应
实际上方波控制也要关注死区效应,所谓的死区就是同一相上下两臂的驱动信号互补,为防止上下臂直通而造成短路(击穿MOS),留一小段上下臂都施加关断信号的死区时间,如下图
T
D
T_D
TD
2.3.2 过调制
首先了解下面几个参数
- 调制频率 f s f_s fs:这里就是正弦波的频率,即电机所需电流的频率
- 载波频率 f c f_c fc:载波就是原来PWM波的频率,即下图的三角波频率,也就是MOS开关频率
- 载波比 m f m_f mf:载波频率 f c f_c fc与调制频率 f s f_s fs之比,即 m f = f c f s m_f=\frac{f_c}{f_s} mf=fsfc
- 电压调制比 M M M:调制波幅值 U m U_m Um与载波复制 U c U_c Uc之比,即 M = U m U c M = \frac{U_m}{U_c} M=UcUm
所谓的过调制就是指,当电压调制比
M
M
M大于1时,称为过调制,此时调制信号幅值有一部分不受控制
当然调制比太小会导致电压利用率低的问题正弦波调制的三相PWM逆变电路,调制度
M
M
M为1时,输出线电压的基波幅值为0.866
U
c
U_c
Uc,直流电压利用率为0.866,实际还更低。
2.3.3 转矩与转速控制
- 转矩控制:SPMW的频率不变,增大调制比
- 速度控制:调制比不变,改变SPWM频率
三、SPWM实现
这里以STM32为例,首先看一下STM32如何生成PWM
如上图所示,实际上就是计数值CNT大于捕获比较值CCR时,输出PWM的高电平,而自动重装寄存器ARR则是PWM周期,所以我们只需要修改CCR的值就可以生成正弦波,那CCR的值怎么算呢?此时我们先看一下正弦函数的表达式:
f
(
t
)
=
sin
(
ω
t
)
f(t) = \sin (ωt)
f(t)=sin(ωt)
根据中学知识,我们知道其周期
T
=
2
π
/
ω
T=2π/ω
T=2π/ω,假设三角波的周期为
T
2
T_2
T2(由定时器的配置决定,如时钟、分频系数、ARR的值),那么一个正弦波周期内三角波发生的次数为
n
=
T
/
T
2
n=T/T_2
n=T/T2,将n加入到正弦函数有
f
(
t
)
=
sin
(
2
π
t
/
n
)
f(t) = \sin (2πt/n)
f(t)=sin(2πt/n)
再代入调制比为M,如果以规则采样法为例,则第一个PWM脉宽的CCR的值为
N
C
C
R
1
=
N
A
R
R
×
M
×
f
(
1
)
N_{CCR1} = N_{ARR}×M×f(1)
NCCR1=NARR×M×f(1)
以此类推,最后一个为
N
C
C
R
n
=
N
A
R
R
×
M
×
f
(
n
)
N_{CCRn} = N_{ARR}×M×f(n)
NCCRn=NARR×M×f(n)
以下图为例,半个正弦波周期的n为20,那么整个周期的n为40,假设调制比为0.8,ARR为100,则第一个CCR的值为
N
C
C
R
1
=
100
×
0.8
×
sin
(
2
π
/
40
)
N_{CCR1} = 100×0.8×\sin(2π/40)
NCCR1=100×0.8×sin(2π/40)
为了减小直接计算法的计算量,在软件上可以配合查表法,查表法本质就是用空间换取时间,即将占空比提前算好放进数组,当然也可以选择取点工具
int const talab[250]=
{
100 , 102 , 108 , 116 , 126 , 140 , 154 , 172 , 194 , 216 ,
242 , 270 , 300 , 334 , 370 , 408 , 448 , 490 , 536 , 582 ,
632 , 684 , 738 , 794 , 854 , 914 , 976 ,1040 ,1108 ,1176 ,
1246 ,1320 ,1394 ,1470 ,1548 ,1626 ,1708 ,1790 ,1874 ,1960 ,
2046 ,2136 ,2224 ,2316 ,2408 ,2502 ,2596 ,2690 ,2786 ,2884 ,
2982 ,3080 ,3180 ,3280 ,3382 ,3482 ,3584 ,3686 ,3788 ,3892 ,
3994 ,4096 ,4200 ,4304 ,4406 ,4508 ,4612 ,4714 ,4816 ,4918 ,
5018 ,5120 ,5220 ,5320 ,5418 ,5516 ,5614 ,5710 ,5804 ,5898 ,
5992 ,6084 ,6176 ,6264 ,6354 ,6440 ,6526 ,6610 ,6692 ,6774 ,
6852 ,6930 ,7006 ,7080 ,7154 ,7224 ,7292 ,7360 ,7424 ,7486 ,
7546 ,7606 ,7662 ,7716 ,7768 ,7818 ,7864 ,7910 ,7952 ,7992 ,
8030 ,8066 ,8100 ,8130 ,8158 ,8184 ,8206 ,8228 ,8246 ,8260 ,
8274 ,8284 ,8292 ,8298 ,8300 ,8300 ,8298 ,8292 ,8284 ,8274 ,
8260 ,8246 ,8228 ,8206 ,8184 ,8158 ,8130 ,8100 ,8066 ,8030 ,
7992 ,7952 ,7910 ,7864 ,7818 ,7768 ,7716 ,7662 ,7606 ,7546 ,
7486 ,7424 ,7360 ,7292 ,7224 ,7154 ,7080 ,7006 ,6930 ,6852 ,
6774 ,6692 ,6610 ,6526 ,6440 ,6354 ,6264 ,6176 ,6084 ,5992 ,
5898 ,5804 ,5710 ,5614 ,5516 ,5418 ,5320 ,5220 ,5120 ,5018 ,
4918 ,4816 ,4714 ,4612 ,4508 ,4406 ,4304 ,4200 ,4096 ,3994 ,
3892 ,3788 ,3686 ,3584 ,3482 ,3382 ,3280 ,3180 ,3080 ,2982 ,
2884 ,2786 ,2690 ,2596 ,2502 ,2408 ,2316 ,2224 ,2136 ,2046 ,
1960 ,1874 ,1790 ,1708 ,1626 ,1548 ,1470 ,1394 ,1320 ,1246 ,
1176 ,1108 ,1040 , 976 , 914 , 854 , 794 , 738 , 684 , 632 ,
582 , 536 , 490 , 448 , 408 , 370 , 334 , 300 , 270 , 242 ,
216 , 194 , 172 , 154 , 140 , 126 , 116 , 108 , 102 , 100
};
uint16_t Counter_sine1 = 0; //A相
uint16_t Counter_sine2 = 83; //滞后A相120度
uint16_t Counter_sine3 = 166; //超前A相120度
void TIM1_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9| GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13| GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
#define CKTIM ((u32)72000000uL) //主频
#define PWM_PRSC ((u8)0) //TIM1分频系数
#define PWM_FREQ ((u16) 10000) //PWM频率(Hz)
#define PWM_PERIOD ((u16) (CKTIM / (u32)(2 * PWM_FREQ *(PWM_PRSC+1))))
#define MODULAT (float)0.7 //调制度
void TIM1_Mode_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_BDTRInitTypeDef TIM1_BDTRInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseStructure.TIM_Period = PWM_PERIOD; //计数周期
TIM_TimeBaseStructure.TIM_Prescaler = PWM_PRSC; //分频系数
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV2;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned1;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //配置为PWM模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能CHx的PWM输出
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;//互补输出使能,使能CHxN的PWM输出
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set;
TIM_OC1Init(TIM1, &TIM_OCInitStructure); //配置CH1
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC2Init(TIM1, &TIM_OCInitStructure); //配置CH2
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC3Init(TIM1, &TIM_OCInitStructure); //配置CH3
//死区时间
TIM1_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM1_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM1_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
TIM1_BDTRInitStructure.TIM_DeadTime = 360; //设置死区时间
TIM1_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
TIM1_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
TIM1_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable;
TIM_BDTRConfig(TIM1, &TIM1_BDTRInitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //4个抢先级、4个子优先级
NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_ITConfig(TIM1,TIM_IT_CC1|TIM_IT_CC2|TIM_IT_CC3,ENABLE); //使能中断
TIM_CtrlPWMOutputs(TIM1, ENABLE); //PWM输出使能
TIM_Cmd(TIM1, ENABLE); //使能TIM1
}
void TIM1_PWM_Init(void)
{
TIM1_GPIO_Config();
TIM1_Mode_Config();
}
//定时器1中断服务函数
void TIM1_CC_IRQHandler(void)
{
if(Counter_sine1>=250)
{
Counter_sine1 = 0;
}
if(Counter_sine2>=250)
{
Counter_sine2 = 0;
}
if(Counter_sine3>=250)
{
Counter_sine3 = 0;
}
//CCR1
if (TIM_GetITStatus(TIM1, TIM_IT_CC1)!=RESET)
{
TIM_SetCompare1(TIM1,(uint32_t)(talab[Counter_sine1])*MODULAT); //A相
Counter_sine1++;
TIM_ClearITPendingBit(TIM1 , TIM_IT_CC1);
}
//CCR2
if (TIM_GetITStatus(TIM1, TIM_IT_CC2) !=RESET)
{
TIM_SetCompare2(TIM1,((uint32_t)talab[Counter_sine2])*MODULAT); //B相
Counter_sine2++;
TIM_ClearITPendingBit(TIM1 , TIM_IT_CC2);
}
//CCR3
if (TIM_GetITStatus(TIM1, TIM_IT_CC3) !=RESET)
{
TIM_SetCompare3(TIM1,(uint32_t)(talab[Counter_sine3])*MODULAT); //C相
Counter_sine3++;
TIM_ClearITPendingBit(TIM1 , TIM_IT_CC3);
}
}
当然也可以使用STM32的DSP库,然后在定时器中断计算正弦值,具体操作如下:
//定义角频率
spwm_struct.w = 2*pi*50; //50HZ正弦波
//确定每次进入定时器中断的时间间隔
spwm_struct.T = 0.00005; //20K的定时器中断,每次进入间隔50us
//更新正弦值,注意这里是用了dsp库的sin(实测F446 180M主频下运算只要400ns,而math.h的sin要算16us)
spwm_struct.uref = A*arm_sin_f32(spwm_struct.WT); //A是幅值
//在定时器中断里更新角度(相位)
spwm_struct.WT += spwm_struct.w * spwm_struct.T;
if(spwm_struct.WT >= 2 * pi) spwm_struct.WT = 0; //WT在0到2pi变化
实现如下
//定义spwm结构体
typedef struct
{
float w; //角频率
float fre; //频率
float wt; //相角
float mod_dep; //调制度
short ch1_ccr; //ccr1
short ch2_ccr;
float jibo;
float T; //每次进入定时器中断的时间
}spwm_t;
spwm_t spwm_struct;
//*参数初始化*/
void spwm_init()
{
spwm_struct.w = 2*pi*50; //2*pi*f
spwm_struct.wt = 0;
spwm_struct.fre = 50;
spwm_struct.uref = 1;
spwm_struct.rqd_flag = 1;
spwm_struct.mod_dep = 0.5; //调制度
spwm_struct.T = 0.00005;
/*2104使能*/
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET);
/*PWM输出开启*/
HAL_TIM_Base_Start_IT(&htim1);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
}
//单极性倍频调制
void unimp_modulation(float insignal, unsigned short cnt, spwm_t *ccr)
{
ccr->ch1_ccr = (1+insignal)/2 * (cnt-1);
ccr->ch2_ccr = (1-insignal)/2 * (cnt-1);
}
//双极性调制
void bipolar_modulation(float insignal, unsigned short cnt, spwm_t *ccr)
{
insignal = (insignal+1) / 2;
ccr->ch1_ccr = insignal * (cnt - 1);
}
//定时器中断
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM1)
{
spwm_struct.jibo = spwm_struct.mod_dep*arm_cos_f32(spwm_struct.wt);//更新正弦波数据
bipolar_modulation(spwm_struct.jibo, tim_cnt, &spwm_struct);
TIM1->CCR1 = spwm_struct.ch1_ccr;
spwm_struct.wt += spwm_struct.w * spwm_struct.T;//更新相角wt
if(spwm_struct.wt>=2*pi) spwm_struct.wt=0;//计满2π后归零,防止溢出
}
}
四、补充
关于无刷电机相关介绍见下链接
https://blog.csdn.net/weixin_44567668/article/details/133609017