直流电机调速课设报告.docx
《直流电机调速课设报告.docx》由会员分享,可在线阅读,更多相关《直流电机调速课设报告.docx(15页珍藏版)》请在冰豆网上搜索。
直流电机调速课设报告
基于ATMEGA16的直流电机调速
1设计题目
本次单片机原理与系统课程设计题目是基于ATMEGA16单片机的直流电机调速系统,根本要求是调节电机转速使之到达指定速度;主要使用了ATMEGA16三个定时器〔计数器〕分别用来定时,脉冲计数,PWM波产生。
利用ATMEGA16自带的160位A/D转换采集电位器电压从而得到目标速度,用pid控制器调节输出pwm波占空比,调节直流电机的电枢电压,并用1602液晶显示器显示当前的速度和目标速度,实现负反应电机调速。
2设计目的
直流电机具有良好的启动性能和调速特性,对直流电机的调速在现实中有广泛的应用。
这次课程设计也是对本学期学习的单片机原理,电机学,自动控制原理等知识的应用。
3设计方案及原理
3.1总体设计方案
本设计是基于ATMEGA16单片机的直流电机调速,通过采集电位器上的电压得到目标速度,通过定时器定时采集脉冲计数器采集的个数得到当前速度,然后通过pid控制器计算出需要输出的占空比,通过MEGA16的16位PWM发生器产生PWM方波,输入到电机驱动模块,改变电机的电枢电压,从而控制电机的运行。
3.2系统组成框图
本系统主要包括10位A/D转换,定时器,脉冲计数模块,PWM发生器,LCD液晶显示模块,电机驱动模块等。
系统组成框图如图1所示。
图1系统组成框图
4硬件设计
4.1驱动电路
直流电机的驱动采用L298驱动芯片来驱动电机。
L298N是ST公司生产的一种高电压、大电流电机驱动芯片。
主要特点是:
工作电压高,最高工作电压可达46V;输出电流大,瞬间峰值电流可达3A,持续工作电流为2A;额定功率25W。
内含两个H桥的高电压大电流全桥式驱动器。
图2l298驱动电路
4.2LCD液晶显示设计
液晶显示模块:
本系统设计的显示电路由液晶显示器LCD1602取代普通的数码管完成密码显示,并伴有提示信息,方便操作。
液晶显示模块如图3所示。
图3LCD液晶显示模块
4.3速度给定〔电位器位移传感器〕
用A/D采集电位器电压的方式来判断电位器的位移量百分比。
这样就可以随意调节电机转速的给定量,较键盘输入的给定方式,这样更方便调节给定速度,也更容易实现。
此模块如图4所示:
图4速度给定模块
5软件设计
这个系统是基于Atmel公司的AVRMAGA16单片机实现的。
ATmega16是8位AVR微控制器具有16KB系统内可编程Flash的8位AVR微控制器,基于增强的AVRRISC结构的低功耗CMOS微控制器。
系统集成两个具有独立预分频器和比拟器功能的8位定时器/计数器,一个具有预分频器、比拟功能和捕捉功能的16位定时器/计数器,四通道PWM,8路10位ADC等模块,正好符合本次课程设计的要求。
5.1液晶显示程序局部
对LCD1602进行初始化。
并同步显示当前速度和目标速度。
5.2定时模块初始化
采用T/C2定时器模块的CTC模式,产生基准定时时间,作为定时对脉冲数读取和定时更新PWM占空比的控制周期。
5.3PWM发生模块
采用16位T/C1定时器模块的相位修正PWM模式。
这是一种双斜波操作,其对称性十分适合于电机控制。
5.4脉冲计数模块
采用T/C0计数器模块,通过设置T/C0控制存放器,使得时钟由TO引脚引入,上升沿触发。
5.5A/D模块
采用10位A/D转换来获取电位器的电压,从而求出其位移量,得到给定的目标速度。
5.6PID控制模块
采用增量式PID控制方法。
以实现电机能快速响应并能尽量结束静差。
其实现代码为:
change=(Kp*(error0-error1)+Ki*error0+Kd*(error0-2*error1+error2));
speed_control=(speed_control+change);
程序流程图如图5所示:
图5程序流程图
6系统仿真及实际调试
此系统软件由IAR编译完成,然后在仿真软件proteus上进行仿真。
当改变电位器的位移时,目标速度发生改变,在大约1s的调整时间后,速度到达稳定,静态误差在±1左右。
仿真结果如图6所示。
图6仿真电路图
7总结
通过这次课程设计,我得到了一次用电子技术知识、单片机知识、C语言知识等知识的一次综合应用的时机,尤其对于软硬件的综合系统控制让我对电子世界的研究建立了浓厚的兴趣,同时我也对这些方面的知识有了更深的理解。
本次课程设计我是独立完成,这使我们能锻炼自己各方面的能力,并在以后的生活中加以改善。
在课程设计中碰到了很多的问题,感谢老师的精心指导,使我能够顺利地解决问题,少走了很多弯路,最终让系统趋于完善。
同时,在后续的学习过程中我会继续努力争取解决上述问题。
当然,通过这次课程设计,我也发现了自身的很多缺乏,在以后的学习中,我会不断的完善自我,让自己的水平更上一层楼。
参考文献
[1]王思明,张金敏.单片机原理及应用系统设计[M].北京:
科学出版社,2021.
[2]彭伟.单片机C语言程序设计实训100例[M].北京:
电子工业出版社,1996.
[3]谭浩强.C程序设计[M].北京:
清华大学出版社,2004.
附录
程序清单:
/*IncludeI/Odefinitionfile*/
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
#definelcd_rsPORTA_PORTA5
#definelcd_rwPORTA_PORTA6
#definelcd_enPORTA_PORTA7
uchartable0[16]="YouSetis";
uchartable1[16]="NowSpeedis";
uchartable2[16]="CourseDesign";
uchartable3[16]="Madebyhuqay";
uinti,count;
ucharbm_count;
uintadc_data;
floatset_speed;
floatspeed_control;
struct{//电机pid
interror0;
interror1;
interror2;
floatchange;
floatKp,Kd,Ki;
}SpeedPid;
voiddelay(uintk)
{
unsignedintm,n;
for(m=0;m{
for(n=0;n<114;n++);
}
}
voidwrite_com(ucharcom)
{
lcd_rs=0;
PORTC=com;
delay(5);
lcd_en=1;
delay(5);
lcd_en=0;
}
voidwrite_data(uchardata)
{
lcd_rs=1;
PORTC=data;
delay(5);
lcd_en=1;
delay(5);
lcd_en=0;
}
voidlcd_init()
{
lcd_en=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
}
voidlcd_write(uchara,ucharb,ucharc,uchard,uchare)
{
ucharnum=0;
if(e==1)
{
table0[12]=a+'0';
table0[13]=b+'0';
table0[14]=c+'0';
table0[15]=d+'0';
write_com(0x80);
for(num=0;num<16;num++)
{
write_data(table0[num]);
delay(5);
}
}else
{
table1[12]=a+'0';
table1[13]=b+'0';
table1[14]=c+'0';
table1[15]=d+'0';
write_com(0x80+0x40);
for(num=0;num<16;num++)
{
write_data(table1[num]);
delay(5);
}
}
}
voiddata_in(intdata,uchare)
{
uchara,b,c,d;
a=data/1000;
b=(data/100)%10;
c=(data/10)%10;
d=data%10;
lcd_write(a,b,c,d,e);
}
voidfirst_lcd()
{
ucharnum=0;
for(num=0;num<16;num++)
{
write_data(table2[num]);
delay(5);
}
write_com(0x80+0x40);
for(num=0;num<16;num++)
{
write_data(table3[num]);
delay(5);
}
for(num=0;num<20;num++)
{
delay(100);
}
}
voidspeed_pid()
{
SpeedPid.error2=SpeedPid.error1;
SpeedPid.error1=SpeedPid.error0;
SpeedPid.error0=(int)(set_speed-bm_count);
SpeedPid.Kp=10.7;
SpeedPid.Ki=0.95;
SpeedPid.Kd=0;
SpeedPid.change=(SpeedPid.Kp*(SpeedPid.error0-SpeedPid.error1)+SpeedPid.Ki*SpeedPid.error0+SpeedPid.Kd*(SpeedPid.error0-2*SpeedPid.error1+SpeedPid.error2));
speed_control=(speed_control+SpeedPid.change);
if(speed_control<0)speed_control=0;
if(speed_control>1023)speed_control=1023;
}
voidport_init()
{
DDRA=0XFE;
PORTA=0X00;
DDRB=0XFE;
PORTB=0X00;
DDRC=0XFF;
PORTC=0XFF;
DDRD=0XFF;
PORTD=0X00;
}
voidadc_init()
{
ADMUX=0X40;//
SFIOR=0X00;//连续转换
ADCSRA=0XEE;//单次转换
}
voidtimer()
{
TCCR2=0X1D;//1024分频,ctc模式
TCNT0=0X00;
OCR2=0XFF;//4ms定时
TIMSK=0X80;//比拟中断翻开
}
voidpwm_init()
{
TCCR1A=0X83;
TCCR1B=0X03;
}
voidcounter_init()
{
TCCR0=0X07;//t0引脚引入,上升沿触发
TCNT0=0X00;
TIMSK|=0X01;
}
voidmain()
{
port_init();
lcd_init();
adc_init();
timer();
pwm_init();
counter_init();
first_lcd();
SREG=0X80;//开全局中断
while
(1)
{
;
}
}
#pragmavector=TIMER2_COMP_vect
__interruptvoidT2_CTC(void)
{
count++;
if(count>2)
{
count=0;
bm_count=TCNT0;
TCNT0=0;
}
speed_pid();
OCR1A=adc_data;
data_in(bm_count,2);
}
#pragmavector=TIMER0_OVF_vect
__interruptvoidT0_OVF(void)
{
TCNT0=0X00;
}
#pragmavector=ADC_vect
__interruptvoidADC_get(void)
{
adc_data=ADC;
set_speed=((float)adc_data/1024)*100;
data_in((uint)set_speed,1);
ADCSRA_ADSC=1;
}