硬件原理:加热电阻为400,电源为市电,固态继电器控制通断,并提取市电的过零信号,单片机采用mega48,继电器通断最小时间为10ms,通断PWM的周期为100个过零信号.
本程序采用绝对式PID算法,当温度相差很多时,采用P算法(比例算法),当到达设定温度时,采用PID算法,实际实用稳定性还可以,上下波动在0.5度以内.
#include <avr/io.h>
#include "PID.h"
//static PID sPID;
//static PID *sptr=&sPID;
TADD Tadd1;
TADD Tadd2;
void IncPIDInit(PID *sptr)
{
sptr->SumError=0;
sptr->LastError=0;
sptr->PrevError=0;
//sptr->Proportion = 900;
//sptr->Integral=20;
//sptr->Derivative = 2;
//sptr->SetPoint = 0;
}
typedef struct
{
int SetPoint; //设定目标值
int32_t SumError; //误差累计
//int Proportion;
//int Integral; //积分常数
//int Derivative; //微分常数
int LastError; //Error[-1]
int PrevError; //Error[-2]
}PID;
#define PID_Proportion 900 //比例常数
#define PID_Integral 20 //积分常数
#define PID_Derivative 2 //微分常数
#define PWM_T 100
#define MAX_T 80 //加热的最大温度
typedef struct
{
PID spid; //PID控制器
unsigned char pwm_H;//输出
unsigned char EnAdd;//加热使能
int real_T; //实际温度值
unsigned char Taddset[3]; //加热的设定温度
unsigned char set_NO; //加热的档数
unsigned char error**;
unsigned char addok**;
}TADD;
void LocPIDCalc(TADD *sptr)
{
int iError,dError;
int32_t result;
iError = (sptr->spid.SetPoint*4) - (sptr->real_T/4);
//sptr->spid.LastError = iError;
if(iError>-2&&iError<4)
{
sptr->addok**=1;
sptr->spid.SumError +=iError;
dError = iError-sptr->spid.LastError;
sptr->spid.LastError = iError;
result=(PID_Proportion * iError +
PID_Integral * sptr->spid.SumError +
PID_Derivative * dError)/20;
}
else
{
sptr->spid.SumError =0;
sptr->spid.LastError=0;
if(iError>0)
sptr->addok**=0;
result=(PID_Proportion * iError)/20;
}
if(result>PWM_T)
result=PWM_T;
else if(result<0)
result=0;
if((sptr->real_T>>4)>MAX_T||sptr->error**==0)
result=0;
sptr->pwm_H=(unsigned char) result;
//return (unsigned char) result;
|