简介
今天来分享一下我是如何用最短的时间进行智能小车的PID调速的。在疫情期间比较无聊,在某宝买了一个智能小车底盘和一堆零件,基于Arduino Due和树莓派进行开发,Due负责底层控制,树莓派进行上层控制器开发,比如斯坦利控制器或者模型预测控制器进行轨迹跟踪。 本次采用Simulink工具链完成,小车的所有代码均基于Simulink Target Support Package完成。
所需要的硬件&软件
1.普通带编码器的直流电机。 2.Arduino Due控制板及数据线(类似dSPACE MAB进行RCP开发,但是性能完全没有可比性,开个玩笑)。 3.Matlab&Simulink R2019b (民间通用版本即可)。 4.电脑一台。
前期准备工作
(1)安装Arduino硬件支持包
这并不是本文的重点,网上有许多这方面的教程,包括MATLAB录制的研讨会均有类似的视频教程。有意的同学可以自行查阅相关资料,十分简单。如下类似教程。 https://blog.csdn.net/u013732401/article/details/70161200
(2)Simulink模型
新建Simulink Model,并且打开Library Browser。找到Simulink Supprot Package for Arduino Hardware
按照下图搭建模型。其中Tachometer模块在硬件支持包中的Sensor模块里(2019b有,低版本2018a并没有,需要自己通过编码器脉冲的上升沿或者下降沿捕获进行),具体通过高低电平进行捕获的模型在硬件支持包中的DrivePID例程中的Encoder子模块中有搭建。
可以看到,Tachometer输出量并不是help中讲的RPM,而是脉冲/每分钟。Tachometer模块中设置的即是编码器的单个信号线连接的PIN口(这里用一根信号线就无法测量方向了,请注意编码器信号线是5V电压,本次使用的单片机IO最高容忍3.3V,需要初中知识进行分压电路的搭建,如果使用其他芯片,请查询数据手册该IO口的最高容忍电压),采样时间设置0.05即可。由于我智能小车轮子转一圈采集390个脉冲,轮子直径64毫米。所以简单计算即可得到轮速转一圈行驶的距离,单位m/s。后面经过了一个一阶低通滤波器,这个在网上可以找到关于一阶低通滤波的公式,然后进行搭建,这里就不是赘述了。 接下来进行驱动模块的搭建,关于L298N驱动模块的使用,这里我使用一路电机进行调试,29和27PIN脚设置成高电平和低电平,PIN2设置为ENA。在Arduino 支持包中,PWM模块输入值0-255对应0-100%占空比,PWM频率在Due中驱动模块固定1KHz。
Step阶跃信号目的在于仿真时间2s时进行阶跃输入,占空比改变至100,我们需要做的就是进行数据记录,记录本次仿真的时间,输入和输出。如何记录呢,那么我们需要在相应的信号线上右键,选择Log Selected Signals。我们需要对Step输出线,低通滤波后的速度进行Datalog。最后设置Arduino外部仿真调试环境。
在Set COM port端口中可以手动输入您的硬件串口号如果在上传程序失败的时候。接下来进行在线调试,类似keil软件中的debug模式。在2019b以下版本的同学点击仿真按钮旁边的下拉菜单选择External模式即可。我在使用2018a版本无法进行数据datalog,可以通过串口进行数据传输,具体请查阅相关资料。
点击按钮开始离线仿真,模型会编译成代码刷写进硬件。前期准备工作完成,相信无论用基于模型设计的方式还是手动写代码的方式,完成以上工作都不会难。接下来就进入本次教程的正题。
正题
数据导出到Workspace
如图所示,点击Data Inspector
分别将左侧数据拖入进对应的框图即可查看数据记录效果,如果您已经有小车并且已经进行开环PWM测速,您需要关注以下的每一步。只要您有相应的PWM和速度值都可以使用以下方法进行PID调速,不仅限于使用Aruduino类似的快速原型开发。如图所示,右键数据,进行导出,导出至Workspace即可。
同样的方式将两组数据全部导出,分别是PWM和Speed。 返回Matlab主界面,您会看在工作空间看到如下图所示。
使用代码即可将数据解析出来,如下图所示。
再看工作空间内容,即可得到我们熟悉的数据类型。
系统辨识
我们通过输入和输出基于Matlab的System Identification工具箱即可辨识出小车驱动的传递函数,从而进行PID整定。具体方法如下。打开系统辨识工具箱。
将时域数据导入。
导入后,点击导入后的曲线,然后点击Time Plot即可查看曲线。
然后如图选择系统估计的模式。
您可以根据您的需要选择辨识的传递函数结构,这里我选择二阶振荡模型。
然后点击Estimate,稍等片刻,可以在工具箱主界面查看我们的辨识结果,高亮辨识后的曲线,点击Model Output,即可查看辨识曲线。我辨识出来后的重合度达到98.2。效果还是可观的。
这一步的最后,右键上面的辨识曲线,即出现需要的传递函数参数了。
离线仿真
得到系统的传递函数,那当然是十分愉悦的事情,在学习控制理论的时候总是先给出系统模型,但是在实际项目中模型是需要辨识的,这就是课本和实际的差距。我们得到参数后即可在Simulink环境进行仿真环境的搭建了,将上图的参数输入至Transfer Fcn模块中。在进行仿真前,因为进行的是连续系统仿真,所以将仿真时间改成变步长。看一下仿真效果和实际输出基本一致。
因为需要PID控制,那么我们可以添加PID控制器模块进行模型的搭建,搭建完如下图所示。简单仿真一下,没有更改PID模块的任何参数,所以结果很差。
这时我们需要打开PID模块,点击Tune按钮,请求Matlab帮助我们进行自整定!随后自动打开PID Tune的App。
似乎已经帮您完成了整定功能,您只需要调整Robust to Aggressive横条去看系统的响应,选择您喜欢的位置,然后点击Updata Block参数会更新至您的控制器。
此时您发下PID模块的参数已经被更改了,那么调整模型,在Step模块设置您期望速度,例如我需要小车行驶速度为1m/s。点击仿真看看效果。
控制器离散化
是不是借助Maltab/Simulink环境很简单就完成了PID的整定了,有同学会问,这有啥用,我需要跑进板子里啊,别急,我们现在研究的是S域,计算机控制器是离散系统,我们需要把控制器从S域转换到Z域去。步骤如下图所示。 2019b用户如下图找到该App,2019b之前的用户在Analysis->Control Design->Model Disretizer找到即可。
您可以选择0阶保持或者1阶保持进行离散化,采样时间我个人设置0.05s。然后点击s->z按钮,最后Store Setting。
回到模型,您可以看见算法和模型都从S域变成Z域了。在Solver中将采样时间改成定步长,采样时间设置成0.05,再次进行仿真。很不幸模型输出已经振荡!这时您需要重复上述步骤再次在PID tune中进行整定。这里我就不重复步骤,直接给整定后的
这是最后自整定的PID参数。
实车效果
仿真效果可以接受,这个时候我们就完成了PID离散控制器的设计了,接下来就需要刷写到板子里。重新改变模型如下图所示。替换传递函数模型,也可以进行对比。将实车速度替换掉传递函数的反馈值。点击外部模式仿真,看一下实车效果如何。
经过模型自动生成代码刷写到控制器后,实车测试和仿真结果图有如下对比,在超调量上有些区别,但是实际控制器中超调更小。最后都趋于平稳。蓝色是仿真结果,紫色是实际控制器效果。
总结
仿真可以节省我们太多时间,如果您使用STM32,S12K进行手工代码开发,可以通过串口进行数据采集导入Excel,然后导入到Matlab进行模型的系统辨识,将PID控制器生成原子子系统,进行编写数据字典,管理输入输出信号和参数(非常重要),再使用Embedded Coder生成代码,在中断服务函数中调用生成的代码函数,基于模型设计的方法可以加快控制器的开发。这是一次在贵平台分享软件开发的经验。如果有问题可以联系我的qq:664157262,一起进步!