精华内容
下载资源
问答
  • 2021-04-22 04:04:13

    (3)专家控制器

    专家控制器的模型是整个仿真模型中的重点。其实质就是把专家规则用Matlab现有计算元件实现出来。当前一般的做法就是利用“IF…THEN…”语句来表述一条一条的专家规则[28]。把单回路控制中的部分规则做成的专家控制器如下所示:

    图4-3 专家控制器

    Fig 4-3 Expert controller

    4.1.2 多回路仿真模型

    上一小节中建立了一个完整的单回路专家PID系统,这其中的专家控制器只是针对单个回路的一些问题提出的处理措施,而在多回路中,其中的专家控制器主要是协调各个回路之间的关系以保障整个浓度调节系统的稳定。按照前面介绍的方法,并结合专家规则,建立如下的多回路专家控制器。

    在如下图所示的仿真模型中,专家控制器收集三个回路的浓度传感器测量信号,并对其进行微分运算,根据这个微分值的大小,查询专家规则得出第一、第二个回路的设定值。对第三个回路而言,主要是修改抄前池在浓度传递上的数学模型的相关参数[29]。

    图4-4 多回路专家控制器仿真模型

    4.2 Matlab仿真

    根据上面建立的数学模型,分别就单回路和多回路进行仿真。首先让单个浓度回路的专家PID在不添加任何干扰的情况下进行仿真[30],得到如下的仿真曲线。

    图4-5 单回路专家PID仿真结果

    Fig 4-5 simulink result of single circuit expert PID

    为了比较,去掉回路中的专家控制器,调整合适的PID参数,得到无外界干扰情况的PID控制曲线:

    图4-6 PID仿真曲线

    Fig 4-6 simulink curve of PID

    对比这两条曲线,发现在稳态性能上两者没有太大的区别,但是在调节时间上,专家控制下的系统明显要比传统PID控制下的要快。

    下面,人为在被控对象上添加一个阶跃干扰,该阶跃信号在时间值为120上加上,122上结束,观察两个系统在这个扰动下的变化过程,得到如下一组仿真曲线:

    图4-7 专家PID控制在干扰下曲线

    Fig 4-7 simulink curve of expert PID under disturb

    图4-8 PID控制在干扰下曲线

    Fig 4-8 simulink curve of PID under disturb

    这组曲线很生动地说明了专家控制在处理干扰下的优势。在生产过程中,如前文所说的那样,浆泵转速的改变、调浓白水压力的改变等因素都可能给控制回路带来干扰,抗干扰能力的强弱是决定控制器在浓度控制回路中应用效果的一个重要指标。

    单浓度调节回路下的仿真结果充分说明了专家PID较之传统PID在调节时间、抗干扰等方面有优势。接下来对专家控制在多段回路之间协调作用来仿真验证。

    a)第一个回路设定值变化曲线 b)第一个回路响应曲线

    c)第二个回路设定值变化曲线 d)第二个回路响应曲线

    图4-9 第一、第二回路之间的专家控制效果曲线

    Fig 4-9 curve of expert control between NO.1 and NO.2 circuit

    强制给第二个回路(即成浆池出口浓度控制回路)的偏差信号上叠加一个增量,观察两个回路的设定的改变情况,如上图中的a)、b)所示,可以看到,第一个回路的设定值增幅大于第二个回路的设定值增幅。再以测量值的变化情况来考察浓度值的变化情况,如图中的c)、d)所示,第一个回路的浓度测量值变化比较剧烈,且稳定时间比较长,但在第二个回路中,由于设定值改变幅度不大,并结合内部的专家控制器的作用,系统在一段时间之后就恢复到了新的设定值上来。这种变化情况和前文的分析是一致的。一样的道理,在干扰停止之后,设定值恢复到原来的参考设定值上来,尽管第一个回路的浓度值可能还会有一个变化剧烈的过程,但是对于第二个回路来说,其波动幅度大大减小了,成浆池出口浓度的这种变化大大降低了抄前池出口浓度控制的干扰,为提高整个浓度控制回路的控制精度有着重要意义。

    专家控制器在第二个和第三个回路之间的相关控制规则主要是选择抄前池的浓度传递模型中的衰减因子。前文中也提及过,这个衰减因子是确实存在的,但是对于具体的数学表达式还有待进一步的探究,本文的衰减因子只是一个模糊化的值,一共只分了三个值,这主要是出于简化模型难度考虑的。

    上面的建立仿真模型和仿真都是针对局部的,在此基础上,搭建完整的浓度控制的仿真模型如下所示:

    图4-10 浓度控制仿真模型

    Fig 4-10 simulink model of consistency control

    在这个仿真模型中,三个回路分别用子系统的形式来表示的,每个子系统下都是上面建立的单回路模型。专家控制器根据专家规则输出相应结果给各个回路的设定值或者控制参数等。整个制浆流送线上干扰点很多,要想一一验证这些干扰对回路的影响是不现实的,为此,本论文选定在第二个回路上发生浓度扰动时,三个浓度回路的测量值的变化情况,图如下所示:

    a)第一个回路响应曲线

    b)第二个回路响应曲线

    c)第三个回路响应曲线

    图4-11 浓度控制仿真曲线

    Fig 4-11 simulink curve of consistency control

    更多相关内容
  • 专家PIDsimulink仿真

    2022-02-20 14:51:39
    M文件生成simulink仿真形式 对专家PID进行了仿真,已测试
  • 神经网络PID-模糊PID-专家PID-等高级PID.rar
  • 实现专家控制,专家pid很好用,尤其用到电厂控制里面
  • 专家系统PID引入至控制领域后,取得更加的控制性能,专家PID较常规PID控制器控制更加灵活。为了满足控制系统对控制精度的要求,专家系统控制逐渐成为国内外的研究热点。本文研究基于专家系统PID设计电加热炉炉温控制...
  • 【精品课设】经典PID与专家PID控制的对比与分析(二) 0研究背景 1经典PID控制的设计与仿真 1.1 被控对象传递函数的设计 1.2 经典PID控制的仿真 2专家PID控制的设计 2.1 专家PID控制律的设计 2.2 专家PID控制的仿真...
  • 基于自适应模糊补偿的倒立摆PD控制\基于模糊规则表的模糊PD控制
  • 专家PID与模糊PID的C语言实现,及文档 ,有算法实现,和原理
  • 为解决长距离带式输送机液压自动张紧系统的压力调节不连续不平稳的问题,在常规PID控制算法的基础上,针对具有时变、大滞后及非线性的系统,根据操作人员及专家的实际经验,提出专家PID控制策略。以带式输送机张紧装置...
  • 专家PID与模糊PID(第3章专家P控制和模糊PⅠD控制)
  • 专家PID控制

    2022-01-25 22:25:30
    专家PID控制 专家PID控制就是基于被控对象和控制规律的各种知识,而不需要知道被控对象的精确模型,利用专家经验来设计PID参数。 我们假设当前为第k采样,当前偏差为e(k),同样前一采样时刻的偏差为e(k-1),而前两个...

    专家PID控制

    专家PID控制就是基于被控对象和控制规律的各种知识,而不需要知道被控对象的精确模型,利用专家经验来设计PID参数。

    我们假设当前为第k采样,当前偏差为e(k),同样前一采样时刻的偏差为e(k-1),而前两个采样时刻的偏差为e(k-2),则可以得到两次的偏差增量为:
    △ e ( k ) = e ( k ) − e ( k − 1 ) △ e ( k − 1 ) = e ( k − 1 ) − e ( k − 2 ) \bigtriangleup e\left( k \right) =e\left( k \right) -e\left( k-1 \right) \\ \bigtriangleup e\left( k-1 \right) =e\left( k-1 \right) -e\left( k-2 \right) e(k)=e(k)e(k1)e(k1)=e(k1)e(k2)

    清楚了以上公式,我们再设定偏差的一个极大值,记为Mmax;设定一个偏差较大的中间值,记为Mmid;设定一个偏差的极小值,记为Mmin。根据以上偏差、偏差增量以及偏差极值的设定,我们分析如下:

    (1)如果|e(k)|>Mmax

    这种情况说明偏差的绝对值已经很大了,不论偏差变化趋势如何,都应该考虑控制器的输入应按最大(或最小)输出,以达到迅速调整偏差的效果,使偏差绝对值以最大的速度减小。
    这种情况下其实相当于实施开环控制,是一种对偏差出现极限情况的快速响应。

    (2)如果|e(k)|≤Mmax

    这种情况我们需要更具系统的变化趋势来分析,具体的情况实施不同的控制方式,我们引入偏差增量来协助分析。

    (2.1)当e(k)*∆e(k)>0或者∆e(k)=0时

    这种情况说明偏差在朝向偏差绝对值增大的方向变化,或者偏差为某一固定值,此时我们再判断偏差的绝对值与偏差的中间值Mmid之间的关系。

    (2.1.1)此时如果|e(k)|>Mmid,说明偏差也较大,可考虑由控制器实施较强的控制作用,以达到扭转偏差绝对值向减小的方向变化,并迅速减小偏差的绝对值。
    u ( k ) = u ( k − 1 ) + k 1 ( k p ( e r r ( k ) − e r r ( k − 1 ) ) + k i e r r ( k ) + k d ( e r r ( k ) − 2 e r r ( k − 1 ) + e r r ( k − 2 ) ) ) u\left( k \right) =u\left( k-1 \right) +k_1\left( k_p\left( err\left( k \right) -err\left( k-1 \right) \right) +k_ierr\left( k \right) \\ +k_d\left( err\left( k \right) -2err\left( k-1 \right) +err\left( k-2 \right) \right) \right) u(k)=u(k1)+k1(kp(err(k)err(k1))+kierr(k)+kd(err(k)2err(k1)+err(k2)))

    (2.1.2)此时如果|e(k)|≤Mmid,说明尽管偏差是向绝对值增大的方向变化,但是偏差绝对值本身并不是很大,可以考虑控制器实施一般的控制作用,只需要扭转偏差的变化趋势,使其向偏差绝对值减小的方向变化即可。

    (2.2)当e(k)*∆e(k)<0且∆e(k)*∆e(k-1)>0或者e(k)=0时,说明偏差的绝对值向减小的方向变化,或者已经达到平衡状态,此时保持控制器输出不变即可。即:U(k)=U(k-1)。

    (2.3)当e(k)*∆e(k)<0且∆e(k)*∆e(k-1)<0时,说明偏差处于极限状态。如果此时偏差的绝对值较大,|e(k)|>Mmid,可以考虑实施较强控制作用。
    u ( k ) = u ( k − 1 ) + k 1 k p e r r ( k ) u\left( k \right) =u\left( k-1 \right) +k_1k_perr\left( k \right) u(k)=u(k1)+k1kperr(k)

    如果此时偏差绝对值较小,|e(k)|<Mmid,可以考虑实施较弱控制作用。
    u ( k ) = u ( k − 1 ) + k 2 k p e r r ( k ) u\left( k \right) =u\left( k-1 \right) +k_2k_perr\left( k \right) u(k)=u(k1)+k2kperr(k)

    其中,k1为增益放大系数,k1取大于1的值;k2为增益抑制系数,取大于0而小于1的值。

    (3)如果|e(k)|<Mmin

    这种情况实际上说明偏差绝对值很小,这种偏差有可能是系统静差引起的,此时必须要引入积分作用,实施PID控制或者PI控制。
    u ( k ) = u ( k − 1 ) + k p ( e r r ( k ) − e r r ( k − 1 ) ) + k i e r r ( k ) u\left( k \right) =u\left( k-1 \right) +k_p\left( err\left( k \right) -err\left( k-1 \right) \right) +k_ierr\left( k \right) u(k)=u(k1)+kp(err(k)err(k1))+kierr(k)

    Kp和Ki可以适当减小,以减小控制作用。当偏差小到一定程度后,甚至可以引入死区的概念,是系统稳定下来而不需要去进行调节。

    展开全文
  • 压电陶瓷作为驱动器应用于弹头偏转是一种新型技术,但是压电陶瓷具有迟滞性和蠕变性,导致输出达不到理想结果,本文针对如何提高压电弹药精度,提出专家PID控制算法弥补压电陶瓷驱动器迟滞性和蠕变性,利用单片机...
  • 专家PID(C语言实现)

    2022-01-08 09:36:47
    一、专家PID的原理 专家PID 控制主要是利用受控对象和控制规律的知识进行控制,对被控制的对象不需要精确的模型,使用专家经验来对系统模型进行设计控制。对于系统模型的控制专家PID 具有灵活性、适应性和鲁棒性。...

    一、专家PID的原理

    专家PID 控制主要是利用受控对象和控制规律的知识进行控制,对被控制的对象不需要精确的模型,使用专家经验来对系统模型进行设计控制。对于系统模型的控制专家PID 具有灵活性、适应性和鲁棒性。可根据系统的工作状态及误差情况去灵活的选择相应的控制规律去控制,并根据专家知识和经验,能动性的去调整控制器的参数,适应对象特性及环境的变化,通过利用专家规则,控制系统模型可以在非线性、大偏差下进行可靠地工作。

    专家PID 主要由五个控制律组成,通过工作状态及误差去选择相应的控制律去稳定数据,并对参数进行调节达到对控制系统稳定的作用。其控制结构如图 所示。

     设定偏差的一个极大值,记为Mmax;设定一个偏差较大的中间值,记为Mmid;设定一个偏差的极小值,记为Mmin。根据以上偏差、偏差增量以及偏差极值的设定,我们分析如下:

    (1)如果|e(k)|>Mmax (规则一)

    这种情况说明偏差的绝对值已经很大了,不论偏差变化趋势如何,都应该考虑控制器的输入应按最大(或最小)输出,以达到迅速调整偏差的效果,使偏差绝对值以最大的速度减小。同时避免超调,此时相当于开环控制。

    (2)当e(k)*∆e(k)>0或者∆e(k)=0时(规则二)

    这种情况说明偏差在朝向偏差绝对值增大的方向变化,或者偏差为某一固定值,此时我们再判断偏差的绝对值与偏差的中间值Mmid之间的关系。

    (2.1)此时如果|e(k)|>Mmid

    说明偏差也较大,可考虑由控制器实施较强的控制作用,以达到扭转偏差绝对值向减小的方向变化,并迅速减小偏差的绝对值。

    (2.2)此时如果|e(k)|≤Mmid

    说明尽管偏差是向绝对值增大的方向变化,但是偏差绝对值本身并不是很大,可以考虑控制器实施一般的控制作用,只需要扭转偏差的变化趋势,使其向偏差绝对值减小的方向变化即可。

    (3)当e(k)*∆e(k)<0∆e(k)*∆e(k-1)>0或者e(k)=0

    说明偏差的绝对值向减小的方向变化,或者已经达到平衡状态,此时保持控制器输出不变即可。

    (4)当e(k)*∆e(k)<0∆e(k)*∆e(k-1)<0

    说明偏差处于极限状态。

    (4.1)如果此时偏差的绝对值较大,|e(k)|>Mmid

    可以考虑实施较强控制作用。

    (4.2)如果此时偏差绝对值较小,|e(k)|<Mmid

    可以考虑实施较弱控制作用。

    其中,k1为增益放大系数,k1取大于1的值;k2为增益抑制系数,取大于0而小于1的值。

    (5)如果|e(k)|<Mmin

    这种情况实际上说明偏差绝对值很小,这种偏差有可能是系统静差引起的,此时必须要引入积分作用,减小系统的稳态误差。

     (6)如果u(k)没变过

    这种情况说明以上规则均未触发,所以输出不变,否者会(控制量直接为0,震荡)

    二、源代码

    sp_pid.h

    #ifndef INCLUDE_SP_PID_H_
    #define INCLUDE_SP_PID_H_
    
    #include "xxxxx底层文件XXXXX.h"
    
    
    typedef  struct
    {
        float  Ref;           // 输入:参考输入  Input: Reference input
        float  Fdb;           // 输入:反馈输入  Input: Feedback input
        float  Err;            //偏差
        float  Err_1;          // 变量:误差信号e(k-1)   Variable: Error
        float  Err_2;          // 变量:误差信号e(k-2)   Variable: Error
        float  Ts;            // 控制周期
    
    
        float  Kp;            // 参数:比例增益  Parameter: Proportional gain
        float  Ki;            // 参数:积分增益 Parameter: Integral gain
        float  Kd;            // 参数:微分增益Parameter: Derivative gain
    
    
        float ErrorAbsMax;            /*偏差绝对值最大值*/
        float ErrorAbsMid;            /*偏差绝对值中位值*/
        float ErrorAbsMin;            /*偏差绝对值最小值*/
    
        float  OutPreSat;     // 变量:饱和输出  Variable: Pre-saturated output
        float  OutMax;        // 参数:最大输出  Parameter: Maximum output
        float  OutMin;        // 参数:最小输出  Parameter: Minimum output
        float  Out;           // 输出:SP_PID输出  Output: SP_PID output
    
        void (*init)();          // Pointer to the init funcion
        void (*calc)();         // 计算函数指针  Pointer to calculation function
    } SP_PID;
    typedef   SP_PID  *SP_PID_handle;
    /*-----------------------------------------------------------------------------
      默认初始化   Default initalizer for the AW_PID object.
    -----------------------------------------------------------------------------*/
    #define  SP_PID_DEFAULTS { 0, 0, 0, 0, 0, 0,\
                               0, 0, 0, \
                               0, 0, 0,\
                               0, 0, 0, 0, \
                               (void (*)(unsigned long)) sp_pid_init,\
                               (void (*)(unsigned long)) sp_pid_calc }
    /*------------------------------------------------------------------------------
      函数原型   Prototypes for the functions in  <SP_PID.c>
    ------------------------------------------------------------------------------*/
    
    void sp_pid_init(SP_PID_handle);
    void sp_pid_calc(SP_PID_handle);
    
    
    #endif /* INCLUDE_SP_PID_H_ */
    
    
    
    

    sp_pid.c

    
    
    #include "sp_pid.h"
    
    #include <stdlib.h>
    
    // include the header for PID data structure definition
    
    void sp_pid_init(SP_PID *v)
    {
        //以下初始化时针对阶跃输入而言
    
        v->ErrorAbsMax = v->Ref * 0.20f;
        v->ErrorAbsMid = v->Ref * 0.10f;
        v->ErrorAbsMin = v->Ref * 0.05f;
    
    //    v->ErrorAbsMax = v->Ref *0.45f;
    //    v->ErrorAbsMid = v->Ref *0.30f;
    //    v->ErrorAbsMin = v->Ref *0.1f;
    }
    
    
    
    void sp_pid_calc(SP_PID *v)
    {
    
        float Delta_Err;                  //e(k)-e(k-1)
        float Last_Delta_Err;             //e(k-1)-e(k-2)
        float uk=0;                         //本次调节输出值
    
        v->Err = v->Ref - v->Fdb;
        Delta_Err = v->Err - v->Err_1;
        Last_Delta_Err = v->Err_1 - v->Err_2;
    
        if (fabs(v->Err) >= v->ErrorAbsMax)
        {
            /*执行规则1*/
            if (v->Err > 0)
            {
    //            uk = v->OutMax;
                uk = v->Ref / (12+v->Ref) * 6000;
            }
            if (v->Err < 0)
            {
    //            uk = v->OutMin;
                uk = v->Ref / (12+v->Ref) * 6000;
            }
        }
    
        if ((v->Err * Delta_Err > 0) || (Delta_Err == 0))
        {
            /*执行规则2*/
            if (fabs(v->Err) >= v->ErrorAbsMid)
            {
                uk = v->Out + 1.5f * (v->Kp * Delta_Err + v->Ki * v->Err + v->Kd * (Delta_Err - Last_Delta_Err));
            }
            else
            {
                uk = v->Out + 0.3f * (v->Kp * Delta_Err + v->Ki * v->Err + v->Kd * (Delta_Err - Last_Delta_Err));
            }
        }
    
        if (((v->Err * Delta_Err < 0) && (Delta_Err * Last_Delta_Err > 0)) || (v->Err == 0))
        {
            /*执行规则3*/
            uk = v->Out;
        }
    
        if ((v->Err * Delta_Err < 0) && (Delta_Err * Last_Delta_Err < 0))
        {
            /*执行规则4*/
            if (fabs(v->Err) >= v->ErrorAbsMid)
            {
                uk = v->Out + 1.5f * v->Kp * v->Err;
            }
            else
            {
                uk = v->Out + 0.4f * v->Kp * v->Err;
            }
        }
    
        if ((fabs(v->Err) <= v->ErrorAbsMin) && (fabs(v->Err) > 0))
        {
            /*执行规则5*/
            uk = v->Out + 0.5f * v->Kp * Delta_Err + 0.3f * v->Ki * v->Err;
        }
    
        if(uk==0)//防止触发这五条规则导致输出为0
            uk=v->Out;
        v->OutPreSat = uk;
    
        // Saturate the output
        if (v->OutPreSat > v->OutMax)
            v->Out =  v->OutMax;
        else if (v->OutPreSat < v->OutMin)
            v->Out =  v->OutMin;
        else
            v->Out = v->OutPreSat;
        v->OutPreSat = v->Out;
    
        v->Err_2 = v->Err_1;
        v->Err_1 = v->Err;
    
    
    }
    
    
    

    说明:规则是死的,人是活的

    比如规则一,偏差很大 就开环输出

    在电机控制,可以直接给最大电压;

    但是在电源控制不能这么给,而是输出固定占空比。

    在其他领域的控制可能不太一样。

    PS;该代码移植来自《智能控制》的专家PID控制

    详细可参考我这篇博文专家PID控制Matlab仿真_龙晨天的博客-CSDN博客_专家pid控制matlab

    三、调用方法

    //声明
    SP_PID pid = SP_PID_DEFAULTS;
    
    //初始化
        
         /*增量式PID初始化*/
         pid.Kp = 25.4597502;
         pid.Ki = 10.053997;
         pid.Kd = 15.59500027;
    
         pid.Ts = Ts;
    
    
         pid.OutMax = 2900;
         pid.OutMin =  100;
         pid.Ref = VoltageRef2;
    
    //注意更改给定后必须要初始化以下内容(偏差最大值、最小值等等的大小)
         pid.init(&pid);
    
    //反馈完调用     
       pid.Fdb = man;
       pid.calc(&pid);
       control_uk = pid.Out;
    

    展开全文
  • 专家PID仿真

    2021-03-04 11:49:43
    专家PID仿真 用Simulink中的S函数进行专家PID仿真 传送们: 编写简单的S函数 专家PID S函数代码 #include "math.h" //********************************PID算法部分************************************// #define ...

    专家PID仿真

    用Simulink中的S函数进行专家PID仿真

    传送们:
    编写简单的S函数
    专家PID

    S函数代码

    #include "math.h"
    //********************************PID算法部分************************************//
    #define OUT_MIN		-1000
    #define OUT_MAX		1000
    
    //积分限幅
    #define INERGRAL_MAX 200
    #define INERGRAL_MIN -200
    
    #define DEAD_BAND 25 //死区控制线
    double Error;//输入偏差
    /****************************************************************************************/
    //定义PID结构体//
    /****************************************************************************************/
    
    typedef struct
    {
    	volatile double    Proportion; // 比例常数 Proportional Const
    	volatile double    Integral; // 积分常数 Integral Const
    	volatile double    Derivative;// 微分常数 Derivative Const
    	volatile double      Error1; // Error[n-1]
    	volatile double      Error2; // Error[n-2]
    	volatile double      iError;  // Error[n]
    	volatile double		 Error_sum;//积分值
    	volatile double		 iIncpid;//PID输出值
    	volatile double      inc_iError;//Error[n]增量
    	volatile double      inc_Error1;//Error[n-1]增量
    	volatile double		 Error_abs_Max;//偏差绝对值最大值
    	volatile double		 Error_abs_Mid;//偏差绝对值最中值
    	volatile double		 Error_abs_Min;//偏差绝对值最小值
    } PID;
    
    
    //PID指针
    PID pid_increase;
    PID* sptr_increase=&pid_increase;
    
    //PID初始化
    void PID_Init(PID *sptr)
    {
    	sptr->Derivative = 0;//Kd
    	sptr->Proportion = 0;//Kp
    	sptr->Integral = 0;//Ki
    	sptr->Error2 = 0;
    	sptr->Error1 = 0;
    	sptr->iError = 0;
    	sptr->Error_sum = 0;
    	//sptr->index=1;
    	sptr->iIncpid = 0;
    	sptr->inc_iError = 0;
    	sptr->inc_Error1 = 0;
    	sptr->Error_abs_Max = 200;
    	sptr->Error_abs_Mid = 100;
    	sptr->Error_abs_Min = 50;
    
    }
    
    //PID输出限幅处理
    double PID_OutputLimit(double output)
    {
    	double x;
    	x = output;
    	if (x <= OUT_MIN)
    	{
    		x = (double)OUT_MIN;
    	}
    	else if (x >= OUT_MAX)
    
    	{
    		x = (double)OUT_MAX;
    	}
    	return x;
    }
    
    /****************************************************************************************/																												//								位置式专家
    //										//pwm=Kp*e(k)+Ki*∑e(k)+Kd[e(k)-e(k-1)]	
    /****************************************************************************************/
    double Exper_Pid(double iError, PID* sptr)
    {
    	double result = 0;
    	sptr->iError = iError;  //传入当前误差
    	sptr->inc_iError = sptr->iError - sptr->Error1;//得到这次增量
    	sptr->inc_Error1 = sptr->Error1 - sptr->Error2;//得到上次增量
    	sptr->iError = iError;                                    // 计算当前误差
    
    	sptr->Error_sum += sptr->iError;//积分项	
    		///当输出限幅的时候,积分累加部分也应同时进行限幅,以防输出不变而积分项继续累加,也即所谓的积分饱和过深。
    	//积分量限幅
    	if (sptr->Error_sum > INERGRAL_MAX)
    	{
    		sptr->Error_sum = INERGRAL_MAX;
    	}
    	if (sptr->Error_sum < INERGRAL_MIN)
    	{
    		sptr->Error_sum = INERGRAL_MIN;
    	}
    
    	if (fabs(sptr->iError) > sptr->Error_abs_Max)//误差超过设定的最大值(M1)
    	{
    		if (sptr->iError > 0)  result = OUT_MAX;
    		if (sptr->iError < 0)  result = OUT_MIN;
    	}
    
    	if (fabs(sptr->iError) <= sptr->Error_abs_Min)//若误差小于设定的最小值(M3)
    	{
    		if (fabs(sptr->iError) > DEAD_BAND) //死区控制
    		{
    			result = 1*sptr->Proportion * sptr->iError// P
    				+ 1*sptr->Integral * sptr->Error_sum;                // I
    		}
    		else result = 0;
    	}
    	if (((sptr->iError*sptr->inc_iError < 0) && (sptr->inc_iError*sptr->inc_Error1 > 0)) || (sptr->iError == 0))
    		//说明误差正在减小,或者为零,此时维持原输出
    	{
    		result = sptr->iIncpid;//保持上一次输出
    	}
    
    	if (((sptr->iError*sptr->inc_iError < 0) && (sptr->inc_iError*sptr->inc_Error1 < 0)))//误差处于极值状态
    	{
    		if (fabs(sptr->iError) > sptr->Error_abs_Mid)    result = 4*sptr->Integral*sptr->Error_sum;
    		if (fabs(sptr->iError) < sptr->Error_abs_Mid)    result = 3*sptr->Integral*sptr->Error_sum;
    	}
        
    	if ((sptr->iError*sptr->inc_iError > 0) || (sptr->inc_iError == 0))//误差在变大,或维持长值
    	{
    		if (fabs(sptr->iError) > sptr->Error_abs_Mid)    result = 3 * (sptr->Integral*sptr->Error_sum + sptr->Proportion*sptr->iError + sptr->Derivative*sptr->inc_iError);
    
    		if (fabs(sptr->iError) < sptr->Error_abs_Mid)    result = 1.2*(sptr->Integral*sptr->Error_sum + sptr->Proportion*sptr->iError + sptr->Derivative*sptr->inc_iError);
    	}
        
    	//更新值
    	sptr->iIncpid = result;
    	sptr->Error2 = sptr->Error1;
    	sptr->Error1 = sptr->iError;
    	result = PID_OutputLimit(result);//PID输出限幅								
    	return(result);          // 返回计算值
    
    }
    //下面是主要编写S函数的部分
    
    
    #define S_FUNCTION_NAME  exper_pid   //修改s函数名称,此处为test
    #define S_FUNCTION_LEVEL 2      //不需要改使用LEVEL 2,可以提供更过API函数
    #define SAMPLE_TIME 0.01        //自己设置的采样时间
    
    #include "simstruc.h"//必须包含的头文件
    
    //**输出函数:**
    static void mdlInitializeSizes(SimStruct *S)
    {
        ssSetNumSFcnParams(S, 3); /*设置参数个数,这里为3,分别设置PID的三个参数分别是P I D */
        if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) /*判断参数个数,这里为3 ,在S-Function的对话框里面设置3个*/
        {
            return;
        }
        
        ssSetNumContStates(S, 0);//设置连续状态的个数,缺省为0;
        ssSetNumDiscStates(S, 0);//设置离散状态的个数,缺省为0;
    
        if (!ssSetNumInputPorts(S, 1)) return;//设置输入变量的个数,这里为1
        ssSetInputPortWidth(S, 0, 1);//指定输入端口的宽度。0号,1维
        ssSetInputPortRequiredContiguous(S, 0, true); //指定进入端口的信号元素必须是连续的。
        //连续指的是:指定端口的信号元素必须占用内存的连续区域。以便于访问信号指针即可访问信号的元素,可以使用ssGetInputPortSignal访问。
        //指定进入指定端口的信号元素必须占用内存的连续区域。以便于访问信号指针即可访问信号的元素ssGetInputPortSignal
       
        
        //端口的输入用于mdlOutputs或mdlGetTimeOfNextVarHit函数。设置直接馈通标志(1=yes,0=no)   
        ssSetInputPortDirectFeedThrough(S, 0, 1);
     
        if (!ssSetNumOutputPorts(S, 1)) return;设置输出变量的个数
        ssSetOutputPortWidth(S, 0, 1);//指定输入端口的宽度。0号,1维
    
        ssSetNumSampleTimes(S, 1);//设定的样本采样次数,此处为1次
        ssSetNumRWork(S, 0);//用于mdlInitializeSizes将real_T工作向量元素的数量指定为0,
        ssSetNumIWork(S, 0);//可以不用管,一些清零操作
        ssSetNumPWork(S, 0);//可以不用管,一些清零操作
        ssSetNumModes(S, 0);//可以不用管,一些清零操作
        //如果该选项设置为使用默认SIM状态,并且S函数不使用PWorks,则Simulink将S函数视为内置块。
        ssSetNumNonsampledZCs(S, 0);
    
        ssSetOptions(S, 0);//有许多选项,使用or连接,采取默认值
    }
    
    //指定采样时间函数
    static void mdlInitializeSampleTimes(SimStruct *S)
    {
        ssSetSampleTime(S, 0, SAMPLE_TIME);//指定采样时间SAMPLE_TIME也就是0.01 秒,索引从0开始的采样时间段
        ssSetOffsetTime(S, 0, 0.0);//使用此宏mdlInitializeSizes指定从0开始的采样时间的偏移量。
    
    }
    
    
    
    #define MDL_INITIALIZE_CONDITIONS   /* Change to #undef to remove function */
    #if defined(MDL_INITIALIZE_CONDITIONS)
      /* Function: mdlInitializeConditions ========================================
       * Abstract:
       *    In this function, you should initialize the continuous and discrete
       *    states for your S-function block.  The initial states are placed
       *    in the state vector, ssGetContStates(S) or ssGetRealDiscStates(S).
       *    You can also perform any other initialization activities that your
       *    S-function may require. Note, this routine will be called at the
       *    start of simulation and if it is present in an enabled subsystem
       *    configured to reset states, it will be call when the enabled subsystem
       *    restarts execution to reset the states.
       */
    //初始化连续和离散状态,此处不使用,使用ssGetContStates(S) or ssGetRealDiscStates(S).访问状态
    //例如 real_T *xdisc    = ssGetRealDiscStates(S);
      static void mdlInitializeConditions(SimStruct *S)
      {
      }
    #endif /* MDL_INITIALIZE_CONDITIONS */
    
    
    
    #define MDL_START  /* Change to #undef to remove function */
    #if defined(MDL_START) 
    
    //此函数在模型执行开始时调用一次。自己需要初始化的函数可以放在这里面。*/
      static void mdlStart(SimStruct *S)
      {
          PID_Init(sptr_increase);//PID参数初始化
      }
    #endif /*  MDL_START */
    
    
    
    //用于计算S函数的输出,算法一般是在这里实现的。
    static void mdlOutputs(SimStruct *S, int_T tid)
    {
    
      real_T *para1 = mxGetPr(ssGetSFcnParam(S, 0));  //获得参数1,P
      real_T *para2 = mxGetPr(ssGetSFcnParam(S, 1));  //获得参数2,I
      real_T *para3 = mxGetPr(ssGetSFcnParam(S, 2));  //获得参数2,D
     
      const real_T *u1 = (const real_T*) ssGetInputPortSignal(S,0);  //获得输入u1
      real_T       *y1 = ssGetOutputPortSignal(S,0);  //输出y1
      sptr_increase->Proportion=(double)*para1;
      sptr_increase->Integral=(double)*para2;
      sptr_increase->Derivative=(double)*para3;
      Error=(int)*u1;
      *y1=(double)Exper_Pid(Error,sptr_increase);//PID输出
       
    }
    
    
    
    #define MDL_UPDATE  /* Change to #undef to remove function */
    #if defined(MDL_UPDATE)
      /* Function: mdlUpdate ======================================================
       * Abstract:
       *    This function is called once for every major integration time step.
       *    Discrete states are typically updated here, but this function is useful
       *    for performing any tasks that should only take place once per
       *    integration step.
       */ 
       //离散状态通常在此更新,做任何任务都应该更新一次,需要k'kssSetNumDiscStates宏指定它具有离散状态。
      static void mdlUpdate(SimStruct *S, int_T tid)
      {
      }
    #endif /* MDL_UPDATE */
    
    
    
    #define MDL_DERIVATIVES  /* Change to #undef to remove function */
    #if defined(MDL_DERIVATIVES)
      /* Function: mdlDerivatives =================================================
       * Abstract:
       *    In this function, you compute the S-function block's derivatives.
       *    The derivatives are placed in the derivative vector, ssGetdX(S).
       */
      //计算S函数块的导数。
      //*导数被放置在导数向量ssGetdX(S)中
      static void mdlDerivatives(SimStruct *S)
      {
      }
    #endif /* MDL_DERIVATIVES */
    
    
    
    /* Function: mdlTerminate =====================================================
     * Abstract:
     *    In this function, you should perform any actions that are necessary
     *    at the termination of a simulation.  For example, if memory was
     *    allocated in mdlStart, this is the place to free it.
     */
      //函数结束时执行的操作,例如释放内存等必要操作
    static void mdlTerminate(SimStruct *S)
    {
        Error=0;
        PID_Init(sptr_increase);
    }
    
    
    /*=============================*
     * Required S-function trailer *
     *=============================*/
    
    #ifdef  MATLAB_MEX_FILE    /* Is this file being compiled as a MEX-file? */
    #include "simulink.c"      /* MEX-file interface mechanism */
    #else
    #include "cg_sfun.h"       /* Code generation registration function */
    #endif
    
    

    搭建Simulink简单模型

    在这里插入图片描述

    控制效果:
    可以说非常好了,超调量很小,反应时间也很迅速,不到1s就达到稳定值了。
    在这里插入图片描述

    调试由于参数较多,需要确定输出的最值和积分的最值,和设定误差的最大最小,和中值。

    然后结合普通PID的调试技巧,先将Ki置零,调节Kp,然后根据误差曲线的变化规律和输出曲线,判断误差处于那个状态。在进去里面调节增益系数。期间可以对设定误差的最值和中值进行微调以边更适合系统。

    当Kp调试差不多了,在调试Ki就差不多了

    展开全文
  • 本科毕业论文 设计 论文 设计题目 专家PID 控制在快速系统中的仿真及应用 学 院 专 业 班 级 学 号 学生姓名 指导教师 2010 年 06 月 07 日 贵州大学本科毕业论文 设计 诚信责任书 本人郑重声明本人所呈交的毕业论文...
  • 基于目前的压力控制和微小体积控制系统不能满足微流控芯片自动化进样的需求,本文提出一种新型的基于专家PID控制和卡尔曼滤波的恒压控制系统,通过精确控制压力实现精确控制进样体积。MATLAB仿真和实际测量表明,该...
  • 专家PID控制仿真代码

    2016-04-30 15:33:38
    专家PID控制仿真代码
  • 倒立摆稳定的PID控制 自营模糊补偿的倒立摆PD控制 模糊自适应控制
  • 专家pid控制,模糊控制
  • 1.领域:matlab,基于自适应模糊补偿PD控制算法和专家PID控制算法 2.内容:基于自适应模糊补偿的倒立摆PD控制以及专家PID控制matlab仿真 +代码操作视频 3.用处:用于基于自适应模糊补偿PD控制算法和专家PID控制...
  • 专家PID控制Matlab仿真

    千次阅读 2021-01-22 13:11:52
    专家PID控制 一、简介 专家PID控制,专家PID控制不同于常规意义下的PID控制,是专家经验与PID控制算法的结合,是基于PID控制器的智能化优化。 专家PID控制就是基于被控对象和控制规律的各种知识,而不需要知道被...
  • 基于matlab的PID和专家PID控制,用于工业控制过程
  • 专家PID控制matlab程序

    2022-04-17 10:42:10
    专家PID控制matlab程序 1 专家PID控制 专家PID控制的实质是:基于受控对象和控制规律的各种知识,无须知道被控对象的精确模型,利用专家经验来设计PID参数。专家PID控制是一种直接型专家控制器。 典型的二阶系统单位...
  • 专家PID控制原理 PID专家控制的实质是,基于受控对象和控制规律的各种知识,无需知道被控对象的精确模型,利用专家经验来设计PID参数。 专家PID控制是一种直接型专家控制器。 对典型的二阶系统单位阶跃响应过程作...
  • 专家PID控制系统Matlab仿真摘要:分析了一个速度控制器的控制仿真。其传递函数为:使用专家PID控制系统,输入信号为阶跃信号,取采样时间为1ms,画出阶跃响应曲线和误差变化曲线。0引言专家控制(Expert Control)的...
  • 专家PID控制仿真程序

    2013-11-28 20:08:56
    来自与智能卡控制 课本第一章 专家PID控制仿真程序
  • 代码清晰有详细注释!可直接运行! 通过matlab模拟仿真PID控制系统和专家PID控制系统,对各参量单独变化对系统控制作用的影响进行讨论,得出结论。专家PID程序五条规则与算法五种情况对应。
  • 基于专家PID调节的变频调速恒压供水系统的研究

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,218
精华内容 2,487
关键字:

专家pid

友情链接: PlayRecordMusic.rar