tag 标签: PID算法

相关帖子
相关博文
  • 热度 1
    2015-4-3 22:15
    345 次阅读|
    0 个评论
    #include stdio.h #includemath.h struct _pid { int pv; //integer that contains the process value 过程量 int sp; //*integer that contains the set point   设定值 float integral; // 积分值 -- 偏差累计值 float pgain; float igain; float dgain; int deadband;    //死区 int last_error; }; struct _pid warm,*pid; int process_point, set_point,dead_band; float p_gain, i_gain, d_gain, integral_val,new_integ;; //---------------------------------------------- pid_init DESCRIPTION This function initializes the pointers in the _pid structure to the process variable and the setpoint . *pv and *sp are integer pointers . //---------------------------------------------- void pid_init(struct _pid *warm, int process_point, int set_point) { struct _pid *pid; pid = warm; pid-pv = process_point; pid-sp = set_point; } //----------------------------------------------pid_tune DESCRIPTION Sets the proportional gain (p_gain), integral gain (i_gain), derivitive gain (d_gain), and the dead band (dead_band) of a pid control structure _pid.  设定PID参数 ---- P,I,D,死区 //---------------------------------------------- void pid_tune(struct _pid *pid, float p_gain, float i_gain, float d_gain, int dead_band) { pid-pgain = p_gain; pid-igain = i_gain; pid-dgain = d_gain; pid-deadband = dead_band; pid-integral= integral_val; pid-last_error=0; } //---------------------------------------------- pid_setinteg DESCRIPTION Set a new value for the integral term of the pid equation. This is useful for setting the initial output of the pid controller at start up. 设定输出初始值 //---------------------------------------------- void pid_setinteg(struct _pid *pid,float new_integ) { pid-integral = new_integ; pid-last_error = 0; } //---------------------------------------------- pid_bumpless DESCRIPTION Bumpless transfer algorithim. When suddenly changing setpoints, or when restarting the PID equation after an extended pause, the derivative of the equation can cause a bump in the controller output. This function will help smooth out that bump. The process value in *pv should be the updated just before this function is used. pid_bumpless 实现无扰切换 当突然改变设定值时,或重新启动后,将引起扰动输出。这个函数将能实现平顺扰动,在调用该函数之前需要先更新PV值 //---------------------------------------------- void pid_bumpless(struct _pid *pid) { pid-last_error = (pid-sp)-(pid-pv);  //设定值与反馈值偏差 } //---------------------------------------------- pid_calc DESCRIPTION Performs PID calculations for the _pid structure *a. This function uses the positional form of the pid equation, and incorporates an integral windup prevention algorithim. Rectangular integration is used, so this function must be repeated on a consistent time basis for accurate control. RETURN VALUE The new output value for the pid loop. USAGE #include "control.h" 本函数使用位置式PID计算方式,并且采取了积分饱和限制运算 PID计算 //---------------------------------------------- float pid_calc(struct _pid *pid) { int err; float pterm, dterm, result, ferror; // 计算偏差 err = (pid-sp) - (pid-pv); // 判断是否大于死区 if (abs(err) pid-deadband) { ferror = (float) err;   //do integer to float conversion only once 数据类型转换 // 比例项 pterm = pid-pgain * ferror; if (pterm 100 || pterm -100) { pid-integral = 0.0; } else { // 积分项 pid-integral += pid-igain * ferror; // 输出为0--100% // 如果计算结果大于100,则等于100 if (pid-integral 100.0) { pid-integral = 100.0; } // 如果计算结果小于0.0,则等于0 else if (pid-integral 0.0) pid-integral = 0.0; } // 微分项 dterm = ((float)(err - pid-last_error)) * pid-dgain; result = pterm + pid-integral + dterm; } else result = pid-integral; // 在死区范围内,保持现有输出 // 保存上次偏差 pid-last_error = err; // 输出PID值(0-100) return (result); }   //---------------------------------------------- void main(void) { float display_value; int count=0; pid = warm; // printf("Enter the values of Process point, Set point, P gain, I gain, D gain n"); // scanf("%d%d%f%f%f", process_point, set_point, p_gain, i_gain, d_gain); // 初始化参数 process_point = 30; set_point = 40; p_gain = (float)(5.2); i_gain = (float)(0.77); d_gain = (float)(0.18); dead_band = 2; integral_val =(float)(0.01); printf("The values of Process point, Set point, P gain, I gain, D gain n"); printf(" %6d %6d %4f %4f %4fn", process_point, set_point, p_gain, i_gain, d_gain); printf("Enter the values of Process pointn"); while(count=20) { scanf("%d",process_point); // 设定PV,SP值 pid_init(warm, process_point, set_point); // 初始化PID参数值 pid_tune(warm, p_gain,i_gain,d_gain,dead_band); // 初始化PID输出值 pid_setinteg(warm,0.0); //pid_setinteg(warm,30.0); //Get input value for process point pid_bumpless(warm); // how to display output display_value = pid_calc(warm); printf("%fn", display_value); //printf("n%f%f%f%f",warm.pv,warm.sp,warm.igain,warm.dgain); count++; } }
  • 热度 2
    2015-4-3 22:09
    580 次阅读|
    1 个评论
    ==================================================*/   #include string.h #include stdio.h /*================================================= PID Function The PID function is used in mainly control applications. PID Calc performs one iteration of the PID algorithm. While the PID function works, main is just a dummy program showing a typical usage.   PID功能 在PID功能主要用于控制应用。 PID 计算器执行一个PID的迭代算法。虽然PID功能的工程, 主要只是一个虚拟程序显示一个典型的使用。 ==================================================*/ typedef struct PID { double SetPoint; // 设定目标 Desired Value double Proportion; // 比例常数 Proportional Const double Integral; // 积分常数 Integral Const double Derivative; // 微分常数 Derivative Const double LastError; // Error double PrevError; // Error double SumError; // Sums of Errors } PID;     /*====================== PID计算部分===================*/ double PIDCalc( PID *pp, double NextPoint ) { double dError, Error;   Error = pp-SetPoint - NextPoint; // 偏差 pp-SumError += Error; // 积分 dError = pp-LastError - pp-PrevError; // 当前微分 pp-PrevError = pp-LastError; pp-LastError = Error; return (pp-Proportion * Error // 比例项 + pp-Integral * pp-SumError // 积分项 + pp-Derivative * dError // 微分项 ); }   /*========== 初始化的PID结构 Initialize PID Structure==========*/ void PIDInit (PID *pp) { memset ( pp,0,sizeof(PID)); }     /*============= 主程序 Main Program==================*/ double sensor (void) // 虚拟传感器功能 Dummy Sensor Function{ return 100.0;} void actuator(double rDelta) // 虚拟驱动器功能 Dummy Actuator Function{} void main(void) { PID sPID; // PID控制结构 PID Control Structure double rOut; // PID响应(输出) PID Response (Output) double rIn; // PID反馈(输入) PID Feedback (Input) PIDInit ( sPID ); // 初始化结构 Initialize Structure sPID.Proportion = 0.5; // 设置PID系数 Set PID Coefficients sPID.Integral = 0.5; sPID.Derivative = 0.0; sPID.SetPoint = 100.0; // 设置PID设定 Set PID Setpoint for (;;) { // 模拟最多的PID处理 Mock Up of PID Processing rIn = sensor (); // 读取输入 Read Input rOut = PIDCalc ( sPID,rIn ); // 执行的PID迭代 Perform PID Interation actuator ( rOut ); // 所需的更改的影响 Effect Needed Changes }
  • 热度 2
    2015-3-24 11:48
    551 次阅读|
    0 个评论
    1.引言 在许多现代化的工业生产如冶金、电力等,实现对温度的精度控制至关重要的,不仅直接影响着产品的质量,而且还关系到生产安全、能源节约等一系列重大经济指标。 PID控制由于其鲁棒性好,可靠性高,在常规的温度控制中应用非常广泛。目前工程的实际应用中,大多数模糊PID控制器都利用单片机软件编程来实现,然而单片机的指令是按顺序执行的,实时性不强,加上软件实现容易受外界的干扰,抗干扰性能力差,对于实时性要求很高和外界干扰比较严重的系统不太适宜。本文选取FPGA(现场可编程门阵列)作为系统的主控制芯片,FPGA所有的信号都是时钟驱动的,对于程序的执行具有并行运算的能力,显著的提高了系统控制的实时性,在FPGA内部硬件实现还可以防止像单片机程序一样,在恶劣的环境条件下发生程序跑飞的问题。尤其是现在FPGA器件有越来越多的参考设计方案以及IP(知识产权)核心库方面的支持。利用FPGA设计的PID控制器一方面可以将实现PID算法的模块单独作为控制模块来使用,直接去实现对控制对象的调节,另一方面,基于FPGA的PID控制算法也可以将其作为系统内的IP核,以便在多路或复杂的系统上直接调用,加快研发设计速度。 2.PID算法分析 2.1 离散PID算法 PID控制系统是一个简单的闭环系统,如图1所示,PID系统框图中,整个系统主要包括比较器、PID控制器和控制对象,其中PID包括三个环节,即比例、积分和微分。 图1 PID系统框图 图1中的r(t)作为系统的给定值,y(t)作为系统的输出值,e(t)是给定值与输出值的偏差,所以系统的偏差可以求得: e(t)=r(t)-y(t) (1) u(t)作为控制系统中的中间便量,既是偏差e(t)通过PID控制算法处理后的输出量,又是被控对象的输入量,因此模拟PID控制器的控制规律为: 其中,K P 为模拟控制器的比例增益,T I 为模拟控制器的积分时间常数,T D 为模拟控制器的微分时间常数。 2.2 离散PID算法 为了用微处理器实现PID算法,我们需要将模拟PID离散化,根据采样时刻的偏差来实现PID算法,因此式(3.2)中的微分和积分项两项内容作离散化处理。 假设T为采样周期,则积分项可作如下变换: 采样周期的时间非常短,故微分可以近似的表示为: 将式(3)和式(4)带入式(2)后,可得到离散PID算法为(限于篇幅,推导过程省略): 这个等式被叫做增量式PID控制算法。其中,乘积因子由PID控制参数K P 、K I 、K D 确定: 3.PID算法的FPGA实现 由公式(5)知,增量式PID控制算法的具体实现步骤为:先通过误差计算模块求出偏差值e(k)、e(k-1)、e(k-2),再通过乘积模块求出三个信号分别与乘积因子的相乘,最后对乘积项求和得到最后的控制量。图2所示为增量式PID算法结构图。 3.1 误差计算模块 误差计算模块的目的是为了求出三次相邻的偏差采样值,即公式(3.8)中提到的e(k)、e(k-1)、e(k-2),输入的给定值r(t)与实际输出值y(t)相减得到误差值。Verilog HDL程序代码如下,其中,ek0、ek1、ek2、rt、yt分别对应偏差值e(k)、e(k-1)、e(k-2)、r(t)、y(t)。 将上述程序在Quartus II软件环境里完成编译后,其仿真结果如图3所示。 图2 增量式PID算法结构图 图3 误差模块仿真图 3.2 乘积和求和模块 通过误差计算模块求出e(k)、e(k-1)、e(k-2)后,由公式(5)知,要计算出控制量还必须将其分别与乘积因子做乘法运算,通过硬件描述语言来实现乘法运算的功能: 按照上述程序,在Quartus II完成编译后,其仿真结果如图4所示。 图4 乘法器仿真图 现在可计算出α 0 e(k)、α 1 e(k-1)、α 2 e(k-2)三个乘积项的计算结果,将上面三个乘积项求和就可以得出控制量△u(k)。程序代码如下所示,其中输入val0 、val1 、val2 分别对应α 0 e(k)、α 1 e(k-1) 、α 2 e(k-2)乘积的结果,输出val 就是控制量△u(k)的值。 按照上述程序,在Quartus II完成编译后,其仿真结果如图5所示。 图5 PID求和模块仿真波形图 3.3 温度检测及输出控制电路设计 本文用到的温度测量器件是K型热电偶,温度测量范围为0~1200℃。热电偶输出的是模拟电压信号,必须进行A/D转换,同时还需对热电偶进行冷端补偿和非线形校正。为了解决上面的问题,本文采用的是K型热电偶专用数字转换器MAX6675芯片,MAX6675芯片内部集成了热电偶放大器,内置高达12位的模数转换器。还包括了非线性矫正、冷端补偿、断线检测等功能模块。MAX6675的工作温度范围为-20~85℃,温度的测量范围为0~1024℃,温度分辨率可以达到0.25℃。假设D为A/D转换后得到的数字量对应的十进制数值,那么测量温度值T可以通过如下公式算出: 输出控制电路采用的是PWM(脉宽调制)方式,实现对电阻炉的温度控制。光耦芯片选用MOC3061,用于对强弱电路的隔离,双向导通可控硅选用的是BT137_600E。如果占空比越高,那么相对可控硅导通的时间也就越长,电阻炉加热温度也就越高,反之温度也就会慢慢散热降低,从而达到控制炉温的目的。 4.结语 本文分析了PID算法,给出了在FPGA内部硬件实现增量式PID控制的主要设计思路。在电阻炉为控制对象的温控系统中,系统工作稳定,在整个过程没有出现震荡和较大波动,并且温度控制精度在始终保持在5%以内;系统的抗干扰能力增强,对现场的各种噪声和干扰具有较好的抑制作用。
  • 热度 2
    2014-7-10 22:01
    378 次阅读|
    0 个评论
    1.引言 在许多现代化的工业生产如冶金、电力等,实现对温度的精度控制至关重要的,不仅直接影响着产品的质量,而且还关系到生产安全、能源节约等一系列重大经济指标。 PID控制由于其鲁棒性好,可靠性高,在常规的温度控制中应用非常广泛。目前工程的实际应用中,大多数模糊PID控制器都利用单片机软件编程来实现,然而单片机的指令是按顺序执行的,实时性不强,加上软件实现容易受外界的干扰,抗干扰性能力差,对于实时性要求很高和外界干扰比较严重的系统不太适宜。本文选取FPGA(现场可编程门阵列)作为系统的主控制芯片,FPGA所有的信号都是时钟驱动的,对于程序的执行具有并行运算的能力,显著的提高了系统控制的实时性,在FPGA内部硬件实现还可以防止像单片机程序一样,在恶劣的环境条件下发生程序跑飞的问题。尤其是现在FPGA器件有越来越多的参考设计方案以及IP(知识产权)核心库方面的支持。利用FPGA设计的PID控制器一方面可以将实现PID算法的模块单独作为控制模块来使用,直接去实现对控制对象的调节,另一方面,基于FPGA的PID控制算法也可以将其作为系统内的IP核,以便在多路或复杂的系统上直接调用,加快研发设计速度。 2.PID算法分析 2.1 离散PID算法 PID控制系统是一个简单的闭环系统,如图1所示,PID系统框图中,整个系统主要包括比较器、PID控制器和控制对象,其中PID包括三个环节,即比例、积分和微分。 图1 PID系统框图 图1中的r(t)作为系统的给定值,y(t)作为系统的输出值,e(t)是给定值与输出值的偏差,所以系统的偏差可以求得: e(t)=r(t)-y(t) (1) u(t)作为控制系统中的中间便量,既是偏差e(t)通过PID控制算法处理后的输出量,又是被控对象的输入量,因此模拟PID控制器的控制规律为: 其中,K P 为模拟控制器的比例增益,T I 为模拟控制器的积分时间常数,T D 为模拟控制器的微分时间常数。 2.2 离散PID算法 为了用微处理器实现PID算法,我们需要将模拟PID离散化,根据采样时刻的偏差来实现PID算法,因此式(3.2)中的微分和积分项两项内容作离散化处理。 假设T为采样周期,则积分项可作如下变换: 采样周期的时间非常短,故微分可以近似的表示为: 将式(3)和式(4)带入式(2)后,可得到离散PID算法为(限于篇幅,推导过程省略): 这个等式被叫做增量式PID控制算法。其中,乘积因子由PID控制参数K P 、K I 、K D 确定: 3.PID算法的FPGA实现 由公式(5)知,增量式PID控制算法的具体实现步骤为:先通过误差计算模块求出偏差值e(k)、e(k-1)、e(k-2),再通过乘积模块求出三个信号分别与乘积因子的相乘,最后对乘积项求和得到最后的控制量。图2所示为增量式PID算法结构图。 3.1 误差计算模块 误差计算模块的目的是为了求出三次相邻的偏差采样值,即公式(3.8)中提到的e(k)、e(k-1)、e(k-2),输入的给定值r(t)与实际输出值y(t)相减得到误差值。Verilog HDL程序代码如下,其中,ek0、ek1、ek2、rt、yt分别对应偏差值e(k)、e(k-1)、e(k-2)、r(t)、y(t)。 将上述程序在Quartus II软件环境里完成编译后,其仿真结果如图3所示。 图2 增量式PID算法结构图 图3 误差模块仿真图 3.2 乘积和求和模块 通过误差计算模块求出e(k)、e(k-1)、e(k-2)后,由公式(5)知,要计算出控制量还必须将其分别与乘积因子做乘法运算,通过硬件描述语言来实现乘法运算的功能: 按照上述程序,在Quartus II完成编译后,其仿真结果如图4所示。 图4 乘法器仿真图 现在可计算出α 0 e(k)、α 1 e(k-1)、α 2 e(k-2)三个乘积项的计算结果,将上面三个乘积项求和就可以得出控制量△u(k)。程序代码如下所示,其中输入val0 、val1 、val2 分别对应α 0 e(k)、α 1 e(k-1) 、α 2 e(k-2)乘积的结果,输出val 就是控制量△u(k)的值。 按照上述程序,在Quartus II完成编译后,其仿真结果如图5所示。 图5 PID求和模块仿真波形图 3.3 温度检测及输出控制电路设计 本文用到的温度测量器件是K型热电偶,温度测量范围为0~1200℃。热电偶输出的是模拟电压信号,必须进行A/D转换,同时还需对热电偶进行冷端补偿和非线形校正。为了解决上面的问题,本文采用的是K型热电偶专用数字转换器MAX6675芯片,MAX6675芯片内部集成了热电偶放大器,内置高达12位的模数转换器。还包括了非线性矫正、冷端补偿、断线检测等功能模块。MAX6675的工作温度范围为-20~85℃,温度的测量范围为0~1024℃,温度分辨率可以达到0.25℃。假设D为A/D转换后得到的数字量对应的十进制数值,那么测量温度值T可以通过如下公式算出: 输出控制电路采用的是PWM(脉宽调制)方式,实现对电阻炉的温度控制。光耦芯片选用MOC3061,用于对强弱电路的隔离,双向导通可控硅选用的是BT137_600E。如果占空比越高,那么相对可控硅导通的时间也就越长,电阻炉加热温度也就越高,反之温度也就会慢慢散热降低,从而达到控制炉温的目的。 4.结语 本文分析了PID算法,给出了在FPGA内部硬件实现增量式PID控制的主要设计思路。在电阻炉为控制对象的温控系统中,系统工作稳定,在整个过程没有出现震荡和较大波动,并且温度控制精度在始终保持在5%以内;系统的抗干扰能力增强,对现场的各种噪声和干扰具有较好的抑制作用。
  • 热度 10
    2013-11-4 16:07
    1115 次阅读|
    10 个评论
            前两天网友超发的一个国外工程师怎么精准控制飞机模型而引发的一次讨论,其实对于这个话题,就现在还只是学习了几个月程序,只做过一个测温仪校准测试项目的我来说,还谈不上有很深刻、很直观的体会,只能就我做项目的过程中所感觉到的一点隐隐约约的印象来浅显的谈谈。        因为之前我一直做的是硬件,所以养成了一就是一,二就是二,什么东西都要明明白白的思维方式,这个刚开始阻碍了软件的进度,特别是当做到用PID算法去控制温度的时候,这个过程很曲折。在刚开始做PID控制的时候,凤舞天用很简单的常识跟我解释过PID算法,tomsu也很细心的跟我分析了整个温度控制的流程和算法理论,但是我感觉还是不踏实,感觉完全懂了,但又不是很透彻,这种感觉让我很难受。后来我又在网上找了很多关于PID算法的文章和例程去看,可是越看越是迷糊,因为那些理论差不多都是基于理论的算法,在看的时候感觉明白了,可实际上根本不知道怎么着手去做,这个让我既郁闷,也着急。因为这个问题,项目就卡在这里不能继续进行,而且必须要搞明白了,才能过这个难点,整个项目也只有过了这个难题,才能继续往下做,所以,到最后我选择放弃去看那些高深的算法理论和算法例程(虽然凤舞天一开始也提醒过我不要过多的看那些理论,可是不看这些理论,总是感觉站在门外了解不到精髓,只有走进去再走出来才能够真正的了解),就是按照常识的理解,从基础的常识理论去控制。        就是:P是控制I算法介入的门限,在这之前全速加热,如果当前温度大于目标温度,就减;当前温度小于目标温度就加;在门限以内,比如说当前温度与目标温度相差100度时,就开始降低速度或者提高速度,这个就是I算法;再当温度非常接近目标温度时,比如说在2、3度左右变化了,就控制加速度的变化。结果能够控制了,而且也能够达到预期效果。        后来公司另外一同事要做高频机加热控制程序,在做到PID算法这一难点的时候,也是因为看了过多的理论和过多的算法例程,最后被套进去了,根本就跳不出来,就是满脑子的算法、控制,可是她不管怎么用理论的算法去控制,就达不到想要的效果,最后没办法她只能从东莞调试的工厂回来。在她回来后,我跟她讨论算法问题,她一开口都是那些理论,可实际上她对那些理论又都似懂非懂,完全把握不了,后来我按照我的经验,花了两天时间让她放弃之前的PID理论算法思维,用我理解的方式去控制。最后又花了一天的时间去调试,也能达到预期的效果(要知 道,光这个PID,她用她理解的标准PID算法程序调了两个多星期)。        当然,从这两个例子并不是说用复杂的算法不对,当一个产品要实现一个复杂的功能的时候肯定会需要用到复杂的算法。可是我们还必须明白一点,不管多复杂的算法都必须是基于浑厚的基础理论之上的。当基础理论都还谈不上积累的情况下去追求高深的、复杂的算法,简直是自找死路。       所以,我想在工业控制方面大部分功能需求还是比较简单的,而对于简单的需求,有基础的理论和技术再加上常识就够了。   
相关资源
  • 所需E币: 3
    时间: 2019-6-7 22:23
    大小: 1.06MB
    上传者: royalark_912907664
    水温控制无论是在日常生活还是工业生产中都扮演着重要的角色。本设计是基于STC12C5A60S2的智能型水温控制系统,在硬件上实现键盘输入、温度釆集、AD转换和液晶显示,在软件上采用模糊控制与PID算法相结合构成的模糊PID控制器来对水温进行实时监测和调节。结果显示,采用模糊PID控制策略,改善了系统的动态响应,提高响应速度,能够实现水温的数字式精确调节。
  • 所需E币: 3
    时间: 2019-6-5 22:43
    大小: 1.58MB
    上传者: royalark_912907664
    为实现对帆板角度的精准控制以及实时显示,本文设计了一种抗干扰能力强、能够快速响应的角度自动控制系统。本系统采用STC89C52单片机作为核心控制器,LM7805和LM7812提供+5V和+12V电源,通过按键设置帆板的角度,P3022-V1-CW360角度传感器实时采集角度信息,实时角度和设定角度以及PWM波的占空比由LCD1602进行显示,利用PID反馈调节机制控制单片机输出的PWM波送入L298N电机驱动芯片,通过改变电机的转速改变实时风力,进而改变帆板的角度如果帆板角度超出60度,立刻进行声光报警提示。经实验测试表明,本系统可以完成对帆板角度的快速调节,系统响应时间小于5s,角度相对误差小于10%,整个系统具有良好的稳定性以及快速响应性能,实现了设计要求。
  • 所需E币: 3
    时间: 2019-6-2 19:19
    大小: 1.49MB
    上传者: royalark_912907664
    针对我国北方农村地区煤改电的需求,通过对暖气混水系统的控制技术研究,提出了一种新的暖气混水系统的控制方案,并完成了相关的软硬件及控制算法的设计。控制系统由单片机控制器、温度传感器、编码器、电机驱动模块以及串口通讯模块等模块组成。在暖气混水系统的软件及控制算法上,提出了采用一阶数字滤波及数字式二阶平均滤波算法对数据进行滤波,使用PID控制的方法,通过调节热水阀来调节混水的水温,并且可以将实时温度通过串口通讯返回给上位机。实验结果表明,控制系统能够完成供暖系统温度的稳定控制。
广告