直流有刷电机调速系统设计以及matlab仿真
在《直流有刷电机及机械特性》我们对直流有刷电机的工作原理、机械特性以及电动机的启动、制动、调速进行了详细的介绍。本节主要介绍电机的驱动器以及调速控制方案的实现。
一、电机介绍
由于我们需要学习直流有刷电机的控制,所以我们手里必须要有一款直流有刷电机。
这里我在淘宝购买的电机为:常规775
高速电机吹风机马达电动机双滚珠轴承高转速调速 12V~24V
。
具体型号信息:电压为24V
,转速一分钟20000
转,双出轴。
1.1 产品参数
直流有刷电机电机基本信息如下:
-
品牌:
Vantel
; -
型号:
VT-775
; -
额定电压:\(24V\);
-
转速:\(6000 \sim 20000rpm\);
-
电机尺寸:\(1.15A\);
-
出轴尺寸:\(\phi 5*17.5mm\);
-
调速方式:
PWM
/无极调速; -
最大转矩:\(0.6kgf.cm\);
空载运行参数:
- 空载转速:\(20000 rpm\);
- 空载电流:\(1.15A\);
堵转运行状态:
- 堵转电流:\(96A\);
- 堵转转矩:\(10000g.cm\);
最大效率状态:
- 效率:\(72.4 \%\);
- 转矩:\(1000 g.cm\);
- 转速:\(18000 rpm\);
- 电流:\(10.64A\);
- 输出功率:\(184.62W\);
最大功率输出状态:
- 输出功率:\(513.07 W\);
- 转矩:\(5000g.cm\);
- 转速:\(10000 rpm\);
- 电流:\(48.58 A\)。
1.1.1 图纸

1.1.2 实物尺寸图

1.1.3 3D
建模图

1.2 机械特性
VT-775
电机性能曲线如下:

图中绘制了电机工作在额定电压\(24V\),转矩-工作效率、转矩-功率、转矩-转速、转矩-电流之间的关系。
其中转矩-转速曲线就是固有机械特性曲线,根据空载点\((0,20000)\)和堵转点\((10000, 0)\)我们可以计算出固有机械特性方程式:
注意:这里转矩单位为\(g.cm\)。
由于\(n_0 = \frac{U_N}{C_e \phi_N}\),因此可以计算出:
\(C_e \phi_N = \frac{24}{20000} = 0.0012\)。
额定电流通常是指电机在额定负载下稳定运行时的电流。然而该电机的参数信息中并没有给出额定电流信息,通常,额定电流会接近最大效率点的电流,因为这是电机最节能、发热最少的工作状态。因此:
估算电枢电阻\(R_a\)的公式为:
因此这里计算可以得到:
额定电磁转矩:
\(T_N = 9.55C_e \phi_N I_N = 9.55 \times 0.0012 \times 10.64 = 0.122N.m = 0.122 \times 10,204.08 = 1244.89 g.cm\)
这个值和厂家给出的转矩值\(1000g.cm\)是有点偏差的。
1.2.1 常规单位换算
这里我们看到的转矩单位为g.cm
,这个和我们经常见到的N.m
如何进行换算呢?
g.cm | kg.cm | N.m | mN.m | N.cm |
---|---|---|---|---|
1.0 | 0.001 | 0.000098 | 0.098 | 0.0098 |
1000 | 1.0 | 0.098 | 98 | 9.8 |
10,204.08 | 10.204 | 1.0 | 1000 | 100 |
10.20 | 0.010 | 0.001 | 1.0 | 0.1 |
102.04 | 0.102 | 0.01 | 10 | 1.0 |
1.2.2 选型标准
通常点击参数表扭矩代表的是什么意思?
电机标准转矩为\(10kg.cm\),假设使用皮带轮传动,皮带轮的半径为\(1cm\)。皮带输出的拉力就是\(10kg\)。
如果皮带轮的半径为\(2cm\)。皮带输出的拉力就是\(5kg\)。
1.2.3 扭矩概念
扭矩 = 垂直于力臂的拉力 x 力劈。
例如:滚筒起吊,左图滚筒半径 = 力臂 = \(10cm\),起重量 = \(5kg\),需要扭矩 = \(5kg \times 10cm = 50 kg.cm\)。
右图滚筒半径 = 力臂 = \(5cm\),起重量 = \(5kg\),需要扭矩 = \(5kg \times 5cm = 25 kg.cm\)。
从该例子看出力臂很重要,同样重量起吊扭矩完全不一样,不同用法要看实际计算。

1.2.4 调速范围
正常且合理的调速范围应为\(50\% \sim 100\%\)。调速器越往下调速,速度就越慢,力道就越大。
二、驱动器设计
2.1 为什么要用驱动
MCU
的IO
口的电流输出能力一般在20mA
左右,那么输出功率\(P=UI=3.3V*20mA=66mW\)。
而我们所使用的VT-775
直流电机的额定功率为\(20W\),很显然,\(66mW\)的驱动能力驱动能力是无法推动\(30W\)的负载的。
所以MCU
的IO
口输出的PWM
信号,必须经过功率放大才能驱动电机,直流电机通常采用H
桥进行驱动。
2.2 H
桥工作原理
下面以MOS
管搭建的H
桥电路解释电机正反转控制。要使电机运转,必须使对角线上的一对MOS
管导通。如下图;

当Q1
管和Q4
管导通时(此时必须保证Q2
和Q3
关断),电流就从电源正极经Q1
从左至右流过电机,然后再经Q4
回到电源负极。按图中电流箭头所示,该流向的电流将驱动电机顺时针转动。
另一对MOS
管Q2
和Q3
导通的时候(此时必须保证Q1
和Q4
关断),电流从右至左流过电机,从而驱动电机沿逆时针方向转动。
驱动电机时,保证H
桥两个同侧的MOS
管不会同时导通非常重要,如果MOS
管Q1
和Q2
同时导通,那么电流就会从电源正极穿过两个MOS
管直接回到负极,此时电路中除了MOS
管外没有其它任何负载,因此电路上的电流就达到最大值,烧坏MOS
管和电源。Q3
和Q4
同时导通是同样的道理。
简单的开关只能控制电机正反转,引入PWM
控制可以实现方向和速度调节。调节占空比实现控速,占空比越大平均电压(电流)越大,速度越快PWM
频率一般在10KHz~20KHz
之间。频率太低会导致电机转速过低,噪声较大。频率太高,会因为MOS
管的开关损耗而降低系统的效率。
根据不同桥臂的PWM
控制方式不同,大致上可以分为三种控制模式:受限单极模式、单极模式、双极模式。
2.2.1 受限单极模式
电机电枢驱动电压极性是单一的,需要对一个MOS
采用PWM
控制,电流在电机中单向流动,通过PWM
调制控制电机的平均电压。
优点:
- 效率高:由于只有一个桥臂进行
PWM
调制,开关损耗较小; - 控制简单:实现相对简单,适用于单向控制。
缺点:
- 不能刹车,不能能耗制动,在负载超过设定速度时不能提供反向力矩。调速静差大,调速性能很差,稳定性也不好。
2.2.2 单级模式
电机电枢驱动电压极性是单一的,需要对同一侧桥臂的两个MOS
管进行互补PWM
控制。要使用高级定时器的互补通道进行控制。电流在电机中双向流动,通过PWM
调制控制电机的平均电压和方向。
优点:启动快,能加速,刹车,能耗制动,能量反馈,调速性能不如双极模式好,但是相差不多,电机特性也比较好。在负载超速时也能提供反向力矩。
缺点:刹车时,不能减速到0
,速度接近0
时没有制动力。不能突然倒转。动态性能不好,调速静差稍大。
以正转控制过程为例(反转控制与之类似):MOS
管Q1
和Q2
由一对互补PWM
进行控制;
- 当
Q1
为高电平时,由VCC-Q1-Motor-Q4-GND
形成通路,电机电枢电流上升; - 当
Q1
为低电平时,Q2
变为高电平,根据楞次定律,当不再给电机供电,线圈中存在自感电动势,电流继续往同一方向流动,于是由D2-Motor-Q4
形成通路,给线圈电流继续提供通路;

对于单极性控制,电机电枢平均电压\(U=U_N \cdot D\),其中\(U_N\)为输入的额定电压,\(D\)为占空比。
2.2.3 双级模式
电枢电压极性是正负交替的。需要两组互补PWM
同时对4
个MOS
管进行控制。

优点:能正反转运行,启动快,调速精度高,动态性能好,调速静差小,调速范围大,能加速,减速,刹车,倒转,能在负载超过设定速度时提供反向力矩,能克服电机轴承的静态摩擦力,产生非常低的转速。
缺点:控制电机复杂,在工作期间,4
个MOS
管都处于开关状态,功耗大。
假设PWM
周期为\(T\),Q1
和Q4
导通时间为\(t_{on}\),控制过程如下:
- 当\(0 ≤ t ≤ t_{on},\)
Q1
和Q4
同时处于PWM
的高电平,Q1
和Q4
导通,Q1
和Q4
同时处于PWM
的低电平,Q2
和Q3
关断,于是由VCC-Q1-Motor-Q4-GND
形成通路,电流上升;电源电压加到电动机正负两端\(U=U_N\); - 当\(t_{on} ≤ t ≤ T,\)
Q1
和Q4
同时处于PWM
的低电平,Q2
和Q3
同时处于PWM
的高电平,因为楞次定律,线圈上的电流方向不变,于是由GND-D2-Motor-D3-VCC
形成通路,在D2
、D3
上的压降使Q2
和Q3
的D-S
级承受着反压,这时电动机两端电压\(U=-U_N\);

- 当电枢电流反向,
Q2
和Q3
导通,于是由VCC-Q3-Motor-Q2-GND
形成通路,电流上升,电机处于制动状态;电源电压加到电动机正负两端\(U=-U_N\); - 当下一个周期,在
Q2
和Q3
关断时,Q1
和Q4
也不能立即导通,电枢电流沿GND-D4-Motor-D1-VCC
形成通路。
电动机电枢平均电压计算为:
当\(D > 0.5\),电动机正转;$ D < 0.5 $ 时,电动机反转;$ D = 0.5$,电动机停止。
2.3 L298N
芯片
通常在驱动电机的时候我们会选择集成H
桥的IC
,因为H
桥使用分立元件搭建比较麻烦,增加了硬件设计难度。
当然如果集成IC
无法满足我们的功率要求时,还是需要我们自己使用MOS
管、三极管等元件来搭建H
桥电路, 这样的分立元件搭建的H
桥一般驱动能力都会比集成IC
要高。
当我们在选择集成IC
时, 我们需要考虑集成IC
是否能满足电机的驱动电压要求,是否能承受电机工作时的电流等情况。
市面上已经有很多比较常用的IC
方案,比如常用的L293D
、L298N
、TA7257P
、SN754410
等。接上电源、电机,通过输入控制信号就可以驱动电机了。
L298N
驱动板使用了优质的L298N
作为驱动芯片。具有驱动能力强发热量低,抗干扰能力强的特点。
2.3.1 基本介绍
L298N
芯片是ST
公司的一款电机驱动芯片,可以驱动一台两相步进电机或四相步进电机,也可以驱动两台直流电机。L298N
芯片主要特点是:
- 工作电压高,工作电压最高可达\(46V\);
- 输出电流大,瞬间峰值电流可达\(3A\),持续工作电流为\(2A\);
- 额定功率\(25W\);
- 内含两个
H
桥的高电压大电流全桥式驱动器,可以用来驱动直流电动机和步进电动机,继电器线圈等感性负载; - 采用标准逻辑电平信号控制具有两个使能控制端,在不受输入信号影响的情况下允许或禁止器件;
- 接收标准的
TTL
逻辑电平信号; - 可以外接检测电阻,将变化量反馈给控制电路。
2.3.2 功能框图
L298N
芯片内部结构如下图所示:

L298N
驱动芯片,它内部用两个H
桥电路。我们分别称之为A
和B
;
A
电路分别有3
个控制端口:分别是ENA
、IN1
、IN2
;B
电路分别有3
个控制端口:分别是ENA
,IN3
,IN4
。
15
脚封装;
脚名称 | 引脚标号 | I/O | 功能 | 引脚名称 | 引脚标号 | I/O | 功能 |
---|---|---|---|---|---|---|---|
Sense A | 1 | O | H桥A的电流控制,可通过一个电阻接地限制电流(不限电流时直接接地) | Vss | 9 | – | 给内部逻辑电路供电,一般接5V |
OUT 1 | 2 | O | H桥A的输出1脚 | IN 3 | 10 | I | H桥B的逻辑输入1 |
OUT 2 | 3 | O | H桥A的输出2脚 | EN B | 11 | I | H桥B的使能控制端,高电平打开,低电平关闭 |
Vs | 4 | – | 电机驱动电压3~48V,需要一个100nF的滤波电容接地 | IN 4 | 12 | I | H桥B的逻辑输入2 |
IN 1 | 5 | I | H桥A的逻辑输入1 | OUT 3 | 13 | O | H桥B的输出1脚 |
EN A | 6 | I | H桥A的使能控制端,高电平打开,低电平关闭 | OUT 4 | 14 | O | H桥B的输出2脚 |
IN 2 | 7 | I | H桥A的逻辑输入2 | Sense B | 15 | O | H桥B的电流控制,可通过一个电阻接地限制电流(不限电流时直接接地) |
GND | 8 | – | 接地 |
2.3.3 逻辑控制
以H
桥A
为例,L298N
逻辑功能表;
IN1 | IN2 | ENA | 电机状态 |
---|---|---|---|
× | × | 0 | 电机停止 |
1 | 0 | 1 | 电机正转 |
0 | 1 | 1 | 电机反转 |
0 | 0 | 1 | 电机停止 |
1 | 1 | 1 | 电机停止 |
当IN1
和IN2
全0
时,Q1
和Q3
截止,电流关断,电路停止工作。
当IN1
和IN2
全1
时,Q2
和Q4
截止,电流关断,电路也停止工作。
当IN1=0
,IN2=1
时,Q2
和Q3
导通,Q1
和Q4
截止,电流从OUT2
端流入电机,从OUT1
端流出电机。
当IN1=1
,IN2=0
时,Q2
和Q3
截止,Q1
和Q4
导通,电流从OUT1
端流入电机,从OUT2
端流出电机。
2.4 L298N
驱动板
驱动板如下:

2.4.1 产品参数
产品参数:
- 驱动芯片:
L298N
双H
桥直流电机驱动芯片; - 驱动电压
Vs
:+5V~+35V
; 如需要板内取电,则供电范围Vs
:+5V~+12V
; - 驱动电流
Io
:2A
(MAX
单桥); - 逻辑电压
Vss
:+5V~+7V
; - 逻辑电流:
0~36mA
; - 控制信号输入电压范围:
- 低电平:
-0.3V ≤ Vin ≤ 1.5V
; - 高电平:
2.3V ≤ Vin ≤ Vss
;
- 低电平:
- 使能信号输入电压范围:
- 低电平:
-0.3V ≤ Vin ≤ 1.5V
(控制信号无效); - 高电平:
2.3V ≤ Vin ≤ Vss
(控制信号有效);
- 低电平:
- 最大功耗:
25W
; - 存储温度:
-20℃ ~ +135℃
。
在实际测试的时候发现,H
桥输出如果是空载时,输出电压等于\(Vs\);但是如果H
桥连接了直流电机,输出电压会有2V
的压降。
2.4.2 电路原理图

这个模块还有一个板载\(5V\)稳压器78M05
(图中并没有画出,主要是我们找到驱动板的原理与图),该稳压器可使用跳线帽的方式进行使能。
2.4.3 驱动电压\(7V \sim 12V\)
当驱动电压为\(7V \sim 12V\)时,我们可以启用板载的78M05
供给L298N
芯片的逻辑电源,指示灯亮,可以不用再外接逻辑电源。

当使用板载\(5V\)供电后,接口中的\(+5V\)供电端子不要输入电压,但是可以引出\(5V\)电压供外部使用。
2.4.4 驱动电压\(12V \sim 24V\)
如果驱动电压大于\(12V\),小于等于\(24V\)(芯片手册中提出可以支持到\(35V\),但是按照经验一般L298N
保守应用最大电压支持到\(24V\)已经很了不起),则必须断开跳线,因为该电压会损坏板载稳压器78M05
。
断开跳线后,指示灯熄灭,不使用板载的78M05
供给L298N
芯片的逻辑电源,然后再\(5V\)输出端口外接输入\(5V\)电压对L298N
芯片内部逻辑电路供电。

2.4.5 补充
LN298N
使能端,高电平有效,常态下用跳线帽连接到\(5V\)电平。
注意事项:L298N
逻辑供电电压\(Vss\)如果是用另外电源供电的话(即不是和MCU
的电源共用),那么需要将MCU
的GND
和模块上的GND
连接在一起,只有这样MCU
上过来的逻辑信号才有个参考0
点。
三、电机调速控制
在《直流有刷电机及机械特性》我们介绍了直流电机的调速方式主要包括:
- 电枢串电阻调速:属于有级调速,效率低,用于各种对调速性能要求不高的设备上;
- 降压调速:可达到无级调速、低速时电损耗小,效率高;是一种性能优越的调速方法,广泛应用于对调速性能要求较高的设备上;
- 弱磁调速:可达到无级调速、功率损耗小,调速范围较小。
在实际生产中,通常把降压调速和弱磁调速配合起来使用,以电动机的额定转速作为基准,在基速以下调压,在基速以上调磁,以实现双向调速,扩大调节范围。
由于这里我是用的电机定子励磁采用永磁体,因此无法进行弱磁调速,因此本节主要介绍降压调速方式。
只要MCU
输出占空比可调的方波,即PWM
信号即可控制电机两端的电压发生变化,从而实现电机转速的控制。
3.1 PWM
信号调速的原理
脉冲宽度调制(Pulse width modulation
,PWM
):这种控制方式是指开关管调制信号的周期固定不变,而开关管导通信号的宽度可调。
其具有两个很重要的参数:频率和占空比;
- 频率,就是周期的倒数;
- 占空比,就是高电平在一个周期内所占的比例。
PWM
方波的示意图如下图所示:

在上图中,频率\(f\)的值为\(\frac{1}{T_1 + T_2}\),占空比\(D\)的值为\(\frac{T_1}{T_1+T_2}\)。
通过改变单位时间内脉冲的个数可以实现调频。
通过改变占空比可以实现调压,以单极性控制为例平均电压\(U=U_N \cdot D\);
- 占空比越大,所得到的平均电压也就越大,幅值也就越大;
- 占空比越小,所得到的平均电压也就越小,幅值也就越小。
通过以上原理就可以知道,只要改变PWM
信号的占空比,就可以改变直流电机两端的平均电压,从而实现直流电机的调速。
3.1.1 直流电机机械特性
我们知道直流电机的机械特性方程式:
式中:
- \(U\)是电枢回路的直流电源电压;
- \(R_a\)为电枢电阻;
- \(R_C\)为电枢回路外串电阻;
- \(C_e\)为电动势常数,\(C_e=\frac{pz}{60a}\);
- \(z\)为电枢绕组的导体中枢;
- \(a\)为并联支路对数;
- \(C_T\)为转矩常数,\(C_T=\frac{pz}{2 \pi a}\);
- \(\phi\)为每极主磁通,\(\phi=B_{av} \tau_p l_e\);
- \(B_{av}\)为每极平均气隙磁通密度,
- \(\tau_p\)值的是两个相邻主极之间的长度,
- \(l_e\)为电枢铁芯的有效长度。
3.1.2 降压调速原理
当电压下降时,则可得到与固有机械特性相互平行的人为机械特性。

从上图可以看到,相同负载转矩\(T_L\)下,转速随着电压的下降而下降。
因此当占空比\(D(0≤D≤1)\)的大小改变时,电压\(U\)下降,速度\(n\)也会随着下降,所以只要改变占空比就能达到控制速度的目的。
3.2 硬件设计
3.2.2 STM32F103RTC6
开发板
我们在《STM32
》系列相关博文中介绍了PWM
的配置,当时使用的是型号为STM32F103RTC6
的开发板。
本节实验只用到了TIM1
的CH1
和CH2
, 即PA8
和PA9
来输出PWM
信号来控制电机,注意主控板需要和电机驱动板供地。
3.2.1 L298N
驱动板
这里我们使用到 L298N
驱动板H
桥A
,引脚接线如下:
L298N驱动板 | STM32 开发板 |
其它 |
---|---|---|
IN1 | PA8 | |
IN2 | PA9 | |
ENA | 使用跳线帽连接到5V | |
5V供电 | VT-775电机额定电压为24V,需要拔掉L298N驱动板的跳线帽 外接输入5V电压对L298N芯片内部逻辑电路供电 |
|
供电GND | 和STM32开发板供地 | |
驱动电压 | 24V | |
OUT1 | 直流电机VT-775的M+端子 | |
OUT2 | 直流电机VT-775的M-端子 |
3.3 软件设计
接下来我们实现一个功能:
- 按下
KEY0
加速电机; - 按下
KEY1
减速电机。
既然我们需要实现该功能,就需要实现如下代码:
(1)定时器2
通道 CH1
以及通用CH2 PWM
初始化,设置频率为10kHz
,占空比均设置为0;
- 定时器
2
通道CH1
使用的引脚是PA0
; - 定时器
2
通道CH2
使用的引脚是PA1
; - 这里并没有使用定时器
1
的通道CH1
和CH2
,主要是因为串口1
的TX
引脚和定时器1
的CH2
引脚冲突了(PA9
引脚)。
(2)编写外部中断处理程序:
KEY0
连接STM32
的PC5
,按下时输出低电平;- 配置
GPIOC
对应的EXTI
线[9:5]
外部中断,下降沿触发; - 中断处理函数检测
KEY0
按键按下,增加通道CH1
的占空比,最大为100
;
- 配置
KEY1
连接STM32
的PA15
,按下时输出低电平;- 配置
PA15
对应的EXTI
线[15:10]
外部中断,下降沿触发; - 中断处理函数检测
KEY1
按键按下,减小通道CH1
的占空比,最小为0
。
- 配置
注意:由于我们定时器2
通道 CH2
占空比始终为0
,那么Q3
处于截止状态,Q4
处于导通状态;我们通过改变定时器1
通道CH1
的占空比,即Q1
使用一堆互补的PWM
进行调速控制,这种控制方式对应我们前面介绍单级模式。
3.3.1 main
函数实现
#include "common.h"
#include "stdio.h"
#include "motor.h"
int main()
{
int duty;
STM32_Clock_Init(9); //系统时钟初始化
// 串口初始化
STM32_NVIC_Init(2,USART1_IRQn,0,1); //串口中断优先级初始化,其中包括中断使能
usart_init(USART_1,115200); //串口1初始化,波特率115200 映射到PA9 PA10
// 按键KEY初始化
gpio_init(PC5,GPI_UP,HIGH); //PC5接按键KEY0
gpio_init(PA15,GPI_UP,HIGH); //PA15接按键KEY1
Ex_NVIC_Congig(PC5,FALLING); //按键KEY0按下触发 高电平->低电平
Ex_NVIC_Congig(PA15,FALLING); //按键KEY1按下触发 高电平->低电平
STM32_NVIC_Init(2,EXTI9_5_IRQn,2,2); //EXTI线[9:5]中断优先级初始化,其中包括中断使能
STM32_NVIC_Init(2,EXTI15_10_IRQn,2,2); //EXTI线[15:10]中断优先级初始化,其中包括中断使能
motor_init(); // 电机初始化,使用的定时器2,PA0/PA1
while(1)
{
duty = get_motor_duty();
printf("duty: %d\n",duty);
delay_ms(1000);
}
}
3.3.2 motor.h
motor.h
为直流电机驱动头文件:
/******************************************************************************************************
*
* Function : 直流有刷电机控制,L298N驱动板
使用定时器TIME2 CH1生成PWM1,使用PA0引脚
使用定时器TIME2 CH2生成PWM2,使用PA1引脚
*
*
*********************************************************************************************************/
#ifndef _STM32f10x__MOTOR_H
#define _STM32f10x__MOTOR_H
#include "pwm.h"
/*******************************************************************************************/
extern void motor_init(void); //电机初始化
extern void motor_speed_up(void); //电机加速
extern void motor_slow_down(void); //电机减速
extern int get_motor_duty(void); //获取电机PWM占空比
#endif
3.3.3 motor.c
motor.c
为直流电机驱动源文件:
/*********************************************************************************************/
#include "motor.h"
/* 电机占空比 */
volatile int g_motor_pwm = 0;
/* 电机正转/反转 */
volatile bool g_motor_fwd = TRUE;
/**************************************************************************************************
*
* Function : 电机初始化
*
**************************************************************************************************/
void motor_init(void)
{
//电机初始化********************************************************
TIM_PWM_Init(TIMER2, 10, PWM_CH1); // PWM初始化,频率为10kHz PA0
TIM_PWM_Init(TIMER2, 10, PWM_CH2); // PWM初始化,频率为10kHz PA1
TIM_PWM_Duty(TIMER2, 0, PWM_CH1);
TIM_PWM_Duty(TIMER2, 0, PWM_CH2);
}
/**************************************************************************************************
*
* Function : 刷新电机速度
*
**************************************************************************************************/
void motor_update_speed(void)
{
// 电机正转
if(g_motor_fwd)
{
TIM_PWM_Duty(TIMER2, g_motor_pwm, PWM_CH1);
TIM_PWM_Duty(TIMER2, 0, PWM_CH2);
}
else
{
TIM_PWM_Duty(TIMER2, 0, PWM_CH1);
TIM_PWM_Duty(TIMER2, g_motor_pwm, PWM_CH2);
}
}
/**************************************************************************************************
*
* Function : 电机加速
*
**************************************************************************************************/
void motor_speed_up(void)
{
g_motor_pwm++;
if(g_motor_pwm >100)
{
g_motor_pwm = 100;
}
motor_update_speed();
}
/**************************************************************************************************
*
* Function : 电机减速
*
**************************************************************************************************/
void motor_slow_down(void)
{
g_motor_pwm--;
if(g_motor_pwm < 0)
{
g_motor_pwm = 0;
}
motor_update_speed();
}
/**************************************************************************************************
*
* Function : 获取电机PWM占空比
*
**************************************************************************************************/
int get_motor_duty(void)
{
return g_motor_pwm;
}
3.3.4 EXTI9_5_IRQHandler
中断处理函数
在EXTI9_5_IRQHandler
中断处理函数中实现了KEY0
按键按下电机加速的功能;
/*********************************************************************************************************************
* Function Name : EXTI9_5_IRQHandler
* Description : This function handles External lines 9 to 5 interrupt request.
* Input : None
* Output : None
* Return : None
*************************************************************************************************************************/
void EXTI9_5_IRQHandler(void)
{
if( EXTI->PR & 1<<5 ) //来自中断线5上的中断
{
//**********************自定义用户任务****************************//
motor_speed_up();
//*****************************************************************//
EXTI->PR = 1<<5; //清中断线5上的中断标志
}
if( EXTI->PR & 1<<6 ) //来自中断线6上的中断
{
//**********************自定义用户任务****************************//
//*****************************************************************//
EXTI->PR = 1<<6; //清中断线6上的中断标志
}
if( EXTI->PR & 1<<7 ) //来自中断线7上的中断
{
//**********************自定义用户任务****************************//
//*****************************************************************//
EXTI->PR = 1<<7; //清中断线7上的中断标志
}
if( EXTI->PR & 1<<8 ) //来自中断线8上的中断
{
//**********************自定义用户任务****************************//
//*****************************************************************//
EXTI->PR = 1<<8; //清中断线8上的中断标志
}
if( EXTI->PR & 1<<9 ) //来自中断线9上的中断
{
//**********************自定义用户任务****************************//
//*****************************************************************//
EXTI->PR = 1<<9; //清中断线9上的中断标志
}
}
3.3.5 EXTI15_10_IRQHandler
中断处理函数
在EXTI15_10_IRQHandler
中断处理函数中实现了KEY1
按键按下电机减速的功能;
/***********************************************************************************************************************
* Function Name : EXTI15_10_IRQHandler
* Description : This function handles External lines 15 to 10 interrupt request.
* Input : None
* Output : None
* Return : None
*************************************************************************************************************************/
void EXTI15_10_IRQHandler(void)
{
if( EXTI->PR & 1<<10 ) //来自中断线10上的中断
{
//**********************自定义用户任务****************************//
//*****************************************************************//
EXTI->PR = 1<<10; //清中断线10上的中断标志
}
if( EXTI->PR & 1<<11 ) //来自中断线11上的中断
{
//**********************自定义用户任务****************************//
//*****************************************************************//
EXTI->PR = 1<<11; //清中断线11上的中断标志
}
if( EXTI->PR & 1<<12 ) //来自中断线12上的中断
{
//**********************自定义用户任务****************************//
//*****************************************************************//
EXTI->PR = 1<<12; //清中断线12上的中断标志
}
if( EXTI->PR & 1<<13 ) //来自中断线13上的中断
{
//**********************自定义用户任务****************************//
//*****************************************************************//
EXTI->PR = 1<<13; //清中断线13上的中断标志
}
if( EXTI->PR & 1<<14 ) //来自中断线14上的中断
{
//**********************自定义用户任务****************************//
//*****************************************************************//
EXTI->PR = 1<<14; //清中断线14上的中断标志
}
if( EXTI->PR & 1<<15 ) //来自中断线15上的中断
{
//**********************自定义用户任务****************************//
motor_slow_down();
//*****************************************************************//
EXTI->PR = 1<<15; //清中断线15上的中断标志
}
}
3.3.6 测试
编译程序并下载测试,我们通过按下KEY0
/KEY1
调节占空比,可以通过串口查看当前输出的占空比;

如果有条件的话,这里我们先不连接电机,先通过示波器连接到STM32
开发板的PWM
输出引脚上,通过示波器来观察PWM
的变化情况,这里我们将PA0
引脚连接到逻辑分析仪的通道0
,PA1
引脚连接到逻辑分析仪的通道1
;

上图中:
- 红色波形为
CH1
通道,时钟周期为100us
,换算成频率就是10kHz
,此时的占空比为87
,与我们设置的一致; - 蓝色波形为
CH2
通道,始终为低电平。
当CH1
和CH2
都为低电平时,电机停止转动。当CH1
上的平均电压大于电机的启动电压后电机就可以转动了,电源电压为\(24V\),占空比为\(D\),则平均电压为:\(24V \times D\),这个我们可以通过使用万用表测量驱动板H
桥A
端的输出电压来验证。
在确定PWM
输出正确后我们就可以接上电机进行验证我们的程序了;

四、Simulink
仿真
VT-775
电机额定参数:\(U_N=24V\),\(I_N=10.64A\),\(P_N = 184.62W\),\(n_N = 18000 rpm\),$\eta = 72.4% $ 。
估算电机参数:
- 电枢回路电阻\(R_a = 0.312 Ω\);
- 电枢回路电感:对于小型直流电机 通常在几毫亨(\(mH\))到几十毫亨(\(mH\))之间,这里假设为\(0.006H\);
- \(C_e\phi_N = 0.0012\);
- \(C_T\phi_N = 9.55 \times 0.0012 = 0.01146\)。
4.1 建立仿真模型
注意:matlab
版本2023a
。
4.1.1 仿真主电路
第一步建立仿真主电路仿真模型;
1)选择Simscape/Electrical/Specialized Power Systems/Sources
中的直流电压源模块DC Voltage Source
,双击在对话框中将直流电压设置为\(24V\);
2) 然后在Simscape/Electrical/Specialized Power Systems/Power Electronics
库中选择Universal Bridge
模块;双击设置如下参数:
Number of bridge arms
:设置为2
,即两个桥臂,组成全桥电路;Snubber resistances Rs(0hms)
:1e5
,默认值;Power Electronic device
:IGBT/Diodes
;Ron
(0hms
):1e-3
,默认值;Forward voltages
:[0 0]
;
3)在Simscape/Electrical/Specialized Power Systems/Electrical Machine
选择直流电动机DC Machine
,这个模型有三对端子。从上到下分别是:
- 负载转矩信号输入端(写着
TL
的那个):这个端口表示负载转矩; - 电动机运转状态的信号检测端(写着
m
的那个):这个端口输出的是电机的几个运行参数,如转速\(n\)、电枢电流\(I_a\)、励磁电流\(I_f\)、电磁转矩\(T\); - 电枢回路接线端(写着
A+A-
的那个):外接一个电源; - 励磁回路接线端(写着
F+F-
的那个):外接一个电源;
双击这个模型,打开它的参数设置窗口。首先配置configuration
页:
preset model
:这是设置直流电机型号的。这里我选择不使用内置型号,自己设置各个参数,即选择No
;Mechanical input
:选择Torque TL
是设置成输入转矩TL
;field type
:当preset model
选择了某种型号时是灰色的,无法修改,只有在上面的preset model
选择了No
之后才能选;wound
:可以理解成需要外接励磁回路;permanent magnet
:则是永磁体,简单理解成用两块磁铁放在那里,这里我们选择这个;选择类型为永磁体permanent magnet
之后,这个电机的外观会有所变化。励磁回路的两个端子消失了,而出现了表示磁体的N、S
。这个很容易理解,用了永磁体,就不需要外接电源来提供磁场了;
最终configuration
页配置如下:

接着配置parameters
页,这一页是设置电机参数的,除了initial speed
(初速度,单位为rad/s
)和initial field
(初始磁场)两个参数外(最下面两行),其他参数只有在configuration
页的preset model
选择了No
之后才能修改;
Armature resistance and inductance [Ra (ohms) La (H) ]
:电枢回路电阻\(R_a\)设置为0.312
,电枢回路电感\(L_a\)设置成0.006H
;Torque constant (N.m/A)
:即\(C_T\phi_N\),设置为0.01146
;Total inertia J (kg.m^2)
:电机转动惯量,这里我们设置为1e-4
;由于\(T-T_L=J\frac{d \Omega}{dt}\),因此\(J\)会影响电动机转速加速的快速;Viscous friction coefficient Bm (N.m.s)
;粘滞摩擦系数;Coulomb friction torque Tf (N.m)
:静摩擦转矩;Initial speed (rad/s)
:设置为0
;
仿真时当成理想的电机算,没有摩擦,把Bm
、Tf
都设置成0
。最终parameters
页配置如下:

4.1.2 控制
将控制部分封装成了子系统,对外暴露了两个参数:
- 频率(
f
):PWM
频率; - 占空比(
d
):PWM
占空比。
单极性控制和双极性控制,该子系统的搭建是不同的,这个后面介绍。
4.1.3 观察及分析
第三步完成波形观测及分析部分:
1)将电机m
端口通过BusSelector
分解后,输入到是示波器;
- 由于这里转速输出使用的是角速度\(w\),单位为\(rad/s\),转换为转速需要乘以\(60/(2\pi)≈9.55\);
- 此外转矩输出的单位默认为\(N.m\),这里需要转换为\(g.cm\),因此需要乘以\(10204.08\);
2)在Simscape/Electrical/Specialized Power Systems/Sensors and Measurements
选择Voltage Measurement
,连接到全桥的输出的端;
最后完成仿真模型如下图所示:

4.1.3 模型设置
点击菜单栏的建模 -> 模型设置,将仿真参数的Start time
设置为0
,Stop time
设置为2s
,仿真算法采用ode23s
,其它为默认参数。
4.2 单极控制
4.2.1 控制部分
控制部分子系统组成如下:

其中使用到的模块有:
-
Simulink/Sources
库中Pulse Generator
模块; -
Simulink/Sources
库中Relational Operator
模块; -
Simulink/Sources
库中Constant
模块; -
Simulink/Commonly Used Blocks
库中Switch
模块; -
Simulink/Commonly Used Blocks
库中Data Type Conversion
模块; -
Simulink/Logic and Bit Operationss
库中Bitwise Operator
模块。
4.2.2 空载运行
设置PWM
频率为\(10kHz\),占空比为100%
。
首先看一下空载的情况:因为是空载,我们假设空载转矩\(T_0\)为\(0g.cm\),TL
端接入常量,常量值为0
。
启动仿真程序;

测得空载转速为\(19984rpm\),与给定的空载转速为\(20000rpm\)误差很小。
励磁电流恒为\(0A\),因为用的是永磁体,没有励磁电流,这个没问题。
电磁转矩从启动时的\(7637g.cm\)降到稳定值\(0g.cm\)。
重点看一下电枢电流,启动时的瞬时电流最大可以达到\(64.75A\),最终稳定在\(0.0097A\),这与空载电流\(1.15A\)相差甚远,为什么差别这么大?
原因在:parameters
页的参数,我们把Bm
、Tf
都设置成0
,我们认为电机没有摩擦,Bm
、Tf
都为0
,实际上这是绝不可能的!
4.2.3 额定运行
设置PWM
频率为\(10kHz\),占空比为100%
。
给定的额定转矩为\(1000g.cm\)(\(0.098N.m\)),因为我们认为没有摩擦,所以负载转矩等于电磁转矩。直接把负载转矩也设置成\(0.098N.m\)。
启动仿真程序;

稳定状态下
- 转速稳定在\(17760rpm\),与给定的额定转速为\(18000rpm\)误差很小;
- 电磁转矩稳定在\(1005g.cm\),与给定的额定转矩为\(1000g.cm\)误差很小;
- 电枢电流稳定在\(8.6A\),与给定的额定电流为\(10.64A\)相比误差稍微有些大。
4.2.4 降压启动
由于电机启动的瞬时电流比较大,因此我们可以采用降压启动,比如将PWM
占空比依次增大。
下面我们调整PWM
频率为\(10kHz\),占空比为60%
,模拟电动机在空载、额定负载下运行。
4.2.4.1 空载运行
下面是空载运行的仿真结果,PWM
控制信号如下:

电机转速、电枢电流、转矩、电机电枢电压;

可以看到启动瞬时电流明显下降了很多,并且此时的空载转速大概为\(12000rpm\)。将稳定状态下某一时刻放大:

实际上我们可以拖出一个平均值模块,计算电机电枢电压的均值看看是否满足\(U=U_N*D = 0.6U_N\)。
4.2.4.2 额定负载运行
下面是负载转矩为\(0.098N.m\)仿真结果。
电机转速、电枢电流、转矩、电机电枢电压;

从上图可以看到转速稳定在\(9758rpm\),电流稳定在8.56A
。将稳定状态下某一时刻放大:

实际上我们可以拖出一个平均值模块,计算电机电枢电压的均值看看是否满足\(U=U_N*D = 0.6U_N\)。
4.3 双极控制
4.3.1 控制部分
控制部分子系统组成如下:

其中使用到的模块有:
-
Simulink/Sources
库中Relational Operator
模块; -
Simulink/Sources
库中Constant
模块; -
Simulink/Sources
库中Repeating Sequence
模块; -
Simulink/Commonly Used Blocks
库中Data Type Conversion
模块; -
Simulink/Logic and Bit Operationss
库中Bitwise Operator
模块。
4.3.2 降压运行
下面我们调整PWM
频率为\(10kHz\),占空比为80%
,电动机在负载转矩为\(0.098N.m\)下仿真。
PWM
控制信号如下:

电机转速、电枢电流、转矩、电机电枢电压;

从上图可以看到转速稳定在\(9760rpm\),电流稳定在8.55A
。将稳定状态下某一时刻放大:

可以看到稳定状态下的电机转速、电枢电流、转矩、电机电枢电压和【单极控制/降压启动/额定负载】运行的仿真结果基本一致。
实际上我们可以拖出一个平均值模块,计算电机电枢电压的均值看看是否满足\(U=(2 D - 1)U_N = 0.6U_N\)。
五、源码下载
源码下载路径:stm32f103
。
参考文章
[1] 直流有刷电机的驱动电路设计
[2] 4. 直流有刷电机
[3] 他励直流电机 | 起动、调速、制动原理与Simulink
仿真
[4] matlab/simulink
电力电子仿真直流电机设置和使用
[5] 双极式控制直流PWM-M
可逆调速系统的建模与仿真(论文)