控制算法,从仿真到实现

控制算法,从仿真到硬件实现

想对一个控制算法进行实物验证,往往需要我们搭建一个物理平台作为被控对象,这涉及到多领域学科,包括机械、软件、电子、运动学等。让控制算法从仿真到硬件平台实现,按照我的理解大致需要经过以下几个阶段:

  • 被控对象设计和建模
  • 在matlab上进行控制算法仿真验证
  • 电子元件的选择
  • 模块测试、编写控制算法进行联合调试

本文基于以上这个框架,以我用Arduino作为控制器实现倒立摆的状态反馈控制为例,展示让控制算法从仿真到硬件实现的每个阶段,并分享我在这个项目中遇到的问题、解决方案的选择和最终的效果。


被控对象设计和建模

控制算法多种多样,分为无模型控制基于模型控制。如PID控制、模糊控制属于前者,状态反馈控制属于后者。

  • 无模型控制
    PID控制具有算法简单、无需建模的优点,所以对于建模困难的复杂系统而言,是一个优秀的选择方案。比如制作一个两轮自平衡车时,本质是对角度进行镇定控制,如果用PID算法来实现,我只需要得到当前的俯仰角,与期望的角度进行比较,通过PID算法计算输出量来控制电机转动。在这个过程中我可以把被控对象视为一个黑盒,关注输入和输出就可以了。在工控界PID是常青树,但是PID存在参数难以整定、不能保证稳定性等缺点。
    eVwlGt.md.png
  • 基于模型控制
    更多的控制算法还是依赖于被控对象模型的,不同的控制算法适用的控制系统类型也是不相同的。本项目中要实现的极点配置状态反馈控制就是最基本的一种线性系统控制算法。本文所搭建的框架同样适用于其他基于模型的控制算法。
被控对象设计
  • 选择合适的硬件平台
    不同的控制算法适用的控制系统类型也是不相同的,比如你想实现镇定控制那你肯定不能选择电机作为被控对象,因为电机本身就是稳定的,电机可以用来实现追踪控制。

我在这里要选择一个不稳定的线性系统作为被控对象,我选择了一阶倒立摆作为被控对象。倒立摆系统的控制问题一直是控制研究中的一个典型问题,控制目标是通过给小车底座施加一个力,使小车上的摆杆不倒下。虽然一阶倒立摆本身是非线性系统,但是可以在平衡点处进行线性化,在平衡点附近视为对线性系统进行控制。
eVwgZ4.jpg

  • 机械结构
    对于并不擅长机械设计的同学,可以像我一样从淘宝买倒立摆的机械部分,只需要几百元。
    eVwoQK.md.png
    光滑的水平导轨上有一个小车,小车上铰链一根摆杆,摆杆可以在垂面内做自由转动,铰链后方有一个角位移传感器可以测量摆杆偏离法线的角度。小车通过同步带和导轨一端的电机相连,电机转动可以带动小车沿水平方向左右运动,电机后端有一个编码器可以测量小车左右移动的位移。
    模型
    系统建模可以分为两种:机理建模实验建模。机理建模是在了解研究对象的运动规律基础上,通过物理、化学的知识和数学手段建立起系统内部的输入—输出状态关系。实验建模是通过在研究对象上加上一系列的研究者事先确定的输入信号,激励研究对象并通过传感器检测其可观测的输出,应用数学手段建立起系统的输入—输出关系。

对于倒立摆系统,可以视为一个典型的运动的刚体系统,可以在惯性坐标系内应用经典力学理论建立系统的动力学方程。由于我还不会使用markdown插入latex公式,所以大家可以点击下面这个链接来学习用机理建模法建立直线一级倒立摆系统的数学模型。 这里值得注意的是:传统的倒立摆模型有两种,一是把施加在小车上的水平力作为控制输入,二是把小车的加速度作为控制输入。在这里我使用第二种方法,因为力是一个不可测的物理量,而加速度控制可以通过控制电机转速实现。
https://wenku.baidu.com/view/f09f7b287f21af45b307e87101f69e314232fa49.html
最终
在这里我忽视了所有的摩擦系数,带入了
eVc2Pe.png

极点配置控制是一种典型的全状态反馈控制方法,它可以把线性定常系统的极点移置到指定的期望闭环极点。极点配置定理:线性系统能任意配置极点的充分必要条件是,该系统状态完全可控。

1
2
3
4
A=[0 1 0 0 ; 0 0 0 0 ; 0 0 0 1 ; 0 0 39.73 0]; 
B=[0 ; 1 ; 0 ; 4.05];
P=[-1+1i -1-1i -2 -2];  %期望闭环极点
K=acker(A,B,P)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
t = 0;
dt = 0.1; %采样周期设置为0.1s
finaltime=20;
X1=[];
X2=[];
X3=[];
X4=[];
U=[];
T=[];
x=zeros(4,1);
% 初始值设定
x(1)=0.2;
x(2)=0;
x(3)=0.04;
x(4)=0;
tSpan = [0 dt];
while t<finaltime
u= -[ -0.2014 -0.4027 13.3164 1.5809]*[x(1);x(2);x(3);x(4)];
[tt ,xx ]=ode45('daolibai',tSpan,x,[],u); %解ode45函数
x = xx(length(xx),:);
X1=[X1,x(1)];
X2=[X2,x(2)];
X3=[X3,x(3)];
X4=[X4,x(4)];
U=[U,u];
T=[T,t];
t=t+dt;
end
%作图
ax1 = subplot(2,2,1);
plot(T,X1,'LineWidth',1.5);
ylabel('小车位移(m)');xlabel('时间(s)');
ax2 = subplot(2,2,2);
plot(T,X2,'LineWidth',1.5);
ylabel('小车速度(m/s)');xlabel('时间(s)');
ax3 = subplot(2,2,3);
plot(T,X3,'LineWidth',1.5);
ylabel('摆杆倾角(rad)');xlabel('时间(s)');
ax4 = subplot(2,2,4);
plot(T,X4,'LineWidth',1.5);
ylabel('摆杆角速度(rad/s)');xlabel('时间(s)');
axis([ax1 ax2],[0 15 -0.3 0.3]);
axis(ax3,[0 15 -0.05 0.05]);
axis(ax4,[0 15 -0.1 0.1]);
1
2
3
4
5
6
7
8
function dy= PlantModel(t,y,flag,para)
u = para;
dy = zeros(4,1);
dy(1)=y(2);
dy(2)=u;
dy(3)=y(4);
dy(4)=39.73*y(3)+4.05*u;
end