设计智能手机摄像头焦点 SAU
让我们连接必要的库。
import Pkg;
Pkg.add(["ControlSystemIdentification", "ControlSystems"])
using ControlSystems # основная библиотека для работы с САУ
using ControlSystemIdentification # библиотека для оценки динамических моделей на основе данных
控制对象
下面的模型模拟了智能手机摄像头的自动对焦控制系统。

考虑一下智能手机的自动对焦模式。智能手机电子设备通过摄像头的反馈来控制电机。让我们从技术角度抽象一下,从接收到对焦指令开始,我们需要瞬时过程不超过 0.6 秒。让我们尝试使用 PID 控制器来实现这样一个系统。
我们的电机-透镜系统是非线性的,因此首先要将模型线性化。
控制对象的线性化
让我们使用控制指令运行模型。结果,在工作区中我们得到了变量data
,其中包含模拟结果。
modelName = "Линза_ОУ"
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()
为了评估所选系数值是否合适,我们将绘制 LFCC、LFCC 和奈奎斯特霍德图。我们还将评估瞬态过程的质量。为方便显示频率响应图,下面将使用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 控制器的形状,并显示有助于评估所获得控制系统质量的图表。
ω = 17
Tf = 1/1000ω
C0, kp, ki, kd, fig, CF = loopshapingPID(sys_tf, ω; Mt = 1.3, ϕt = 75, form=:parallel, doplot = true)
让我们尝试改变频率。如果我们分析奈奎斯特图,就会发现该特性非常接近临界点。让我们试着修正这一点,并设置ω = 17
。现在,修正后系统的特性将在ω = 17
处以ϕt = 75
的角度触及圆 Mt。
plot(fig)
让我们验证一下所得到系统的稳定性。
isstable(feedback(CF*sys_tf))
让我们绘制出系统的 LFC 和 LFCC,并反映出稳定性储备。
marginplot([sys_tf, CF*sys_tf])
我们还构建了所获 ACS 的暂态过程。我们可以看到,瞬态时间约为 0.4 秒,满足我们的要求。
plot(stepinfo(step(feedback(CF * sys_tf), 1)))
使用获得的 PID 调节器,我们在仿真环境中模拟了系统。并将结果绘制在图表上。