风力摆论文.docx
《风力摆论文.docx》由会员分享,可在线阅读,更多相关《风力摆论文.docx(20页珍藏版)》请在冰豆网上搜索。
风力摆论文
2015年全国大学生电子设计竞赛
风力摆控制系统(B题)
【本科组】
2015年8月15日
摘要
本风力摆系统由继电器、单片机控制模块、角速度传感器模块、电源模块、风力摆装置五部分组成。
本团队风力摆系统以STC单片机为控制核心,配合合适的开关控制系统,通过编程实现对电机使能端或PWM信号输出的调节,控制轴流风机的转速;本系统使用角速度传感器模块和LCD液晶显示模块实时显示系统运动状态;此外,本系统拟采用PID算法对运动方向和运动速度进行修正,实现系统控制和误差修正。
经测试,在题目指定时间内下,系统通过STC12C5A60S2单片机调节电磁继电器的通断时间,配合20V直流电压源,能稳定的在地面画出一条大于50cm的直线段,且线性偏差在左右;该系统可以从静止开始,画出长度在30至50cm不可设置的直线,但长度偏差略大于;同时,本系统使用89C52芯片和mpu6050传感器实现三轴加速度与角速度液晶屏显示。
关键词:
风力摆,单片机,继电器,轴流风机,角速度传感器
风力摆控制系统(B题)
【本科组】
1系统方案
本风力摆控制系统主要包括单片机控制模块、电源模块、角度传感器模块、风力摆模块、液晶显示模块以及风力摆装置。
风力摆支架通过万向节连接碳杆,流风机与碳素纤维杆尾端相连。
位于碳杆下端的角度传感器模块采集系统的姿态角。
单片机控制液晶显示加速度和角加速度数据,并处理数据后通过继电器或电压驱动模块控制风机转速,实现对风力摆的控制。
风力摆制作的论证与选择
方案一:
采用2只直流风机作为动力系统。
流风机并排反向放置,通过细管或棒(如碳素纤维管、PVC管等)通过万向节固定在一支架上。
此方案风力摆负载轻,系统较稳定,控制较方便。
方案二:
采用粗单股导线(减少自旋)将风力摆吊挂在支架上。
导线减小了自旋干扰,但容易形变,控制较复杂。
综合以上两种方案,选择方案一。
角速度传感器的论证与选择
方案一:
采用基于ADXL335芯片的GY-61陀螺仪模块。
GY-61是三维角度传感器,可采集和处理姿态角数据,但其输出模拟信号,需要用具有A/D转换功能的控制芯片,程序处理繁琐。
方案二:
采用MPU6050三轴传感器模块。
该模块输出为数字信号,程序处理较简单,可以直接连接上位机进行加速度和角加速度监测。
综合以上两种方案,选择方案二。
控制系统的论证与选择
方案一:
采用STC12C5A60S作为控制芯片,通过继电器控制流风机的高低电平。
STC12C5A60S2系列单片机具有脉宽调节模式,可以通过程序设定改变PWM输出,通过控制开关调节直流风机的高低转速。
该方案控制简便,程序设置简单,处理速度较快,同时避免了驱动模块的压降损耗,可用于风力摆系统走直线路径。
方案二:
采用89C52芯片和电机驱动模块实现系统控制。
L298N电机驱动模块启动性能好,启动转矩大,可以通过PID算法,按比例、积分、微分的函数关系,进行运算,将其运算结果用以输出。
程序较复杂,可实现较精确转圈和急停等动作。
故实现走直线和急停的要求选择方案一,实现可设置长度的直线路径及静止点转圈需选择方案二。
2系统设计
2.1总体设计
将两个直流轴流风机固定在平板上(轴流风机规格:
24V,),用制作好的直杆将平板固定好,并用万向节将连接平板的直杆固定到支架上,用20V的电源提供电源信号,传到控制模块控制来控制轴流风机的转动,用继电器使轴流风机的交替转动,通过传感器测量转动角度,并用激光笔画出规定路径及距离
电路的设计
系统总体框图
图系统总体框图
单片机控制模块电路原理图
STC12C5A60S2单片机不但和8051指令、管脚完全兼容,而且其片内的具有大容量程序存储器且是FLASH工艺的,内部就自带高达60KFLASHROM,这种工艺的存储器用户可以用电的方式瞬间擦除、改写。
而且STC系列单片机支持串口程序烧写。
显而易见,这种单片机对开发设备的要求很低,开发时间也大大缩短。
传感器模块电路原理图
MPU-6050是9轴运动处理传感器。
它集成了3轴MEMS陀螺仪,3轴MEMS加速度计,以及一个可扩展的数字运动处理器DMP,可用I2C接口连接一个第三方的数字传感器。
MPU-6050对陀螺仪和加速度计分别用了三个16位的ADC,将其测量的模拟量转化为可输出的数字量。
为了精确跟踪快速和慢速的运动,传感器的测量范围都是用户可控的,陀螺仪可测范围为±250,±500,±1000,±2000°/秒(dps),加速度计可测范围为±2,±4,±8,±16g。
电机驱动模块
L298N是直流电机的专用驱动芯片,最高电压可达46V,单路最高的电流可达2A。
它内部由8管构成的双路H桥式驱动电路。
L298N是SGS公司的产品,内部包含4通道逻辑驱动电路。
可以方便的驱动两个直流电机或一个两相步进电机。
L298N可接受标准TTL逻辑电平信号VSS,VSS接~7V电压以驱动芯片。
4脚VS接电源电压用于驱动直流电机,其电压范围为+~46V。
输出电流最大可达A,可驱动电感性负载。
1脚和15脚下管的发射极分别单独引出以便接入电流采样电阻,形成电流传感信号。
L298可驱动2个电动机,OUT1,OUT2和OUT3,OUT4之间可分别接一个直流电动机或步进机,本实验装置我们只需驱动一台电动机,即使用A通道,IN1/IN2脚接输入控制电平,控制电机的转速和方向。
ENA,ENB接控制使能端,控制电机的停转,本设计中IN1接PWM信号,IN2低电平。
下表是L298N功能逻辑图
L298N的控制方式
ENA
IN1
IN2
运转状态
0
X
X
停止
1
1
0
正转
1
0
1
反转
1
1
1
刹停
1
0
0
停止
电源
本系统采用20V直流电源,由于轴流风机的额定电压为24V,为保证轴流风机告诉运行且损耗较小,故选择20V直流电源。
程序的设计
程序功能描述与设计思路
1、程序功能描述
根据题目要求软件部分主要实现键盘的设置和显示。
1)键盘实现功能:
设置频率值、频段、电压值以及设置输出信号类型。
2)显示部分:
显示电压值、频段、步进值、信号类型、频率。
2、程序设计思路
程序流程图
1、主程序流程图
3测试方案与测试结果
测试方案
1、硬件测试
将各个模块按照设计的电路图连接并接通电源,使各个模块可以工作,用万用表测定各模块的输入输出电压,并与理论值进行比较,测试各个模块是否可以正常工作。
2、软件仿真测试
利用AltiumDesigner的仿真功能,将画好的原理图进行仿真测试。
3、硬件软件联调
将写好的程序传入到单片机中,通过单片机和继电器的共同控制,使轴流风机摆动,进行各个要求的测试,并进行不断的调试,使之符合规定要求
测试条件与仪器
测试条件:
通过让轴流风机摆动使摆动轨迹与长度与要求相符
测试仪器:
刻度尺,量角器
测试结果及分析
测试结果(部分数据)
延时参数(ms)
距离(cm)
左移距离(cm)
距离(cm)
右移距离(cm)
移动距离(cm)
3000
15
10
35
10
20
16
9
35
10
19
平均
35
10
4000
10
15
43
18
33
9
16
46
21
37
平均
35
5000
7
18
48
23
41
8
17
47
22
39
6
19
45
20
39
平均
7
18
21.
39.
6000
5
20
47
22
42
47
22
6
19
47
22
41
平均
47
22
7000
5
20
48
23
43
5
20
50
25
45
平均
19.
23.
43.
7250
6
19
48
23
42
平均
48
23
测试分析与结论
根据上述测试数据,XXXXXXXXXXXXXXXXXXXXXXXXXXXXX,由此可以得出以下结论:
1、
2、
3、
综上所述,本设计达到设计要求。
附录1:
电路原理图
附录2:
源程序
继电器控制主程序
#include<>
#include<>
#include""
sbitRUNA=P1^0;
sbitRUNB=P1^1;
voidDelay(unsignedinti);
voidEnable(charID,bitEN)
{
//P0M1=0x02;//00000010
//P0M0=0x08;//00001000P0^3推挽输出P0^1高阻态
if(ID==1)
{
RUNA=~EN;
}
elseif(ID==2)
{
RUNB=~EN;
}
}
voidmain(void)
{
while
(1)
{
Enable(1,0);
Enable(2,1);
Delay(6500);
Enable(1,1);
Enable(2,1);
Delay(1000);
Enable(1,1);
Enable(2,0);
Delay(6500);
}
}
voidDelay(unsignedintms)//1ms@
{
unsignedchari,j;
do
{
_nop_();
_nop_();
i=12;
j=168;
do
{
while(--j);
}while(--i);
}
while(--ms);
}
mpu6050主程序
#include<>
#include<>//Keillibrary
#include<>//Keillibrary
#include<>
typedefunsignedcharuchar;
typedefunsignedshortushort;
typedefunsignedintuint;
//****************************************
//定义51单片机端口
//****************************************
#defineDataPortP0//LCD1602数据端口
sbitSCL=P1^0;//IIC时钟引脚定义
sbitSDA=P1^1;//IIC数据引脚定义
sbitLCM_RS=P2^0;//LCD1602命令端口
sbitLCM_RW=P2^1;//LCD1602命令端口
sbitLCM_EN=P2^2;//LCD1602命令端口
//****************************************
//定义MPU6050内部地址
//****************************************
#defineSMPLRT_DIV0x19//陀螺仪采样率,典型值:
0x07(125Hz)
#defineCONFIG0x1A//低通滤波频率,典型值:
0x06(5Hz)
#defineGYRO_CONFIG0x1B//陀螺仪自检及测量范围,典型值:
0x18(不自检,2000deg/s)
#defineACCEL_CONFIG0x1C//加速计自检、测量范围及高通滤波频率,典型值:
0x01(不自检,2G,5Hz)
#defineACCEL_XOUT_H0x3B
#defineACCEL_XOUT_L0x3C
#defineACCEL_YOUT_H0x3D
#defineACCEL_YOUT_L0x3E
#defineACCEL_ZOUT_H0x3F
#defineACCEL_ZOUT_L0x40
#defineTEMP_OUT_H0x41
#defineTEMP_OUT_L0x42
#defineGYRO_XOUT_H0x43
#defineGYRO_XOUT_L0x44
#defineGYRO_YOUT_H0x45
#defineGYRO_YOUT_L0x46
#defineGYRO_ZOUT_H0x47
#defineGYRO_ZOUT_L0x48
#definePWR_MGMT_10x6B//电源管理,典型值:
0x00(正常启用)
#defineWHO_AM_I0x75//IIC地址寄存器(默认数值0x68,只读)
#defineSlaveAddress0xD0//IIC写入时的地址字节数据,+1为读取
//****************************************
//定义类型及变量
//****************************************
uchardis[4];//显示数字(-511至512)的字符数组
intdis_data;//变量
//intTemperature,Temp_h,Temp_l;//温度及高低位数据
//****************************************
//函数声明
//****************************************
voiddelay(unsignedintk);//延时
//LCD相关函数
voidInitLcd();//初始化lcd1602
voidlcd_printf(uchar*s,inttemp_data);
voidWriteDataLCM(uchardataW);//LCD数据
voidWriteCommandLCM(ucharCMD,ucharAttribc);//LCD指令
voidDisplayOneChar(ucharX,ucharY,ucharDData);//显示一个字符
voidDisplayListChar(ucharX,ucharY,uchar*DData,L);//显示字符串
//MPU6050操作函数
voidInitMPU6050();//初始化MPU6050
voidDelay5us();
voidI2C_Start();
voidI2C_Stop();
voidI2C_SendACK(bitack);
bitI2C_RecvACK();
voidI2C_SendByte(uchardat);
ucharI2C_RecvByte();
voidI2C_ReadPage();
voidI2C_WritePage();
voiddisplay_ACCEL_x();
voiddisplay_ACCEL_y();
voiddisplay_ACCEL_z();
ucharSingle_ReadI2C(ucharREG_Address);//读取I2C数据
voidSingle_WriteI2C(ucharREG_Address,ucharREG_data);//向I2C写入数据
//****************************************
//整数转字符串
//****************************************
voidlcd_printf(uchar*s,inttemp_data)
{
if(temp_data<0)
{
temp_data=-temp_data;
*s='-';
}
else*s='';
*++s=temp_data/100+0x30;
temp_data=temp_data%100;//取余运算
*++s=temp_data/10+0x30;
temp_data=temp_data%10;//取余运算
*++s=temp_data+0x30;
}
//****************************************
//延时
//****************************************
voiddelay(unsignedintk)
{
unsignedinti,j;
for(i=0;i{
for(j=0;j<121;j++);
}
}
//****************************************
//LCD1602初始化
//****************************************
voidInitLcd()
{
WriteCommandLCM(0x38,1);
WriteCommandLCM(0x08,1);
WriteCommandLCM(0x01,1);
WriteCommandLCM(0x06,1);
WriteCommandLCM(0x0c,1);
DisplayOneChar(0,0,'A');
DisplayOneChar(0,1,'G');
}
//****************************************
//LCD1602写允许
//****************************************
voidWaitForEnable(void)
{
DataPort=0xff;
LCM_RS=0;LCM_RW=1;_nop_();
LCM_EN=1;_nop_();_nop_();
while(DataPort&0x80);
LCM_EN=0;
}
//****************************************
//LCD1602写入命令
//****************************************
voidWriteCommandLCM(ucharCMD,ucharAttribc)
{
if(Attribc)WaitForEnable();
LCM_RS=0;LCM_RW=0;_nop_();
DataPort=CMD;_nop_();
LCM_EN=1;_nop_();_nop_();LCM_EN=0;
}
//****************************************
//LCD1602写入数据
//****************************************
voidWriteDataLCM(uchardataW)
{
WaitForEnable();
LCM_RS=1;LCM_RW=0;_nop_();
DataPort=dataW;_nop_();
LCM_EN=1;_nop_();_nop_();LCM_EN=0;
}
//****************************************
//LCD1602写入一个字符
//****************************************
voidDisplayOneChar(ucharX,ucharY,ucharDData)
{
Y&=1;
X&=15;
if(Y)X|=0x40;
X|=0x80;
WriteCommandLCM(X,0);
WriteDataLCM(DData);
}
//****************************************
//LCD1602显示字符串
//****************************************
voidDisplayListChar(ucharX,ucharY,uchar*DData,L)
{
ucharListLength=0;
Y&=0x1;
X&=0xF;
while(L--)
{
DisplayOneChar(X,Y,DData[ListLength]);
ListLength++;
X++;
}
}
//**************************************
//延时5微秒(STC90C52RC@12M)
//不同的工作环境,需要调整此函数
//当改用1T的MCU时,请调整此延时函数
//**************************************
voidDelay5us()
{
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
}
//**************************************
//I2C起始信号
//**************************************
voidI2C_Start()
{
SDA=1;//拉高数据线
SCL=1;//拉高时钟线
Delay5us();//延时
SDA=0;//产生下降沿
Delay5us();//延时
SCL=0;//拉低时钟线
}
//**************************************
//I2C停止信号
//**************************************
voidI2C_Stop()
{
SDA=0;//拉低数据线
SCL=1;//拉高时钟线
Delay5us();//延时
SDA=1;//产生上升沿
Delay5us();//延时
}
//**************************************
//I2C发送应答信号
//入口参数:
ack(0:
ACK1:
NAK)
//**************************************
voidI2C_SendACK(bitack)
{
SDA=ack;//写应答信号
SCL=1;//拉高时钟线
Delay5us();//延时
SCL=0;//拉低时钟线
Delay5us();//延时
}
//*************************************