AVR单片机PID自动控制转速
2014-11-22郝云鹏
郝云鹏
(鞍山师范学院物理科学与技术学院,辽宁鞍山114007)
PID是最常用的一种自动控制方式.PID是按偏差的比例(P)、积分(I)和微分(D)进行自动控制的控制器.
比例环节:即时成比例地反应控制系统的偏差信号,偏差一旦产生,立即产生控制以减少偏差;
积分环节:主要用于消除静差,提高系统的无差度;
微分环节:能反映偏差信号的变化趋势(变化速率),并能在偏差信号的值变得太大之前,在系统中引入一个有效的早期修正信号,从而加快系统的动作速度,减少调节时间[1].
用单片机对直流电机的转速进行自动控制比起其它方法经济性好且系统简单,而用AVR单片机比起51单片机对直流电机的转速进行自动控制更为简便,因为AVR单片机内部有很好用的直接用TC产生PWM的方法.
调速的原理,取测速值与设定值的差值作为输入值,用PWM的方法调节电压的大小,使直流电机转速趋近于设定值[2].
转速自动调节的精度与Kp,Ki,Kd3个系数有很大的关系,需经反复调试才能得出.
转速的显示,采用了4位的数码管.速度的调试采用了外部中断的技术.PWM调速应用了定时计数器的技术.PID算式采用了增量型的PID算式[3].
系统框图如图1.
图1 系统框图
C程序如下:
#include < iom16v.h >[4]
#include < macros.h >[4]
#define F_CPU 8000000
unsigned char Duan[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
unsigned char Data_Buffer[8]={0,0,0,0,0,0,0,0};
unsigned char i=0;
int e,e1,e2;
float uk;
int out=0;
unsigned int SpeedSet=150;
unsigned int Inpluse=0,num=0;
unsigned char time=0,bit=0;
#pragma interrupt_handler timer2_fun:5
void timer2_fun(void)
{
bit++;
time++;
if(bit>7)bit=0;
PORTA=0XFF;
PORTC=Duan[Data_Buffer[bit]];
switch(bit)
{
case 0:PORTA=0X7F;break;
case 1:PORTA=0XBF;break;
case 2:PORTA=0XDF;break;
case 3:PORTA=0XEF;break;
case 4:PORTA=0XF7;break;
case 5:PORTA=0XFB;break;
case 6:PORTA=0XFD;break;
case 7:PORTA=0XFE;break;
}
}
#pragma interrupt_handler int0_fun:2
void int0_fun(void)
{
Inpluse++;
}
void init()
{
DDRA=0XFF;PORTA=0X00;
DDRB=0X00;PORTB=0X00;
DDRC=0XfF;PORTC=0X00;
DDRD=0XF0;PORTD=0XFF;
TCCR1A=0XA3;
TCCR1B=0x0D;
TCCR0=0X6D;
TCCR2=0X05;
TCNT2=256-F_CPU/128/500;
TIMSK|=0X40;
MCUCR=0X02;
SEI();
GICR=0X40;
}
void PIDControl()
{
float Kp=50,Ki=30,Kd=3;
if(time==200)
{
time=0;
num=Inpluse*5;
Inpluse=0;
e=SpeedSet-num;
uk=uk+(Kp*(e-e1)+Ki*e+Kd*(e-2*e1+e2))/50;
out=(int)uk;
e2=e1;
e1=e;
if(out>1022){ out=1022;
}
else if(out<0)
{
out=0;
}
OCR1A=out;
}
}
void SetSpeed()
{
if((PIND&0X01)==0)
{
SpeedSet+=10;
if(SpeedSet>1500)
{
SpeedSet=1500;
}
while(!(PIND&0X01));
}
if((PIND&0X02)==0)
{
SpeedSet-=10;
if(SpeedSet<0)
{
SpeedSet=0;
}
while(!(PIND&0X02))
;
}
}
void SegRefre()
{
Data_Buffer[0]=SpeedSet/1000;
Data_Buffer[1]=SpeedSet%1000/100;
Data_Buffer[2]=SpeedSet%100/10;
Data_Buffer[3]=SpeedSet%10;
Data_Buffer[4]=num/1000;
Data_Buffer[5]=num%1000/100;
Data_Buffer[6]=num%100/10;
Data_Buffer[7]=num%10;
}
void main(void)
{
init();
while(1)
{
SegRefre();
SetSpeed();
PIDControl();
}
}
调速的难点是精度和响应快慢,本文是采用反复试验的方法,不断调整Kp,Ki,Kd3个参数,直到实现我们的要求.
本文先在Proteus仿真软件上进行了实验,获得通过后,又在实物上进行了实验.
[1]江海波.深入浅出AVR单片机[M].北京:中国电力出版社,2007.
[2]老杨.AVR单片机工程师是怎样炼成的[M].北京:电子工业出版社,2012.
[3]张军.AVR单片机应用系统开发典型实例[M].北京:中国电力出版社,2005.
[4]ATMEL Corporation.AVR 单片机 ATmega16中文说明书[M].USA:ATMEL Corporation,2001.