pid控制算法的c语言实现(pid控制c代码实现)

今天给各位分享pid控制算法的c语言实现的知识,其中也会对pid控制c代码实现进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

1、温度控制的PID算法的C语言程序2、pid控制的C语言编程3、PID算法的C语言实现4、C语言编程,怎么计算PID控制

温度控制的PID算法的C语言程序

//PID算法温控C语言2008-08-17 18:58

#includereg51.h

#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 PrevError; // Error[-2]

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;

sbit plus=P2^0;

sbit subs=P2^1;

sbit stop=P2^2;

sbit output=P3^4;

sbit DQ=P3^3;

unsigned char flag,flag_1=0;

unsigned char high_time,low_time,count=0;//占空比调节参数

unsigned char set_temper=35;

unsigned char temper;

unsigned char i;

unsigned char j=0;

unsigned int s;

/***********************************************************

延时子程序,延时时间以12M晶振为准,延时时间为30us×time

***********************************************************/

void delay(unsigned char time)

{

unsigned char m,n;

for(n=0;ntime;n++)

for(m=0;m2;m++){}

}

/***********************************************************

写一位数据子程序

***********************************************************/

void write_bit(unsigned char bitval)

{

EA=0;

DQ=0; /*拉低DQ以开始一个写时序*/

if(bitval==1)

{

_nop_();

DQ=1; /*如要写1,则将总线置高*/

}

delay(5); /*延时90us供DA18B20采样*/

DQ=1; /*释放DQ总线*/

_nop_();

_nop_();

EA=1;

}

/***********************************************************

写一字节数据子程序

***********************************************************/

void write_byte(unsigned char val)

{

unsigned char i;

unsigned char temp;

EA=0; /*关中断*/

TR0=0;

for(i=0;i8;i++) /*写一字节数据,一次写一位*/

{

temp=vali; /*移位操作,将本次要写的位移到最低位*/

temp=temp1;

write_bit(temp); /*向总线写该位*/

}

delay(7); /*延时120us后*/

// TR0=1;

EA=1; /*开中断*/

}

/***********************************************************

读一位数据子程序

***********************************************************/

unsigned char read_bit()

{

unsigned char i,value_bit;

EA=0;

DQ=0; /*拉低DQ,开始读时序*/

_nop_();

_nop_();

DQ=1; /*释放总线*/

for(i=0;i2;i++){}

value_bit=DQ;

EA=1;

return(value_bit);

}

/***********************************************************

读一字节数据子程序

***********************************************************/

unsigned char read_byte()

{

unsigned char i,value=0;

EA=0;

for(i=0;i8;i++)

{

if(read_bit()) /*读一字节数据,一个时序中读一次,并作移位处理*/

value|=0x01i;

delay(4); /*延时80us以完成此次都时序,之后再读下一数据*/

}

EA=1;

return(value);

}

/***********************************************************

复位子程序

***********************************************************/

unsigned char reset()

{

unsigned char presence;

EA=0;

DQ=0; /*拉低DQ总线开始复位*/

delay(30); /*保持低电平480us*/

DQ=1; /*释放总线*/

delay(3);

presence=DQ; /*获取应答信号*/

delay(28); /*延时以完成整个时序*/

EA=1;

return(presence); /*返回应答信号,有芯片应答返回0,无芯片则返回1*/

}

/***********************************************************

获取温度子程序

***********************************************************/

void get_temper()

{

unsigned char i,j;

do

{

i=reset(); /*复位*/

}while(i!=0); /*1为无反馈信号*/

i=0xcc; /*发送设备定位命令*/

write_byte(i);

i=0x44; /*发送开始转换命令*/

write_byte(i);

delay(180); /*延时*/

do

{

i=reset(); /*复位*/

}while(i!=0);

i=0xcc; /*设备定位*/

write_byte(i);

i=0xbe; /*读出缓冲区内容*/

write_byte(i);

j=read_byte();

i=read_byte();

i=(i4)0x7f;

s=(unsigned int)(j0x0f);

s=(s*100)/16;

j=j4;

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

{

unsigned char i;

if(set_tempertemper)

{

if(set_temper-temper1)

{

high_time=100;

low_time=0;

}

else

{

for(i=0;i10;i++)

{ get_temper();

rin = s; // Read Input

rout = PIDCalc ( spid,rin ); // Perform PID Interation

}

if (high_time=100)

high_time=(unsigned char)(rout/800);

else

high_time=100;

low_time= (100-high_time);

}

}

else if(set_temper=temper)

{

if(temper-set_temper0)

{

high_time=0;

low_time=100;

}

else

{

for(i=0;i10;i++)

{ get_temper();

rin = s; // Read Input

rout = PIDCalc ( spid,rin ); // Perform PID Interation

}

if (high_time100)

high_time=(unsigned char)(rout/10000);

else

high_time=0;

low_time= (100-high_time);

}

}

// else

// {}

}

/*****************************************************

T0中断服务子程序,用于控制电平的翻转 ,40us*100=4ms周期

******************************************************/

void serve_T0() interrupt 1 using 1

{

if(++count=(high_time))

output=1;

else if(count=100)

{

output=0;

}

else

count=0;

TH0=0x2f;

TL0=0xe0;

}

/*****************************************************

串行口中断服务程序,用于上位机通讯

******************************************************/

void serve_sio() interrupt 4 using 2

{

/* EA=0;

RI=0;

i=SBUF;

if(i==2)

{

while(RI==0){}

RI=0;

set_temper=SBUF;

SBUF=0x02;

while(TI==0){}

TI=0;

}

else if(i==3)

{

TI=0;

SBUF=temper;

while(TI==0){}

TI=0;

}

EA=1; */

}

void disp_1(unsigned char disp_num1[6])

{

unsigned char n,a,m;

for(n=0;n6;n++)

{

// k=disp_num1[n];

for(a=0;a8;a++)

{

clk=0;

m=(disp_num1[n]1);

disp_num1[n]=disp_num1[n]1;

if(m==1)

data1=1;

else

data1=0;

_nop_();

clk=1;

_nop_();

}

}

}

/*****************************************************

显示子程序

功能:将占空比温度转化为单个字符,显示占空比和测得到的温度

******************************************************/

void display()

{

unsigned char code number[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6};

unsigned char disp_num[6];

unsigned int k,k1;

k=high_time;

k=k%1000;

k1=k/100;

if(k1==0)

disp_num[0]=0;

else

disp_num[0]=0x60;

k=k%100;

disp_num[1]=number[k/10];

disp_num[2]=number[k%10];

k=temper;

k=k%100;

disp_num[3]=number[k/10];

disp_num[4]=number[k%10]+1;

disp_num[5]=number[s/10];

disp_1(disp_num);

}

/***********************************************************

主程序

***********************************************************/

main()

{

unsigned char z;

unsigned char a,b,flag_2=1,count1=0;

unsigned char phil[]={2,0xce,0x6e,0x60,0x1c,2};

TMOD=0x21;

TH0=0x2f;

TL0=0x40;

SCON=0x50;

PCON=0x00;

TH1=0xfd;

TL1=0xfd;

PS=1;

EA=1;

EX1=0;

ET0=1;

ES=1;

TR0=1;

TR1=1;

high_time=50;

low_time=50;

PIDInit ( spid ); // Initialize Structure

spid.Proportion = 10; // Set PID Coefficients

spid.Integral = 8;

spid.Derivative =6;

spid.SetPoint = 100; // Set PID Setpoint

while(1)

{

if(plus==0)

{

EA=0;

for(a=0;a5;a++)

for(b=0;b102;b++){}

if(plus==0)

{

set_temper++;

flag=0;

}

}

else if(subs==0)

{

for(a=0;a5;a++)

for(b=0;a102;b++){}

if(subs==0)

{

set_temper–;

flag=0;

}

}

else if(stop==0)

{

for(a=0;a5;a++)

for(b=0;b102;b++){}

if(stop==0)

{

flag=0;

break;

}

EA=1;

}

get_temper();

b=temper;

if(flag_2==1)

a=b;

if((abs(a-b))5)

temper=a;

else

temper=b;

a=temper;

flag_2=0;

if(++count130)

{

display();

count1=0;

}

compare_temper();

}

TR0=0;

z=1;

while(1)

{

EA=0;

if(stop==0)

{

for(a=0;a5;a++)

for(b=0;b102;b++){}

if(stop==0)

disp_1(phil);

// break;

}

EA=1;

}

}

//DS18b20 子程序

#include REG52.H

sbit DQ=P2^1; //定义端口

typedef unsigned char byte;

typedef unsigned int word;

//延时

void delay(word useconds)

{

for(;useconds0;useconds–);

}

//复位

byte ow_reset(void)

{

byte presence;

DQ=0; //DQ低电平

delay(29); //480us

DQ=1; //DQ高电平

delay(3); //等待

presence=DQ; //presence信号

delay(25);

return(presence);

} //0允许,1禁止

//从1-wire 总线上读取一个字节

byte read_byte(viod)

{

byte i;

byte value=0;

for (i=8;i0;i–)

{

value=1;

DQ=0;

DQ=1;

delay(1);

if(DQ)value|=0x80;

delay(6);

}

return(value);

}

//向1-wire总线上写一个字节

void write_byte(char val)

{

byte i;

for (i=8;i0;i–) //一次写一个字节

{

DQ=0;

DQ=val0x01;

delay(5);

DQ=1;

val=val/2;

}

delay(5);

}

//读取温度

char Read_Temperature(void)

{

union{

byte c[2];

int x;

}temp;

ow_reset();

write_byte(0xcc);

write_byte(0xBE);

temp.c[1]=read_byte();

temp.c[0]=read_byte();

ow_reset();

write_byte(0xCC);

write_byte(0x44);

return temp.x/2;

}

pid控制的C语言编程

#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

__gxx_personality_v0 /var/tmp//ccuHN8IS.o

ld: fatal: Symbol referencing errors. No output written to t5

collect2: ld returned 1 exit status

其次,g++编译后运行结果如下

This is the parent process! child process id=27406

This is the child process!

pid控制算法的c语言实现(pid控制c代码实现)

PID算法的C语言实现

基本流程

积分环节:主要是用来消除 静差 (系统稳定后输出值和设定值之间的差值,积分环节实际上就是偏差累积的过程,把累积的误差加到原来系统上以抵消系统造成的静差)

微分环节:反映了偏差信号的变化规律,根据偏差信号的变化规律来进行超前调节,从而增加系统的快速性

对上述公式进行离散化(采样):两个公式

增量型PID:

通过增量型PID公式可以看出,最终表达结果和最近三次的偏差有关,最终输出结果应该为:

首先定义结构变量体:

然后初始化变量

最后编写控制算法

基本算法,没有考虑死区问题,没有设定上下限

在启动、结束或大幅度增减设定时,短时间内系统输出有很大的偏差,会造成PID运算的积分积累,导致控制量超过执行机构可能允许的最大动作范围对应的极限控制量,从而引起较大的超调,甚至是振荡。

为了克服这个问题,引入积分分离的概念,即当被控量和设定值偏差较大时,取消积分作用;当被控量接近设定值时,引入积分控制,以消除静差,提高精度。

abs :绝对值

令index=0使积分环节失效

积分饱和现象:如果系统存在一个方向的偏差,PID控制器的输出由于积分作用的不断累加而加大,从而导致执行机构达到极限位置。此时计算器输出量超出正常运行范围而进入饱和区,一旦系统出现反向偏差,输出量将逐渐从饱和区退出,进入饱和区越深则退出饱和区时间越长,在这段时间里,执行机构仍然停留在极限位置而不随偏差反向而立即做出相应改变,造成性能恶化。

采用梯形积分能够减小余差,提高精度

改变积分系数,若偏差大,积分作用减弱,系数减小;若偏差小,积分作用增强,系数增大。

变积分PID的基本思想是设法改变积分项的累加速度,使其与偏差大小对应。

使整个系统的稳定速度非常快

比例系数Kp的作用是加快系统的响应速度提高系统的调节精度

积分系数Ki的作用是消除系统的稳态误差

微分系数Kd的作用是改善系统的动态特性

反应系统性能的两个参数是系统误差和误差变化律

C语言编程,怎么计算PID控制

Step 7写的PID控制的FC模块。带”_IN”与带”_OUT”的变量,如果前缀是一样的,要求连接同一个变量。

FUNCTION FC1 : VOID

VAR_INPUT

Run:BOOL; //True-运行,False-停止

Auto:BOOL; //True-自动,False-手动

ISW:BOOL; //True-积分有效,False-积分无效

DSW:BOOL; //True-微分有效,False-微分无效

SetMV:REAL; //手动时的开度设定值

SVSW:REAL; //当设定值低于SVSW时,开度为零

PV:REAL; //测量值

SV:REAL; //设定值

DeadBand:REAL; //死区大小

PBW:REAL; //比例带大小

IW:REAL; //积分带大小

DW:REAL; //微分带大小

dErr_IN:REAL; //误差累积

LastPV_IN:REAL; //上一控制周期的测量值

END_VAR

VAR_OUTPUT

MV:REAL; //输出开度

dErr_OUT:REAL; //误差累积

LastPV_OUT:REAL;//上一控制周期的测量值

END_VAR

VAR

Err:REAL; //误差

dErr:REAL; //误差累积

PBH:REAL; //比例带上限

PBL:REAL; //比例带下限

PVC:REAL; //测量值在一个控制周期内的变化率,即测量值变化速率

P:REAL; //比例项

I:REAL; //积分项

D:REAL; //微分项

END_VAR

IF Run=1 THEN

IF Auto=1 THEN

IF SV=SVSW THEN

Err:=SV-PV;

PBH:=SV+PBW;

PBL:=SV-PBW;

IF PVPBL THEN

MV:=1;

ELSIF PVPBH THEN

MV:=0;

ELSE

P:=(PBH-PV)/(PBH-PBL); //计算比例项

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////以下为积分项的计算//////////////////////////////////////////////////////////////

IF ISW=1 THEN

dErr:=dErr_IN;

IF (PV(SV-DeadBand)) OR (PV(SV+DeadBand)) THEN

IF (dErr+Err)(0-IW) THEN

dErr:=0-IW;

ELSIF (dErr+Err)IW THEN

dErr:=IW;

ELSE

dErr:=dErr+Err;

END_IF;

END_IF;

I:=dErr/IW;

dErr_OUT:=dErr;

ELSE

I:=0;

END_IF;

/////////////////////////////////////////////以上为积分项的计算//////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////以下为微分项的计算//////////////////////////////////////////////////////////////

IF DSW=1 THEN

PVC:=LastPV_IN-PV;

D:=PVC/DW;

LastPV_OUT:=PV;

ELSE

D:=0;

END_IF;

/////////////////////////////////////////////以上为微分项的计算//////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

IF (P+I+D)1 THEN

MV:=1;

ELSIF (P+I+D)0 THEN

MV:=0;

ELSE

MV:=P+I+D;

END_IF;

END_IF;

ELSE

MV:=0;

END_IF;

ELSE

MV:=SetMV;

END_IF;

ELSE

MV:=0;

END_IF;

END_FUNCTION

进行整定时先进行P调节,使I和D作用无效,观察温度变化曲线,若变化曲线多次出现波形则应该放大比例(P)参数,若变化曲线非常平缓,则应该缩小比例(P)参数。比例(P)参数设定好后,设定积分(I)参数,积分(I)正好与P参数相反,曲线平缓则需要放大积分(I),出现多次波形则需要缩小积分(I)。比例(P)和积分(I)都设定好以后设定微分(D)参数,微分(D)参数与比例(P)参数的设定方法是一样的。

当初写这段程序的就是为了使用调功器来控制炉子的温度的,已经在我单位的调功器上运行成功了,还有就是我单位的调功器没有使用微分(D),只是用了比例(P)和积分(I)。

关于pid控制算法的c语言实现和pid控制c代码实现的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

本文来自投稿,不代表【】观点,发布者:【

本文地址: ,如若转载,请注明出处!

举报投诉邮箱:253000106@qq.com

(1)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2024年4月9日 23:37:56
下一篇 2024年4月9日 23:44:38

相关推荐

  • c语言新手吧,新手c语言编程软件

    新手如何学习C语言 1、最重要的是,坚持练习和编写代码是学好C语言的关键。尝试解决一些简单的编程问题,并逐渐挑战更复杂的项目。通过实践,你会逐渐掌握C语言的基础知识和编程技巧。 2、(一)先从视频课程入手如果是0基础的小白,不建议上来就啃书,可以先从视频课程入手。这里推荐中国大学好慕课上翁恺老师的两门C语言课程 也可以看B站鹏哥的视频,鹏哥讲课接地气,适合新…

    2024年5月18日
    4300
  • c语言中规划问题的简单介绍

    c语言的动态规划算法的这道题怎么做啊,求大神!!! 1、动态规划关键是找到问题中的子问题,写出状态方程。这个问题的子问题可以定义为前n件物品,总费用为v的最大价值总和。先考虑第n件物品,如果c[n]v的话,它有两种选择,放入背包和不放入背包。 2、设f[i,k]是将i万元投资到前k个项目得到的最高利润。 3、这道题考的是动态规划的思想。代码思路如下:假设我们…

    2024年5月18日
    4300
  • 国外c语言考试,考c语言的学校

    计算机初级证考些什么内容? (1)单项选择题,55题,55分(含计算机基础知识部分20分,Photoshop知识与操作部分35分);(2)Photoshop 操作题,45分(含3道题目,每题15分)。 这科考试主要内容为计算机基础知识、网络原理、操作系统、网络应用。电信、通信、电子信息科学等专业可以报考网络技术。 计算机等级初级考试即一级考试。考试科目:计算…

    2024年5月18日
    3900
  • java代码图片,java 图片

    怎么样用Java实现将一张图片转成字符画?? 1、找一张合适的图片,点击“浏览”,然后点Submit,这样就得到字符画了。 2、一起跟随小编过来看看吧字符画真的很有意思,将图片中的像素用字符代替,就生成了字符画。 3、先获取这样比较精确),然后再进行逻辑判断就Ok了。 4、这类软件转成字符画,然后找个能对屏幕录像的软件比如snagit,用记事本打开刚才的字符…

    2024年5月18日
    3500
  • c语言简单木马程序,c语言编写木马教程

    c语言木马代码,简单点的,我保证不做违法的 最简单的C语言代就是输出“helloWord”,通常是作为初学编程语言时的第一个程序代码。 define NUM 10 /* run this program using the console pauser or add your own getch, system(pause) or input loop */…

    2024年5月18日
    3400
  • c语言开关怎么自保持,c语言开关灯问题简单

    c语言开关语句是什么? break在for循环来实现开关语句、while循环等循环流程控制中起的作用是停止执行break后面的语句,跳出本次循环,并跳出该循环控制体。 Switch在C语言中是保留字,其作用是进行判断选择。switch(开关语句)常和case break default一起使用。Switch用在编程中,如C语言中它经常跟Case一起使用,是一…

    2024年5月18日
    3500
  • c语言的汇编版本,c语言 汇编

    学了C语言后想学汇编,请问汇编有分版本么?我应该学习哪一种的? 1、我也是学自动化的,自动化这个专业学的东西很多很杂,汇编语言当然是要学的,我们当时就是学的微机原理这门课。如果你要自学单片机,讲单片机这方面的书都差不多可以的,像《51单片机》这种。 2、有一本书特别适合C的入门,《C Primer Plus(第五版)中文版》,它是目前C的讲解最细最全的,十分…

    2024年5月18日
    3000
  • for是c语言关键字,c语言中for的功能

    C语言For是用户标识符吗,好像小写for才是关键字吧 1、你写错了是小写的for 这个是C语言的关键字,关键字不可以做标识符。因为C语言拿它做循环了。 2、不能把C语言关键字作为用户标识符,例如if ,for, while等.标识符长度是由机器上的编译系统决定的,一般的限制为8字符(注:8字符长度限制是C89标准,C99标准已经扩充长度,其实大部分工业标准…

    2024年5月18日
    4000
  • java编写自动取款机系统,用java写取款机系统代码

    如何用Java编写模拟ATM取款机的程序 1、代码如下package BaiDdu;import java.util.Scanner;public class ATM {/*1提示请输入密码然后直接进入下一步。 2、jf.setTitle(模拟自动取款机);jf.setBounds(300, 300, 400, 400);tf = new TextField…

    2024年5月18日
    3800
  • c语言ctype.h,c语言ctype函数

    C语言判断字符串是不是都是字母 1、isalnum() 用来判断一个字符是否为英文字母或数字,相当于 isalpha(c) || isdigit(c),其原型为:int isalnum(int c);【参数】c 为需要检测的字符。 2、根据ascii码值判断即可。由于数字,大小写字母均分别为连续存储,所以只需要与对应的最大最小值比较即可确定字符类型。代码如下…

    2024年5月18日
    4700

发表回复

登录后才能评论



关注微信