2019年全国大学生电子竞赛风板设计
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
2019年全国大学生电子竞赛
风板控制装置(I题)
【高职高专组】
2019年5月25日
本系统以STC15W1K16S单片机作为主控芯片,使用PID算法软件编程,实现对风板的精准控制。
系统主要有电源模块、角度测量模块、电机驱动模块、显示模块、按键模块、和声光模块。
通过精密电位器反馈实际风板角度,在利用软件PID反馈输出PWM来改变直流风机风力的大小,使得风板达到需求的角度。
LCD显示风板的角度,单片机对采集的数据进行分析,实时调整PWM输出,通过驱动芯片L298N控制风机风速,使其到达稳定状态,并带有声光提醒功能,让系统更直观、智能化,经反复测试达到了设计要求。
关键词:STC15W1K16S;PID;PWM;精密电位器
1.系统方案 (4)
1.1主控模块的论证与选择 (4)
1.2电机驱动模块的论证与选择 (4)
1.3角度测量模块的论证与选择 (4)
1.4显示模块的论证与选择 (4)
1.5电源模块的论证与选择 (4)
2.系统理论分析与计算 (5)
2.1角度的确定 (5)
2.2风速的控制 (5)
3硬件电路与程序设计 (5)
3.1硬件电路设计 (5)
3.1.1电机模块电路原理图 (5)
3.1.2电源模块电路原理图 (6)
3.1.3显示模块电路原理图 (6)
3.1.4按键模块电路原理图 (7)
3.1.5声光报警模块电路原理图 (7)
3.1.6单片机最小系统电路原理图 (7)
3.2程序设计 (8)
3.2.1程序功能描述 (8)
3.2.2程序流程图 (8)
4.测试方案与测试结果 (9)
4.1硬件电路测试 (9)
4.2软件调试 (9)
4.3硬件软件联调 (9)
4.4测试分析与结论 (9)
5.设计总结 (9)
附录一 (10)
1.系统方案
风板系统主要由主控模块、角度测试模块、电机驱动模块、显示模块、电源模块组成,下面分别论证这几个模块的选择。
1.1主控模块的论证与选择
方案一:使用传统的STC51系列芯片作为主控芯片,优点是成本低,使用简单。
缺点是I/O口少,运算能力弱,不能满足风板的PID算法,功能单一。
方案二:使用STC15W1K16S系列单片机作为主控芯片,优点是运算能力较快,低功耗,功能较丰富,性价比高。
综合以上两种方案,选择方案二。
1.2电机驱动模块的论证与选择
方案一:采用纯硬件组合构成驱动电路,这种方法成本低,但是结构复杂,需要构建电路图,在驱动电路中采用大量的晶体管相互连接,使得电路复杂,抗干扰能力差,可靠性低。
方案二:采用专门的电机驱动芯片,这种芯片它内部已经考虑到了电路的抗干扰能力,安全、可靠。
连接电路简单,设计者不需要多硬件电路考虑很多,可将重点放在软件中的算法设计,大大提高了工作效率。
综合以上两种方案,选择方案二。
1.3角度测量模块的论证与选择
方案一:采用精密电位器,它根据风板的转动改变输出信号的电压值,通过A/D转换读取信号,从而检测风板的角度。
这种方法构建电路简单,性价比高。
对于这次的角度测量可以满足要求,所以选择方案一。
1.4显示模块的论证与选择
方案一:采用常见的数码管显示,这种方案,虽然成本低,但是只能显示简单的字符和数字,显示位数较多时会占用大量的I/O接口,且显示不稳定。
方案二:采用LCD显示,用12864的显示为128*64,显示面积大,数字和
汉字显示容易实现,程序要求不是很高,电路搭建简单,使用I/O接口少。
综合以上两种方案,选择方案二。
1.5电源模块的论证与选择
电源是任何系统能否运行的能量来源,本系统的电源模块是为单片机控制器、电机驱动、角度检测模块等提供电源。
方案一:通过电阻分压的形式将整流后的电压分别降为控制芯片和电机所需的电压,此种方案原理和硬件电路连接都比较简单,但是能量损耗比较大,发热严重,对系统的稳定性不够好,在实际应用中一般不采用。
方案二:通过稳压芯片对整流的电压进行降压、稳压处理,比如利用7805/7812等稳压芯片,此种方案的可靠性、安全性都比较高,而且电路设计比较简单,易实现。
根据系统的具体要求,采用方案二作为系统的供电模块。
2.系统理论分析与计算
2.1角度的确定
本系统的角度的确定主要是对定位器进行量化,然后在具体确定风板的角度的,此方法比较简单方便。
但是也存在一定的误差。
但对于系统的额影响不大,所以采用方法来确定风板的角度。
2.2风速的控制
风速的快慢直接决定了系统风板角度的大小。
通过PID调节,单片机输出PWM波形,可对风板进行快速、准确的调整。
通过不断调整P(比例)、I(积分)、D(微分)值,系统的稳定性得到明显的提高,响应时间也提高了,由实验可得知比例使反应变快,微分使反应提前,积分使反应滞后,在一定范围内,P,D 值越大,调节的效果越好。
3硬件电路与程序设计
3.1硬件电路设计
系统总体框图如图3.1所示。
图3.1 系统总体框图
3.1.1电机模块电路原理图
3.1.2电源模块电路原理图
电源模块是采用的三端稳压芯片7805完成的输入12v输出5v的功能,在采用这个方式的电源有以下这些优点,比较简单,方便,电路简单,稳压效果相对比较好,但是缺点是,在为后面的电机供电的时候会导致其他部分的电路出现电源不稳定的情况。
如图3.1.2是电源部分电路原理图。
图3.1.2 电源电路原理图
3.1.3显示模块电路原理图
显示电路采用的是12864液晶显示,12864相对于1602来说显示的类容会更多,而且结构也比较简单,所以用12864来显示风板的角度,以及状态等信息。
12864和1602液晶差不多,它有20个引脚,一脚接地,2脚和3脚一起用来调节光度,4脚到14脚分别接到单片机的P2.2/P2.1/P2.0/P0口作为信息的输入,15脚、17脚、19脚接电源,16脚18脚置空,20脚接地。
如图3.1.3所示是显示模块的电路原理图。
另外还有一部分的显示是用来指示用的,采用的是发光二极管来显示状态信息。
发光二极管的阴极接到单片机端口,阳极接到电源正极,这样驱动能力更强,显示更清楚。
图3.1.3 12864显示部分
3.1.4按键模块电路原理图
按键部分有四个按键,分别对应四种功能,按键分别接到单片机P3.2到P3.5端口,中间分别连接这一个1K的电阻,起到限流的作用,如图3.1.4所示
图3.1.4 按键部分原理图
3.1.5声光报警模块电路原理图
次设计结构简单,三极管驱动扬声器,驱动能力比较强。
有较好的效果。
如图3.1.5所示,是声光报警原理图。
图3.1.5 声光报警原理图
3.1.6单片机最小系统电路原理图
本系统的单片机采用的是STC15W1K16S系列单片机作为主控芯片,优点是运算能力较快,低功耗,功能较丰富,性价比高。
对于风板角度的测量进行的PID算法有比较好的作用。
如图3.1.6所示是单片机的最小系统的原理图。
图3.1.6 单片机最小系统原理图
3.2程序设计
3.2.1程序功能描述
根据设计要求,软件部分要实现风机转速控制以及声光报警与液晶显示。
(1)风机转速控制部分:在按键按下设定风板的角度后,风板15s内处于指定位置并稳定5秒以上,上下波动不超过5度,根据精密电位器反馈的电量信号使得软件程序通过PID算法调整风机转速来调整风板的位置。
(2)键盘设置:在按键按下后,设定相应的角度,使得风机做出相应转速,风板达到指定位置。
(3)液晶显示部分:液晶显示设定角度和风板实际角度。
3.2.2程序流程图
4.测试方案与测试结果
4.1硬件电路测试
对各个模块进行测试,测试后使得电路能够正常额运动,部分电压正常。
4.2软件调试
对程序调试,对程序调试出现的错误进行修改,进行调试。
使得软件能够正常的运行,在下载到控制芯片。
4.3硬件软件联调
把软件下载到控制芯片单片机上,然后把电路通电,测试电路能否能够正常的工作,是否能够到达预定的效果。
4.4测试分析与结论
5.设计总结
这次电子设计比赛中,学到了许多知识,拓宽了我们的眼界,只是说它让我们的能力提高就已经足以成为我们努力付出的回报。
但在设计时,我们团队也遇到了许多的困哪,搭建硬件时,由于对角度的测量不准确,误差较大,我们想尽了一切办法来解决这个问题,最后还是解决了误差大的问题,软件调试中PID参数设置成为了最难得问题,过大调整系统波动较大,过小调整风板很难到达预定的角度,但是我们积极的去解决问题,找最合适的方法使得系统在稳定的情况下使得风板又能到达预定的角度。
理论总是与实际密不可分的,所以我们通过大量的实验,测试数据,对测量的数据处理,使得结果更加的准确。
在硬件的方面,我们自己动手焊接了不少的硬件电路,用到了大量的基础知识,还把实训中学到的焊接技术运用到这次比赛,使得焊接的工艺大大的提高了,我们组在面对困难时就十分团结,大家有明确的分工,共同讨论,为我们日后的工作能力打下了基础。
这次大赛给予了我们很多,通过这次比赛大家一起交流学习,互相帮助,增强了合作的意识,老师的指导也是我们成功的一个总要因素。
所以感谢我们的指导老师,也祝愿此次大赛圆满成功,我们团队取得较好的成绩。
附录一 程序清单
【主函数】
#include "12864.h"
#include "PWM_12.H"
#include "menu_12864.h"
#include "keyfeng.h" #define ADC_POWER 0x80 #define ADC_FLAG 0x10 //ADC complete flag #define ADC_START 0x08 //ADC start control bit #define ADC_SPEEDLL 0x00 //420 clocks #define SPEEDL 0x20 //280 clocks #define ADC_SPEEDH 0x40 //140 clocks 37 #define ADC_SPEEDHH 0x60 //70 clocks #define ADC_MAX 386 #define ADC_MIN 53
#define ADC_K
(ADC_MAX-ADC_MIN)/9 sbit LED1=P3^6; sbit LED2=P3^7; sbit LED3=P4^1; sbit LED4=P4^2; sbit BEEP=P2^3; u8 ch=2,adc_pv; int adc_look;
u8 num[5];
u8 num2[5];
u8 pv=90;
u16 pvp;
void ADCinit(); void PWM_INIT();
void delay(unsigned int z) {
unsigned int x,y; for(x=z;x>0;x--)
for(y=110;y>0;y--); } void main()
{
IE |= 0xa0;
_12864__shezhi();
menu_init();
num[4]=0;
num2[4]=0;
ADCinit();
PWM_INIT();
adc_look=228;
/*LED1=0;
LED2=0;
LED3=0;
LED4=0;
BEEP=0;*/
while(1)
{
ADC_CONTR|=ADC_START;
num[0]=adc_look/1000+' 0';
num[1]=adc_look/100%10 +'0';
num[2]=adc_look/10%10+ '0';
num[3]=adc_look%10+'0' ;
_12864_str(6,1,num);
delay(300);
pvp=pv*5.7;
adc_pv=((adc_look-53)* 10)/28.1+52;
num2[1]=adc_pv/100+'0' ;
num2[2]=adc_pv/10%10+' 0';
num2[3]=adc_pv%10+'0';
_12864_str(5,0,&num2[1 ]);
PWM_CONTROL(80);
key_floor();
key_po_num();
key_mos(); //模式的选择与启动
//mos_run(); //启动设备工作
menu_F5(); //刷
新屏幕相应位置的变化*/ }
}
void ADCinit()
{
P1ASF = 0X04;
ADC_RES = 0;
ADC_CONTR = ADC_POWER | SPEEDL | ch;
delay(20); }
void PWM_INIT()
{
CMOD|=0X00;
CCON|=0X00;
CL = 0; CH = 0;
PCA_PWM0 = 0x00;
//系统时
钟12分频
CCAP0H = CCAP0L = 0xef;
//设置50%的
占空比
CCAPM0=0X42;
//使能
pwm0
PCA_PWM0 = 0x00;
//系统时
钟12分频
CCAP1H = CCAP1L = 0xEF;
//设置50%的
占空比
CCAPM1=0X42; //使能pwm1 CR = 1; }
void adc_isr() interrupt 5 {
adc_look=ADC_RES;
adc_look=(adc_look<<2)+ADC_RESL; ADC_CONTR
&= !ADC_FLAG;
//Clear ADC interrupt flag ADC_CONTR = (ADC_POWER | SPEEDL | ch)&(~ADC_START) ; }
【12864函数】 #include "12864.h"
#include "intrins.h" #define DB P0 sbit RS=P2^2; sbit RW=P2^1; sbit E=P2^0;
void Busy()
{ unsigned char sta; DB = 0xff; RS = 0; RW = 1; do { E = 1; sta =DB;
E = 0; }while(sta & 0x80); }
void _12864__cmd(u8 i) {
Busy();
E=0;
RS=0;
RW=0;
DB=i;
_nop_();
_nop_();
E=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
E=0;
}
void _12864__data(u8 i) {
Busy();
E=0;
RS=1;
RW=0;
DB=i;
_nop_();
_nop_();
E=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
E=0;
}
void _12864__shezhi() {
_12864__cmd(0x38);
_12864__cmd(0x0c);
_12864__cmd(0x06);
_12864__cmd(0x01);
}
void _12864__zuobiao(u8 x,u8 y)
{
if(y==0)_12864__cmd(0x 80+x);
if(y==1)_12864__cmd(0x 90+x);
if(y==2)_12864__cmd(0x 88+x);
if(y==3)_12864__cmd(0x 98+x);
}
void _12864_str(u8 x,u8 y,char *str)
{
_12864__zuobiao(x,y);
while(*str!=0)
{
_12864__data(*str);
str++;
}
}
void _12864__picture(u8* picture)
{ u8 i,j;
_12864__cmd(0x36);
_12864__cmd(0x36);
_12864__cmd(0x3e);
_12864__cmd(0x01);
for(i=0;i<32;i++)
{
_12864__cmd(0x80+i);
_12864__cmd(0x80);
for(j=0;j<16;j++)
{
_12864__data(*picture) ;
picture++;
}
}
for(i=0;i<32;i++) {
_12864__cmd(0x80+i);
_12864__cmd(0x88);
for(j=0;j<16;j++)
{
_12864__data(*picture) ;
picture++;
}
}
}
【PWM函数】
#include "PWM_12.H"
#include "stc15f2k60s2.h" #include "intrins.h"
#include "keyfeng.h"
#include "math.h"
void Delay1ms()
//@12.000MHz
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
void delay12_ms(u16 t) {
while(t--)
{
Delay1ms();
}
}
void PWM_CONTROL(u8 po) {
static u8
pwm1=200,bi=20,detime;
static u8 pwm0=200;
static int adc_v;
u8 num[4];
CCAP1H = CCAP1L =pwm1;
CCAP0H = CCAP0L=pwm0;
adc_pv=((adc_look-53)* 10)/28.1+52;
num[3]=0;
num[0]=pwm0/100+'0';
num[1]=pwm0/10%10+'0';
num[2]=pwm0%10+'0';
_12864_str(6,2,num);
num[0]=pwm1/100+'0';
num[1]=pwm1/10%10+'0';
num[2]=pwm1%10+'0';
_12864_str(6,3,num);
pwm1=200;
if(po>70)
{
pwm1=190;
}
if(po>80)
{
pwm1=180;
}
if((adc_pv<po-1)||((ad c_pv>po+1))) {
if(1)
{
if(adc_pv+30<po)
{
if(adc_pv>(adc_v+5))
{
if(pwm0<240)
{pwm0=pwm0+3;}
}
if(adc_pv<=(adc_v+2))
{
if(pwm0>120)
{pwm0=pwm0-3;}
}
delay12_ms(300);
}
if((adc_pv+30>=po)&&(a dc_pv+20<po))
{
if(adc_pv>(adc_v+4))
{
if(pwm0<240)
{pwm0=pwm0+2;}
}
if(adc_pv<=(adc_v+1))
{
if(pwm0>120)
{pwm0=pwm0-2;}
}
delay12_ms(200);
}
if((adc_pv+20>=po)&&(a dc_pv+10<po))
{
if(adc_pv>(adc_v+3))
{
if(pwm0<240)
{pwm0=pwm0+1;}
}
if(adc_pv<=(adc_v+1))
{
if(pwm0>120)
{pwm0=pwm0-1;}
}
delay12_ms(50);
}
if((adc_pv+10>=po)&&(a dc_pv+5<po))
{
if(adc_pv>(adc_v+2))
{
if(pwm0<240)
{pwm0=pwm0+1;}
}
if(adc_pv<=(adc_v))
{
if(pwm0>120)
{pwm0=pwm0-1;}
}
delay12_ms(10);
}
if((adc_pv+5>=po)&&(ad c_pv+3<=po))
{
if(adc_pv>(adc_v+1))
{
if(pwm0<240)
{pwm0=pwm0+1;}
}
if(adc_pv<=(adc_v))
{
if(pwm0>120)
{pwm0=pwm0-1;}
}
delay12_ms(10);
}
if((adc_pv+2>=po)&&(ad c_pv<=po))
{
delay12_ms(10);
}
if((adc_pv+2>po)&&(adc _pv+4<=po))
{
if(adc_pv+1>(adc_v))
{
if(pwm0<240) {pwm0=pwm0+1;}
}
if(adc_pv<=(adc_v-2))
{
if(pwm0>120)
{pwm0=pwm0-1;}
}
delay12_ms(30);
}
if((adc_pv>=po+2))
{
if(adc_pv<adc_v-2)
{
if(pwm0>120)
{pwm0=pwm0-1;}
}
if(adc_pv>=(adc_v))
{
if(pwm0<240)
{pwm0=pwm0+1;}
}
delay12_ms(30);
}
}
}
/*if((adc_pv+30)<=po) {
if(pwm0>120)
pwm0=pwm0-7;
delay12_ms(2000);
}
if(((adc_pv+30)>po)&&( (adc_pv+20)<=po))
{
if(pwm0>120)
pwm0=pwm0-5;
delay12_ms(1000);
}
if(((adc_pv+20)>po)&&( (adc_pv+10)<=po))
{
if(pwm0>120)
pwm0=pwm0-2;
delay12_ms(1000);
}
if((adc_pv+10)>po&&((a dc_pv+5)<=po))
{
if(pwm0>120)
pwm0=pwm0-1;
delay12_ms(1000);
}
if((adc_pv-10)<po)
{
}
if(((adc_pv-20)<po)&&( (adc_pv-10)>=po))
{
if(pwm1>120)
pwm1=pwm1-2;
pwm0=pwm0+1;
delay12_ms(1000);
}
if((adc_pv>=80)&&(adc_ pv<90))
{
pwm1=180;
}*/
adc_v=adc_pv;
CCAP1H = CCAP1L=pwm1;
CCAP0H = CCAP0L=pwm0; }
void PWM_mo1()
{
u16 time;
if(adc_pv>80)
{
CCAP1H = CCAP1L=70;
delay12_ms(3000);
CCAP1H = CCAP1L=249;
}
while((adc_pv<pocl.po_ look1-1)&&(adc_pv>pocl.p o_look1+1))
{
PWM_CONTROL(pocl.po_lo ok1);
}
for(time=0;time<830;ti me++)
{
PWM_CONTROL(pocl.po_lo ok1);
}
CCAP0H = CCAP0L=70;
delay12_ms(3000);
CCAP0H = CCAP0L=249;
mos_run=0;
}。