#includeunistd.h
#includestdio.h
int main(int argc,int **argv)
{
int pid=fork();
if(pid==-1)
printf("error");
}
else if(pid==0)
printf("This is the child process!\n");
else
printf("This is the parent process! child process id=%d\n",pid);
return 0;
首先为什么这段代码gcc编译不了,只能用g◆◆编译,gcc编译显示结果如下
Undefined first referenced
symbol in file
其次,g◆◆编译后运行结果如下
This is the child process!
基本流程
积分环节:主要是用来消除 静差 (系统稳定后输出值和设定值之间的差值,积分环节实际上就是偏差累积的过程,把累积的误差加到原来系统上以抵消系统造成的静差)
微分环节:反映了偏差信号的变化规律,根据偏差信号的变化规律来进行超前调节,从而增加系统的快速性
对上述公式进行离散化(采样):两个公式
增量型PID:
通过增量型PID公式可以看出,最终表达结果和最近三次的偏差有关,最终输出结果应该为:
首先定义结构变量体:
然后初始化变量
最后编写控制算法
基本算法,没有考虑死区问题,没有设定上下限
在启动、结束或大幅度增减设定时,短时间内系统输出有很大的偏差,会造成PID运算的积分积累,导致控制量超过执行机构可能允许的最大动作范围对应的极限控制量,从而引起较大的超调,甚至是振荡.
为了克服这个问题,引入积分分离的概念,即当被控量和设定值偏差较大时,取消积分作用;当被控量接近设定值时,引入积分控制,以消除静差,提高精度.
abs :绝对值
令index=0使积分环节失效
积分饱和现象:如果系统存在一个方向的偏差,PID控制器的输出由于积分作用的不断累加而加大,从而导致执行机构达到极限位置.此时计算器输出量超出正常运行范围而进入饱和区,一旦系统出现反向偏差,输出量将逐渐从饱和区退出,进入饱和区越深则退出饱和区时间越长,在这段时间里,执行机构仍然停留在极限位置而不随偏差反向而立即做出相应改变,造成性能恶化.
采用梯形积分能够减小余差,提高精度
改变积分系数,若偏差大,积分作用减弱,系数减小;若偏差小,积分作用增强,系数增大.
变积分PID的基本思想是设法改变积分项的累加速度,使其与偏差大小对应.
使整个系统的稳定速度非常快
比例系数Kp的作用是加快系统的响应速度提高系统的调节精度
积分系数Ki的作用是消除系统的稳态误差
微分系数Kd的作用是改善系统的动态特性
反应系统性能的两个参数是系统误差和误差变化律
#include intrins.h
#include"pid.h"
/*********************************函数声明******************
结构体设定
***********************************************************/
typedef struct PIDValue
}PIDValueStr;
PIDValueStr PID; //定义一个结P构体
/***********************************************************************************
函数入口: RK(设定值),CK(实际值),KP,KI,KD PID比例参数
函数出口: U(K)
PID运算函数
**************************************************************************************/
Temp[0] = 0; //给储存中间临时变量赋初值
Temp[1] = 0;
PostSum = 0; //给存储所有的正数变量赋初值
NegSum = 0; //给存储所有的负值变量赋初值
{ //如果偏差大于 piancha=10 不在设定的PID调控范围之内就全速加热
out = 100; //偏差大于piancha=10为上限幅值输出(全速加热)
else //如果偏差小于 piancha=10 再调节的范围内就计算储存起来
{ //下面就是PID算法
//数值移位
/****************************************************************************************/
else //E(k)E(k-1)
/*****************************************************************************************/
/**********************************************************************************************/
/************************以下部分代码是讲所有的正数项叠加,负数项叠加**************************/
/**************************************KP*[E(k)-E(k-1)]********************************************/
PostSum ◆= Temp[0]; //正数和
NegSum ◆= Temp[0]; //负数和
/*************************************** KI*E(k)*************************************************/
PostSum ◆= Temp[1]; //正数和
; //空操作,E(K)0
/**********************************************U(K)*************************************************/
if(PostSum NegSum ) // 是否控制量为正数
out= PostSum - NegSum;
PID.Vaule_Flag=0; //PID调节值是正值
else //控制量输出为负数
out=NegSum-PostSum;
PID.Vaule_Flag=1; //PID调节值是负值
//return out;
else //如果设定值小于实际值,就是当前的值大于设定值,就不进行PID计算直接输出 0
out = 0;
return out;
这个问题属于PID的自整定,有简单的继电器算法,我试过,效果不理想.
说了半天,我也没找到很好用的自整定程序,呵呵.
如果你找到好用的,希望能够分享一下哦.
#includeintrins.h
#includemath.h
#includestring.h
struct PID {
unsigned int SetPoint; // 设定目标 Desired Value
unsigned int Proportion; // 比例常数 Proportional Const
unsigned int Integral; // 积分常数 Integral Const
unsigned int Derivative; // 微分常数 Derivative Const
unsigned int LastError; // Error[-1]
unsigned int SumError; // Sums of Errors
};
struct PID spid; // PID Control Structure
unsigned int rout; // PID Response (Output)
unsigned int rin; // PID Feedback (Input)
sbit data1=P1^0;
sbit clk=P1^1;
unsigned char flag,flag_1=0;
unsigned char high_time,low_time,count=0;//占空比调节参数
unsigned char temper;
unsigned char i;
unsigned char j=0;
unsigned int s;
/***********************************************************
void delay(unsigned char time)
unsigned char m,n;
for(n=0;ntime;n◆◆)
写一位数据子程序
void write_bit(unsigned char bitval)
EA=0;
DQ=0; /*拉低DQ以开始一个写时序*/
if(bitval==1)
_nop_();
DQ=1; /*如要写1,则将总线置高*/
DQ=1; /*释放DQ总线*/
EA=1;
写一字节数据子程序
void write_byte(unsigned char val)
unsigned char temp;
EA=0; /*关中断*/
TR0=0;
temp=vali; /*移位操作,将本次要写的位移到最低位*/
temp=temp1;
write_bit(temp); /*向总线写该位*/
// TR0=1;
EA=1; /*开中断*/
读一位数据子程序
unsigned char read_bit()
unsigned char i,value_bit;
DQ=0; /*拉低DQ,开始读时序*/
DQ=1; /*释放总线*/
value_bit=DQ;
return(value_bit);
读一字节数据子程序
unsigned char read_byte()
unsigned char i,value=0;
if(read_bit()) /*读一字节数据,一个时序中读一次,并作移位处理*/
value|=0x01i;
return(value);
复位子程序
unsigned char reset()
unsigned char presence;
DQ=0; /*拉低DQ总线开始复位*/
presence=DQ; /*获取应答信号*/
return(presence); /*返回应答信号,有芯片应答返回0,无芯片则返回1*/
获取温度子程序
void get_temper()
unsigned char i,j;
do
i=reset(); /*复位*/
}while(i!=0); /*1为无反馈信号*/
i=0xcc; /*发送设备定位命令*/
write_byte(i);
}while(i!=0);
i=0xcc; /*设备定位*/
i=0xbe; /*读出缓冲区内容*/
j=read_byte();
i=read_byte();
s=(unsigned int)(j0x0f);
temper=i|j; /*获取的温度放在temper中*/
/*====================================================================================================
Initialize PID Structure
=====================================================================================================*/
void PIDInit (struct PID *pp)
memset ( pp,0,sizeof(struct PID));
PID计算部分
unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint )
unsigned int 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); // 微分项
温度比较处理子程序
compare_temper()
if(set_tempertemper)
if(set_temper-temper1)
high_time=100;
low_time=0;
for(i=0;i10;i◆◆)
{ get_temper();
rin = s; // Read Input
rout = PIDCalc ( spid,rin ); // Perform PID Interation
if (high_time=100)
low_time= (100-high_time);
else if(set_temper=temper)
if(temper-set_temper0)
high_time=0;
low_time=100;
if (high_time100)
high_time=(unsigned char)(rout/10000);
// else
// {}
/*****************************************************
******************************************************/
void serve_T0() interrupt 1 using 1
if(◆◆count=(high_time))
output=1;
else if(count=100)
output=0;
count=0;
TL0=0xe0;
串行口中断服务程序,用于上位机通讯
/* EA=0;
RI=0;
i=SBUF;
while(RI==0){}
set_temper=SBUF;
while(TI==0){}
TI=0;
SBUF=temper;
EA=1; */
unsigned char n,a,m;
// k=disp_num1[n];
clk=0;
m=(disp_num1[n]1);
disp_num1[n]=disp_num1[n]1;
if(m==1)
data1=1;
data1=0;
clk=1;
显示子程序
功能:将占空比温度转化为单个字符,显示占空比和测得到的温度
unsigned int k,k1;
k=high_time;
k=k00;
k1=k/100;
if(k1==0)
disp_num[0]=0;
k=k0;
disp_num[1]=number[k/10];
k=temper;
disp_1(disp_num);
主程序
main()
unsigned char z;
PCON=0x00;
TH1=0xfd;
TL1=0xfd;
PS=1;
EX1=0;
ET0=1;
ES=1;
TR0=1;
TR1=1;
PIDInit ( spid ); // Initialize Structure
spid.Proportion = 10; // Set PID Coefficients
spid.SetPoint = 100; // Set PID Setpoint
while(1)
if(plus==0)
set_temper◆◆;
flag=0;
else if(subs==0)
if(subs==0)
set_temper--;
else if(stop==0)
if(stop==0)
break;
get_temper();
b=temper;
a=b;
temper=a;
temper=b;
a=temper;
count1=0;
compare_temper();
z=1;
disp_1(phil);
// break;
typedef unsigned char byte;
typedef unsigned int word;
//延时
void delay(word useconds)
for(;useconds0;useconds--);
//复位
byte ow_reset(void)
byte presence;
DQ=0; //DQ低电平
DQ=1; //DQ高电平
presence=DQ; //presence信号
return(presence);
} //0允许,1禁止
//从1-wire 总线上读取一个字节
byte read_byte(viod)
byte i;
byte value=0;
value=1;
DQ=0;
DQ=1;
delay(1);
//向1-wire总线上写一个字节
void write_byte(char val)
byte i;
DQ=val0x01;
//读取温度
char Read_Temperature(void)
union{
int x;
}temp;
ow_reset();
write_byte(0xcc);
write_byte(0xBE);
temp.c[1]=read_byte();
temp.c[0]=read_byte();
write_byte(0xCC);
增量式PID:
typedef?struct{?
float?scope;??//输出限幅量?
float?aim;??//目标输出量?
float?real_out;??//实际输出量?
float?Kp;??
float?Ki;??
float?Kd;??
float?e0;??//当前误差?
float?e1;??//上一次误差?
}PID_Type;?
#define?min(a,?b)???(ab?a:b)?
#define?max(a,?b)???(ab?a:b)?
#define?limiter(x,?a,?b)?(min(max(x,?a),?b))?
#define?exchange(a,?b,?tmp)?(tmp=a,?a=b,?b=tmp)?
#define?myabs(x)??((x0)?-x:x)?
float?pid_acc(PID_Type?*pid)?
{?
float?out;?
float?ep,?ei,?ed;?
pid-e0?=?pid-aim?-?pid-real_out;?
ep?=?pid-e0?-?pid-e1;?
ei?=?pid-e0;?
out?=?pid-Kp*ep?◆?pid-Ki*ei?◆?pid-Kd*ed;?
out?=?limiter(out,?-pid-scope,?pid-scope);?
pid-e1?=?pid-e0;?
return?out;?
位置式PID:
float?scope;?//输出限幅量?
float?aim;?//目标输出量?
float?real_out;?//反馈输出量?
float?Ki;?
float?Kd;?
float?Sum;?
float?pid_pos(PID_Type?*p)?
float?pe,?ie,?de;?
float?out?=?0;?
p-e0?=?p-aim?-?p-real_out;?//计算当前误差?
p-Sum?◆=?p-e0;??//误差积分?
de?=?p-e0?-?p-e1;??//误差微分?
pe?=?p-e0;?
ie?=?p-Sum;?
p-e1?=?p-e0;?
out?=?pe*(p-Kp)?◆?ie*(p-Ki)?◆?de*(p-Kd);?
out?=?limiter(out,?-p-scope,?p-scope);??//输出限幅
以上就是土嘎嘎小编为大家整理的c语言pid函数相关主题介绍,如果您觉得小编更新的文章只要能对粉丝们有用,就是我们最大的鼓励和动力,不要忘记讲本站分享给您身边的朋友哦!!