硬件原理:加热电阻为400,电源为市电,固态继电器控制通断,市电过零信号提取,单片机采用mega48继电器最小通断时间为10ms,通断PWM周期为100个过零信号.
这个程序是绝对的PID当温差较大时,采用P算法(比例算法),当达到设定温度时,采用算法PID算法,实用稳定性还可以,上下波动为0.5度以内.
#include
#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 errorflg;
unsigned char addokflg;
}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->addokflg=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->addokflg=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->errorflg==0)
result=0;
sptr->pwm_H=(unsigned char) result;
//return (unsigned char) result;
}