精华内容
下载资源
问答
  • 专家PID

    2021-03-02 10:54:10
    专家PID 专家控制 专家控制是模拟人类专家控制的方式。它具有大量的专门知识和经验,和专家控制一样不需要知道对象的模型的情况下,对系统进行控制。 专家控制的基本结构 和人类专家控制一样,知识库越是丰富,推理...

    专家PID

    专家控制

    专家控制是模拟人类专家控制的方式。它具有大量的专门知识和经验,和专家控制一样不需要知道对象的模型的情况下,对系统进行控制。

    专家控制的基本结构

    和人类专家控制一样,知识库越是丰富,推理机越是精确,控制效果也就越好。不同的知识库和推理机,控制效果也不经相同。这也是专家控制的一个特点,利用这个特点,可以设计属于自己的专家控制系统。

    在这里插入图片描述

    专家控制的基本实现

    直接性专家控制

    专家控制器直接对执行机构进行控制。
    在这里插入图片描述

    间接型专家控制

    专家控制通过控制算法,对控制器进行操作,由控制器对执行机构进行控制。
    在这里插入图片描述

    专家PID

    专家PID是专家控制和PID的结合,两者都不需要知道被控对象的模型。

    简单的专家PID
    下面的例子是增量式PID的实现方式,理解了思路,也就是对偏差和偏差增量的判断采取控制。便可以用C语言进行实现。
    

    通过偏差偏差的增量来判断应采用的PID控制类型,从而更快更平稳地实现收敛。

    下面是这个是普遍型的规则库的实现:

    当前时刻误差
    在这里插入图片描述
    误差增量
    在这里插入图片描述
    上次误差增量在这里插入图片描述
    K1和K2为增益系数,K1>K2
    M1,M2为设定的误差界限,M1>M2>M3

    这里的专家控制有5条控制规则:

    1:误差超过设定的最大值(M1),输出PID控制器的最大值,进行开环控制,对极限情况进行控制。以迅速达到偏差作用。

    在这里插入图片描述

    2:误差的绝对值在变大或者维持常值,实施较强的控制作用

    在这里插入图片描述
    再次对偏差进行判断,选择不同的控制强度。

    若误差超过设定的最大值(M2),实行较强控制,减少误差

    控制器输出:
    在这里插入图片描述
    若误差小于设定的最大值(M2),实现一般较弱控制

    控制器输出:也可以减少K1的值
    在这里插入图片描述
    说明此时误差仍然较大,可将 k1增大,反之可以减小。这样可以比分别使用两套参数减少2个待调参数,当然模型的容量也有一定程度下降。

    3:误差的绝对值减少后者误差已经达到平衡状态,维持控制器输出不变

    在这里插入图片描述
    在这里插入图片描述

    4:误差处于极值状态

    在这里插入图片描述
    再次对偏差进行判断,选择不同的控制强度。

    若误差超过设定的最大值(M2),实行较强控制,减少误差

    控制器输出:
    在这里插入图片描述
    若误差小于设定的最大值(M2),实现较弱控制

    控制器输出:

    在这里插入图片描述

    5:若误差小于设定的最小值(M3),增加控制精度

    在这里插入图片描述
    设置控制精度,可能是由系统的静差导致的,用PI控制,减少静差。
    在这里插入图片描述
    Kp和Ki可以适当减小,以减小控制作用。当偏差小到一定程度后,甚至可以引入死区的概念,是系统稳定下来而不需要去进行调节。

    思维导图

    在这里插入图片描述

    C语言实现:增量式专家PID

    //输出限幅
    #define OUT_MIN		-1000
    #define OUT_MAX		1000
    
    #define DEAD_BAND 10 //死区控制线
    #include"math.h"           
    //PID结构体
    //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;
    
    /****************************************************************************************/																												//								增量式专家
    //										//pwm=Kp*e(k)+Ki*∑e(k)+Kd[e(k)-e(k-1)]	
    /****************************************************************************************/
    double Exper_Pid_Inc (double iError,PID* sptr) 
    {
       double result=0;
       sptr->iError=iError;  //传入当前误差
       sptr->inc_iError=sptr->iError-sptr->Error1;//得到这次增量
       sptr->inc_Error1=sptr->Error1-sptr->Error2;//得到上次增量
       if(abs(sptr->iError)>sptr->Error_abs_Max)//误差超过设定的最大值(M1)
       {
    		if(sptr->iError>0)  result=OUT_MAX;
       	 	if(sptr->iError<0)  result=OUT_MIN;
       }
    
    	if(abs(sptr->iError)<=sptr->Error_abs_Min)//若误差小于设定的最小值(M3)
       {
       	if(fabs(sptr->iError)>DEAD_BAND) //死区控制
       	{
    	 result=sptr->iIncpid+0.5*sptr->Proportion * sptr->inc_iError  // P
             +0.3*sptr->Integral * sptr->iError;                // 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(abs(sptr->iError)>sptr->Error_abs_Mid)    result=sptr->iIncpid+1.2*sptr->Integral*sptr->iError;
        if(abs(sptr->iError)<sptr->Error_abs_Mid)    result=sptr->iIncpid+0.6*sptr->Integral*sptr->iError;
      }
    
      	if(((sptr->iError*sptr->inc_iError>0)||(sptr->inc_iError==0))//误差在变大,或维持长值
      {
      	if(abs(sptr->iError)>sptr->Error_abs_Mid)    result=sptr->iIncpid+2*(sptr->Integral*sptr->iError+sptr->Proportion*sptr->inc_iError+sptr->Derivative*(sptr->inc_iError-sptr->inc_Error1));
      	
        if(abs(sptr->iError)<sptr->Error_abs_Mid)    result=sptr->iIncpid+1.2*(sptr->Integral*sptr->iError+sptr->Proportion*sptr->inc_iError+sptr->Derivative*(sptr->inc_iError-sptr->inc_Error1));
      }
    
      //更新值
      sptr->iIncpid=result;    
      sptr->Error2=sptr->Error1; 
      sptr->Error1=sptr->iError;	
      result=PID_OutputLimit(result);//PID输出限幅								
      return(result);          // 返回计算值
    	
    }
    
    //PID输出限制,根据PWM的输出值进行增量式PID输出限制
    double PID_OutputLimit(double output)  
    {
    		
        if (output < OUT_MIN)
    		{
            output = OUT_MIN;
        }		
    		else if (output > OUT_MAX)
    		
    		{
            output = OUT_MAX;
        }
        return output;
    }
    
    

    C语言实现:位置式专家PID

    //输出限幅
    #define OUT_MIN		-1000
    #define OUT_MAX		1000
    //积分限幅
    #define INERGRAL_MAX 200
    #define INERGRAL_MIX -200
    
    #include"math.h"           
    //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
    //										//pwm=Kp*e(k)+Ki*∑e(k)+Kd[e(k)-e(k-1)]	
    /****************************************************************************************/
    #include "math.h"
    //********************************PID算法部分************************************//
    #define OUT_MIN		-500
    #define OUT_MAX		500
    
    //积分限幅
    #define INERGRAL_MAX 200
    #define INERGRAL_MIN -200
    
    //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 = 150;
    	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_Pos(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 = 0.5*sptr->Proportion * sptr->iError// P
    				+ 0.3*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=1.8*sptr->Integral*sptr->Error_sum;
       	    if(fabs(sptr->iError)<sptr->Error_abs_Mid)    result=1.2*sptr->Integral*sptr->Error_sum;
    	}
    
    	if ((sptr->iError*sptr->inc_iError > 0) || (sptr->inc_iError == 0))//误差在变大,或维持长值
    	{
      	if(abs(sptr->iError)>sptr->Error_abs_Mid)    result=2*(sptr->Integral*sptr->Error_sum+sptr->Proportion*sptr->iError+sptr->Derivative*sptr->inc_iError);
      	
        if(abs(sptr->iError)<sptr->Error_abs_Mid)    result=1.1*(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);          // 返回计算值
    
    }
    
    
    //PID输出限制,根据PWM的输出值进行增量式PID输出限制
    double PID_OutputLimit(double output)  
    {
    		
        if (output < OUT_MIN)
    		{
            output = OUT_MIN;
        }		
    		else if (output > OUT_MAX)
    		
    		{
            output = OUT_MAX;
        }
        return output;
    }
    
    

    总结

    通过这个简单的例子,大概了解直接性专家控制。最明显的优势,控制决策的灵活性,可以根据不同的系统,选择不同和设计不同的控制策略,通过修改、增加控制规则,可不断积累知识,改进控制性能。能够满足任意动态过程的控制需要,尤其适用于带有时变、非线性和强干扰的控制;但问题是,调试比普通PID复杂,设计的控制规则需要经验。

    展开全文
  • 神经网络PID-模糊PID-专家PID-等高级PID.rar
  • 专家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与模糊PID的C语言实现,及文档 ,有算法实现,和原理
  • 专家PID控制

    2018-11-14 09:25:00
    1、专家PID控制原理 PID专家控制的实质是,基于受控对象和控制规律的各种知识,无需知道被控对象的精确模型,利用专家经验来设计PID参数。专家PID控制是一种直接型专家控制器。 典型的二阶系统单位阶跃响应误差...

    1、专家PID控制原理

    PID专家控制的实质是,基于受控对象和控制规律的各种知识,无需知道被控对象的精确模型,利用专家经验来设计PID参数。专家PID控制是一种直接型专家控制器。

    典型的二阶系统单位阶跃响应误差曲线如图2-5所示。对于典型的二阶系统阶跃响应过程作如下分析。

      2-5中,区域,误差朝绝对值减小的方向变化。此时,可采取保持等待措施,相当于实施开环控制;区域,误差绝对值朝增大的方向变化。此时,可根据误差的大小分别实施较强或一般的控制作用,以抑制动态误差。

    令e(k)表示离散化的当前采样时刻的误差值,e(k-1)和e(k-2)分别表示前一个和前两个采样时刻的误差值,则有:

    根据误差及其变化,可设计专家PID控制器,该控制器可分为以下五种情况进行设计:

    (1)当|e(k)|>M1 时,说明误差的绝对值已经很大。不论误差变化趋势如何,都应考虑控制器的输出应按最大(或最小)输出,以达到迅速调整误差,使误差绝对值以最大速度减小。此时,它相当于实施开环控制。

    (2)当e(k)Δe(k)>0或 Δe(k)=0时,说明误差在朝误差绝对值增大方向变化,或误差为某一常值,未发生变化。

           此时,如果|e(k)|≥M2,说明误差也较大,可考虑由控制器实施较强的控制作用,以达到扭转误差绝对值朝减小方向变化,并迅速减小误差的绝对值,控制器输出为:

      如果 |e(k)|<M2,说明尽管误差朝绝对值增大方向变化,但误差绝对值本身并不很大,可考虑控制器实施一般的控制作用,只要扭转误差的变化趋势,使其朝误差绝对值减小方向变化,控制器输出为

    (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时,说明误差处于极值状态。如果此时误差的绝对值较大,即|e(k)|≥M2 ,可考虑实施较强的控制作用。

    如果此时误差的绝对值较小,即|e(k)|<M2,可考虑实施较弱的控制作用

    5)当e(k)<ε时,说明误差的绝对值很小,此时加入积分,减少稳态误差。

    以上各式中:

    em(k)为误差e的第k个极值;

    u(k)为第k次控制器的输出;

    k1为增益放大系数,k1>1;

    k2为抑制系数,0<k2<1;

    M1,M2为设定的误差界限,M1>M2>0

     

    转载于:https://www.cnblogs.com/long5683/p/9956207.html

    展开全文
  • 专家PID控制仿真代码

    2016-04-30 15:33:38
    专家PID控制仿真代码
  • 普通PID、变结构PID、微分先行PID、模糊PID、专家PID

    博主联系方式:
    QQ:1540984562
    微信:wxid_nz49532kbh9u22 QQ交流群:892023501

    系列文章

    【智能车Code review】—曲率计算、最小二乘法拟合
    【智能车Code review】——坡道图像与控制处理
    【智能车Code review】——拐点的寻找
    【智能车Code review】——小S与中S道路判断
    【智能车Code review】——环岛的判定与补线操作
    智能车复工日记【1】——菜单索引回顾
    智能车复工日记【2】——普通PID、变结构PID、微分先行PID、模糊PID、专家PID
    智能车复工日记【3】:图像处理——基本扫线和基本特征提取和十字补线
    智能车复工日记【4】:关于图像的上下位机的调整问题总结
    智能车复工日记【5】:起跑线的识别与车库入库
    智能车复工日记【6】:有bug的模糊PID记录
    智能车复工日记【7】:关于会车的图像问题
    智能车复工日记【N】:图像处理——环岛debug记录(持续更新)

    前言

    这里所解释的都是以位置式为基础的。
    三个参数含义:
    1.比例环节Kp,作用是加快系统的响应速度,提高系统的调节精度,副作用是会导致超调;
    2.积分环节Ki,作用是消除稳态误差,副作用是导致积分饱和现象;
    3.微分环节Kd,作用是改善系统的动态性能,副作用是延长系统的调节时间。

    普通PID

    公式:位置式公式
    参数讲解:除了三个参数外,我们来看三个参数乘的是哪几个变量
    e(k):当前目标值与输出值的偏差。
    e(i):此状态之前(连带此状态)所有e(k)之和
    e(k)-e(k-1):此状态目标值与输出值的偏差和上状态目标值与输出值的偏差的偏差。、
    参数目录一览:

    舵机参数:

    这里的误差均是以此时中线值与目标中线值之差为例(图像一般是70*185,所以中线值92、93都行)。
    不同的打脚行参数也是不同的。
    舵机PD控制,一般来说参数KD是参数KP的两倍左右。

    电机参数:

    舵机参数要分不同的道路来调,电机同样是这个道理,不过略作简化,分为直道和不是直道两种。
    直道上响应要快,因为直道需要急停和急加速。I项调小,否则滞后性较严重。D项看着给,调参这事儿说不准的。
    量级问题:位置式P和D一般来说以整数为量级,考虑到调整参数的快速性上建议按键按下一次增加/减少3、5左右。
    I项以0.01为量级,每次调整0.03-0.05左右为佳。

    变结构PI控制(电机控制,这里对公式进行修改采用正态分布公式)

    参考文章:https://blog.csdn.net/weixin_42164589/article/details/86291824

    //这里为了方便,左右电机参数不做区分,统一管理
    //原公式 : U(t,e)=[ Ap + Bp*(1-exp(-Cp|e|))]*e(t) + [ Ai*exp(-Ci|e|)]*sum_e;
    //        Kp(e) = Ap + Bp(1-exp(-Cp|e|));
    //        Ki(e) = Ai * exp(-Ci|e|);
    /*
    现公式:  Kp(error) = Ap + Bp(1/(sqrt(2*pi)*a)-1/(sqrt(2*pi)*a)*exp(-(abs(error)-b)^2/(2*a^2)));
              Ki(error) = Ai *1/(sqrt(2*pi)*a)*exp(-(abs(error)-b)^2/(2*a^2));
              Kd( ) 手动调整
              U(error,t)=Kp(error)*error + Ki(error)*sum_error + Kd(error)*(now_error - last_error);
              其中1/sqrt(2*pi)=0.3989;
              修改公式:
              Kp(error) = Ap + Bp(0.3989/a-0.3989/a*exp(-(abs(error)-b)^2/(2*a^2)));
              Ki(error) = Ai *0.3989/a*exp(-(abs(error)-b)^2/(2*a^2));
              Kd( ) 手动调整
              U(error,t)=Kp(error)*error + Ki(error)*sum_error + Kd(error)*(now_error- last_error);
    

    公式讲解:当e->无穷,Kp取max Ap+Bp,Ki取min 0;
    当e->0, Kp取min AP,Ki取max Ai;
    基本思想:当误差e较小时,比例增益取小值,误差取大值时,取大值。
    理想效果:这样既可以调高响应速度,又可以防止产生过大的超调量,同时保证有很好的稳定性。
    同时,当误差较大时,希望较小,以防止产生震荡和积分饱和,有利于减小超调量、缩短调节时间,
    随着误差的减小,希望逐渐增大,以消除稳态误差。

    参数大概范围:
    范围

    微分先行PID(电机控制)

    微分先行在普通PID的基础上改变的就是:对输出进行微分而不是对误差进行微分,具体原理可以去参考刘金坤的先进PID控制。
    书
    (丢在学校吃灰的书)。
    也可以参考这两篇博客:
    https://blog.csdn.net/foxclever/article/details/80633275?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522158583112619725211928147%2522%252C%2522scm%2522%253A%252220140713.130056874…%2522%257D&request_id=158583112619725211928147&biz_id=0&utm_source=distribute.pc_search_result.none-task
    https://wenku.baidu.com/view/820bd2e1581b6bd97e19eacf.html
    一开始看书写的代码,由于看不懂公式,所以直接从原理出发:对输出进行微分,然后得到的代码形式是这样的:

    int  L_LocPIDcalc_coder(int setpoint,int nextpoint)		//目标值   和 编码器读回来的值
    {
    	int result=0;
        L_now_output=nextpoint;    	//当前编码器读回来的值
    	L_error1_coder=setpoint-nextpoint;		//当前误差
        if(modeflag==0)     //普通微分先行
        {
                L_sumerror_coder +=L_error1_coder;				//I项
                L_error2_coder=L_error1_coder;
                if( street_flag== 1 ||street_flag== 5||street_flag== 7 ||street_flag== 8 ||street_flag== 9 )	//直道
                {
                    result=Right_Left_P * L_error1_coder + Right_Left_I*L_sumerror_coder + Right_Left_D*(L_now_output-L_last_output);
                }
                else 		//非直道
                {
                    result=Right_Left_P1 * L_error1_coder + Right_Left_I1*L_sumerror_coder + Right_Left_D1*(L_now_output-L_last_output);
                }          
        L_last_output=nextpoint;	
    	//		限幅		
        if(result>=10000) result=10000;
        if(result<=-10000) result=-10000;
    	return result;	
    }
    

    随后翻看其他博客发现公式还需要进行滤波,增加了新变量gama,暂时还不知道gama的取值范围是多少,只知道是在0~1之间。

    float c1=0,c2=0,c3=0,temp=0;
    L_sumerror_coder +=L_error1_coder;	        //计算I项
    if( street_flag== 1 ||street_flag== 5||street_flag== 7 ||street_flag== 8 ||street_flag== 9 )    //直道
    {
        temp=gama_str*Right_Left_D_dif+Right_Left_P_dif;      //temp = gama*KD+KP
        c3=Right_Left_D_dif/temp;
        c2=(Right_Left_D_dif+Right_Left_P_dif)/temp;
        c1=gama_str*c3;
        L_derivative=c1*L_derivative+c2*nowinput-c3*L_last_output;
        result=Right_Left_P * L_error1_coder + Right_Left_I*L_sumerror_coder + L_derivative;
        L_error2_coder=L_error1_coder;      //更新lasterror
        L_last_output=nowinput;     //更新lastoutput
    }
    else            //非直道
    {                  
        temp=gama_wan*Right_Left_D_dif+Right_Left_P_dif;      //temp = gama*KD+KP
        c3=Right_Left_D_dif/temp;
        c2=(Right_Left_D_dif+Right_Left_P_dif)/temp;
        c1=gama_wan*c3;
        L_derivative=c1*L_derivative+c2*nowinput-c3*L_last_output;
        result=Right_Left_P * L_error1_coder + Right_Left_I*L_sumerror_coder + L_derivative;
        L_error2_coder=L_error1_coder;      //更新lasterror
        L_last_output=nowinput;     //更新lastoutput
    }
    

    模糊PID(用于舵机控制,只选择PD控制)

    文章参考见我收藏夹。
    之所以不用微分先行是因为微分先行是在目标值变化频率较高时使用较好,而舵机控制目标值不变,一直是93//92.
    模糊PID实现步骤:
    步骤
    模糊PID推导出来的是三个参数的变化值,所以还要加上我们设定的初始值才是真正送入pid计算的三个参数,
    以直道为例:

        if(type==1)
        {     
            matrix_x=0;
            steer_P=Proportion_str;
            steer_D=Derivative_str;
    		chauncan(steer_P,steer_D,deltap_max_different_road[matrix_x],deltap_min_different_road[matrix_x],deltad_max_different_road[matrix_x],deltad_min_different_road[matrix_x]);        
            steer_fuzzypid_cal(steer_setpoint,nextpoint);    //输入目标值和实际值,得到KP和KD
            result=steerPID.output_Kp*steerPID.e+steerPID.output_Kd*steerPID.de; 
            return   result;          
        } 
    

    调参改动的部分:
    【1】模糊规则表(根据专家经验)
    建立模糊规则表
    【2】输出值限幅
    限幅
    当将变换幅度限制为0,则公式退化为普通PID控制。

    专家PID(基于增量式电机控制)

    增量式PID公式:
    u[n] = Kp(e[n]-e[n-1]) + Ti*e[n] + Td{e[n]-2e[n-1]+e[n-2]}

    基于增量式的专家PID
    e(k):当前采样时刻误差值
    e(k-1):前一个时刻采样时刻误差值
    e(k-1):前两个时刻采样时刻误差值
    delta_e(k)=e(k)-e(k-1);
    delta_e(k-1)=e(k-1)-e(k-2);
    根据误差及其变化,对阶跃相应误差曲线进行如下定性分析:
    (1)当|e(k)|>M_max,说明误差的绝对值已经很大,不论误差变化趋势如何,都应考虑控制器的输出应按最大(或最小)输出,以达到迅速调整误差,使误差绝对值以最大速度减少。
    此时它相当于实施开环控制。
    (2)当e(k)*delta_e(k)>0,说明误差在朝误差绝对值增大方向变化,或误差为某一常数,未发生变化。
    如果|e(k)|>=M_middle,说明误差也较大,可考虑由控制器实施较强的控制作用,以达到扭转误差绝对值朝减小方向变化,并迅速减少误差的绝对值,控制器输出为:
    u(k)=u(k-1)+k1{kp[e(k)-e(k-1)]+kie(k)+kd[e(k)-2e(k-1)+e(k-2)]} ;
    如果|e(k)|<M_middle,说明尽管误差超绝对值增大的方向变化,但误差绝对值本身并不很大,可考虑控制器实施一般的控制作用,扭转误差的变化趋势,
    使其朝误差绝对值减小方向变化,控制器输出为:
    u(k)=u(k-1)+kp[e(k)-e(k-1)]+kie(k)+kd[e(k)-2e(k-1)+e(k-2)] ; //普通增量式
    (3)当e(k)*delta_e(k)<0、delta_e(k)*delta_e(k-1)>0或者e(k)=0时,说明误差的绝对值朝减少的方向变化,或者已经达到平衡状态。此时可以考虑采取保持控制器输出不变。
    (4)当e(k)delta_e(k)<0、delta_e(k)delta_e(k-1)<0时,说明误差处于极值状态。
    如果此时误差的绝对值较大,即|e(k)|>=M_middle,可考虑实施比较强的控制作用:
    u(k)=u(k-1)+k1
    kpem(k);
    如果此时误差的绝对值较小,即|e(k)|<M_middle,可考虑实施比较弱的控制作用:
    u(k)=u(k-1)+k2
    kpem(k);
    (5)当|e(k)|<=sigma,说明误差的绝对值很小,此时加入积分控制,以减少稳态误差。
    以上:em(k)为误差e的第k个极值;k1为增益放大系数,k1>1;k2为抑制系数,0<k2<1;M_max,M_middle为设定的误差界限,M_max>M_middle>0;
    k为控制周期的序号;sigma为任意小的正实数。
    误差朝绝对值减少的方向变化,采取保持等待措施。
    误差朝绝对值增大的方向变化,根据误差的大小分别实施较强或一般的控制作用,抑制动态误差。

    直接上代码:(以左电机为例)

    int errorabsmax=400;
    int errorabsmid=200;
    int errorabsmin=10;
    int maximum=10000;      //手工设定的开环输出最大值
    int minimum=0;      //手工设定的开环输出最小值
    int L_sumerror_coder=0;
    int L_derror_coder = 0;
    int L_dderror_coder = 0;
    int L_error1_coder = 0;
    int L_error2_coder = 0;
    int L_error3_coder = 0;
    int R_sumerror_coder=0;
    int R_derror_coder = 0;
    int R_dderror_coder =0;
    int R_error1_coder = 0;
    int R_error2_coder = 0;
    int R_error3_coder = 0;
    /**********Av为增益:Av>1************/
    /**********Dv为衰减:0<Dv<1 ************/
    float KP = 50;     //60
    float KI=0.55;        //2
    float KD = 5.3;      //5
    float K_kp_Av_rule2=1.5;
    float K_kp_Dv_rule2=0.4;
    float K_kp_Av_rule4=2;
    float K_kp_Dv_rule4=0.6;
    float K_kp_Dv_rule5=0.5;
    float K_ki_Dv_rule5=0.3;
    int L_LocPIDcalc_coder(int setpoint,int nextpoint)
    {
        int result=0;
    	L_error1_coder=setpoint-nextpoint; 
        L_derror_coder=L_error1_coder-L_error2_coder;
        L_dderror_coder=L_error2_coder-L_error3_coder;    
        if(abs(L_error1_coder)>=errorabsmax)
        {
            /*执行规则1*/
            if(L_error1_coder>0)
            {
                result=maximum;
            }
            if(L_error1_coder<0)
            {
                result=minimum;
            }
        }
     
        else if((L_error1_coder*L_derror_coder>0)||(L_derror_coder==0))
        {
            /*执行规则2*/
            if(abs(L_error1_coder)>=errorabsmid)
            {
                result=result+K_kp_Av_rule2*(KP*L_derror_coder+KI*L_error1_coder+KD*(L_derror_coder-L_dderror_coder));
            }
            else
            {
                result=result+K_kp_Dv_rule2*(KP*L_derror_coder+KI*L_error1_coder+KD*(L_derror_coder-L_dderror_coder));
            }
        }
     
        else if(((L_error1_coder*L_derror_coder<0)&&(L_derror_coder*L_dderror_coder>0))||(L_error1_coder==0))
        {
            /*执行规则3*/
            result=result;
        }
        else if((L_error1_coder*L_derror_coder<0)&&(L_derror_coder*L_dderror_coder<0))
        {
            /*执行规则4*/
            if(abs(L_error1_coder)>=errorabsmid)
            {
                result=result+K_kp_Av_rule4*KP*L_error1_coder;
            }
            else
            {
                result=result+K_kp_Dv_rule4*KP*L_error1_coder;
            }
        }
        else if((abs(L_error1_coder)<=errorabsmin)&&(abs(L_error1_coder)>0))
        {
            /*执行规则5*/
            result=result+K_kp_Dv_rule5*KP*L_derror_coder+K_ki_Dv_rule5*KI*L_error1_coder;
        } 
        /*对输出限值,避免超调*/
        if(result>=10000)
        {
            result=10000;
        }
        if(result<=-10000)
        {
            result=-10000;
        }    
        L_error3_coder =L_error2_coder;
        L_error2_coder =L_error1_coder;
        return result;
    }
    

    总结

    感觉模糊PID最难调试,变结构和专家pid次之,微分先行还没开始调(以前调的是错误公式,感觉效果其实还行)。普通pid调试其实也是很复杂。
    最后为了节省调试时间,觉得还是电机以微分先行、变结构来调,舵机以模糊pid来调,模糊输出范围限制小一点,效果其实还行。
    专家pid好久都没试过,记录的参数也是我一开始调试的,以后不想尝试专家pid了。

    展开全文
  • 专家PID与模糊PID(第3章专家P控制和模糊PⅠD控制)
  • 专家PID控制Matlab仿真

    2021-01-22 13:11:52
    专家PID控制 一、简介 专家PID控制,专家PID控制不同于常规意义下的PID控制,是专家经验与PID控制算法的结合,是基于PID控制器的智能化优化。 专家PID控制就是基于被控对象和控制规律的各种知识,而不需要知道被...
  • 压电陶瓷作为驱动器应用于弹头偏转是一种新型技术,但是压电陶瓷具有迟滞性和蠕变性,导致输出达不到理想结果,本文针对如何提高压电弹药精度,提出专家PID控制算法弥补压电陶瓷驱动器迟滞性和蠕变性,利用单片机...
  • PID控制器开发笔记之十一:专家PID控制器的实现

    万次阅读 多人点赞 2018-09-09 21:30:49
    前面我们讨论了经典的数字PID控制算法及其常见的改进与补偿算法,基本已经覆盖了无模型和简单模型PID控制经典算法的...正如前面所说,专家PID算法是专家系统与PID算法的结合与应用优化,所以我们接下来先简单了解...
  • 专家PID控制仿真程序

    2013-11-28 20:08:56
    来自与智能卡控制 课本第一章 专家PID控制仿真程序
  • 专家PID控制原理 PID专家控制的实质是,基于受控对象和控制规律的各种知识,无需知道被控对象的精确模型,利用专家经验来设计PID参数。 专家PID控制是一种直接型专家控制器。 对典型的二阶系统单位阶跃响应过程作...
  • 专家系统PID引入至控制领域后,取得更加的控制性能,专家PID较常规PID控制器控制更加灵活。为了满足控制系统对控制精度的要求,专家系统控制逐渐成为国内外的研究热点。本文研究基于专家系统PID设计电加热炉炉温控制...
  • 基于专家PID调节的变频调速恒压供水系统的研究
  • 专家PID的控制算法-MATLAB实现

    千次阅读 2020-08-07 10:09:20
    专家PID的控制算法-MATLAB实现 PID控制,实际应用中多是PI控制和PD控制,就是根据系统的误差,利用比例,积分和微分计算出控制量进行控制的。PID专家控制的实质,是基于受控对象和控制规律的各种知识,利用专家经验...
  • 为解决长距离带式输送机液压自动张紧系统的压力调节不连续不平稳的问题,在常规PID控制算法的基础上,针对具有时变、大滞后及非线性的系统,根据操作人员及专家的实际经验,提出专家PID控制策略。以带式输送机张紧装置...
  • 基于目前的压力控制和微小体积控制系统不能满足微流控芯片自动化进样的需求,本文提出一种新型的基于专家PID控制和卡尔曼滤波的恒压控制系统,通过精确控制压力实现精确控制进样体积。MATLAB仿真和实际测量表明,该...
  • 本科毕业论文 设计 论文 设计题目 专家PID 控制在快速系统中的仿真及应用 学 院 专 业 班 级 学 号 学生姓名 指导教师 2010 年 06 月 07 日 贵州大学本科毕业论文 设计 诚信责任书 本人郑重声明本人所呈交的毕业论文...
  • 专家PID控制在逆变电源中的应用,是一篇应用类的文章!可能会对大家有帮助!
  • 基于专家PID控制和COM技术的计算机分布式温压测控系统
  • Pid控制算法-专家PID与模糊PID的C++实现

    万次阅读 多人点赞 2017-04-10 17:02:17
    本节是PID控制算法的C++语言实现系列的最后一节,前面7节中,已经分别从PID的实现到深入的过程进行了一个简要的讲解,从前面的讲解中不难看出,PID的控制思想非常简单,其主要问题点和难点在于比例、积分、微分环节...
  • :介绍了一种将专家控制与常规PID控制相结合的专家PID控制算法,并以油田三相分离器的油水分 离液位控制系统为例,阐述了该算法在SIEMENS PLC中的应用。实践证明,该控制方法简单易行,动态响应快,系 统控制效果好...
  • 倒立摆稳定的PID控制 自营模糊补偿的倒立摆PD控制 模糊自适应控制
  • 本节是PID控制算法的C语言实现系列的最后一节,前面8节中,已经分别从PID的实现到深入的过程进行了一个简要的讲解,从前面的讲解中不难看出,PID的控制思想非常简单,其主要问题点和难点在于比例、积分、微分环节上...

空空如也

空空如也

1 2 3 4 5 ... 12
收藏数 224
精华内容 89
关键字:

专家pid