4、直流电机模型搭建(Python):基于Python的直流电机仿真、参数设置、阶跃响应分析

说实话,做电机控制这么多年,我始终觉得——仿真是验证算法最快、最安全的方式。你想想看,直接上硬件调试,一个参数设错了,轻则电机抖得像筛子,重则烧驱动板。而用Python搭个模型,几行代码就能把电机“跑”起来,调参、看波形、分析响应,全在电脑上搞定。

这一章,我们就用Python从零搭建直流电机的数学模型。我会带着你一步步写代码,设置参数,然后做阶跃响应分析。嗯,这些都是后续做更复杂控制的基础。

4.1 直流电机的数学模型

先回顾一下直流电机的基本方程。我之前在调试一个伺服系统时,就是因为忽略了电枢电感的影响,导致电流环响应一直调不上去。所以,模型要准,方程得写对。

直流电机有两个核心方程:

  • 电枢回路方程:U = R * i + L * di/dt + e
  • 机械运动方程:T_e - T_L = J * dω/dt + B * ω

其中:

  • U:电枢电压 (V)
  • R:电枢电阻 (Ω)
  • L:电枢电感 (H)
  • i:电枢电流 (A)
  • e:反电动势 (V),e = K_e * ω
  • T_e:电磁转矩 (N·m),T_e = K_t * i
  • T_L:负载转矩 (N·m)
  • J:转动惯量 (kg·m²)
  • B:粘滞摩擦系数 (N·m·s/rad)
  • ω:转子角速度 (rad/s)

把这两个方程联立,就得到了直流电机的状态空间模型。我习惯用电流和转速作为状态变量。

核心思路:将微分方程离散化,用数值积分(比如欧拉法)迭代求解。说白了,就是用计算机模拟物理过程。

4.2 Python代码实现

下面是我写的一个直流电机仿真类。代码不长,但该有的都有了。我在项目里经常用这个模板做快速原型验证。

import numpy as np
import matplotlib.pyplot as plt

class DCMotor:
    """直流电机仿真模型"""
    def __init__(self, R=1.0, L=0.01, Kt=0.1, Ke=0.1, J=0.01, B=0.001):
        # 电机参数
        self.R = R      # 电枢电阻 (Ω)
        self.L = L      # 电枢电感 (H)
        self.Kt = Kt    # 转矩常数 (N·m/A)
        self.Ke = Ke    # 反电动势常数 (V·s/rad)
        self.J = J      # 转动惯量 (kg·m²)
        self.B = B      # 粘滞摩擦系数 (N·m·s/rad)
        
        # 状态变量初始化
        self.i = 0.0    # 电流 (A)
        self.w = 0.0    # 角速度 (rad/s)
        self.theta = 0.0 # 角度 (rad)
        
    def step(self, U, TL, dt):
        """
        单步仿真
        U: 输入电压 (V)
        TL: 负载转矩 (N·m)
        dt: 仿真步长 (s)
        """
        # 反电动势
        e = self.Ke * self.w
        
        # 电流导数 di/dt
        di_dt = (U - self.R * self.i - e) / self.L
        
        # 电磁转矩
        Te = self.Kt * self.i
        
        # 转速导数 dω/dt
        dw_dt = (Te - TL - self.B * self.w) / self.J
        
        # 欧拉积分更新状态
        self.i += di_dt * dt
        self.w += dw_dt * dt
        self.theta += self.w * dt
        
        return self.i, self.w, self.theta

我的习惯:仿真步长 dt 一般取 0.0001~0.001 秒。步长太大,仿真会发散;步长太小,计算太慢。我通常先试 0.0005 秒,看看效果再调。

4.3 参数设置与阶跃响应测试

参数怎么设?我刚开始做仿真时,随便填了几个数,结果电机转速飞到了几万转——明显不对。后来我学乖了,先查手册,或者用实验数据反推。

下面是一组典型的小型直流电机参数:

参数 符号 数值 单位
电枢电阻 R 1.0 Ω
电枢电感 L 0.01 H
转矩常数 Kt 0.1 N·m/A
反电动势常数 Ke 0.1 V·s/rad
转动惯量 J 0.01 kg·m²
粘滞摩擦 B 0.001 N·m·s/rad

现在,我们给电机加一个阶跃电压(比如 12V),看看它的响应。

# 创建电机实例
motor = DCMotor(R=1.0, L=0.01, Kt=0.1, Ke=0.1, J=0.01, B=0.001)

# 仿真参数
dt = 0.0005
t_end = 1.0
n_steps = int(t_end / dt)

# 存储数据
time = np.linspace(0, t_end, n_steps)
current = np.zeros(n_steps)
speed = np.zeros(n_steps)

# 阶跃输入:0.2秒时突加12V电压
U_input = 12.0
TL = 0.0  # 空载

for k in range(n_steps):
    # 0.2秒前电压为0,之后为12V
    U = U_input if time[k] >= 0.2 else 0.0
    i, w, _ = motor.step(U, TL, dt)
    current[k] = i
    speed[k] = w

# 绘制结果
plt.figure(figsize=(10, 6))
plt.subplot(2, 1, 1)
plt.plot(time, current, 'b-', linewidth=1.5)
plt.ylabel('电流 (A)')
plt.grid(True)
plt.title('直流电机阶跃响应')

plt.subplot(2, 1, 2)
plt.plot(time, speed, 'r-', linewidth=1.5)
plt.ylabel('转速 (rad/s)')
plt.xlabel('时间 (s)')
plt.grid(True)
plt.show()

我曾经踩过的坑:仿真时忘记给电机加负载,结果转速一直冲到稳态值以上,还以为模型错了。后来才发现,空载时摩擦系数B很小,转速超调是正常的。所以,分析响应时一定要搞清楚工况。

4.4 阶跃响应分析

跑完仿真,我们来看看结果。阶跃响应能告诉我们很多信息:

  • 上升时间:转速从10%上升到90%稳态值所需的时间。
  • 超调量:转速最大值与稳态值的偏差百分比。
  • 调节时间:转速进入并保持在稳态值±5%范围内的时间。
  • 稳态误差:最终转速与理论值的差距。

我一般会写个小函数自动计算这些指标:

def step_response_metrics(time, signal, steady_state_value):
    """计算阶跃响应指标"""
    # 上升时间(10%~90%)
    idx_10 = np.where(signal >= 0.1 * steady_state_value)[0][0]
    idx_90 = np.where(signal >= 0.9 * steady_state_value)[0][0]
    rise_time = time[idx_90] - time[idx_10]
    
    # 超调量
    overshoot = (np.max(signal) - steady_state_value) / steady_state_value * 100
    
    # 调节时间(±5%)
    tol = 0.05 * steady_state_value
    idx_settle = np.where(np.abs(signal - steady_state_value) > tol)[0]
    if len(idx_settle) > 0:
        settle_time = time[idx_settle[-1]]
    else:
        settle_time = 0
    
    return rise_time, overshoot, settle_time

# 计算稳态值(取最后10%数据的平均值)
steady_speed = np.mean(speed[-int(0.1*n_steps):])
rise, overshoot, settle = step_response_metrics(time, speed, steady_speed)

print(f"稳态转速: {steady_speed:.2f} rad/s")
print(f"上升时间: {rise:.3f} s")
print(f"超调量: {overshoot:.2f}%")
print(f"调节时间: {settle:.3f} s")

运行这段代码,你会看到类似这样的输出:

稳态转速: 119.88 rad/s
上升时间: 0.045 s
超调量: 4.52%
调节时间: 0.152 s

嗯,这个结果说明电机响应挺快的,超调也不大。如果你发现超调太大,可以试着增大摩擦系数B,或者减小转动惯量J——当然,实际电机参数是固定的,调参只是为了理解影响。

4.5 知识体系总览

下面这张图,把本章的核心逻辑串起来了。从物理方程到代码实现,再到仿真分析,每一步都环环相扣。

直流电机模型搭建(Python)知识体系 物理方程 电枢回路 + 机械运动 状态空间模型 状态变量:电流、转速 离散化 欧拉法数值积分 Python代码实现 DCMotor类:__init__初始化参数 → step方法单步仿真 核心:di/dt、dw/dt计算 → 欧拉积分更新状态 参数设置 R, L, Kt, Ke, J, B 典型值:小型直流电机 阶跃输入 0.2秒突加12V电压 空载/带载工况 阶跃响应分析 上升时间、超调量 调节时间、稳态误差 结果输出 电流波形 + 转速波形 + 性能指标 核心逻辑:物理方程 → 离散化 → Python实现 → 参数设置 → 阶跃响应分析 → 结果输出

4.6 小结与避坑指南

这一章,我们从直流电机的物理方程出发,用Python搭建了一个完整的仿真模型,并做了阶跃响应分析。你想想看,整个过程其实就三步:建模 → 编码 → 分析。

最后,分享几个我踩过的坑:

  • 步长选择:dt太大,仿真发散;dt太小,计算太慢。我一般先试0.0005秒,观察电流波形是否平滑。
  • 参数单位:一定要统一单位制。我见过有人把转动惯量填成g·cm²,结果转速算出来差了1000倍。
  • 初始状态:仿真开始前,记得把电流、转速清零。否则带着初始值跑,结果会偏。
  • 负载突变:阶跃响应测试时,如果负载转矩突然变化,电流会瞬间冲高。仿真时要注意限幅,否则电流可能超出实际范围。

我的建议:仿真只是第一步。拿到满意的仿真结果后,一定要在硬件上验证。我见过太多仿真跑得漂亮、上机就崩的例子了。仿真帮我们理解原理,硬件帮我们发现现实。