Matlab PID控制

PID练习 


clc;
clear
N = 100;
x = linspace(-3*pi,3*pi,N);
% 目标值
% target_val = 20*ones(1,N);
target_val = 5*sin(x);
% 当前值
current_val =2;
% PID 临时变量
integral = 0;
last_err = 0;
% PID 增益参数
Kp = 0.2;
Ki = 0.1;
Kd = 0.5;
% 过程输出变量  方便绘图
PID_data = [];
PID_data_noise = [];
% 无噪声 100% 感知 100% 控制 
for i = 1:N
    % 计算偏差 err
    err = target_val(i) - current_val;
    % 对偏差积分
    integral = integral + err;
    % 对偏差微分
    d_err = err - last_err ;
    % PID 比例+积分+微分 = 输出控制量
    u_out = Kp * err + Ki * integral + Kd * d_err;
    % 在控制量u_out的作用下  当前值转移到下一个状态
    current_val = current_val + u_out;
    % 数据保存
    PID_data(i) = current_val;
end
% figure (1)
% plot([target_val' PID_data'])

% 传感器带噪声 measure_noise = rand()  u_noise = rand()
current_val = 0;
for i = 1:N
    err = target_val(i) - current_val;
    % 传感器加噪声measure_noise
    measure_noise = 0.2*rand();
    err = err + measure_noise;
    integral = integral + err;
    d_err = err - last_err ;
    u_out = Kp * err + Ki * integral + Kd * d_err;
    % 控制加噪声 u_noise
    u_noise = 0.5*rand();
    u_out = u_out + u_noise;
    current_val = current_val + u_out;
    PID_data_noise(i) = current_val;
end
% figure (2)
plot([target_val' PID_data' PID_data_noise'])
C语言版本
#include <stdio.h> 
#include<math.h>  
// PID 参数结构体
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 
// PID 结构体参数设置
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. 
------------------------------------------------------------------------*/ 
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 
// pID 结构体积分项增益系数设置函数接口
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. 
------------------------------------------------------------------------*/ 
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"*/ 
 
 
float pid_calc(struct _pid *pid) 
{ 
	 int err; 
	 float pterm; //比例项 
	 float dterm; //微分项
	 float result; // 输出结果
	 float 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; 
			 if (pid->integral > 100.0) 
			 { 
				pid->integral = 100.0; 
			 } 
			 else 
			 {
				if (pid->integral < 0.0) 
				  pid->integral = 0.0; 
			 }
		 } 
		 // 微分项计算
		 dterm = ((float)(err - pid->last_error)) * pid->dgain; 
		 // PID各项 综合
		 result = pterm + pid->integral + dterm; 
	 } 
	 else 
		 result = pid->integral; 
		
	 pid->last_error = err; 
	 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("%lf %lf %lf %lf %lf\n", process_point, set_point, p_gain, i_gain, d_gain); 

	pid_init(&warm, process_point, set_point); 
	pid_tune(&warm, p_gain,i_gain,d_gain,dead_band);
	pid_setinteg(&warm,0.0); //pid_setinteg(&warm,30.0); 

	//Get input value for process point 
	pid_bumpless(&warm);
	count = 0;
	while(count<=20) 
	{ 
	// how to display output 
	pid_init(&warm, display_value, set_point);
	display_value = pid_calc(&warm); 
	printf("%f\n", display_value); 
	//printf("\n%f%f%f%f",warm.pv,warm.sp,warm.igain,warm.dgain); 
	count++ ; 

	} 
 
} 


猜你喜欢

转载自blog.csdn.net/qq_29796781/article/details/80267926
今日推荐