永磁同步电机由于其转动惯量低、效率高、控制方式便捷等优点,已成为当今伺服系统中最佳的执行结构之一。速度、位置和电流组成了永磁同步电机伺服控制系统。实际控制的过程中,电机所带的转动惯量和负载转矩都会对系统的伺服性能造成不良的影响。高性能的永磁同步电机伺服控制系统需具备:稳态、抗干扰和鲁棒性强的特点。因此,针对永磁同步电机的控制策略需要很强的时变性和抗干扰性。
传统的控制策略有PID控制方法。PID控制策略由于其易实现、结构简单常应用于伺服系统中。但是当永磁同步电机受到外界因素干扰时,该方法往往无法保证得到理想的控制性能。目前,针对永磁同步电机的控制方法专家学者们提出了很多的方法。包括:滑模控制、智能算法控制及自适应控制等。
模糊PID控制方法是一种利用模糊控制器实现整定PID控制器参数的控制方法,其即有模糊控制器不依赖控制对象数学模型的优点,也具有PID控制器良好的稳态精度。因此,本期对永磁同步电机(以下简称PMSM)模型和矢量控制算法进行了分析,设计了一种基于模糊PID的复合控制策略,基于Simulink环境仿真下的结果表明,模糊PID控制具有良好的鲁棒性。
1、永磁同步电机原理
数学模型可以参考上期内容。电机仿真系列-基于最小二乘法的永磁同步电机参数辨识
2、模糊PID控制器
模糊PID控制器可以根据PID参数整定经验或方法获得可行的控制效果,但整定过程具有一定盲目性;尽管初始论域、初始规则通过在线调整一般能保证系统的稳定性,但规则本身往往存在一定的粗造性和冗余性,带来在线调整时间长等问题。模糊控制器的结构如下图所示:
把输入的精确量进行模糊化变成模糊量,得到的模糊量可用相应的模糊语言表示,再由模糊控制规则根据推理的合成规则进行模糊决策,得到模糊控制量,最后进行解模糊处理,得到精确的控制量输入系统。
(1)论域和比例因子量化因子的选择
模糊控制器的输入输出都是精确数值,而模糊推理的决策量都是模糊值。为了进行模糊化处理,需要将输入输出变量从基本论域转化到相应的模糊论域中去。
设置误差、误差变化率、Kp和Ki的基本论域分别为:
则,误差的量化因子Ke、误差变化率的量化因子Kec、输出控制量的比例因子Kup和Kui可表示为:
合理的选择一个模糊控制器的输入变量的量化因子和输出控制量的比例因子是非常重要的。试验结果表明,量化因子和比例因子的大小及其不同量化因子之间的大小的相对关系,对模糊控制器的性能影响很大。实际过程中,需要根据系统要求的性能调节适合的量化因子和比例因子。
(2)模糊控制规则
这里主要以Matlab/Simulink的形式展示:
function [antecedentOutputs,sumAntecedentOutputs] = fcn(inputs, ...
fis,SimulateUsing,diagnostics)
if SimulateUsing==1 && coder.internal.canUseExtrinsic ...
&& (isa(inputs,'double') || isa(inputs,'single'))
antecedentOutputs = zeros(fis.rfsSize,'like',inputs);
sumAntecedentOutputs = zeros(fis.sumSize,'like',inputs);
if fis.inputFuzzySetType==1
if isa(inputs,'double')
[antecedentOutputs(:),sumAntecedentOutputs(:)] = feval(...
'fuzzy.internal.codegen.evaluateRuleAntecedent_double_mex',...
inputs,fis,diagnostics);
else
[ ] = feval(...
'fuzzy.internal.codegen.evaluateRuleAntecedent_single_mex',...
inputs,fis,diagnostics);
end
else
if isa(inputs,'double')
[antecedentOutputs(:),sumAntecedentOutputs(:)] = feval(...
'fuzzy.internal.codegen.evaluateRuleAntecedentType2_double_mex',...
inputs,fis,diagnostics);
else
[ ] = feval(...
'fuzzy.internal.codegen.evaluateRuleAntecedentType2_single_mex',...
inputs,fis,diagnostics);
end
end
else
if fis.inputFuzzySetType==1
[ ] = ...
fuzzy.internal.codegen.evaluateRuleAntecedent(...
inputs,fis,diagnostics);
else
[ ] = ...
fuzzy.internal.codegen.evaluateRuleAntecedentType2(...
inputs,fis,diagnostics);
end
end
end
function aggregatedOutputs = fcn(inputs,antecedentOutputs, ...
fis,samplePoints,SimulateUsing)
if SimulateUsing==1 && coder.internal.canUseExtrinsic ...
&& (isa(inputs,'double') || isa(inputs,'single'))
aggregatedOutputs = zeros(fis.aggSize,'like',inputs);
if fis.inputFuzzySetType==1
if strcmp(char(fis.type),'mamdani')
if isa(inputs,'double')
aggregatedOutputs(:) = feval(['fuzzy.internal.codegen.' ...
'evaluateRuleConsequentForMamdaniFIS_double_mex'],...
antecedentOutputs,fis,samplePoints);
else
aggregatedOutputs(:) = feval(['fuzzy.internal.codegen.' ...
'evaluateRuleConsequentForMamdaniFIS_single_mex'],...
antecedentOutputs,fis,samplePoints);
end
else
if isa(inputs,'double')
aggregatedOutputs(:) = feval(['fuzzy.internal.codegen.' ...
'evaluateRuleConsequentForSugenoFIS_double_mex'],...
inputs,antecedentOutputs,fis);
else
aggregatedOutputs(:) = feval(['fuzzy.internal.codegen.' ...
'evaluateRuleConsequentForSugenoFIS_single_mex'],...
inputs,antecedentOutputs,fis);
end
end
else
if strcmp(char(fis.type),'mamdani')
if isa(inputs,'double')
aggregatedOutputs(:) = feval(['fuzzy.internal.codegen.' ...
'evaluateRuleConsequentForMamdaniFISType2_double_mex'],...
antecedentOutputs,fis,samplePoints);
else
aggregatedOutputs(:) = feval(['fuzzy.internal.codegen.' ...
'evaluateRuleConsequentForMamdaniFISType2_single_mex'],...
antecedentOutputs,fis,samplePoints);
end
else
if isa(inputs,'double')
aggregatedOutputs(:) = feval(['fuzzy.internal.codegen.' ...
'evaluateRuleConsequentForSugenoFISType2_double_mex'],...
inputs,antecedentOutputs,fis);
else
aggregatedOutputs(:) = feval(['fuzzy.internal.codegen.' ...
'evaluateRuleConsequentForSugenoFISType2_single_mex'],...
inputs,antecedentOutputs,fis);
end
end
end
else
if fis.inputFuzzySetType==1
if strcmp(char(fis.type),'mamdani')
aggregatedOutputs = ...
fuzzy.internal.codegen.evaluateRuleConsequentForMamdaniFIS(...
antecedentOutputs,fis,samplePoints);
else
aggregatedOutputs = ...
fuzzy.internal.codegen.evaluateRuleConsequentForSugenoFIS(...
inputs,antecedentOutputs,fis);
end
else
if strcmp(char(fis.type),'mamdani')
aggregatedOutputs = ...
fuzzy.internal.codegen.evaluateRuleConsequentForMamdaniFISType2(...
antecedentOutputs,fis,samplePoints);
else
aggregatedOutputs = ...
fuzzy.internal.codegen.evaluateRuleConsequentForSugenoFISType2(...
inputs,antecedentOutputs,fis);
end
end
end
end
function defuzzifiedOutputs = fcn(sumAntecedentOutputs,...
aggregatedOutputs,fis,samplePoints,SimulateUsing,diagnostics)
if SimulateUsing==1 && coder.internal.canUseExtrinsic ...
&& (isa(aggregatedOutputs,'double') || isa(aggregatedOutputs,'single'))
defuzzifiedOutputs = zeros(fis.numOutputs,1,'like',aggregatedOutputs);
if fis.inputFuzzySetType==1
if strcmp(char(fis.type),'mamdani')
if isa(aggregatedOutputs,'double')
defuzzifiedOutputs(:) = feval(['fuzzy.internal.codegen.' ...
'applyMamdaniDefuzzificationMethod_double_mex'],...
samplePoints,sumAntecedentOutputs,aggregatedOutputs, ...
fis,diagnostics);
else
defuzzifiedOutputs(:) = feval(['fuzzy.internal.codegen.' ...
'applyMamdaniDefuzzificationMethod_single_mex'],...
samplePoints,sumAntecedentOutputs,aggregatedOutputs, ...
fis,diagnostics);
end
else
if isa(aggregatedOutputs,'double')
defuzzifiedOutputs(:) = feval(['fuzzy.internal.codegen.' ...
'applySugenoDefuzzificationMethod_double_mex'],...
sumAntecedentOutputs,aggregatedOutputs, ...
fis,diagnostics);
else
defuzzifiedOutputs(:) = feval(['fuzzy.internal.codegen.' ...
'applySugenoDefuzzificationMethod_single_mex'],...
sumAntecedentOutputs,aggregatedOutputs, ...
fis,diagnostics);
end
end
else
if strcmp(char(fis.type),'mamdani')
if isa(aggregatedOutputs,'double')
defuzzifiedOutputs(:) = feval(['fuzzy.internal.codegen.' ...
'applyMamdaniDefuzzificationMethodType2_double_mex'],...
samplePoints,sumAntecedentOutputs,aggregatedOutputs, ...
fis,diagnostics);
else
defuzzifiedOutputs(:) = feval(['fuzzy.internal.codegen.' ...
'applyMamdaniDefuzzificationMethodType2_single_mex'],...
samplePoints,sumAntecedentOutputs,aggregatedOutputs, ...
fis,diagnostics);
end
else
if isa(aggregatedOutputs,'double')
defuzzifiedOutputs(:) = feval(['fuzzy.internal.codegen.' ...
'applySugenoDefuzzificationMethodType2_double_mex'],...
sumAntecedentOutputs,aggregatedOutputs, ...
fis,diagnostics);
else
defuzzifiedOutputs(:) = feval(['fuzzy.internal.codegen.' ...
'applySugenoDefuzzificationMethodType2_single_mex'],...
sumAntecedentOutputs,aggregatedOutputs, ...
fis,diagnostics);
end
end
end
else
if fis.inputFuzzySetType==1
if isequal(fis.type,uint8('mamdani'))
defuzzifiedOutputs = ...
fuzzy.internal.codegen.applyMamdaniDefuzzificationMethod(...
samplePoints,sumAntecedentOutputs,aggregatedOutputs, ...
fis,diagnostics);
else
defuzzifiedOutputs = ...
fuzzy.internal.codegen.applySugenoDefuzzificationMethod(...
sumAntecedentOutputs,aggregatedOutputs,fis,diagnostics);
end
else
if isequal(fis.type,uint8('mamdani'))
defuzzifiedOutputs = ...
fuzzy.internal.codegen.applyMamdaniDefuzzificationMethodType2(...
samplePoints,sumAntecedentOutputs,aggregatedOutputs, ...
fis,diagnostics);
else
defuzzifiedOutputs = ...
fuzzy.internal.codegen.applySugenoDefuzzificationMethodType2(...
sumAntecedentOutputs,aggregatedOutputs,fis,diagnostics);
end
end
end
end
(3)模糊推理及解模糊化
3、仿真验证
为验证算法的可行性,基于Simulink搭建永磁同步电机仿真模型。
本期对基于矢量控制策略的永磁同步电机数学模型进行了分析,根据系统性能需要,提出了模糊PID策略,将其应用到基于矢量控制的永磁同步电机伺服系统中,对系统负载扰动和惯量扰动的仿真结果表明,相对于传统PID控制器,模糊PID控制器具有更好的动静态性能和鲁棒性。
原文始发于微信公众号(新能源汽车仿真团队):电机仿真系列-基于模糊PID的永磁同步电机矢量控制