通用数字PID调节器设计

kuaidi.ping-jia.net  作者:佚名   更新日期:2024-08-07
急!急!急!求助:设计并实现通用数字PID控制器!

已发送,请查收!

啊实打实

PID调节器主控部分包括以下几个部分:单片机部分、A/D转换部分、D/A转换部分、稳压部分、数字输入输出部分以及串口通信部分。
D1:内部设定点信号灯
S1:内部设定点和外部设定点转换开关
D2:手动信号灯
S2:手动自动转换开关
D3:实际值X显示信号灯
D4:设定值W显示信号灯
S3:参数修改以及实际值和设定值显示转换开关
D5:超过限定值信号灯
D6:低于限定值信号灯
S4:设定值增加按钮
S5:设定值减少按钮
S6:修改手动变量按钮
S7:修改手动变量按钮
附录[1] 主程序—MAIN.C
#include"adconver.h"
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey0.h"
#include"subkey1.h"
#include"subkey2.h"
#include"subkey3.h"
#include"subkey4.h"
#include"subkey5.h"
#include"subkey6.h"
bit insertsetframe=1;//内部设定标志位
bit handframe=1;//手动设定标志位
bit improvedisframe=0;//实际值标志位
bit shineframe=0;//判断是不是第一次开机停止4LED的闪烁
bit canshuframe=0x00;//参数标志位
unsigned char circleframe=0x00;//参数循环变量
unsigned char channelframe=0x00;//通道标志位
unsigned char ledframe=0xfc;//LED灯管状态
unsigned char times=0x00;//记数位
unsigned char readkey;
unsigned int setvalue=0x00;//设定值
unsigned char outputvalue=0x00;//输出值
unsigned int limup=0x270f;//实际值上限
unsigned int limdown=0x00;//实际值下限
unsigned int a1=0x270f;//上限报警值
unsigned int a2=0x00;//下限报警值
unsigned int cp=0x00;//P参数
unsigned int ci=0x00;//I参数
unsigned int cd=0x00;//D参数
unsigned char led[6];//LED值公共
main()
{
unsigned int tmr;
unsigned char keynumber;

for (tmr=0;tmr<0xffff;tmr++);
write7281(0x12,0x80);
write7281(0x10,0xf0);
write7281(0x00,0xc8);
write7281(0x14,0x1b);
write7281(0x14,0x2e);
write7281(0x15,0x30);
write7281(0x15,0x40);
write7281(0x15,0x50);
write7281(0x06,0xfc);
while(1)
{
while(!key)
{
keynumber=read7281(0x13);
switch(keynumber)
{
case 0x00:
subkey0();break;
case 0x01:
subkey1();break;
case 0x02:
subkey2();break;
case 0x03:
subkey3();break;
case 0x04:
subkey4();break;
case 0x05:
subkey5();break;
case 0x06:
subkey6();break;
default:
break;
}
}
}
}
附录[2] S1模块的程序—SUBKEY0.C
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey0.h"
void subkey0()
{
if(insertsetframe==1)
{
insertsetframe=0;
ledframe|=0x01;
write7281(0x06,ledframe);
}
else
{
insertsetframe=1;
ledframe&=0xfe;
write7281(0x06,ledframe);
}
}//更改内部设定和外部设定的状态,并将相应的状态位进行更改,并更改状态灯
附录[3] S2模块的程序—SUBKEY1.C
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey1.h"
void subkey1()
{
if(handframe==1)
{
handframe=0;
ledframe|=0x02;
write7281(0x06,ledframe);
}
else
{
handframe=1;
ledframe&=0xfd;
write7281(0x06,ledframe);
}
} //更改手动自动状态,改变相应的状态位,更改相应的状态灯
附录[4] S3模块的程序—SUBKEY2.C
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey2.h"
#include"adconver.h"
#include"subkey0.h"
#include"subkey1.h"
#include"hdconver.h"
#include"subkey3.h"
#include"subkey4.h"
#include"pid.h"
#include"daconver.h"
void subkey2()
{
if(shineframe==0)
{
write7281(0x10,0xff);
shineframe=1;
}
else
{
skey2();
}
}
void skey2(void)
{ // canshuframe=1;
write7281(0x18,0x17);
switch(circleframe)
{
case 0x00: ledframe|=0x0c;
write7281(0x06,ledframe);
circleframe+=1;
hdconver(limup);//4LED显示上限值
dis4led();
write7281(0x14,0x41);
write7281(0x14,0x5C); //写入2LEDHI
break;
case 0x01: circleframe+=1;
hdconver(limdown);//4LED显示下限值
dis4led();
write7281(0x14,0x40);
write7281(0x14,0x5d); //写入2LEDLO
break;
case 0x02: circleframe+=1;
hdconver(a1);//4LED显示上限报警
dis4led();
write7281(0x14,0x41);
write7281(0x15,0x5a); //写入2LEDA1
break;
case 0x03: circleframe+=1;
hdconver(a2);//4LED显示下限报警
dis4led();
write7281(0x14,0x42);
write7281(0x15,0x5a); //写入2LEDA2
break;
case 0x04: circleframe+=1;
hdconver(cp);//4LED显示P参数
dis4led();
write7281(0x14,0x4e);
write7281(0x14,0x5f); //写入2LEDP
break;
case 0x05: circleframe+=1;
hdconver(ci);//4LED显示I参数
dis4led();
write7281(0x14,0x41);
write7281(0x14,0x5f); //写入2LEDI
break;
case 0x06: circleframe+=1;
hdconver(cd);//4LED显示D参数
dis4led();
write7281(0x15,0x4d);
write7281(0x14,0x5f); //写入2LEDI
break;
case 0x07: improvedisframe=0;
ledframe=(ledframe|0x08)&0xfb;
circleframe+=1;
adconver();
write7281(0x14,0x40);
write7281(0x14,channelframe);
write7281(0x06,ledframe);
break;
case 0x08: improvedisframe=1;
ledframe=(ledframe|0x04)&0xf7;
circleframe=0;
pidcf();
daconver();
hdconver(setvalue);
dis4led();
write7281(0x06,ledframe);
break;
default:
break;
}
}//按相应的S3改变不同的参数
附录[5] S4模块的程序—SUBKEY3.C
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey3.h"
#include"subkey2.h"
#include"hdconver.h"
void subkey3()
{
switch(circleframe)
{
case 0x01:limup=add1(limup);
break;
case 0x02:limdown=add1(limdown);
break;
case 0x03:a1=add1(a1);
break;
case 0x04:a2=add1(a2);
break;
case 0x05:cp=add1(cp);
break;
case 0x06:ci=add1(ci);
break;
case 0x07:cd=add1(cd);
break;
case 0x00:setvalue=add1(setvalue);
break;
default:
break;
}
}
unsigned int add1(unsigned int value)
{
ledframe|=0x20;//关掉下限报警
write7281(0x06,ledframe);
if(value==9999)
{
ledframe&=0xef;//打开上限报警灯
write7281(0x06,ledframe);
write7281(0x06,ledframe);
}
else
{
value+=1;
}
hdconver(value);
dis4led();
return(value);
}
附录[6] S5模块的程序—SUBKEY4.C
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey4.h"
#include"subkey2.h"
#include"hdconver.h"
void subkey4()
{
switch(circleframe)
{
case 0x01:limup=sub1(limup);
break;
case 0x02:limdown=sub1(limdown);
break;
case 0x03:a1=sub1(a1);
break;
case 0x04:a2=sub1(a2);
break;
case 0x05:cp=sub1(cp);
break;
case 0x06:ci=sub1(ci);
break;
case 0x07:cd=sub1(cd);
break;
case 0x00:setvalue=sub1(setvalue);
break;
default:
break;
}
}
unsigned int sub1(unsigned int value)
{
ledframe|=0x10;//关掉上限报?
write7281(0x06,ledframe);
if(value==0)
{

ledframe&=0xdf;//打开上限报警灯
write7281(0x06,ledframe);
}
else
{
value-=1;
}
hdconver(value);
dis4led();
return(value);
}
附录[7] S6模块的程序—SUBKEY5.C
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey5.h"
#include"hdconver.h"
void subkey5()
{
if(improvedisframe==0)
{
channelframe=0x00;
write7281(0x15,0x40);
write7281(0x15,0x50);//若现在状态为实际值,则改变通道状态并显示现在状态为00
}
else
{
if(handframe==1)
{
ledframe|=0x10;//关掉上限报警灯
write7281(0x06,ledframe);
if(outputvalue==0x00)
{
ledframe&=0xdf;//打开下限报警灯
write7281(0x06,ledframe);
}
else
{
outputvalue-=1;
hdconver2(outputvalue);
}
dis2led();
}

}
}
附录[7] S7模块的程序—SUBKEY6.C
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey6.h"
#include"hdconver.h"
void subkey6()
{
if(improvedisframe==0)
{
channelframe=0x01;
write7281(0x15,0x41);
write7281(0x15,0x50);//若现状态为实际值,则2LED显示为01
}
else
{
if(handframe==1)
{
ledframe|=0x20;//关掉下限报警灯
write7281(0x06,ledframe);
if(outputvalue==99)
{
ledframe&=0xef;//打开上限报警档?
write7281(0x06,ledframe);
}
else
{
outputvalue+=1;
hdconver2(outputvalue);
}
}
dis2led();
}
}
附录[8] A/D转换模块的程序—ADCONVER.C
#include"STC12C5410AD.H"
#include"adconver.H"
#include"delay.h"
#include"main.h"
#include"dis7281.h"
#include"hdconver.h"
void adconver()
{ unsigned char adchanne=0xe0;//设置P1的0.1位为AD输入通道
ADC_CONTR=(0x80|ADC_CONTR)+channelframe;//开启AD模拟电源
delay(1000);
P1M0=0x03;
P1M1=0x03;//设置通道为开漏模式
ADC_CONTR=adchanne+channelframe;//设置AD转换通道
delay(22);
ADC_DATA=0x00;
ADC_LOW2=0x00;//清除数据口
ADC_CONTR|=0x08;//开启AD端口
while(!(ADC_CONTR&0x10)){};//等待AD转换完成
ADC_CONTR&=0xe7;//停止AD转换
P1M0&=0xfd;
P1M1&=0xfd;//设置P1口为普通IO模式
addis();
}
void addis()
{
unsigned int addata;
double liangch;
liangch=(limup-limdown)/100;
addata=ADC_DATA+(ADC_LOW2&0x03)*1024;
liangch=liangch/1023*addata;
addata=(unsigned int)liangch;
if(addata>a1)
{
ledframe&=0xef;//打开上限报警灯
write7281(0x06,ledframe);
}
if(addata<a2)
{
ledframe&=0xdf;//打开上限报警灯
write7281(0x06,ledframe);
}
hdconver(addata);
dis4led();
}
附录[8] D/A转换模块的程序—DACONVER.C
#include"delay.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"daconver.h"
sbit TLV5618_SCLK=P1^7;
sbit TLV5618_DIN=P1^5;
sbit TLV5618_CS=P1^4;
void mDelay(unsigned int a)
{unsigned int f;
for(f=0;f<a;f++);
}
void TLV5618 (unsigned int da)
{
unsigned int i;
unsigned int dat;
dat= da|0xc000;
TLV5618_CS=0;
TLV5618_SCLK=0;
for(i=0;i<16;i++)
{
TLV5618_DIN=(bit)(dat&0x8000);
dat=dat<<1;
TLV5618_SCLK=1;
mDelay(50);
TLV5618_SCLK=0;
mDelay(50);
}
TLV5618_CS=1;
}
void daconver(void)
{ float i=100;
unsigned int da;
i=outputvalue/100*4096;
da=(unsigned int)i;
TLV5618 (da);
}
附录[9]显示及键盘模块的程序—DIS7281.C
#include"delay.H"
#include"STC12C5410AD.H"
#include"dis7281.H"
#include"main.h"
void write7281(unsigned char regadd,unsigned char writedata)
{
sendbyte(regadd);
sendbyte(writedata);
}
void sendbyte(unsigned char sendbyte)
{
unsigned char bitcounter;
clk=0;
clk=1;
do{
clk=0;
clk=1;
}while(dat);
clk=0;
clk=1;
while(!dat);
for(bitcounter=0;bitcounter<8;bitcounter++)
{
if ((sendbyte&0x80)==0)
{ dat=0;}
else
{dat=1;}
sendbyte=sendbyte*2;
clk=0;
clk=1;
delay(1);
}
dat=1;
delay(2);
}
unsigned char receivebyte(void)

{
unsigned char bit_counter;
unsigned char in_byte;

clk=0;
clk=1; //只发送一个单元的脉冲

while(dat);//等待BC7281响应DAT底电平

clk=0;
clk=1; //受到响应,再发一脉冲等待接受数据

for (bit_counter=0;bit_counter<8;bit_counter++ ) //接受8个BIT

{
delay(1);
in_byte=in_byte*2 ;//in_byte左移一位

if(dat) //如果DAT为1

{
in_byte=in_byte|0x01; //bit^0=1
}
clk=0;
clk=1;
}
delay(2);
clk=0;
clk=1;
return(in_byte);
}
unsigned char read7281(unsigned char reg_add)
{
sendbyte (0x80+reg_add); //发送读指令(BIT 7=1)

return (receivebyte()); //接受数据字节并返回

}
void dis4led()
{
unsigned char i;
unsigned char id=0x00;
for(i=0;i<4;i++)
{
write7281(0x14,id+led[i]);
id+=0x10;
}
}
void dis2led()
{
unsigned char i;
unsigned char id=0x40;
for(i=4;i<6;i++)
{
write7281(0x14,id+led[i]);
id+=0x10;
}
}
附录[10]PID算法模块的程序—PID.C
#include"adconver.h"
#include"STC12C5410AD.H"
#include"math.h"
#include"pid.h"
#include"hdconver.h"
#include"dis7281.h"
xdata struct _pid
{
int pv;
int sp;
float integral;
float pgain;
float igain;
float dgain;
int deadband;
int last_error;
};
xdata struct _pid warm,*pid;
xdata int process_point,set_point,dead_band;
xdata 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;
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);
}
void pidcf(void)
{
int count=0;
float val=100;
float p_gain=cp/val;
float i_gain=ci/val;
float d_gain=cd/val;
// unsigned int dadata;
pid=&warm;
dead_band=2;
integral_val=(float)(0.01);
while(count<=20)
{
process_point=(unsigned int)addata/val;
set_point=(unsigned int)setvalue/val;
pid_init(&warm,process_point,set_point);
pid_tune(&warm,p_gain,i_gain,d_gain,dead_band);
pid_setinteg(&warm,0.0);
pid_bumpless(&warm);
count++;
}
outputvalue=(unsigned char)pid_calc(&warm);
hdconver2(outputvalue);
dis4led();
}

  • 通用数字PID调节器设计
    答:PID调节器主控部分包括以下几个部分:单片机部分、A/D转换部分、D/A转换部分、稳压部分、数字输入输出部分以及串口通信部分。D1:内部设定点信号灯S1:内部设定点和外部设定点转换开关D2:手动信号灯S2:手动自动转换开关D3:实际值X显示信号灯D4:设定值W显示信号灯S3:参数修改以及实际值和设定值显示转换开关D5:超过限...
  • 急!急!急!求助:设计并实现通用数字PID控制器!
    答:楼主,我也求一份。516370743@qq.com,谢谢
  • 急!!!数字PID控制器的参数整定方法研究
    答:数字PID控制系统是时间的离散系统,计算机对生产过程的控制是断续的过程. 即在每一个采样周期内,传感器将所测数据转换成统一的标准信号后输入给调节器,在调节器中与设定值进行比较得出偏差值,经PID运算得出本次的控制量,输出到执行器后才完成了本次的调节任务。在PID调节中 ,由于PID 算式选择的不同会得到不同的控...
  • 数字PID双闭环直流调速系统课程设计
    答:①同步信号形成电路 ②压控振荡器 ③脉冲整形电路 八、主电路元件选择 1.主回路整流装置 2.整流元件额定电流 九、脉冲变压器结构设计 十、结束语 先给你个“提纲”,将PID单元“数字”化(计算机编程)也就是你要的吧。
  • PID调节器数字实现是什么
    答:基于PLC的数字PID调节器设计 编程是用梯形图 PID是由比例、微分、积分三个部分组成的,在实际应用中经常只使用其中的一项或者两项,如P、PI、PD、PID等。就可以达到控制要求...PLC编程指令里都会有PID这个功能指令...至于P,I,D 数值的确定要在现场的多次调试确定...比例控制(P):比例控制是最...
  • 如何设定数字pid控制器的参数
    答:1、在整定PID控制器参数时,可以根据控制器的参数与系统动态性能和稳态性能之间的定性关系,用实验的方法来调节控制器的参数。有经验的调试人员一般可以较快地得到较为满意的调试结果。在调试中最重要的问题是在系统性能不能令人满意时,知道应该调节哪一个参数,该参数应该增大还是减小。2、为了减少需要整...
  • 数字式调节器pid预算有几种形式
    答:3种。数字PID调节器:全称是比例微分积分调节器,是对被调量与给定值的偏差分别进行比例、微分和积分运算,取其和构成连续信号以控制执行器的模拟调节器
  • 简述调整PID各参数的一般原则、调整方法和步骤。
    答:二、PID控制器参数整定的方法:1、理论计算整定法。它主要是依据系统的数学模型,经过理论计算确定控制器参数。这种方法所得到的计算数据未必可以直接用,还必须通过工程实际进行调整和修改。2、工程整定方法,它主要依赖工程经验,直接在控制系统的试验中进行,且方法简单、易于掌握,在工程实际中被广泛...
  • 什么是PID调节器,并举例说明P、I、D的调节作用。
    答:PID 调节器是一个在工业控制应用中常见的反馈回路部件,PID是以它的三种纠正算法而命名的。这三种算法都是用加法调整被控制的数值。而实际上这些加法运算大部分变成了减法运算因为被加数总是负值。以下是PID的调节作用举例:1.比例- 来控制当前,误差值和一个负常数P(表示比例)相乘,然后和预定的值相加...
  • PID的调节步骤分几步?
    答:1. PID调试步骤 没有一种控制算法比PID调节规律更有效、更方便的了。现在一些时髦点的调节器基本源自PID。甚至可以这样说:PID调节器是其它控制调节算法。因为PID解决了自动控制理论所要解决的最基本问题,既系统的稳定性、快速性和准确性。调节PID的参数,可实现在系统稳定的前提下,兼顾系统的带载能力...