|
发表于 2009-5-10 20:09:53
|
显示全部楼层
请教Gorgon Meducer 傻孩子,我这几天搞可控硅调压真是找不到方向了,我是用于可控硅移相调压,就是过零后延时时间调整导通角,从而调压.在可控硅输出检测电压作为PID的输入量,PID部分程序我参照了本网站的程序,采用的浮点数,我运行了大概62个us,我就不理解,PID的输出量怎么和那个延时时间对应起来.谢谢!!
PID部分程序:
double rOut; // PID Response (Output)
double rIn; // PID Feedback (Input)
typedef struct PID {
double SetPoint; // 设定目标 Desired Value
double Proportion; // 比例常数 Proportional Const
double Integral; // 积分常数 Integral Const
double Derivative; // 微分常数 Derivative Const
double LastError; // Error[-1]
double PrevError; // Error[-2]
double SumError; // Sums of Errors
} PID;
double PIDCalc( PID *pp, double NextPoint )//这里是位置式算法
{
double 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 // 微分项
);
}
void PIDInit (PID *pp)
{
memset ( pp,0,sizeof(PID));
}
主程序对PID初始化:
PID sPID; // PID Control Structure
PIDInit ( &sPID ); // Initialize Structure
sPID.Proportion = 2; // Set PID Coefficients
sPID.Integral = 1;
sPID.Derivative = 1;
sPID.SetPoint = 200.0; // Set PID Setpoint
在过零脉冲来时做PID运算:
rIn=celiangzhi;
rOut = PIDCalc (&sPID,rIn); // Perform PID Interation
dingshishijian=rOut;
celiangzhi是测量的电压;dingshishijian是定时器新的延时时间
整个程序:
#define wsfw_c
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/wdt.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <avr/delay.h>
#include <math.h>
#include <string.h>
#include <stdint.h>
#define BIT(x) (1<<(x))
#define NOP() asm("nop")
#define uint unsigned int
#define uchar unsigned char
#define N 7
#define Nw 7
volatile uchar count;
volatile unsigned long avragew;
volatile uint value_bufw[Nw];
volatile uchar countw,kw,jw;
volatile uint tempw;
volatile uint zhongjiandianya;
volatile uchar shedingdianya;
volatile uchar celiangzhi;
volatile uchar i;
volatile uchar dt;
volatile uint AD_RESULT;
volatile uchar dingshia;
volatile uchar dingshib;
volatile uint dingshishijian;
volatile uchar yanshi1;
volatile uint dingshifa;
volatile uint zhengzhongduan;
volatile uint fuzhongduan;
double rOut; // PID Response (Output)
double rIn; // PID Feedback (Input)
typedef struct PID {
double SetPoint; // 设定目标 Desired Value
double Proportion; // 比例常数 Proportional Const
double Integral; // 积分常数 Integral Const
double Derivative; // 微分常数 Derivative Const
double LastError; // Error[-1]
double PrevError; // Error[-2]
double SumError; // Sums of Errors
} PID;
void delay( )
{
NOP();NOP();NOP();NOP();NOP();NOP();NOP();
}
void ADS8320_READ( )
{
celiangzhi=celiangzhi;
}
double PIDCalc( PID *pp, double NextPoint )//这里是位置式算法
{
double 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 // 微分项
);
}
void PIDInit (PID *pp)
{
memset ( pp,0,sizeof(PID));
}
int main(void)
{
DDRA = 0xFF;
DDRE = 0xFF;PORTE=0x00;
DDRD=0x00; PORTD=0x00;
DDRC=0xff; PORTC=0x00;//0xe7;
DDRF=0xff; //PORTF=0xff;
DDRG=0xff;
PORTG|=(1<<PG3);
//PORTG&=~(1<<PG3);
/*******串口1采集数据********/
UCSR1B = 0x00;
UCSR1A = 0x00;
UCSR1C = 0x06;
UBRR1L = 0x33;
UBRR1H = 0x00;
UCSR1B = 0x98;
/*******串口1采集数据*********/
EICRA=0x0f;//0x0a;//0x0f;
EICRB=0x00;
EIMSK=0x03;
MCUCR = 0x00;
MCUCSR = 0x80;//禁止JTAG
PID sPID; // PID Control Structure
PIDInit ( &sPID ); // Initialize Structure
sPID.Proportion = 2; // Set PID Coefficients
sPID.Integral = 1;
sPID.Derivative = 1;
sPID.SetPoint = 200.0; // Set PID Setpoint
sei();//开全局中断
wdt_enable(WDTO_2S);
while(1)
{
wdt_reset(); //喂狗
++dingshifa;
ADS8320_READ( );
}
}
SIGNAL(SIG_OVERFLOW1)
{
TCCR1B=0x00;
TIMSK=0x00;
TCNT1H = 0x00;
TCNT1L = 0x00;//初始值
PORTG&=~(1<<PG3);//可控硅导通
asm("nop");asm("nop");asm("nop");asm("nop");
asm("nop");asm("nop");asm("nop");asm("nop");
asm("nop");asm("nop");asm("nop");asm("nop");
asm("nop");asm("nop");asm("nop");asm("nop");
PORTG|=(1<<PG3);//可控硅不导通
}
SIGNAL(SIG_INTERRUPT0)
{
PID sPID; // PID Control Structure
//EIFR=EIFR|0x01;
++zhengzhongduan;
rIn=celiangzhi;
rOut = PIDCalc (&sPID,rIn); // Perform PID Interation
dingshishijian=rOut;
TCNT1H = (dingshishijian-1)/256;
TCNT1L = (dingshishijian-1)%256;//初始值
TCCR1A=0x00;
TCCR1B=0x02;
//TCCR1C=0x80;
TIMSK=0x04;
}
SIGNAL(SIG_INTERRUPT1)
{
PID sPID; // PID Control Structure
//EIFR=EIFR|0x02;
++fuzhongduan;
rIn=celiangzhi;
rOut = PIDCalc (&sPID,rIn); // Perform PID Interation
dingshishijian=rOut;
TCNT1H = (dingshishijian-1)/256;
TCNT1L = (dingshishijian-1)%256;//初始值
TCCR1A=0x00;
TCCR1B=0x02;
TIMSK=0x04;
}
我将定时时间做到了1个us,半波10ms,最大10*1000us.过零信号是10ms来一次.我的程序是10ms做一次PID运算. |
|