-
一个实用的单片机
PID
方式控温实例
§
1
:基本情况
p>
本例中控制对象是一款小型专用工业烘箱
要求恒温范围:
室温
--300
℃
恒温精度:
±
1
℃
(其它指标略)
§
< br>2
:控制器硬件
(参考原理图)
①
.
单片机
采用
(C51
系列
)TI
公司的
MCS1210Y4
(
内部有
8
通道
24
位
AD
转换器)
串行口在线编程
②
.
前向通道
温度信号(来自烘箱的
Pt100
电阻
信号)经
INA118
放大送入
AD
通道
CH0
③
.
后向通道
I/O
口驱动光耦
MOC-3061<
/p>
,再驱动大功率双向可控硅输出
④
.
键盘
up
递增按钮和
down
递减按钮,设置目标温度
⑤
.LED
(
3
位)显示
温度值(软件切换显示目标温度或采样温度)
⑥
.
电源
+5V
单电源
§
3
:软件介绍(由
C
语言编写)
①
.
流程
采样当前温度
-->PID
运算
-->PWM
(占空比式)输出
②
.
温度采样
采样周期是一个很重要的参数
其确定
取决于烘箱的固有响应特性参数(比如纯滞后时间
θ
以及
响应时间常数
τ
)
一般值在
4--20
秒之间(例中取
1
6
秒)
③
.
PID
运算
每采样一次之后进行一次
PID
运算,得到一个输出量,供输出函数调用
.
为了下面叙述方便先定义几个变量
定义
:
T_target
表示目标温度
T_real
表示当前温度
T_diff
表示当前温差
并且
T_diff=T_target-T_real
PID
运算表达式如下
PWM_OUT=P_OUT+I_OUT+D_OUT+P_H;
(求代数
和)
其中
P_OUT=KP*(T_diff)
称为比例项,
KP
是比例系数
,<
/p>
比例项的作用是纠正偏
差
.
比例项输出等于比例系数乘当前温差
(
原理图
)
I_OUT=KI*Σ(diff)
称为积分项,
KI
是积分系数
,
p>
积分项用于消除系统稳态误差
Σ(diff)
含义是由当前算起前面
N
次采样温差的和
(
例中
N
取
20
)
D-
_OUT=KD*Δdiff
称为微分项,
KD
< br>是微分系数
,
微分项用于减小系统超调量,增加系统稳定性
.
(Δdiff=
当前温差
-
上次温差)
P_H=KC*
(
T_target
)
称为维持功率项
,
达温后(其它项均趋于
0
)此项起抵消散热维持温度的作用,可
增加系统稳定性<
/p>
.
KC
是维持功率系数
如果约定满功率值为
100
,停止输出功率值为
0
那末
PWM_OUT
的取值范围就确
定为
0--100
主要是为了后面编制输出函数时方便简明,直接调用
PWM_OUT
作为
输出占空比的百分数)
后面
整定系数时就要兼顾
PWM_OUT
的取值范围
§
4.
< br>源程序(部分)
#define KP 3.0
#define KI 0.3
#define KD
200.0
#define KC 0.1
#define T_c 16
//
比例系数
//
积分系数
//
微分系数
//
维持功率系数
< br>//
采样周期
(
单位
:
秒
)
sbit
pid_port=P3^5; //
控制输出端口
float T_target=0;
//
目标温度
float
T_real=0;
//
当前温度
float PWM=0;
//
输出控制量
1-100
bit
read_AD_enable=0;
//PID
运算允许标志位
//T0
定时器初始化
void Timer0_Init()
{
TMOD|=0x01;
TF0
=0;
TR0 =1;
IE |=0x02;
}
//
读取
AD
转换值并刻度
void
read_AD(void)
{
int
delta_ad;
unsigned char
ad[3];
ad[0]=ADRESH;
ad[1]=ADRESM;
ad[2]=ADRESL;
delta_ad=ad[0]*0x100+ad[1]-0x23cb;//
???
if(delta_ad<=0)delta_ad=0;
T_real=(float)delta_ad/70;
}
//*--------PID
运
算函数
void pid(void)
{
//
当前温度
static float diff[20]={0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0};
//
静态变量
第
n
次温<
/p>
差
static float
sum_diff=0;
static int curr_=0;
float pwm_0;
//Σ(diff)
温差求和
积分
//20
次采样记数
//
维持功率
//
记录上一次温差
供微分用
//20
次采样
float p_out,i_out,d_out,temp;
temp=diff[curr_];
if(curr_+1>=20)curr_=0;
else curr_+=1;
sum_diff-=diff[curr_];
//
减去最老的一次温差值
diff[curr_]=T_target-T_real;
//
当前温差
sum_diff+=diff[curr_];
//
加上最新的一次温差值,即当前
//
比例项输出
比例<
/p>
x
当前温差
//
积分项输出
积分系数
x
积分值
p_out=KP*diff[curr_];
i_out=KI*sum_diff;
d_out=KD*(diff[curr_]-temp);
//
微分项输出
微分系数
x
微分值
pwm_0=KC*T_target;
if(i_out>100)i_out=100;
if(i_out<-100)i_out=-100;
PWM=p_out+i_out+d_out+pwm_0;
if(PWM<0)PWM=0;
//
总输出量
//
维持功率项
维持系
数
x
设定温度
防止积分饱和
//
积分分离
//
小于
0
时为
0
//
大于
100
时为
100
else
if(PWM>=100)PWM=100;
}
-
-
-
-
-
-
-
-
-
上一篇:土壤温湿度传感器c程序
下一篇:微机原理与接口技术期终试卷