微机原理无刷直流风扇调速与测速分析.docx
《微机原理无刷直流风扇调速与测速分析.docx》由会员分享,可在线阅读,更多相关《微机原理无刷直流风扇调速与测速分析.docx(21页珍藏版)》请在冰豆网上搜索。
微机原理无刷直流风扇调速与测速分析
████工学院
微机原理
(3级)项目报告
项目名称:
微机原理课程设计
项目题目:
无刷直流风扇调速与测速
指导教师:
███
系别:
机电系专业:
机械设计制造及其自动化
组员信息学号:
姓名:
王██
组员信息学号:
姓名:
郭██
完成时间:
2014年12月01日至2016年1月3日
成绩:
评阅人:
1、学习目标....................................................
(1)
2、项目要求....................................................
(1)
3、转速测量和调节系统的硬件构成................................
(1)
4、程序流程图并说明方案思路....................................(3)
5、风扇转速与占空比之间的关系表格和曲线........................(4)
6、设计程序....................................................(5)
7、分析设计过程出现的问题......................................(12)
8、方案总结....................................................(13)
一、学习目标
本次系统作业的目的在于:
①通过脉冲宽度调节实现无刷直流风扇转速的改变;
②借助风扇转动时产生的脉冲信号,测量风扇的转速并显示;
③比较每组风扇从某一转速(600r/min)到另一转速(2000r/min)稳定运转的所需要的时间。
通过比较试验结果的估算结果并讨论结果差异的主要原因,让学生展示对无刷直流风扇数学模型建立和调节方法局限性有深入理解。
二、项目要求
检查项目
要求
转速显示
风扇转速能够显示在LED上,转速单位是r/min,刷新周期为1秒钟左右
风扇转速可调
风扇转速可以改变,根据要求转速在700-1400r/min
风扇转速与显示
通过简单方法给风扇加负载,随着转速的下降应该看到转速变化的显示
转速指令输入环节
通过串口或键盘输入
给定转速
给定某一转速,1200-1500之间,看显示转速的稳定性
转速调节功能
在稳定转动条件下1500r/min,在30cm处加载一个外加一个风扇,对照加载前后的稳态转速
回答问题
随机提出有关转速测量、PWM输出和转速控制方面的问题,要有针对性,检查设计过程中的付出。
三、系统硬件构成
风扇电路:
接线:
黄线接Vcc,黑线接地,绿线接P3^2,蓝线接P2^5。
输出:
OC输出,如下图
4、画程序流程图并说明方案思路
程序主要用查询法判断需要执行的操作,并且利用中断处理函数来产生各种对应的标志位来通知主循环,在主循环中进行要求的运算。
其中T0定时约500us,它的每次中断相当于输出一个载波脉冲,实际上是用载波脉冲数为200个,载波周期为500us的方式构成周期为100ms的PWM波。
T1用做波特率发生器。
T2定时60ms。
每次T2中断能重置一次按键处理标志位,这个标志位能保证每60ms内只允许处理一次按键操作,让按键处理既能高速增减,也能准确;此外当有合计25次T2的中断发生时,它能保存当前的转速值并且通知主循环刷新数码管显示请况,因此我们计算转速的方式是“统计1.5s内风扇的转动圈数”。
利用在T2中断的定时判断,也能把当前数码管的显示请况发回PC机。
串口通讯方面,也是利用一个标志位来申明是否接受了数据。
使用“操作符+操作数据”的5字节字符串数据格式,例如用“A0980”代表需要风扇按n=980r/min的速度运行。
通知标志被主循环检测到的时候,会将串口数据检查并且保存成整数形式,方便后续函数的调用。
当串口数据不合理时,会发送信息到PC机。
五、风扇转速与占空比之间的关系表格和曲线
编程实现单片机给PC定时发送转速与占空比数据后,取对应的数据制表如下。
占空比(%)
100
95
90
85
80
75
70
65
60
55
50
转速n/(r/min)
2140
1960
1820
1740
1680
1600
1500
1420
1300
1180
1060
占空比(%)
45
40
35
30
25
20
15
10
5
0
转速n/(r/min)
900
740
580
440
100
0
0
0
0
0
将500个转速与占空比数据拟合成关系曲线如下
可以发现,在风扇正常转动时,转速与占空比有着正相关的关系,占空比越大,风扇的转速越高。
此外,当占空比小于26%时,风扇停转。
六、设计程序
1、主程序:
#include
#definejingzhen11059200UL/*使用11.0592M晶体*/
#definebotelv9600UL/*波特率定义为9600*/
volatileunsignedcharsending;
sbitdula=P2^6;//段选信号的锁存器控制
sbitwela=P2^7;//位选信号的锁存器控制
sbitPwmOut=P2^5;//PWM输出位置蓝线
sbitneed_steady=P3^4;//接地后开始调整
sbitHideValue=P3^5;//接地后显示目标转速
sbitK3=P3^6;//增加占空比按钮
sbitK4=P3^7;//减少占空比按钮
unsignedcharcodewei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//数码管各位的码表
unsignedcharcodeduan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//0-9的码表
unsignedcharSPEED,SPEED_temp,count_time,count_send,wait;
unsignedcharPWM_count,PWM_turn,PWM_max;//控制PWM波的计数,转变值,周期个数,
unsignedcharNumber[8]={0},value[6]={0};//数码管显示缓存和串口字符串数据缓存
intTarget;
bitflag=0,flag_k=0,flag_send=0,flag_direct=0;//通知标志
voidTimer0Init(void);//初始化函数
voidTimer2Init(void);
voidExt0Init(void);
voidUARTInit(void);
voidcheck();
voidVALUE_To_Num(intnum,unsignedchard);//数据填入数码管函数
voiddirect();//直接与反馈调节PWM函数
voidadjust();
voidDisplay();
voidsend(unsignedchard);
voidsendc(unsignedchar*pd);
voidsendc_num(unsignedchar*pd);
voidmain()
{
flag_direct=0;
flag_send=0;
wait=5;
PWM_count=0,PWM_turn=170,PWM_max=200;
Timer0Init();
Timer2Init();
Ext0Init();
UARTInit();
need_steady=1;//接地后开始调整
HideValue=1;//接地后显示目标转速
K3=1;//增加占空比按钮
K4=1;//减少占空比按钮
while
(1)//主循环
{
if(flag_k)//控制每60ms允许通过按键调整一次PWM_turn
{
if(!
K3&&PWM_turn<190)PWM_turn++;
if(!
K4&&PWM_turn>10)PWM_turn--;
flag_k=0;
}
if(flag_direct)
{
check();
direct();
flag_direct=0;
wait=4;//传送了直接值后不能马上进行反馈调整,误差太大了
}
if(flag)//控制约1.5s允许调整数码管显示值
{
VALUE_To_Num((500*(SPEED_temp)/25),4);
if(wait>0)
wait--;//减缓约4.5~6s才允许反馈调整
if((0==wait)&&(!
need_steady))
{//满足条件时启用转速反馈调整
adjust();
}
flag=0;
}
VALUE_To_Num(PWM_turn,0);
if(!
HideValue)
{VALUE_To_Num(Target,0);}//直接按下K2显示当前的目标转速的值,可以检查有没有收到串口数据
if(flag_send)
{sendc_num(Number);
flag_send=0;
}
Display();
}
}
2、初始化子程序
voidTimer0Init(void)
{
TMOD|=0x01;//T016位定时
TL0=0x33;//设置定时初值
TH0=0xFE;//设置定时初值
TF0=0;//清除TF0标志
EA=1;//总中断打开
ET0=1;//定时器0中断打开
TR0=1;//定时器0开始计时
}
voidTimer2Init(void)
{
RCAP2H=0x28;
RCAP2L=0x00;//定时60ms
EA=1;//打开总中断
ET2=1;//打开定时器2中断
TR2=1;//定时器2开始计时
}
voidext0Init(void)
{
INT0=1;//置高接收口P3.2
PX0=1;//设置高中断优先级
EA=1;//全局中断开
IT0=1;//边沿触发
EX0=1;//外部中断0开
}
voidUARTInit(void)//9600bps@11.0592MHz
{
EA=0;//暂时关闭中断
TMOD|=0x20;//定时器1工作在模式2,自动重装模式
SCON=0x50;//串口工作在模式1
TH1=256-jingzhen/(botelv*12*16);//计算定时器重装值
TL1=256-jingzhen/(botelv*12*16);
PCON|=0x80;//串口波特率加倍
PS=1;//给串口中断高优先级
ES=1;//串行中断允许
TR1=1;//启动定时器1
REN=1;//允许接收
EA=1;//允许中断
}
3、中断操作程序
/*********************************************************
外部中断0统计转速脉冲
*********************************************************/
voidext0(void)interrupt0//负责统计速度值,信号下降沿产生中断
{
SPEED++;
}
/*********************************************************
定时器0负责调控PWM波
*********************************************************/
voidtime0(void)interrupt1using1//负责产生PWM波
{
TL0=0x33;//设置定时初值
TH0=0xFE;//设置定时初值
PwmOut=PWM_count1:
0;//计数值在0~199共200个组成;PWM_turn=0时只输出低电平,PWM_turn=PWM_max时只输出高电平
PWM_count++;
if(PWM_count>=PWM_max)//PWM_count达到顶端时回到初始
PWM_count=0;
}
/*********************************************************
串行中断服务函数接受速度控制命令
*********************************************************/
voidserial()interrupt4
{
staticunsignedcharwrite_point=0;
staticbitread_able=0;
unsignedcharTemp;
if(RI)//判断是接收中断产生
{
RI=0;//标志位清零
Temp=SBUF;//读入缓冲区的值
if(read_able)
{
value[write_point]=Temp;
write_point++;
if(write_point>4)//只读入4个字节
{
flag_direct=1;//通知主函数可以调节PWM了
read_able=0;
write_point=0;
wait=4;//立即暂停反馈调整
}
}
if(Temp=='A')//'A'作为特征码检测,也可以使用其他的字母来规定控制代码
{
write_point=0;//一旦收到A____,指针回到开头并且允许接受数据
read_able=1;
}
}
if(TI)//如果是发送标志位,清零
{
TI=0;
sending=0;//清正在发送标志
}
}
/*********************************************************
定时器2调节数码管的刷新速度
*********************************************************/
voidtime2(void)interrupt5using1//定时器2中断
{
TF2=0;//必要的软件清中断标志
count_time++;
flag_k=1;
if(count_time>=25)
{
flag=1;
SPEED_temp=SPEED;
SPEED=0;
count_time=0;
count_send++;
}
if(count_send>=5)
{
flag_send=1;
count_send=0;
}
}
4、辅助处理程序
/*********************************************************
检查串口数据
*********************************************************/
voidcheck()
{unsignedchari;
for(i=0;i<4;i++)
{
if(value[i]<'0'||value[i]>'9')
value[i]='0';
}
Target=(value[0]-'0')*1000+(value[1]-'0')*100+(value[2]-'0')*10+(value[3]-'0');
if(Target>2180||Target<280)//禁止不可调节范围的PWM
sendc("范围外的转速值!
!
\n");
}
/*********************************************************
将数据填入数码管缓存
*********************************************************/
voidVALUE_To_Num(intNum,unsignedchard)
{unsignedchari;
for(i=7;i>3;i--)
{
Number[i-d]=Num%10;
Num=Num/10;
}
}
/*********************************************************
直接调节PWM函数
*********************************************************/
voiddirect()
{
if(Target>2180||Target<280)//禁止不可调节范围的PWM
return;
if(Target<1520)
PWM_turn=(0.00003*Target*Target+0.01311*Target+53.467);//使用分段函数更贴合PWM-n的关系
else
PWM_turn=(-0.00009*Target*Target+0.4299*Target-302.08);
if(PWM_turn>200)PWM_turn=200;
}
/*********************************************************
反馈调节PWM函数
*********************************************************/
voidadjust()
{
doublenum;
num=SPEED_temp*20;
if(Target>2180||Target<280)//禁止不可调节范围的PWM
return;
if(Target<1520)
PWM_turn=PWM_turn+(0.00006*Target+0.01311)*(Target-num);//原理是dy=f'(x)*dx
else//属于比例调节
PWM_turn=PWM_turn+(-0.00018*Target+0.4299)*(Target-num);
if(num<(Target/4))//防堵转检测
{direct();
wait=4;
}
if(PWM_turn>200)PWM_turn=200;
}
/*********************************************************
数码管显示程序
*********************************************************/
voidDisplay()
{unsignedcharnum;
unsignedintm;
for(num=0;num<8;num++)
{P0=wei[num];
wela=1;
wela=0;
P0=duan[Number[num]];
dula=1;
dula=0;
for(m=128;m>0;m--);//时间间隔短,利用人眼的余辉效应,觉得每个数码管都一直在亮。
}
}
/*------------------------------------------------
发送一个字节
------------------------------------------------*/
voidsend(unsignedchard)//发送一个字节的数据,形参d即为待发送数据。
{
SBUF=d;//将数据写入到串口缓冲
sending=1;//设置发送标志
while(sending);//等待发送完毕
}
/*------------------------------------------------
发送一个字符串
------------------------------------------------*/
voidsendc(unsignedchar*pd)
{
while((*pd)!
='\0')//发送字符串,直到遇到0才结束
{
send(*pd);//发送一个字符
pd++;//移动到下一个字符
}
}
voidsendc_num(unsignedchar*pd)
{unsignedchart;
for(t=0;t<8;t++)
{
if(t==4)send('');
send((*pd)+'0');//发送一个字符
pd++;//移动到下一个字符
}
send('\n');
}
7、分析设计过程出现的问题
1.在设计PWM的调控方式的过程中,我们遇到了一个选择PWM波周期的问题。
查阅资料后发现,PWM波的周期大小能直接影响小风扇的输出转矩。
在实际测试过程中,第一次选用载波脉冲数为200个,载波周期为250us的方式构成周期为50ms的PWM。
我们发现,此时使风扇恰好保持转动的占空比为35%。
第二次选用载波脉冲数为200个,载波周期为500us的方式构成周期为100ms的PWM。
此时使风扇恰好保持转动的占空比为26%,并且相对上一次的选择在调速过程中,相同的占空比能输出更大的转速。
因此相对的,第二种方案调速能力更加优秀。
最终选择了用载波脉冲数为200个,载波周期为500us的方式构成周期为100ms的PWM。
2.设计中关于测定转速与占空比的关系的次序也是一个问题。
在设计的后期,我们注意到从高占空比测到低占空比以及从低到高测,得到的PWM-n关系曲线在占空比相同时,转速的差值可以很大,这直接影响到占空比直接调节函数的精度。
为解决这个问