《基于stm32的风力摆控制系统设计.docx》由会员分享,可在线阅读,更多相关《基于stm32的风力摆控制系统设计.docx(43页珍藏版)》请在工友文库上搜索。
1、第十二届智能控制设计大赛高级组之基于stm32的风力摆控制系统队名: 队长: 队员: 队员: 专业及班级: 目录【摘要】3一、设计要求4(一)基本要求:4(二)拓展要求:4二、系统的硬件设计与实现52.1系统硬件概述52.2 主要单元电路的设计5三、系统的软件设计113.1 系统上位机设计11设计目的:11设计思路:12四、作品展示17五、设计总结19六、附录20附录一 参考文献20附录二 代码21【摘要】1节 长约 60cm70cm 的细管上端用万向节固定在支架上,下方悬挂一组(24只)风机,构成风力摆。风力摆上安装一个向下的激光笔,静止时,激光笔的下端距地面不超过 20cm。 设计一个测控
2、系统,控制各风机使风力摆按照一定规律运动,激光笔在地面画出要求的轨迹。 关键词: stm32,空心杯风机,MPU6050,风力摆一、设计要求(一)基本要求:设计一个风力摆的测控硬件系统,具备风机驱动控制、摆杆角度检测等功能;从静止开始,控制风力摆20秒内做类似自由摆运动,使激光笔在地面画出不短于40厘米,线性偏差小于3cm的直线段;设计良好的人机界面,对系统的实时数据进行输出并绘制动态曲线,信息包括:摆杆运动角速度、实际角度等;(二)拓展要求:1 1.从静止开始,15秒内完成幅度可控的摆动,画出长度在3060厘米间可设置,长度偏差不大于2.5厘米的直线段,并且具有较好的重复性;2 风力摆在一定
3、角度放开后快速静止,风力摆拉开一定角度,10秒内达到静止;3 做可控半径的圆周运动,评委指定半径,40秒内重复三圈,轨迹应落在指定半径2.5厘米的圆环内;4 其他拓展功能;二、系统的硬件设计与实现2.1系统硬件概述本电路是由 STM32 单片机为控制核心,具有操作简单的优点。MPU6050的灵敏度高,操作简单,利用上位机输出显示结果,显示控制的角度和波形 ;空心杯电机的重量低,推重比较强,机动性较高,可以很好实现摆杆的推动效果。2.2 主要单元电路的设计2.2.1 单片机主控制模块的设计STM32F103C8T6单片机STM32F103xx增强型系列使用高性能的ARM Cortex-M3 32
4、位的RISC内核,工作频率为72MHz,内置高速存储器(高达128K字节的闪存和20K字节的SRAM),丰富的增强I/O端口和联接到两条APB总线的外设。所有型号的器件都包含2个12位的ADC、3个通用16位定时器和一个PWM定时器,还包含标准和先进的通信接口:多达2个I2C和SPI、3个USART、一个USB和一个CAN。 STM32F103xx增强型系列工作于-40C至+105C的温度范围,供电电压2.0V至3.6V,一系列的省电模式保证低功耗应用的要求。 完整的STM32F103xx增强型系列产品包括从36脚至100脚的五种不同封装形式;根据不同的封装形式,器件中的外设配置不尽相同。2.
5、2.2 传感器模块的设计在本系统中,利用MPU6050传感器获得数据。 MPU-6050 是全球首例9 轴运动处理传感器。它集成了3 轴MEMS 陀螺仪,3 轴MEMS加速度计,以及一个可扩展的数字运动处理器DMP(Digital Motion Processor),可用I2C接口连接一个第三方的数字传感器,比如磁力计。扩展之后就可以通过其I2C 或SPI 接口输出一个9 轴的信号(SPI 接口仅在MPU-6000 可用)。MPU-60X0 也可以通过其I2C 接口连接非惯性的数字传感器,比如压力传感器。 MPU-6050 对陀螺仪和加速度计分别用了三个16 位的ADC,将其测量的模拟量转化为
6、可输出的数字量。为了精确跟踪快速和慢速的运动,传感器的测量范围都是用户可控的,陀螺仪可测范围为250,500,1000,2000/秒(dps),加速度计可测范围为2,4,8,16g。 一个片上1024 字节的FIFO,有助于降低系统功耗。和所有设备寄存器之间的通信采用400kHz 的I2C 接口或1MHz 的SPI 接口(SPI 仅MPU-6000 可用)。对于需要高速传输的应用,对寄存器的读取和中断可用20MHz 的SPI。 另外,片上还内嵌了一个温度传感器和在工作环境下仅有1%变动的振荡器。芯片尺寸440.9mm,采用QFN 封装(无引线方形封装),可承受最大10000g 的冲击,并有可编
7、程的低通滤波器。 关于电源,MPU-6050 可支持VDD 范围2.5V5%,3.0V5%,或3.3V5%。另外MPU-6050 还有一个VLOGIC 引脚,用来为I2C 输出提供逻辑电平。VLOGIC 电压可取1.85%或者VDD。MPU6050引脚和信号描述2.2.3 空心杯电机动力系统 空心杯电动机在结构上突破了传统电机的转子结构形式,采用的是无铁芯转子,也叫空心杯型转子。这种新颖的转子结构彻底消除了由于铁芯形成涡流而造成的电能损耗,同时其重量和转动惯量大幅降低,从而减少了转子自身的机械能损耗。由于转子的结构变化而使电动机的运转特性得到了极大改善,不但具有突出的节能特点,更为重要的是具备
8、了铁芯电动机所无法达到的控制和拖动特性。2.2.4 L9110电机驱动芯片原理L9110电机驱动芯片特点: 1 低静态工作电流; 2 宽电源电压范围:2.5V-12V; 3 每通道具有800mA连续电流 输出能力;4 较低的饱和压降; 5 输出具有正转、反转、高阻和刹车四种 状态; 6 TTL/CMOS 输出电平兼容,可直接连 CPU; 7 输出内置钳位二极管,适用于感性负 载; 8 控制和驱动集成于单片IC之中;9 具备管脚高压保护功能; 10 工作温度:-20-80。管脚封装如下:L9110是为控制和驱动电机设计的两通道推挽式功率放大专用集成电路器件,将分立 电路集成在单 片IC之中,使外
9、围器件成 本降低,整机可靠性提高。该芯片 有两个 TTL/CMOS 兼容电平的输入,具有良好的抗干扰性;两个输出端能直接驱动电机的 正反向运动及刹车,它具有较大的电流驱动能力,每通道能通过750800mA的持续电 流,峰值电流能力可达1.52.0A;同时它具有较低的输出饱和压降;内置的钳位二极管能 释放感性负载的反向冲击电流,使它在驱动 继电器、直 流电 机、步进电机或 开关功率 管的使用上安全可靠。L9110被广泛应用于保险柜、玩具汽车的电机驱动、步进电机驱 动和开关功率管等电路上。三、系统的软件设计3.1 系统上位机设计设计目的:对于界面的设计,我们选择了labview制作一个简单的上位机
10、软件,主要目的是接受来自串口的数据,然后显示出来。设计思路:(1) 串口通信我们选择VISA Configure Serial Port对串口进行资源配置,包括波特率、数据比特、奇偶位、流控制等,其中除了资源名称和波特率外,我们都选择默认参数。详细见下图:读取串口的是下图:写出串口的是下图:串口读取完毕我们关闭串口用到的是:其他我们还是用到的一些vi分别有我们初步使用的是下图模型但采样速度由于while循环占用资源过多,很是缓慢,所以我们修改后的结构如把读取、写出综合一起的程序框图:(2) 前面板设计四、作品展示电机展示:驱动展示:整体展示:上位机展示:见上文。五、设计总结 这一次的智控大赛,
11、可以说是说是受益匪浅。通过这一风力摆的随动控制系统的学习,有助于我们对于自动化的自动控制原理、现代控制原理等控制原理的知识的理解,对电力电子器件和PWM脉冲调频技术有了更深入的了解,在上位机labview也有所所获。调节PID的过程,搭建硬件的过程,写程序的过程,都是烦闷的,也正是队友之间彼此的鼓励和支持我们才能坚持下来,合作和团队的收获也是我们过程中最为珍贵。六、附录附录一 参考文献【1】廖义奎嵌入式实战开发精解-基于STM32F1.北京:清华大学出版社,2005.【2】王屯令、苏亚辉5STM32开发指南LabVIEW卷.北京:机械工业出版社,2013.【3】华成英、童诗白模拟电子技术基础(
12、第四版)高等教育出版社, 2007 【4】阎石数字电子技术基础高等教育出版社,2007.11【5】赵星寒从0开始教你学STM32.北京航空航天大学出版社,2013.附录二 代码Main.c:#include sys.h#include usart.h#include delay.h#include led.h #include timer.h #include mpu6050.h/#include usmart.h #include inv_mpu.h#include inv_mpu_dmp_motion_driver.h #include motor_diver.h#include moto
13、r_pwm.h#include motor_control.h#include stdio.h/*- 全局变量-*/ /extern uint8_t Q1_Start;/extern uint8_t Q2_Start;/extern uint8_t Q3_Start;/extern uint8_t Q4_Start;/extern uint8_t Q5_Start;/extern uint8_t Q6_Start;extern uint8_t ChooseMode;extern short PWM1;extern short PWM2;extern int pitchit,rollit; /*
14、- 初始化外设-*/ int main(void) u8 t=0,report=1;/默认开启上报 float pitch,roll;float yaw; /欧拉角short aacx,aacy,aacz;/加速度传感器原始数据short gyrox,gyroy,gyroz;/陀螺仪原始数据/ short pitcha=0,rolla=0,yawa=0;/short temp;/温度 /NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);delay_init(); /延时函数初始化 uart_init(115200); /串口初始化为9600/usma
15、rt_dev.init(72);/初始化USMARTLED_Init(); /初始化与LED连接的硬件接口/ GPIO_ResetBits(GPIOC,GPIO_Pin_13); MPU_Init();/初始化MPU6050 /PWM_Init();TIM4_PWM_Init(99,36); / xdirver(5000); / ydirver(5000);while( mpu_dmp_init(); TIM2_Config(5000-1,71); / xdirver(99); / ydirver(99);/delay_ms(2000);/ xdirver(49); / ydirver(49)
16、;/ xdirver(98);/ ydirver(98);/ xdirver(4999);/ ydirver(4999);/ / TIM4_Config(5000-1,72); /* TIM4 5ms Inturrupt 采样率200Hz 不能更改*/ GPIO_SetBits(GPIOB,GPIO_Pin_1);while(1)/while(mpu_dmp_get_data(&pitch,&roll,&yaw);/ xdirver(7000);/ ydirver(7000);/delay_ms(600);/delay_ms(600);/delay_ms(600);/ xdirver(3000
17、);/ ydirver(3000); /roll=roll+180.000;/yaw=yaw-161;/temp=MPU_Get_Temperature();/得到温度值/MPU_Get_Accelerometer(&aacx,&aacy,&aacz);/得到加速度传感器数据/MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz);/得到陀螺仪数据/if(report)mpu6050_send_data(aacx,aacy,aacz,gyrox,gyroy,gyroz);/用自定义帧发送加速度和陀螺仪原始数据/if(report)usart1_report_imu(aa
18、cx,aacy,aacz,gyrox,gyroy,gyroz,(int)(roll*100),(int)(pitch*100),(int)(yaw*10);/send_three_data(int)(roll*100),(int)(pitch*100),(int)(yaw*10); /发送三个角给labview上位机/ GPIO_SetBits(GPIOC,GPIO_Pin_13) ;/LED4/ delay_ms(600);/ GPIO_ResetBits(GPIOC,GPIO_Pin_13);/pitcha=pitch*10;/rolla=roll*10;/yawa=yaw*10;/TIM
19、_SetCompare1(TIM2,499);/摆杆离地约20cm,摆高约92cm/TIM_SetCompare2(TIM2,499);/TIM_SetCompare3(TIM2,499);/TIM_SetCompare4(TIM2,499);/TIM_SetCompare2(TIM2,997);/TIM_SetCompare3(TIM2,997);/delay_ms(600);delay_ms(600);delay_ms(600);delay_ms(600);/TIM_SetCompare2(TIM2,4999);/TIM_SetCompare3(TIM2,4999); MPU6050.c:
20、 /初始化MPU6050/返回值:0,成功/ 其他,错误代码u8 MPU_Init(void) u8 res; MPU_IIC_Init();/初始化IIC总线MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X80);/复位MPU6050 delay_ms(100);MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X00);/唤醒MPU6050 MPU_Set_Gyro_Fsr(3);/陀螺仪传感器,2000dpsMPU_Set_Accel_Fsr(0);/加速度传感器,2gMPU_Set_Rate(50);/设置采样率50HzMPU_Write_Byt
21、e(MPU_INT_EN_REG,0X00);/关闭所有中断MPU_Write_Byte(MPU_USER_CTRL_REG,0X00);/I2C主模式关闭MPU_Write_Byte(MPU_FIFO_EN_REG,0X00);/关闭FIFOMPU_Write_Byte(MPU_INTBP_CFG_REG,0X80);/INT引脚低电平有效res=MPU_Read_Byte(MPU_DEVICE_ID_REG); if(res=MPU_ADDR)/器件ID正确MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X01);/设置CLKSEL,PLL X轴为参考MPU_Write
22、_Byte(MPU_PWR_MGMT2_REG,0X00);/加速度与陀螺仪都工作MPU_Set_Rate(50);/设置采样率为50Hz else return 1;return 0;/设置MPU6050陀螺仪传感器满量程范围/fsr:0,250dps;1,500dps;2,1000dps;3,2000dps/返回值:0,设置成功/ 其他,设置失败 u8 MPU_Set_Gyro_Fsr(u8 fsr)return MPU_Write_Byte(MPU_GYRO_CFG_REG,fsr3);/设置陀螺仪满量程范围 /设置MPU6050加速度传感器满量程范围/fsr:0,2g;1,4g;2,8
23、g;3,16g/返回值:0,设置成功/ 其他,设置失败 u8 MPU_Set_Accel_Fsr(u8 fsr)return MPU_Write_Byte(MPU_ACCEL_CFG_REG,fsr=188)data=1;else if(lpf=98)data=2;else if(lpf=42)data=3;else if(lpf=20)data=4;else if(lpf=10)data=5;else data=6; return MPU_Write_Byte(MPU_CFG_REG,data);/设置数字低通滤波器 /设置MPU6050的采样率(假定Fs=1KHz)/rate:41000(
24、Hz)/返回值:0,设置成功/ 其他,设置失败 u8 MPU_Set_Rate(u16 rate)u8 data;if(rate1000)rate=1000;if(rate4)rate=4;data=1000/rate-1;data=MPU_Write_Byte(MPU_SAMPLE_RATE_REG,data);/设置数字低通滤波器 return MPU_Set_LPF(rate/2);/自动设置LPF为采样率的一半/得到温度值/返回值:温度值(扩大了100倍)short MPU_Get_Temperature(void) u8 buf2; short raw;float temp;MPU_
25、Read_Len(MPU_ADDR,MPU_TEMP_OUTH_REG,2,buf); raw=(u16)buf08)|buf1; temp=36.53+(double)raw)/340; return temp*100;/得到陀螺仪值(原始值)/gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)/返回值:0,成功/ 其他,错误代码u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz) u8 buf6,res; res=MPU_Read_Len(MPU_ADDR,MPU_GYRO_XOUTH_REG,6,buf);if(res=0)*gx=
26、(u16)buf08)|buf1; *gy=(u16)buf28)|buf3; *gz=(u16)buf48)|buf5; return res;/得到加速度值(原始值)/gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)/返回值:0,成功/ 其他,错误代码u8 MPU_Get_Accelerometer(short *ax,short *ay,short *az) u8 buf6,res; res=MPU_Read_Len(MPU_ADDR,MPU_ACCEL_XOUTH_REG,6,buf);if(res=0)*ax=(u16)buf08)|buf1; *ay=(u16)buf28)
27、|buf3; *az=(u16)buf48)|buf5; return res;/IIC连续写/addr:器件地址 /reg:寄存器地址/len:写入长度/buf:数据区/返回值:0,正常/ 其他,错误代码u8 MPU_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf)u8 i; MPU_IIC_Start(); MPU_IIC_Send_Byte(addr1)|0);/发送器件地址+写命令if(MPU_IIC_Wait_Ack()/等待应答MPU_IIC_Stop(); return 1; MPU_IIC_Send_Byte(reg);/写寄存器地址 MPU_I
28、IC_Wait_Ack();/等待应答for(i=0;ilen;i+)MPU_IIC_Send_Byte(bufi);/发送数据if(MPU_IIC_Wait_Ack()/等待ACKMPU_IIC_Stop(); return 1; MPU_IIC_Stop(); return 0; /IIC连续读/addr:器件地址/reg:要读取的寄存器地址/len:要读取的长度/buf:读取到的数据存储区/返回值:0,正常/ 其他,错误代码u8 MPU_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf) MPU_IIC_Start(); MPU_IIC_Send_Byte(a
29、ddr1)|0);/发送器件地址+写命令if(MPU_IIC_Wait_Ack()/等待应答MPU_IIC_Stop(); return 1; MPU_IIC_Send_Byte(reg);/写寄存器地址 MPU_IIC_Wait_Ack();/等待应答 MPU_IIC_Start();MPU_IIC_Send_Byte(addr1)|1);/发送器件地址+读命令 MPU_IIC_Wait_Ack();/等待应答 while(len)if(len=1)*buf=MPU_IIC_Read_Byte(0);/读数据,发送nACK else *buf=MPU_IIC_Read_Byte(1);/读数
30、据,发送ACK len-;buf+; MPU_IIC_Stop();/产生一个停止条件 return 0;/IIC写一个字节 /reg:寄存器地址/data:数据/返回值:0,正常/ 其他,错误代码u8 MPU_Write_Byte(u8 reg,u8 data) MPU_IIC_Start(); MPU_IIC_Send_Byte(MPU_ADDR1)|0);/发送器件地址+写命令if(MPU_IIC_Wait_Ack()/等待应答MPU_IIC_Stop(); return 1; MPU_IIC_Send_Byte(reg);/写寄存器地址 MPU_IIC_Wait_Ack();/等待应答
31、 MPU_IIC_Send_Byte(data);/发送数据if(MPU_IIC_Wait_Ack()/等待ACKMPU_IIC_Stop(); return 1; MPU_IIC_Stop(); return 0;/IIC读一个字节 /reg:寄存器地址 /返回值:读到的数据u8 MPU_Read_Byte(u8 reg)u8 res; MPU_IIC_Start(); MPU_IIC_Send_Byte(MPU_ADDR1)|0);/发送器件地址+写命令MPU_IIC_Wait_Ack();/等待应答 MPU_IIC_Send_Byte(reg);/写寄存器地址 MPU_IIC_Wait_
32、Ack();/等待应答 MPU_IIC_Start();MPU_IIC_Send_Byte(MPU_ADDR250)MPU_IIC_Stop();return 1;MPU_IIC_SCL=0;/时钟输出0 return 0; /产生ACK应答void MPU_IIC_Ack(void)MPU_IIC_SCL=0;MPU_SDA_OUT();MPU_IIC_SDA=0;MPU_IIC_Delay();MPU_IIC_SCL=1;MPU_IIC_Delay();MPU_IIC_SCL=0;/不产生ACK应答 void MPU_IIC_NAck(void)MPU_IIC_SCL=0;MPU_SDA_
33、OUT();MPU_IIC_SDA=1;MPU_IIC_Delay();MPU_IIC_SCL=1;MPU_IIC_Delay();MPU_IIC_SCL=0; /IIC发送一个字节/返回从机有无应答/1,有应答/0,无应答 void MPU_IIC_Send_Byte(u8 txd) u8 t; MPU_SDA_OUT(); MPU_IIC_SCL=0;/拉低时钟开始数据传输 for(t=0;t7; txd=1; MPU_IIC_SCL=1;MPU_IIC_Delay(); MPU_IIC_SCL=0;MPU_IIC_Delay(); /读1个字节,ack=1时,发送ACK,ack=0,发送
34、nACK u8 MPU_IIC_Read_Byte(unsigned char ack)unsigned char i,receive=0;MPU_SDA_IN();/SDA设置为输入 for(i=0;i8;i+ ) MPU_IIC_SCL=0; MPU_IIC_Delay();MPU_IIC_SCL=1; receive=1; if(MPU_READ_SDA)receive+; MPU_IIC_Delay(); if (!ack) MPU_IIC_NAck();/发送nACK else MPU_IIC_Ack(); /发送ACK return receive;Timer.c#include motor_control.h#include motor_pid.h#include motor_pwm.h#include Timer.h#include stm32f10x.h#include stdio.h#include stdlib.h#include delay.h/#include usart1.h/#include indkey.h#include ahrs.h#include mpu6050.h#includ