席萌0209 发表于 2015-3-26 10:51:04

【安富莱DSP教程】第15章 ControllerFunctions的使用(PID控制)

特别说明:完整45期数字信号处理教程,原创高性能示波器代码全开源地址:链接
第15章 ControllerFunctions的使用(PID控制)

    本期教程主要讲解控制函数中PID部分,PID的应用十分广泛,希望初学的同学认真学习这部分知识。
15.1 PID介绍
15.2 PID形象解释
15.3 CMSIS的PID库
15.4 浮点数PID库
15.5 定点数Q31格式PID库
15.6 定点数Q15格式PID库
15.7 实例讲解
15.8 总结

15.1 PID介绍

    当今的自动控制技术都是基于反馈的概念。反馈理论的要素包括三个部分:测量、比较和执行。测量关心的变量,与期望值相比较,用这个偏差纠正调节控制系统的响应。

15.1.1 概述
    这个理论和应用的关键是,做出正确的测量和比较后,如何才能更好地纠正系统。
    PID(比例(proportion)、积分(integration)、微分(differentiation))控制器作为最早实用化的控制器已有近百年历史,现在仍然是应用最广泛的工业控制器。PID控制器简单易懂,使用中不需精确的系统模型等先决条件,因而成为应用最为广泛的控制器。
    PID控制器由比例单元(P)、积分单元(I)和微分单元(D)组成。其输入e (t)与输出u (t)的关系为u(t)=kp   式中积分的上下限分别是0和t
    因此它的传递函数为:G(s)=U(s)/E(s)=kp
    其中kp为比例系数; TI为积分时间常数; TD为微分时间常数

15.1.2 基本用途
    它由于用途广泛、使用灵活,已有系列化产品,使用中只需设定三个参数(Kp, Ti和Td)即可。在很多情况下,并不一定需要全部三个单元,可以取其中的一到两个单元,但比例控制单元是必不可少的。
    首先,PID应用范围广。虽然很多工业过程是非线性或时变的,但通过对其简化可以变成基本线性和动态特性不随时间变化的系统,这样PID就可控制了。
    其次,PID参数较易整定。也就是,PID参数Kp,Ti和Td可以根据过程的动态特性及时整定。如果过程的动态特性变化,例如可能由负载的变化引起系统动态特性变化,PID参数就可以重新整定。
    第三,PID控制器在实践中也不断的得到改进,下面两个改进的例子。
    在工厂,总是能看到许多回路都处于手动状态,原因是很难让过程在“自动”模式下平稳工作。由于这些不足,采用PID的工业控制系统总是受产品质量、安全、产量和能源浪费等问题的困扰。PID参数自整定就是为了处理PID参数整定这个问题而产生的。现在,自动整定或自身整定的PID控制器已是商业单回路控制器和分散控制系统的一个标准。
    在一些情况下针对特定的系统设计的PID控制器控制得很好,但它们仍存在一些问题需要解决:
    如果自整定要以模型为基础,为了PID参数的重新整定在线寻找和保持好过程模型是较难的。闭环工作时,要求在过程中插入一个测试信号。这个方法会引起扰动,所以基于模型的PID参数自整定在工业应用不是太好。
    如果自整定是基于控制律的,经常难以把由负载干扰引起的影响和过程动态特性变化引起的影响区分开来,因此受到干扰的影响控制器会产生超调,产生一个不必要的自适应转换。另外,由于基于控制律的系统没有成熟的稳定性分析方法,参数整定可靠与否存在很多问题。
    因此,许多自身整定参数的PID控制器经常工作在自动整定模式而不是连续的自身整定模式。自动整定通常是指根据开环状态确定的简单过程模型自动计算PID参数。
    PID在控制非线性、时变、耦合及参数和结构不确定的复杂过程时,工作得不是太好。最重要的是,如果PID控制器不能控制复杂过程,无论怎么调参数都没用。
    虽然有这些缺点,但简单的PID控制器有时却是最好的控制器。

15.1.3 现实意义
    目前工业自动化水平已成为衡量各行各业现代化水平的一个重要标志。同时,控制理论的发展也经历了古典控制理论、现代控制理论和智能控制理论三个阶段。智能控制的典型实例是模糊全自动洗衣机等。自动控制系统可分为开环控制系统和闭环控制系统。一个控制系统包括控制器、传感器、变送器、执行机构、输入输出接口。控制器的输出经过输出接口、执行机构,加到被控系统上;控制系统的被控量,经过传感器,变送器,通过输入接口送到控制器。不同的控制系统,其传感器、变送器、执行机构是不一样的。比如压力控制系统要采用压力传感器,电加热控制系统的传感器是温度传感器。目前,PID控制及其控制器或智能PID控制器(仪表)已经很多,产品已在工程实际中得到了广泛的应用,有各种各样的PID控制器产品,各大公司均开发了具有PID参数自整定功能的智能调节器 (intelligent regulator),其中PID控制器参数的自动调整是通过智能化调整或自校正、自适应算法来实现。有利用PID控制实现的压力、温度、流量、液位控制器,能实现PID控制功能的可编程控制器(PLC),还有可实现PID控制的PC系统等等。可编程控制器(PLC) 是利用其闭环控制模块来实现PID控制,而可编程控制器(PLC)可以直接与ControlNet相连,如Rockwell的PLC-5等。还有可以实现 PID控制功能的控制器,如Rockwell 的Logix产品系列,它可以直接与ControlNet相连,利用网络来实现其远程控制功能。

15.1.4 系统分类
l 开环系统
开环控制系统(open-loop control system)是指被控对象的输出(被控制量)对控制器(controller)的输入没有影响。在这种控制系统中,不依赖将被控量反送回来以形成任何闭环回路。
l 闭环系统
    闭环控制系统(closed-loop control system)是指被控对象的输出(被控制量)会反送回来影响控制器的输入,形成一个或多个闭环。闭环控制系统有正反馈和负反馈,若反馈信号与系统给定值信号相反,则称为负反馈( Negative Feedback),若极性相同,则称为正反馈,一般闭环控制系统均采用负反馈,又称负反馈控制系统。闭环控制系统的例子很多。比如人就是一个具有负反馈的闭环控制系统,眼睛便是传感器,充当反馈,人体系统能通过不断的修正最后作出各种正确的动作。如果没有眼睛,就没有了反馈回路,也就成了一个开环控制系统。另例,当一台真正的全自动洗衣机具有能连续检查衣物是否洗净,并在洗净之后能自动切断电源,它就是一个闭环控制系统。
l 阶跃响应
    阶跃响应是指将一个阶跃输入(step function)加到系统上时,系统的输出。稳态误差是指系统的响应进入稳态后,系统的期望输出与实际输出之差。控制系统的性能可以用稳、准、快三个字来描述。稳是指系统的稳定性(stability),一个系统要能正常工作,首先必须是稳定的,从阶跃响应上看应该是收敛的;准是指控制系统的准确性、控制精度,通常用稳态误差(Steady-state error)来描述,它表示系统输出稳态值与期望值之差;快是指控制系统响应的快速性,通常用上升时间来定量描述。

15.1.5 调节方法
    PID是工业生产中最常用的一种控制方式,PID调节仪表也是工业控制中最常用的仪表之一,PID 适用于需要进行高精度测量控制的系统,可根据被控对象自动演算出最佳PID控制参数。
    PID参数自整定控制仪可选择外给定(或阀位)控制功能。可取代伺服放大器直接驱动执行机构(如阀门等)。PID外给定(或阀位)控制仪可自动跟随外部给定值(或阀位反馈值)进行控制输出(模拟量控制输出或继电器正转、反转控制输出)。可实现自动/手动无扰动切换。手动切换至自动时,采用逼近法计算,以实现手动/自动的平稳切换。PID外给定(或阀位)控制仪可同时显示测量信号及阀位反馈信号。
    PID光柱显示控制仪集数字仪表与模拟仪表于一体,可对测量值及控制目标值进行数字量显示(双LED数码显示),并同时对测量值及控制目标值进行相对模拟量显示( 双光柱显示),显示方式为双LED数码显示+双光柱模拟量显示,使测量值的显示更为清晰直观。
    PID参数自整定控制仪可随意改变仪表的输入信号类型。采用最新无跳线技术,只需设定仪表内部参数,即可将仪表从一种输入信号改为另一种输入信号。
    PID参数自整定控制仪可选择带有一路模拟量控制输出(或开关量控制输出、继电器和可控硅正转、反转控制)及一路模拟量变送输出,可适用于各种测量控制场合。
    PID参数自整定控制仪支持多机通讯,具有多种标准串行双向通讯功能,可选择多种通讯方式,如RS-232、RS-485、RS-422等,通讯波特率300~9600bps 仪表内部参数自由设定。可与各种带串行输入输出的设备(如电脑、可编程控制器、PLC 等)进行通讯,构成管理系统。
1.PID常用口诀:
    参数整定找最佳,从小到大顺序查
    先是比例后积分,最后再把微分加
    曲线振荡很频繁,比例度盘要放大
    曲线漂浮绕大湾,比例度盘往小扳
    曲线偏离回复慢,积分时间往下降
    曲线波动周期长,积分时间再加长
    曲线振荡频率快,先把微分降下来
    动差大来波动慢。微分时间应加长
    理想曲线两个波,前高后低4比1
    一看二调多分析,调节质量不会低
2.PID控制器参数的工程整定,各种调节系统中P.I.D参数经验数据以下可参照:
    温度T: P=20~60%,T=180~600s,D=3-180s
    压力P: P=30~70%,T=24~180s,
    液位L: P=20~80%,T=60~300s,
    流量F: P=40~100%,T=6~60s。

15.1.6 原理特点
    在工程实际中,应用最为广泛的调节器控制规律为比例、积分、微分控制,简称PID控制,又称PID调节。PID控制器问世至今已有近70年历史,它以其结构简单、稳定性好、工作可靠、调整方便而成为工业控制的主要技术之一。当被控对象的结构和参数不能完全掌握,或得不到精确的数学模型时,控制理论的其它技术难以采用时,系统控制器的结构和参数必须依靠经验和现场调试来确定,这时应用PID控制技术最为方便。即当我们不完全了解一个系统和被控对象,或不能通过有效的测量手段来获得系统参数时,最适合用PID控制技术。PID控制,实际中也有PI和PD控制。PID控制器就是根据系统的误差,利用比例、积分、微分计算出控制量进行控制的。
比例控制
    比例控制是一种最简单的控制方式。其控制器的输出与输入误差信号成比例关系。当仅有比例控制时系统输出存在稳态误差(Steady-state error)。
积分控制
    在积分控制中,控制器的输出与输入误差信号的积分成正比关系。对一个自动控制系统,如果在进入稳态后存在稳态误差,则称这个控制系统是有稳态误差的或简称有差系统(System with Steady-state Error)。为了消除稳态误差,在控制器中必须引入“积分项”。积分项对误差取决于时间的积分,随着时间的增加,积分项会增大。这样,即便误差很小,积分项也会随着时间的增加而加大,它推动控制器的输出增大使稳态误差进一步减小,直到等于零。因此,比例+积分(PI)控制器,可以使系统在进入稳态后无稳态误差。
微分控制
    在微分控制中,控制器的输出与输入误差信号的微分(即误差的变化率)成正比关系。自动控制系统在克服误差的调节过程中可能会出现振荡甚至失稳。其原因是由于存在有较大惯性组件(环节)或有滞后(delay)组件,具有抑制误差的作用,其变化总是落后于误差的变化。解决的办法是使抑制误差的作用的变化“超前”,即在误差接近零时,抑制误差的作用就应该是零。这就是说,在控制器中仅引入 “比例”项往往是不够的,比例项的作用仅是放大误差的幅值,而目前需要增加的是“微分项”,它能预测误差变化的趋势,这样,具有比例+微分的控制器,就能够提前使抑制误差的控制作用等于零,甚至为负值,从而避免了被控量的严重超调。所以对有较大惯性或滞后的被控对象,比例+微分(PD)控制器能改善系统在调节过程中的动态特性。

15.1.7 参数整定
    PID控制器的参数整定是控制系统设计的核心内容。它是根据被控过程的特性确定PID控制器的比例系数、积分时间和微分时间的大小。
    PID控制器参数整定的方法很多,概括起来有两大类:一是理论计算整定法。它主要是依据系统的数学模型,经过理论计算确定控制器参数。这种方法所得到的计算数据未必可以直接用,还必须通过工程实际进行调整和修改。二是工程整定方法,它主要依赖工程经验,直接在控制系统的试验中进行,且方法简单、易于掌握,在工程实际中被广泛采用。
    PID控制器参数的工程整定方法,主要有临界比例法、反应曲线法和衰减法。三种方法各有其特点,其共同点都是通过试验,然后按照工程经验公式对控制器参数进行整定。但无论采用哪一种方法所得到的控制器参数,都需要在实际运行中进行最后调整与完善。现在一般采用的是临界比例法。
    利用该方法进行 PID控制器参数的整定步骤如下:
    (1)首先预选择一个足够短的采样周期让系统工作;
    (2)仅加入比例控制环节,直到系统对输入的阶跃响应出现临界振荡,记下这时的比例放大系数和临界振荡周期;
    (3)在一定的控制度下通过公式计算得到PID控制器的参数。
    此条应该不属于大的,抽象的PID控制理论的内容了,而是PID理论的具体应用。

15.1.8 预制调整
比例增益
    变频器的 PID 功能是利用目标信号和反馈信号的差值来调节输出频率的,一方面,我们希望目标信号和反馈信号无限接近,即差值很小,从而满足调节的精度:另一方面,我们又希望调节信号具有一定的幅度,以保证调节的灵敏度。解决这一矛盾的方法就是事先将差值信号进行放大。比例增益 P 就是用来设置差值信号的放大系数的。任何一种变频器的参数 P 都给出一个可设置的数值范围,一般在初次调试时, P 可按中间偏大值预置.或者暂时默认出厂值,待设备运转时再按实际情况细调。
积分时间
    如上所述.比例增益 P 越大,调节灵敏度越高,但由于传动系统和控制电路都有惯性,调节结果达到最佳值时不能立即停止,导致“超调”,然后反过来调整,再次超调,形成振荡。为此引入积分环节 I ,其效果是,使经过比例增益 P 放大后的差值信号在积分时间内逐渐增大 ( 或减小 ) ,从而减缓其变化速度,防止振荡。但积分时间 I 太长,又会当反馈信号急剧变化时,被控物理量难以迅速恢复。因此, I 的取值与拖动系统的时间常数有关:拖动系统的时间常数较小时,积分时间应短些;拖动系统的时间常数较大时,积分时间应长些。
微分时间
    如上所述.比例增益 P 越大,调节灵敏度越高,但由于传动系统和控制电路都有惯性,调节结果达到最佳值时不能立即停止,导致“超调”,然后反过来调整,再次超调,形成振荡。为此引入积分环节 I ,其效果是,使经过比例增益 P 放大后的差值信号在积分时间内逐渐增大 ( 或减小 ) ,从而减缓其变化速度,防止振荡。但积分时间 I 太长,又会当反馈信号急剧变化时,被控物理量难以迅速恢复。因此, I 的取值与拖动系统的时间常数有关:拖动系统的时间常数较小时,积分时间应短些;拖动系统的时间常数较大时,积分时间应长些。
调整原则
    PID 参数的预置是相辅相成的,运行现场应根据实际情况进行如下细调,被控物理量在目标值附近振荡,首先加大积分时间 I ,如仍有振荡,可适当减小比例增益 P。被控物理量在发生变化后难以恢复,首先加大比例增益 P ,如果恢复仍较缓慢,可适当减小积分时间 I ,还可加大微分时间 D。

席萌0209 发表于 2015-3-26 10:52:53

15.2 PID形象解释
    这个解释形象的说明了参数P,I,D的使用。(内容来自网上)
    小明接到这样一个任务:有一个水缸点漏水(而且漏水的速度还不一定固定不变),要求水面高度维持在某个位置,一旦发现水面高度低于要求位置,就要往水缸里加水。 小明接到任务后就一直守在水缸旁边,时间长就觉得无聊,就跑到房里看小说了,每30分钟来检查一次水面高度。水漏得太快,每次小明来检查时,水都快漏完了,离要求的高度相差很远,小明改为每3分钟来检查一次,结果每次来水都没怎么漏不需要加水,来得太频繁做的是无用功。几次试验后,确定每10分钟来检查一次。这个检查时间就称为采样周期。
    开始小明用瓢加水,水龙头离水缸有十几米的距离,经常要跑好几趟才加够水,于是小明又改为用桶加,一加就是一桶,跑的次数少了,加水的速度也快了,但好几次将缸给加溢出了,不小心弄湿了几次鞋,小明又动脑筋,我不用瓢也不用桶,老子用盆,几次下来,发现刚刚好,不用跑太多次,也不会让水溢出。这个加水工具的大小就称为比例系数。
    小明又发现水虽然不会加过量溢出了,有时会高过要求位置比较多,还是有打湿鞋的危险。他又想了个办法,在水缸上装一个漏斗,每次加水不直接倒进水缸,而是倒进漏斗让它慢慢加。这样溢出的问题解决了,但加水的速度又慢了,有时还赶不上漏水的速度。于是他试着变换不同大小口径的漏斗来控制加水的速度,最后终于找到了满意的漏斗。漏斗的时间就称为积分时间 。
    小明终于喘了一口,但任务的要求突然严了,水位控制的及时性要求大大提高,一旦水位过低,必须立即将水加到要求位置,而且不能高出太多,否则不给工钱。小明又为难了!于是他又开努脑筋,终于让它想到一个办法,常放一盆备用水在旁边,一发现水位低了,不经过漏斗就是一盆水下去,这样及时性是保证了,但水位有时会高多了。他又在要求水面位置上面一点将水凿一孔,再接一根管子到下面的备用桶里这样多出的水会从上面的孔里漏出来。这个水漏出的快慢就称为微分时间。

席萌0209 发表于 2015-3-26 10:56:12

15.3 CMSIS的PID库
    PID库使用的算法如下:
y = y + A0 * x + A1 * x + A2 * x
A0 = Kp + Ki + Kd
A1 = (-Kp ) - (2 * Kd )
A2 = Kd
    框图如下:
   PID控制器计算一个“误差”值作为测得的输出和参考输入之间的差值。PID控制器通过调整输入参数来使这个误差最小。比例值决定是误差的反应,积分值是决定误差之和的反应,微分值决定误差的改变频率。

席萌0209 发表于 2015-3-26 10:58:17

15.4 浮点数PID库

15.4.1 arm_pid_f32
函数定义如下:
    static __INLINE float32_t arm_pid_f32(arm_pid_instance_f32 * S, float32_t in)
参数定义:
    *S is an instance of the floating-point PID Control structure
    in input sample to process
   return out processed output sample.
注意事项:
    1. 数据类型arm_pid_instance_f32的定义如下:
/**
   * @brief Instance structure for the floating-point PID Control.
   */
typedef struct
{
    float32_t A0;          /**< The derived gain, A0 = Kp + Ki + Kd . */
    float32_t A1;          /**< The derived gain, A1 = -Kp - 2Kd. */
    float32_t A2;          /**< The derived gain, A2 = Kd . */
    float32_t state;   /**< The state array of length 3. */
    float32_t Kp;               /**< The proportional gain. */
    float32_t Ki;                /**< The integral gain. */
    float32_t Kd;               /**< The derivative gain. */
      } arm_pid_instance_f32;
    2. 这个函数在文件arm_math.h文件里面。

15.4.2 arm_pid_init_f32
函数定义如下:
    void arm_pid_init_f32(arm_pid_instance_f32 * S, int32_t resetStateFlag)
参数定义:
    *S             points to an instance of the PID structure.   
    resetStateFlagflag to reset the state. 0 = no change in state 1 = reset the state.
注意事项:
    1. 这个函数是通过用户配置了Kp,Ki,Kd后,获得A0,A1和A2。
    2. 通过设置标志resetStateFlag,用户也可以选择是否初始化所有相关变量为0。

15.4.3 arm_pid_reset_f32
函数定义如下:
    void arm_pid_reset_f32(arm_pid_instance_f32 * S)
参数定义:
    *S    Instance pointer of PID control data structure.   
注意事项:
    1. 这个函数比较的简单,仅是复位相关变量为0.

席萌0209 发表于 2015-3-26 11:00:30

15.5 定点数Q31格式PID库

15.5.1 arm_pid_q31
函数定义如下:
    static __INLINE q31_t arm_pid_q31(arm_pid_instance_q31 * S, q31_t in)
参数定义:
    *S points to an instance of the Q31 PID Control structure
    in input sample to process
    return out processed output sample.
注意事项:
    1. 这个函数使用了内部的64位累加器。
    2. 64位累加器的数据格式是2.62,这样的话,只有一个保护位,为了防止溢出,输入参数需要右移两位,右移两位是因为函数内部有四个加数需要进行加法运算。所有运算结束后2.62格式的数据会被截取成1.31格式,并作饱和运算。
    3. 数据类型arm_pid_instance_q31的定义如下:
/**
   * @brief Instance structure for the Q31 PID Control.
   */
typedef struct
{
    q31_t A0;            /**< The derived gain, A0 = Kp + Ki + Kd . */
    q31_t A1;            /**< The derived gain, A1 = -Kp - 2Kd. */
    q31_t A2;            /**< The derived gain, A2 = Kd . */
    q31_t state;      /**< The state array of length 3. */
    q31_t Kp;            /**< The proportional gain. */
    q31_t Ki;            /**< The integral gain. */
    q31_t Kd;            /**< The derivative gain. */
      } arm_pid_instance_q31;

15.5.2 arm_pid_init_q31
函数定义如下:
    void arm_pid_init_q31(arm_pid_instance_q31 * S, int32_t resetStateFlag)
参数定义:
    *S             points to an instance of the PID structure.   
    resetStateFlagflag to reset the state. 0 = no change in state 1 = reset the state.
注意事项:
    1. 这个函数是通过用户配置了Kp,Ki,Kd后,获得A0,A1和A2。
    2. 通过设置标志resetStateFlag,用户也可以选择是否初始化所有相关变量为0。

15.5.3 arm_pid_reset_q31
函数定义如下:
    void arm_pid_reset_q31(arm_pid_instance_q31 * S)
参数定义:
    *S    Instance pointer of PID control data structure.   
注意事项:
    1. 这个函数比较的简单,仅是复位相关变量为0.

席萌0209 发表于 2015-3-26 11:02:28

15.6 定点数Q15格式PID库

15.6.1 arm_pid_q15
函数定义如下:
    static __INLINE q15_t arm_pid_q15(arm_pid_instance_q31 * S, q31_t in)
参数定义:
    *S points to an instance of the Q15 PID Control structure
    in input sample to process
    return out processed output sample.
注意事项:
    1. 这个函数使用了内部的64位累加器。
    2. 输入参数和内部变量都是用的1.15格式,它们相乘后是2.30格式,由于内部用的是64位累加器,那么最终结果就是34.30格式,基本没有溢出的危险。最终输出结果需要丢弃低15位,并饱和成1.15格式的数据。
    3. 数据类型arm_pid_instance_q31的定义如下:
/**
   * @brief Instance structure for the Q15 PID Control.
   */
typedef struct
{
    q15_t A0;            /**< The derived gain, A0 = Kp + Ki + Kd . */
    q15_t A1;            /**< The derived gain, A1 = -Kp - 2Kd. */
    q15_t A2;            /**< The derived gain, A2 = Kd . */
    q15_t state;      /**< The state array of length 3. */
    q15_t Kp;            /**< The proportional gain. */
    q15_t Ki;            /**< The integral gain. */
    q15_t Kd;            /**< The derivative gain. */
      } arm_pid_instance_q15;

15.6.2 arm_pid_init_q15
函数定义如下:
    void arm_pid_init_q15(arm_pid_instance_q15 * S, int32_t resetStateFlag)
参数定义:
    *S             points to an instance of the PID structure.   
    resetStateFlagflag to reset the state. 0 = no change in state 1 = reset the state.
注意事项:
    1. 这个函数是通过用户配置了Kp,Ki,Kd后,获得A0,A1和A2。
    2. 通过设置标志resetStateFlag,用户也可以选择是否初始化所有相关变量为0。

15.6.3 arm_pid_reset_q15
函数定义如下:
    void arm_pid_reset_q15(arm_pid_instance_q15 * S)
参数定义:
    *S    Instance pointer of PID control data structure.   
注意事项:
    1. 这个函数比较的简单,仅是复位相关变量为0.

席萌0209 发表于 2015-3-26 11:04:40

15.7 实例讲解
实验目的:
    1. 学习ControllerFunctions中浮点PID
实验内容:
    1. 不需要外部操作,实现PID的自动调节。
    2. 用户只需调节电阻器器即可(特别注意:这里我仅调试出了PID正向调整,也就是PID函数的返回值是逐渐增大的,方向调整没有实现)。
    3. 用户需要自制一个可变电阻器10K欧和一个电阻1K欧串联,串联后1K欧端接地,另一端接DAC输出(使用引脚PA4),可变电阻和电阻连接的地方接ADC(使用引脚PF9)。使用前请将可变电阻调至1K欧。
    4. 这里特别注意,在初始化DAC的时候,我们是设置DAC输出100(12位DAC输出范围0-4095)。这里的目标是ADC采集得200以上就认为稳定。
实验现象:
    通过窗口上位机软件SecureCRT(V5光盘里面有此软件)查看打印信息现象如下:
程序设计:
    ADC和DAC的驱动及其实现请参考安富莱_STM32-V5开发板_用户手册的第18章和第19章。这里我们重点说PID主函数。
/*
*********************************************************************************************************
*    函 数 名: main
*    功能说明: c程序入口
*    形    参:无
*    返 回 值: 错误代码(无需处理)
*********************************************************************************************************
*/
int main(void)
{
int16_t i;                     
arm_pid_instance_f32 S;
float32_t out;
S.Kp = 1;//比例因子                                                                            (1)
S.Ki = 1;//积分因子
S.Kd = 0;//微分因子
arm_pid_init_f32(&S, 1);                                                                         (2)

   
bsp_Init();   /* 硬件初始化 */
PrintfLogo();    /* 打印例程信息到串口1 */

bsp_StartAutoTimer(0, 100);    /* 启动1个100ms的自动重装的定时器 */                                 (3)

/* 进入主程序循环体 */
while (1)
{
bsp_Idle();   /* 这个函数在bsp.c文件。用户可以修改这个函数实现CPU休眠和喂狗 */

if (bsp_CheckTimer(0))    /* 判断定时器超时时间 */
{
/* 每隔500ms 进来一次 */
bsp_LedToggle(4);    /* 翻转LED4的状态 */

uiAverage = 0;
for(i = 0; i < 20; i++)
{
uiAverage += ADC3ConvertedValue;
}
uiAverage = uiAverage/20;
if(uiAverage > 200)                                                                  (4)
{
}
else
{
out = arm_pid_f32(&S, uiAverage);                                                 (5)
}
TIM_Cmd(TIM6, DISABLE);   
for(i =0; i < 128; i++)                                                                (6)
{
Sine12bit = (uint16_t)out % 4095;
}
TIM_Cmd(TIM6, ENABLE);   
printf("out = %d uiAverage/20 = %dr", (uint16_t)out % 4095, uiAverage);
}

}
}
1. 设置PID的参数。
2. 初始化PID变量。
3. 配置一个100ms的软定时器,这个就是PID的采样时间。
4. 如果ADC采集的参数超过200就认为稳定,不再需要做PID调节。
5. ADC采集的参数小于200的话,PID会自动的进行调节。
6. 将PID调节后的数值赋值给DAC进行输出。

jcx0324 发表于 2015-3-26 14:35:45

bebj2009 发表于 2019-11-20 14:27:41

席萌0209 发表于 2015-3-26 10:52
15.2 PID形象解释
    这个解释形象的说明了参数P,I,D的使用。(内容来自网上)
    小明接到这样一个任 ...

相当经典

youxiu 发表于 2020-4-5 18:56:41

席萌0209 发表于 2015-3-26 10:58
15.4 浮点数PID库

15.4.1 arm_pid_f32

float32_t arm_pid_f32(arm_pid_instance_f32 * S, float32_t in)这个函数在哪个文件里?

eric2013 发表于 2020-4-7 08:28:18

youxiu 发表于 2020-4-5 18:56
float32_t arm_pid_f32(arm_pid_instance_f32 * S, float32_t in)这个函数在哪个文件里?

在源码文件里面。

longjunyi 发表于 2020-7-31 15:51:08

收藏,学习一下

wdliming 发表于 2020-7-31 19:22:16

非常感谢,正好用到

ddymen 发表于 2023-10-25 10:55:30

微分时间用了积分时间的定义,楼主可以修改一下

eric2013 发表于 2023-10-25 16:03:54

ddymen 发表于 2023-10-25 10:55
微分时间用了积分时间的定义,楼主可以修改一下

谢谢告知。

xtaozi001 发表于 2023-11-15 12:17:33

{:32:}{:32:}{:32:}牛叉,形象!
页: [1]
查看完整版本: 【安富莱DSP教程】第15章 ControllerFunctions的使用(PID控制)