PID算法(c语言)(来自老外).doc
PID算法(c语言)(来自老外)(2010-02-17 00:18:24)转载#include <stdio.h>#include<math.h>/定义PID的结构体struct _pidint 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;/ 输出为0100%/ 如果计算结果大于100,则等于100if (pid->integral > 100.0)pid->integral = 100.0;/ 如果计算结果小于0.0,则等于0else if (pid->integral < 0.0)pid->integral = 0.0;/ 微分项dterm = (float)(err - pid->last_error) * pid->dgain;result = pterm + pid->integral + dterm;elseresult = 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 pointpid_bumpless(&warm);/ how to display outputdisplay_value = pid_calc(&warm);printf("%fn", display_value);/printf("n%f%f%f%f",warm.pv,warm.sp,warm.igain,warm.dgain);count+;增量式PID算法#include<stdio.h> #include<stdlib.h> struct _pid double set; double actual; double err; double err_one; double err_two; double Kp,Ki,Kd; pid; void PID_init() pid.set=0.0; pid.actual=0.0; pid.err=0.0; pid.err_one=0.0; pid.err_two=0.0; pid.Kp=0.2; pid.Ki=0.02; pid.Kd=0.2; double PID_real(double speed) double increment; pid.set=speed; pid.err=pid.set-pid.actual; increment=pid.Kp*(pid.err-pid.err_one)+pid.Ki*pid.err+pid.Kd*(pid.err-2*pid.err_one+pid.err_two); pid.actual+=increment; pid.err_two=pid.err_one; pid.err_one=pid.err; return pid.actual; main() int i; PID_init(); for(i=0;i<1200;i+) double speed=PID_real(100.0); printf("%fn",speed); system("pause");