Engee 文档
Notebook

基于测量的SDM参数化

本例展示了如何根据实验测量确定永磁同步电机的参数。

为了确定SDPM引擎的参数,我们将进行三次实验。 发动机参数的期望值是我们事先知道的,我们将它们与从实验中获得的值进行比较。

引擎文档中的数据:

In [ ]:
nPolespairs = 2;        # 对极数
iRated = 2.5;           # 额定转速和负载下的电流(A)
rpmRated = 7500;        # 额定转速(rpm)
torqueRated = 0.07;     # 额定转速下的扭矩(NM)

torqueStall = 0.28;     # 预设扭矩(NM)
iStall = 8.5;           # 峰值电流(A)

inertia = 5e-6;                        # 转动惯量(kg·m2)
viscousDamping = 1.13e-6;              # 粘性摩擦系数
staticFriction = 7e-4;                 # 干摩擦系数
coulombFriction = 0.8*staticFriction;  # 库仑摩擦系数

R = 3.43;               # 电阻(欧姆)
L = 0.53e-3;            # 电感(Gn)

# PMSM块的参数
torqueConstant = 2/3*torqueStall/iStall; # 扭矩常数(Nm/A)
emfConstant = torqueConstant; # 恒定反电动势(V*s/rad)
PM = torqueConstant/nPolespairs; # 永磁流量联轴器(Vb)

# 控制器参数和标志
rpmDemand = rpmRated; # 预设转速(rpm)
enableDrive = 1; # 启用控制
dt = 1e-4; # 控制器的采样周期

测试1。 用静止转子测定R和L

第一个实验是在具有锁定转子的发动机上进行的。 在各相之间施加电压阶跃,并研究瞬态响应过程。 由此产生的时间常数τ由定子的电阻和电感值决定:

image_2.png

让我们设置转子的初始旋转角度:

In [ ]:
rotorangle = -90/(nPolespairs);

启动模型:

In [ ]:
engee.addpath(@__DIR__)

if "PMSMFromMeasurement1" in [m.name for m in engee.get_all_models()]
    m = engee.open( "PMSMFromMeasurement1" ) # 加载模型
else
    m = engee.load( "PMSMFromMeasurement1.engee" )
end
results1 = engee.run(m, verbose=true)
Building...
Progress 0%
Progress 12%
Progress 64%
Progress 100%
Progress 100%
Out[0]:
SimulationResult(
    run_id => 91,
    "ia" => WorkspaceArray{Float64}("PMSMFromMeasurement1/ia")
,
    "uab" => WorkspaceArray{Float64}("PMSMFromMeasurement1/uab")

)

从模型读取数据:

In [ ]:
t = results1["uab"].time;       # 时间
uab_1 = results1["uab"].value;  # A相和b相之间的电压
ia  = results1["ia"].value;     # A相电流

从稳态电压和电流的值计算电阻。
绕组ab在实验中串联,因此我们将所得电阻除以2:

In [ ]:
R_e = uab_1[end] / ia[end] / 2;

让我们找到电路的时间常数-这是电流达到值所需的时间 从已建立的:

In [ ]:
idx = findfirst(x -> x >= (0.63 * ia[end]), ia);
tau = t[idx];

从公式 让我们来表达和计算电感L:

In [ ]:
L_e = R_e * tau;

预期的过渡进程:

In [ ]:
iEstimated = uab_1[end] / (2 * R_e) * (1 .- exp.(-t .* R_e ./ L_e));

在下图中,您可以比较来自模型的测量电流和从计算中获得的电流图。

In [ ]:
using Plots
plotlyjs();
plot(t, ia, xlabel="时间,c", ylabel="电流,A", w = 2, label="测量电流", linecolor =:blue)
plot!(t, iEstimated, xlabel="时间,c", ylabel="电流,A", w = 2, label="预期电流", linecolor =:green)
plot!([tau, tau], [0, ia[end]], linecolor =:red, line =:dashdot, label="τ" )
xlims!(0, 10*tau)   # 设置x轴限制
ylims!(0, ia[end])  # 设置y轴的限制

annotate!(0.0008, 4.5, text(string("R是参考= ", R, " 嗡"), :left, 10))
annotate!(0.0008, 4, text(string("R测量= ", round(R_e, digits=2), " 嗡"), :left, 10))
annotate!(0.0008, 3.5, text(string("L参考= ", L*1000, " 经理"), :left, 10))
annotate!(0.0008, 3, text(string("L测量= ", round(L_e*1000, digits=2), " 经理"), :left, 10))
annotate!(tau, 1, text(string("测得的时间常数= ", round(1000*tau, digits=3), " 女士"), :left, 10))
Out[0]:

测试2。 恒定反电动势的确定

在第二个实验中,电机在没有电负载的情况下旋转。 这使我们能够估计恒定的反电动势。

请注意,以SI单位表示的反电动势常数等于电机的扭矩常数,因此在本例中只计算一个常数。

image_2.png

启动模型:

In [ ]:
if "PMSMFromMeasurement2" in [m.name for m in engee.get_all_models()]
    m = engee.open( "PMSMFromMeasurement2" ) # 加载模型
else
    m = engee.load( "PMSMFromMeasurement2.engee" )
end
results2 = engee.run(m, verbose=true)
Building...
Progress 0%
Progress 34%
Progress 100%
Progress 100%
Out[0]:
SimulationResult(
    run_id => 92,
    "uab" => WorkspaceArray{Float64}("PMSMFromMeasurement2/uab")

)

从模型读取数据:

In [ ]:
t = results2["uab"].time;       # 时间
uab_2  = results2["uab"].value; # 电压A-b

反电动势常数的确定

反电动势常数 它可以使用公式计算:

哪里 -电机相位a的电压降,

-电机轴的角速度。

扭矩常数等于以SI单位表示的反电动势常数。

In [ ]:
wRef = rpmRated*2*pi/60;        # 转子角速度(rad/s)
vPeakLL = maximum(abs.(uab_2)); # 峰值线电压(V)
vPeakLN = vPeakLL/sqrt(3);      # 峰值电压中性相(V)
emfConstantE = vPeakLN/wRef;    # wq反电动势常数

下图显示了实验发动机以额定速度运动时发生的反电动势。

极对的数量可以通过计算转子每旋转电流变化的周期数来确定。

In [ ]:
plot(t, uab_2, xlabel="时间,c", ylabel="反电动势", label="实验发动机的反电动势", w = 2)
annotate!(0.0013, -20, text(string("反电动势参考常数= ", round(emfConstant,digits=4), " 在*s/rad"), :left, 10))
annotate!(0.0013, -25, text(string("反电动势测量常数= ", round(emfConstantE,digits=4), " 在*s/rad"), :left, 10))
Out[0]:

3. 摩擦系数和转动惯量的测定

在第三个实验中,卸载电机由控制器控制。
在之前的实验中,获得了矩的常数。 在它的帮助下,通过转换定子电流,可以计算摩擦系数。

image_2.png

控制器仿真所需的变量:

In [ ]:
rpm2rad = 2*pi/60;
rad2rpm = 60/(2*pi);
powermax = torqueRated*rpmRated*2*pi/60;
Kp = 0.01;
Ki = 2.0;
ts = 0.0001;
t2eq_Iq = 2/(3*nPolespairs*PM);

让我们测量在四种不同速度下保持恒定转速所需的机械扭矩。
在较低转速下所需的扭矩主要是为了克服干摩擦,在较高转速下-粘性摩擦。
图表显示了四个速度的测量力矩。 通过这些点绘制一条直线。 零速度交点给出干摩擦系数,斜率给出粘滞摩擦系数。

In [ ]:
function trapz(x, y)
    n = length(x)
    integral = 0.0
    for i in 1:n-1
        integral += (x[i+1] - x[i]) * (y[i+1] + y[i]) / 2
    end
    return integral
end
rpmVec = [0.25, 0.5, 0.75, 1.0]*rpmRated;
trqVec = zeros(size(rpmVec));
for i=1:length(rpmVec)
    if "PMSMFromMeasurement3" in [m.name for m in engee.get_all_models()]
        m = engee.open( "PMSMFromMeasurement3" ) # 加载模型
    else
        m = engee.load( "PMSMFromMeasurement3.engee" )   
    end
    rpmDemand = rpmVec[i]; 
    engee.set_param!("PMSMFromMeasurement3", "StopTime" => 2*60/rpmDemand)
    results3 = engee.run(m, verbose=true)
    t = results3["ia"].time;        # 从模型的时间
    ia_3  = results3["ia"].value;   # 相电流-来自模型的a
    idx = findfirst(x -> x >= (60/rpmDemand), t); 
    temp = trapz(t[idx:end],(ia_3[idx:end]).^2)
    iaRms = sqrt(temp/(t[end]-t[idx]));
    trqVec[i] = 3*torqueConstant*iaRms;
end
rpmDemand = rpmRated;
Building...
Progress 0%
Progress 6%
Progress 14%
Progress 20%
Progress 25%
Progress 30%
Progress 36%
Progress 42%
Progress 47%
Progress 53%
Progress 59%
Progress 64%
Progress 70%
Progress 76%
Progress 83%
Progress 91%
Progress 97%
Progress 100%
Progress 100%
Building...
Progress 0%
Progress 7%
Progress 26%
Progress 37%
Progress 49%
Progress 59%
Progress 69%
Progress 79%
Progress 89%
Progress 99%
Progress 100%
Progress 100%
Building...
Progress 0%
Progress 5%
Progress 27%
Progress 47%
Progress 61%
Progress 76%
Progress 89%
Progress 100%
Progress 100%
Building...
Progress 0%
Progress 10%
Progress 47%
Progress 69%
Progress 91%
Progress 100%
Progress 100%
In [ ]:
scatter(rpmVec, 1000*trqVec, title="机械扭矩损失", xlabel="速度,m/s", ylabel="时刻,mN*m", w = 2, label="测量值", legend=:bottomright )
using Polynomials
coef = coeffs(fit(2*pi/60*rpmVec, trqVec,1));
estimatedStaticFriction = coef[1];
estimatedViscousDamping = coef[2];
rpmVec0 = [0; rpmVec];
plot!(rpmVec0, 1000*(estimatedStaticFriction.+rpmVec0*2*pi/60*estimatedViscousDamping), label="线性近似")
annotate!(trqVec[end], 2.1, text(string("干摩擦系数参考= ", staticFriction), :left, 10))
annotate!(trqVec[end], 2.0, text(string("测得的干摩擦系数= ", round(estimatedStaticFriction,digits=6)), :left, 10))
annotate!(trqVec[end], 1.9, text(string("粘性摩擦系数为基准= ", viscousDamping), :left, 10))
annotate!(trqVec[end], 1.8, text(string("测量的粘性摩擦系数= ", round(estimatedViscousDamping, digits=9)), :left, 10))
Out[0]:

第二个曲线图示出了发动机减速试验。 对于此测试,所需扭矩设置为零或关闭电机。
使用测量的减速度,在摩擦和阻尼力矩的指定值下,可以确定电机转子的转动惯量。

In [ ]:
enableDrive = 0; 
engee.set_param!("PMSMFromMeasurement3", "StopTime" => 2*60/rpmDemand)
if "PMSMFromMeasurement3" in [m.name for m in engee.get_all_models()]
    m = engee.open( "PMSMFromMeasurement3" ) # 加载模型
else
    m = engee.load( "PMSMFromMeasurement3.engee" )
end 
results4 = engee.run(m, verbose=true) 
Building...
Progress 0%
Progress 6%
Progress 50%
Progress 69%
Progress 87%
Progress 100%
Progress 100%
Out[0]:
SimulationResult(
    run_id => 97,
    "ia" => WorkspaceArray{Float64}("PMSMFromMeasurement3/Controller/Sensing_iabc/ia")
,
    "rpm" => WorkspaceArray{Float64}("PMSMFromMeasurement3/Controller/Encoder/rpm")

)
In [ ]:
enableDrive = 1;
t = results4["rpm"].time;       # 从模型的时间
rpm  = results4["rpm"].value;   # 转子转速
plot(t, rpm, xlabel="时间,c", ylabel="转速(rpm)", label="减速试验", w = 2)
initialTorque = -staticFriction - rpmRated*2*pi/60*viscousDamping;
initialAccel = 2*pi/60*(rpm[end]-rpm[1])/(2*60/rpmDemand);
estimatedInertia = initialTorque/initialAccel;
annotate!(0, 7465, text(string("转动惯量为基准= ", inertia, " 公斤×m^2"), :left, 10))
annotate!(0, 7460, text(string("测量的转动惯量= ", round(estimatedInertia,digits=6), " 公斤×m^2"), :left, 10))
Out[0]:

结论

在本例中,我们根据实验测量确定了永磁同步电机的参数。
为此,我们进行了三次测试。 在第一个测试中,我们发现了电机绕组的电阻和电感,在第二个测试中我们确定了反电动势常数,在第三个测试中我们确定了摩擦系数和转动惯量。
实验发现的值与文档中的发动机参数相当。