设计智能手机相机对焦系统
我们将连接必要的库。
import Pkg;
Pkg.add(["ControlSystemIdentification", "ControlSystems"])
using ControlSystems # основная библиотека для работы с САУ
using ControlSystemIdentification # библиотека для оценки динамических моделей на основе данных
管理对象
下面所示的模型模拟了智能手机相机的自动对焦控制系统。
考虑智能手机的自动对焦模型。 智能手机的电子设备通过摄像头的反馈控制电机。 让我们从技术中抽象出来,并说我们需要过渡过程从我们收到焦点命令的那一刻起不超过0.6秒。 使用PID控制器,我们将尝试实现这样的系统。
我们的电机-镜头系统是非线性的,因此首先我们对模型进行线性化。
控制对象的线性化
让我们使用团队管理运行模型。 结果,我们在工作区中得到一个变量 data,其中包含仿真结果。
modelName = "lens"
if !(modelName in [m.name for m in engee.get_all_models()]) engee.load( "$(@__DIR__)/$(modelName).engee"); end;
data = engee.run( modelName )
让我们将输入和输出信号的数据写入变量并将它们绘制在图形上。
dataIn = collect(data["Ступенчатая функция.1"]).value;
dataOut = collect(data["Преобразование единиц измерения.1"]).value;
data_t = collect(data["Преобразование единиц измерения.1"]).time;
plot( data_t, [dataIn dataOut], label=["Входной сигнал" "Выходной сигнал"] )
让我们继续讨论模型的线性化。 识别库模型的所有方法 ControlSystemIdentification 它们接受AbstractIdData类型对象作为输入。 该函数允许您获取时域标识数据的对象 iddata. 接下来,使用方法 subspaceid 我们以状态空间的形式获得系统的描述。
Ts = data_t[2] - data_t[1] # Получим частоту дискретизации системы из вектора времени
d = iddata(dataOut, dataIn, Ts); # создаем объект идентификации данных во временном пространстве
sys_d = subspaceid(d, :auto); # запускаем метод идентификации модели пространства состояний
让我们将获得的模型描述与建模环境中组装的模型进行比较。 要做到这一点,使用块 Пространство состояний 作为矩阵的值,我们将写出获得的值A,B,C,D。
sys = d2c(sys_d); # перейдем к непрерывной модели
A = sys.A; # находим матрицу A
B = sys.B; # находим матрицу B
C = sys.C; # находим матрицу C
D = sys.D; # находим матрицу D
系数的选择:pid()函数
为了评估所选系数值的合适程度,我们将绘制LFX,Lfx和Nyquist hodograph。 并且还要评估过渡过程的质量。 为了方便显示频率响应图,下面实现了该功能 pid_marginplot. 它将得到的板系统的值代入用于构造频率特性的函数。: marginplot 和 nyquistplot,并将它们显示在图形上。
function pid_marginplot(C)
f1 = marginplot(sys_tf * C, w)
f2 = nyquistplot(sys_tf * C, xlims=(-10,1), ylims=(-2, 10), title="")
plot(f1,f2, titlefontsize=10)
end
设置其他变量。 让我们将系统的表示转换为传递函数,并设置我们将构建时间和频率特性的频率。
sys_tf = tf(sys);
w = exp10.(LinRange(-2.5, 3, 500));
我们将使用单元掩码设置系数。 通过移动滑块,您可以设置一个新的变量值。 当一个系数被改变时,掩码下的代码被重新计算。 如果要一次更改多个参数,请在单元格开始按钮下禁用自动刷新并手动启动单元格。
系数的选择是迭代的,因此首先我们将在没有调节器的情况下评估系统的特性,然后我们将开始改变每一个并评估变化对系统的影响。
kp = 0.4 # @param {type:"slider", min:0.1, max:5, step:0.1}
ki = 1.322 # @param {type:"slider", min:0.0, max:20, step:0.001}
kd = 0.03 # @param {type:"slider", min:0.0, max:0.5, step:0.01}
Tf = 0.012 # @param {type:"slider", min:0.0, max:1, step:0.001}
C0 = pid(kp, ki, kd; Tf, form=:parallel, filter_order=2)
pid_marginplot(C0)
让我们检查一下我们的系统是否稳定。 这可以让你做的功能 isstable.
isstable(feedback(sys_tf * C0)) # Проверка: устойчива ли система с полученным ПИД регулятором
此外,如果系统稳定,稳定性储备符合我们的要求,我们将建立一个过渡过程并评估其特性的质量。
plot(stepinfo(step(feedback(sys_tf * C0), 5))) # Оценка переходного процесса САУ
获得的控制器数据可用于仿真环境中的模型。 为此,您可以从工作区中获取系数值,并在PID控制器块中指定它们。
系数选择:loopshapingPID()函数
使用函数选择系数 loopshapingPID 它基于频率方法(环路整形),它允许您设置开环系统的所需频率响应,以确保闭环的所需特性。 因此,如果系统的期望频率属性是已知的(例如,所需带宽或扰动抑制水平),则该方法是方便的。
让我们尝试将此方法应用于我们的示例,并获得所需的特性。
该函数以传递函数的形式对系统进行描述,以及期望实现开放系统的单个增益的频率。 另外,该函数接受附加灵敏度函数Mt和期望相移ζt的参数值。 默认情况下,这些参数具有最佳值,但可以更改它们。 您还可以调整合成PID控制器的形状并显示有助于评估生成的ACS质量的图形。
ω = 17
Tf = 1/1000ω
C0, kp, ki, kd, fig, CF = loopshapingPID(sys_tf, ω; Mt = 1.3, ϕt = 75, form=:parallel, doplot = true)
让我们试着改变频率。 如果我们分析奈奎斯特图,我们可以看到特征非常接近临界点。 让我们尝试调整并安装 ω = 17. 现在调整后的系统的特性将在点处触及圆Mt。 ω = 17 在一个角度 ϕt = 75.
plot(fig)
让我们确保生成的系统是稳定的。
isstable(feedback(CF*sys_tf))
我们将建立LCH和LFCH系统,并反映可持续性的储备.
marginplot([sys_tf, CF*sys_tf])
我们还将假设接收到的ACS的过渡过程。 我们看到过渡时间约为0.4秒,这符合我们的要求。
plot(stepinfo(step(feedback(CF * sys_tf), 1)))
使用获得的PID控制器,我们将在模拟环境中模拟系统。 我们将在图表上显示结果。
tuned_mdl = engee.load(joinpath("$(@__DIR__)","lens_pid.engee");force=true)
res = engee.run(tuned_mdl);
res_step = collect(res["Ступенчатая функция.1"]);
res_out = collect(res["Преобразование единиц измерения.1"]);
plot(res_step.time, [res_step.value res_out.value], label=["Входной сигнал" "Выходной сигнал"])