|
发表于 2008-5-31 11:06:06
|
显示全部楼层
#include <mega16.h>
#include <math.h>
/*****************************************
pid定义
****************************************/
#define adc_result 100
#define kp 5
#define ki 2
#define kd 1
#define T 30
double PID_Calculate(double PIDe0);
double PID_turn(double p,double q);
double value_Calculate(void);
void compare_adc_result(void);
double value_Calculate(void);
static unsigned char pid_stste=0;
int PID_output=0;
unsigned char PIDoutput1=0,PIDe1=0,PIDe2=0;
unsigned char pi_PIDoutput1=0,pi_PIDe1=0,pi_PIDe2=0;
/********************************
先前设定量
********************************/
unsigned int time_value0=40;
unsigned int degree_value0=140; //从前面的程序中得来
/*******************************
定时器变量
********************************/
unsigned int key_stime_counter, key_stime_counter1,key_stime_counter2;
bit key_stime_ok, key_stime_ok1= 1,key_stime_ok2 ,key_stime_ok3,time_compare_ok;
interrupt [TIM0_COMP] void timer0_comp_isr(void)
{
//key_check();
if (++key_stime_counter >=5)
{
key_stime_counter = 0;
key_stime_ok = 1; // 10ms到
//adc_degree=read_adc();
//p+=adc_degree/10;
if(++key_stime_counter1>=50)
{
key_stime_counter1 = 0;
key_stime_ok1= 1;
time_compare_ok=1; //500ms到
// adc_result= p/5;
// p=0;
// ADC_DISBUFFER();
// ADC_TIMEDISBUFFER();
if(++key_stime_counter2>=2)
{
key_stime_counter2 = 0;
key_stime_ok2= 1;
key_stime_ok3= 1;
// display_adc();
}
}
}
}
// Timer 1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
OCR1A=PID_output;
}
/****************************************************
pid计算控制
***************************************************/
double PID_Calculate(double PIDe0)
{
double sum_error;
double h,temper;
int PIDoutput;
sum_error+=PIDe0;
h=abs(PIDe0);
if(h<=3)
{
PIDoutput=kp* PIDe0+ki*sum_error; //pi控制
}
else
{
temper=(kp+ki+kd)*PIDe0-(kp+2*kd)*PIDe1+kd*PIDe2; //pid控制
PIDoutput=PIDoutput1+temper;
}
PIDoutput1=PIDoutput;
PIDe2=PIDe1;
PIDe1=PIDe0;
if(PIDoutput>=1024) //当饱和时输出最大值
{
return 1024;
}
else if(PIDoutput<=0) //当小于零输0
{
return 0;
}
else if(PIDoutput>=0&PIDoutput<=200)
{
return PIDoutput;
}
}
/**************************************
pi控制
****************************************/
double PD_Calculate(double PIDe0)
{
double pi_sum_error;
int pi_PIDoutput;
pi_sum_error+=PIDe0;
pi_PIDoutput=kp* PIDe0+ki*pi_sum_error; //pi控制
pi_PIDoutput1=pi_PIDoutput;
pi_PIDe2=pi_PIDe1;
pi_PIDe1=PIDe0;
if(pi_PIDoutput>=1024) //当饱和时输出最大值
{
return 1024;
}
else if(pi_PIDoutput<=0) //当小于零输0
{
return 0;
}
else if(pi_PIDoutput>=0&pi_PIDoutput<=200)
{
return pi_PIDoutput;
}
}
/****************************************
pid差量计算
******************************************/
double PID_turn(double p,double q)
{
double PID_e0;
PID_e0=p-q;
return PID_e0;
}
/********************************************
把区间分为2*timer_value0倍,控制温度沿曲线上升
********************************************/
double value_Calculate(void)
{
double y;
static unsigned char x=0;
if(key_stime_ok1)
{
key_stime_ok1= 0;
if(x<=time_value0)
{
x+=0.5;
}
}
y=(degree_value0-160)/(time_value0*time_value0)*(x-T-time_value0)+160;
return y;
}
/**************************************
检测值比较判断
**************************************/
void compare_adc_result(void)
{
static unsigned char x=3;
double PID_OUT, PID_in;
switch(pid_stste)
{
case 0:
if(adc_result<125)
{
double h0,error0;
PID_OUT=adc_result;
PID_in=120;
error0=PID_turn(PID_in,PID_OUT);
h0=abs(error0);
if(h0<=3)
{
if(time_compare_ok)
{
time_compare_ok=0;
--x;
if(x==0)
{
x=3;
++pid_stste;
}
}
}
PID_output=255;
}
else ++pid_stste;
break;
case 1:
if(adc_result<=145)
{
double h1,error1;
PID_OUT=adc_result;
PID_in=degree_value0;
error1=PID_turn(PID_in,PID_OUT);
h1=abs(error1);
if(h1<=3)
{
if(time_compare_ok)
{
time_compare_ok=0;
--x;
if(x==0)
{
x=3;
++pid_stste;
}
}
}
PID_output=PID_Calculate(error1);
}
else ++pid_stste;
break;
case 2:
if(adc_result<=165)
{
double h2,error2;
PID_in=value_Calculate();
PID_OUT=adc_result;
error2=PID_turn(PID_in, PID_OUT);
h2=abs(error2);
if(h2<=3)
{
if(time_compare_ok)
{
time_compare_ok=0;
--x;
if(x==0)
{
x=3;
++pid_stste;
}
}
}
PID_output=PID_Calculate(error2);
}
else ++pid_stste;
break;
case 3:
if(adc_result<=230)
{
double h3,error3;
PID_OUT=adc_result;
PID_in=230;
error3=PID_turn(PID_in, PID_OUT);
h3=abs(error3);
if(h3<=3)
{
if(time_compare_ok)
{
time_compare_ok=0;
--x;
if(x==0)
{
x=3;
++pid_stste;
}
}
}
PID_output=PD_Calculate(error3);
}
else ++pid_stste;
break;
case 4:
PID_output=0;
pid_stste=0;
//stop_flag=1;
//stop_device();
pid_stste=0;
break;
}
}
void main(void)
{
PORTD=0x00;
DDRD=0x20;
ASSR=0x00;
TCCR0=0x0C;
TCNT0=0x00;
OCR0=0x7C;
TCCR1A=0xC3;
TCCR1B=0x05;
TCNT1H=0x00;
TCNT1L=0x00;
OCR1AH=0x00;
OCR1AL=0x56;
OCR1BH=0x00;
OCR1BL=0x00;
ASSR=0x00;
TIMSK=0x06;
ACSR=0x80;
SFIOR=0x00;
#asm("sei")
while (1)
{
compare_adc_result();
};
}
用AVR STUDIO4仿真就是出不来效果,想请教马潮老师 |
|