微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 单片机PID算法实现

单片机PID算法实现

时间:12-01 来源:互联网 点击:
在avr单片机上实现的100%通过测试,用单片机调的倒立摆非常稳定.

#include

#include

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;;

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;

}

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;

}

void pid_setinteg(struct _pid *pid,float new_integ)

{

pid->integral = new_integ;

pid->last_error = 0;

}

void pid_bumpless(struct _pid *pid)

{

pid->last_error = (pid->sp)-(pid->pv); //设定值与反馈值偏差

}

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;

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;

result = pterm + pid->integral + dterm;

}

else

result = pid->integral; // 在死区范围内,保持现有输出

// 保存上次偏差

pid->last_error = err;

return (result);

}

//----------------------------------------------

参数说明:

p_gain = (float)(5.2);//比例系数

i_gain = (float)(0.77);//积分系数

d_gain = (float)(0.18);//微分系数

process_point为设定的稳定值

display_value为系统输出值

process_point为传感器传入当前值

函数调用示例:

float display_value;

int count=0;

pid = &warm;

process_point = 30;

set_point = 40;

dead_band = 2;

integral_val =(float)(0.01);

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);

pid_bumpless(&warm);

display_value = pid_calc(&warm);

printf("%f", display_value);

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top