版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
两轮自平衡车的软件设计案例分析1.1开发环境的介绍本次开发环境使用的是Keil5,因为Keil5能生成.hex文件的软件,STM32单片机需要hex文件,所以选择keil5作为本次设计的编译工具。1.2程序设计的总体方案程序功能主要包括对各个传感器信号的采集和处理;汽车交通控制、垂直控制、速度控制、转向控制、障碍物预防控制;PWM发动机输出;汽车循环过程控制:启动程序、汽车启动和结束、汽车状态监控;车辆信息对话框及参数配置:状态查看器、上位机监控、参数配置等。上述功能可分为两类:第一类包括前三类功能。所有这些函数都是在一个精确的时间周期内运行的,因此它们可以在一个周期内中断。第二种类型包括最后两个函数。执行不需要精确的时间周期,可以在主程序中完成。这两种类型的任务可以通过全局变量在Si之间进行通信。小车垂直控制的主要框图如图4-1所示。从以上程序的主框图可以看出,程序连接后,MCU将被初始化,初始化的主要任务包括两个:第一个任务是初始化MCU使用的所有模块;第二个是应用程序的初始化,即应用于变量值的自动控制程序的初始化。启动后,第一个输入是垂直车辆检测程序。该程序读取加速度计的值以评估车辆是否垂直。在垂直方向中,车辆的垂直控制、转向控制和速度控制被激活。图4-1主程序框图主程序的程序设计如下:Main主程序:intmain(void){u8t=0;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组2 SystemInit();//72Mhz delay_init(); //延时函数初始化 OLED_Init(); MPU_Init(); //初始化MPU6050 TIM1_PWM_Init(7799,0); OLED_ShowString(0,0,"Angle:",16); OLED_ShowString(72,0,",",16); OLED_ShowString(0,16,"Kp=",16); OLED_ShowNum(24,16,Vertical_Kp,3,16);// OLED_ShowString(56,16,"PL=",16);// OLED_ShowString(0,32,"I=",16); OLED_ShowString(56,16,"D=",16); D=Vertical_Kd*100;OLED_ShowNum(72,16,D/100,1,16); OLED_ShowString(80,16,".",16); OLED_ShowNum(88,16,D%100,2,16);// OLED_ShowNum(24,16,Velocity_Kp,3,16);//速度// OLED_ShowNum(80,16,Vertical_Kp,3,16);// OLED_ShowNum(24,32,Velocity_Ki,3,16);// OLED_ShowNum(80,32,Vertical_Kd,3,16); OLED_Refresh(); while(mpu_dmp_init())//自检 {if(t==0) {OLED_ShowString(0,32,"Error",16); OLED_Refresh(); t++;} else {OLED_ShowString(0,32,"",16); OLED_Refresh(); t=0;} delay_ms(1000); }设置中断优先级分组2,抢占优先级取值为0到3,相应的优先级为0到3,2bit抢占优先级、2bit响应优先级。OLED_ShowString方法则是使用OLED显示字符串进行展示使用的,mpu_dmp_init()则是能够使用dmp读出姿态角,如果程序while能够进入,切t等于0则OLED屏幕会报错告知读取姿态角失败,否则屏幕会重新刷新。OLED_ShowString(0,32,"PWM=",16); OLED_Refresh();// EXTIX_Init(); Encoder_Init_TIM2(); Encoder_Init_TIM4();TIM3_FLASH(3599,99);//刷新角度平衡1.3模块程序的设计1.3.1pid控制器的设计平衡车是一个闭环控制的负反馈系统,需要两级PID来保持垂直和静止。PD的垂直电路控制器根据IMU数据(使用mpu6050的惯性测量单元)控制汽车的运动状态。速度调节器PI根据静止编码器的数据调节车轮的速度和运动状态,使两个车轮趋于平衡,本图PID结构图如图所示4-2。图4-2pid结构框图设置机械中值,能使得小车真正平衡住的角度,floatMed_Angle=0;对于平衡车来说,直立环是最为重要的,而PID的调节也是一级一级的来调节,所以我们从直立PD环开始调节。直立PD环代码:float Vertical_Kp=240, //直立环KP、KD500 Vertical_Kd=1.68;//3intVertical(floatMed,floatAngle,floatgyro){ intPWM_out; PWM_out=Vertical_Kp*Angle+Vertical_Kd*(gyro-0); returnPWM_out;}在设置KD之后,我们从零开始逐渐增加KD,直到机器对角度变化非常敏感,当几乎没有振荡时,PD调节器的参数设置就完成了。速度PI环代码:float Velocity_Kp=-1.0, //速度环KP、KI-0.5 Velocity_Ki=0;intVelocity(intencoder_left,intencoder_right)//高速转动后会失控,高速转动是因为离开地面负载变小{ staticintPWM_out,Encoder_Err,EnC_Err_Lowout,EnC_Err_Lowout_last;//【2】 floata=0.7;//【3】滤波值越大,滤波越好 //1.计算速度偏差 Encoder_Err=(encoder_left+encoder_right)-0;//舍去误差 //2.对速度偏差进行低通滤波作用是低速可以通过,高速削去 //low_out=(1-a)*Ek+a*low_out_last;=误差+a*(上次误差-这次误差)作用比较上次和这次误差,差越大输出越小 EnC_Err_Lowout=(1-a)*Encoder_Err+a*EnC_Err_Lowout_last;//使得波形更加平滑,滤除高频干扰,防止速度突变。 EnC_Err_Lowout_last=EnC_Err_Lowout;//防止速度过大的影响直立环的正常工作。 //3.对速度偏差积分,积分出位移? Encoder_S+=EnC_Err_Lowout;//【4】 //1.积分限幅 Encoder_S=Encoder_S>10000?10000:(Encoder_S<(-10000)?(-10000):Encoder_S) //5.速度环控制输出计算 PWM_out=Velocity_Kp*EnC_Err_Lowout+Velocity_Ki*Encoder_S;//【5】 returnPWM_out;我们调整PI积分去控制小车转速这个过程就叫做控制速度环的正反馈的过程,它就是在两轮自平衡小车的电机转子在转动的时候,电机的编码器数据的绝对值如果比零要大,那么进过PI的速度环积分运算之后就会变得更大了,如果PI的这个运算放大之后的数值如果放在了PWM的占空比的数值上面的话,那么还会使得电机转子转动的更加快速,转动快速的结果就是导致电机转动的会更加快,然后电机的编码器的数据绝对值也就变得更大,这一个运算放大的效果会一直持续到PWM的占空比变成最大值的时候。1.3.2陀螺仪加速度计的设计陀螺仪是用于测量或维护方位和角速度的设备。它是一个旋转的轮子或圆盘,其中旋转轴可以不受影响的设定在任何方向。当旋转发生时,根据角动量守恒定律,该轴的方向不受支架倾斜或旋转的影响,MPU6050的工作原理图如图4-3所示。图4-3MPU的工作原理图我们直接得到的是加速度计(测量的加速度)和陀螺仪(测量的角速度)。我们使用的是姿态角,分别是发射角、偏航角和滚转角,mpu6050DMP模块需要将原始数据转换成四元数,然后通过公式将四元数直接转换成姿态角如图4-4。图4-4MPU6050数据转化检测姿态角姿态检测完成后,mpu6050实时采集汽车的角速度和角加速度,并将数据传输给主控制器。主控制器驱动直流发动机驱动模块,负责将主控制器输出的PWM信号转换为控制信号,驱动两台直流发动机的转速和方向,发动机编码器应负责测量直流发动机的速度和方向,并将测量数据输入主控制器,以形成闭环控制。流程表如图4-5所示。图4-5MPU6050的总体框图MPU6050代码:u8MPU_Init(void){ u8res; MPU_IIC_Init();//初始化IIC总线 MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X80); //复位MPU6050delay_ms(100); MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X00); //唤醒MPU6050 MPU_Set_Gyro_Fsr(3); //陀螺仪传感器,±2000dps MPU_Write_Byte(MPU_USER_CTRL_REG,0X00); //I2C主模式关闭 MPU_Write_Byte(MPU_FIFO_EN_REG,0X00); //关闭FIFO MPU_Write_Byte(MPU_INTBP_CFG_REG,0X80); //INT引脚低电平有效 res=MPU_Read_Byte(MPU_DEVICE_ID_REG); if(res==MPU_ADDR)//器件ID正确 { }elsereturn1; return0;}这个是初始化代码,主要内容:初始化I2c总线,如果返回0为成功,其他就为错误代码,复位MPU,设置模式,设置CLKSEL,PLLX轴为参考,设置采样率。u8MPU_Set_Gyro_Fsr(u8fsr){ returnMPU_Write_Byte(MPU_GYRO_CFG_REG,fsr<<3);//设置陀螺仪满量程范围设置MPU6050陀螺仪传感器满量程范围,fsr等于0,为±250dps;fsr等于1,为±500dps;fsr等于2,为±1000dps;fsr等于3,±2000dps,本次设置为fsr等于3。设置MPU6050加速度传感器满量程范围,fsr设置等于0,为±2g;fsr设置等于1,为±4g;fsr设置等于2,为±8g;fsr设置等于3,为±16g,如果返回值是0的话,就表示设置成功,如果为其他值的,就表示设置失败。u8MPU_Set_LPF(u16lpf){ u8data=0; if(lpf>=188)data=1; elseif(lpf>=98)data=2; elseif(lpf>=42)data=3; elseif(lpf>=20)data=4; elseif(lpf>=10)data=5; elsedata=6; returnMPU_Write_Byte(MPU_CFG_REG,data);//设置数字低通滤波器设置MPU6050的数字低通滤波器的数字低通滤波频率lpf,在程序中做判断,如果是188的话,data等于1;如果是98的话,data等于2;如果是42的话,data等于3;如果是20的话,data等于4;如果是10的话,data等于5;如果返回值是0的话,就表示设置成功,如果为其他值的,就表示设置失败。u8MPU_Set_Rate(u16rate){ u8data; if(rate>1000)rate=1000; if(rate<4)rate=4; data=1000/rate-1; data=MPU_Write_Byte(MPU_SAMPLE_RATE_REG,data); //设置数字低通滤波器 returnMPU_Set_LPF(rate/2); //自动设置LPF为采样率的一半}设置MPU6050的采样率rate,在4到1000赫兹之中,程序会返回LPF为rate的一半。shortMPU_Get_Temperature(void){u8buf[2];shortraw; floattemp; MPU_Read_Len(MPU_ADDR,MPU_TEMP_OUTH_REG,2,buf);raw=((u16)buf[0]<<8)|buf[1];temp=36.53+((double)raw)/340;returntemp*100;;}该方法能够得到MPU的温度,拿到温度值返回温度值的100倍率,可以进行控温,测温。u8MPU_Get_Gyroscope(short*gx,short*gy,short*gz){u8buf[6],res; res=MPU_Read_Len(MPU_ADDR,MPU_GYRO_XOUTH_REG,6,buf); if(res==0) { *gx=((u16)buf[0]<<8)|buf[1]; *gy=((u16)buf[2]<<8)|buf[3]; *gz=((u16)buf[4]<<8)|buf[5]; } returnres;;}拿到并返回陀螺仪值(原始值),gx,gy,gz是原陀螺仪的x,y,z轴的初始值。u8MPU_Get_Accelerometer(short*ax,short*ay,short*az){u8buf[6],res; res=MPU_Read_Len(MPU_ADDR,MPU_ACCEL_XOUTH_REG,6,buf); if(res==0) { *ax=((u16)buf[0]<<8)|buf[1]; *ay=((u16)buf[2]<<8)|buf[3]; *az=((u16)buf[4]<<8)|buf[5]; } returnres;;}拿到并返回加速度计值(原始值),ax,ay,az是原加速度计的x,y,z轴的初始值。u8MPU_Read_Len(u8addr,u8reg,u8len,u8*buf){ MPU_IIC_Start();MPU_IIC_Start(); MPU_IIC_Send_Byte((addr<<1)|1);//发送器件地址+读命令 MPU_IIC_Wait_Ack(); //等待应答 while(len) {u8MPU_Write_Byte(u8reg,u8data) {}u8MPU_Read_Byte(u8reg){ u8res;MPU_IIC_Start(); }这三个方法则是MPU读写寄存的方法,IIC可以连续读,读取寄存器地址和长度,还能选择读取到的数据存储区域,将数据写入寄存器地址,返回读到的数据。1.3.2蓝牙模块的设计系统在编程过程中以STM32微处理器为核心,通知并控制蓝牙模块的高低电平,进而控制发动机的旋转方向,控制车的旋转模式通过蓝牙模块实现。蓝牙移动助理连接到蓝牙模块,以检查汽车的各种操作模式。总体框图如图4-6所示。图4-6蓝牙模块框图串口初始化:#include"usart3.h" voiduart3_init(u32bound){ //GPIO端口设置 GPIO_InitTypeDefGPIO_InitStructure; USART_InitTypeDefUSART_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//时钟GPIOB,USART3 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);//USART3_TXPB.10 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; GPIO_Init(GPIOB,&GPIO_InitStructure); //USART3_RX PB.11 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOB,&GPIO_InitStructure); //USART初始化设置 USART_InitStructure.USART_BaudRate=bound;//一般设置为9600; USART_InitStructure.USART_WordLength=USART_WordLength_8b; USART_InitStructure.USART_StopBits=USART_StopBits_1; USART_InitStructure.USART_Parity=USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx; USART_Init(USART3,&USART_InitStructure); USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);//开启中断 USART_Cmd(USART3,ENABLE);//使能串口}通过串口3与蓝牙连接,手机连接蓝牙将信息发送给蓝牙模块,再传至STM32获取控制信息。串口1中断服务程序,接收中断标志位拉高,保存接收到的指令。保存就收指令的程序如下:u8Fore,Back,Left,Right;voidUSART3_IRQHandler(void) //串口1中断服务程序{intBluetooth_data;if(USART_GetITStatus(USART3,USART_IT_RXNE)!=0)//接收中断标志位拉高{Bluetooth_data=USART_ReceiveData(USART3);//保存接收到的指令if(Bluetooth_data==0x00)Fore=0,Back=0,Left=0,Right=0;//刹车elseif(Bluetooth_data==0x01)Fore=1,Back=0,Left=0,Right=0;//前进elseif(Bluetooth_data==0x05)Fore=0,Back=1,Left=0,Right=0;//后退elseif(Bluetooth_data==0x03)Fore=0,Back=0,Left=1,Right=0;//左转elseif(Bluetooth_data==0x07)Fore=0,Back=0,Left=0,Right=1;//右转elseFore=0,Back=0,Left=0,Right=0;}}保存到发送的指令之后,需要通过蓝牙串口发射信号给stm32://发送一个voidUSART3_Send_Data(chardata){USART_SendData(USART3,data);while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==0);//除非发送完成}//发送一串voidUSART3_Send_String(char*String){u16len,j;len=strlen(String);for(j=0;j<len;j++){USART3_Send_Data(*String++);}}1.3.3避障模块的设计图4-7避障模块程序框图超声波模块接舵机信号端输入PWM信号调节速度,避障程序框图如图4-7所示,实现控制电机转向的程序如下:#include<AT89x51.H>
#include<intrins.h>
#defineSevro_moto_p
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 语文文学常识初中
- 师建筑工程管理与实务考试复习模拟试题及答案
- 护理精神科护理与心理护理培训
- 2026西北工业大学水下信息技术陕西省重点实验室招聘2人(陕西)备考题库及参考答案详解(模拟题)
- 2026广东广电网络江门新会分公司招聘10人笔试题库及答案详解(名校卷)
- 2026年潍坊寒亭区融媒体中心公开招聘播音主持人员简章参考题库带答案详解(典型题)
- 2026西北工业大学无人系统发展战略研究中心招聘1人(陕西)笔试题库附参考答案详解【基础题】
- 2026年6月云南玉溪市易门菌乡大酒店有限责任公司招聘2人参考题库【基础题】附答案详解
- 2026年安徽财经大学国际教育学院工作人员招聘1名参考题库附完整答案详解(有一套)
- 2026湖南永州市映山小学公开选聘教师12人备考题库及答案详解【基础+提升】
- 2026年全国土地登记代理人之地籍调查考试重点黑金模拟题(附答案)
- 2026年高考真题-语文(全国二卷) 含解析
- 世界之外工作方案
- SLT 336-2025水土保持工程全套表格
- 甲状腺癌诊疗规范
- AI赋能教育作业批改:技术、应用与实践指南
- 设计院转型升级的策略与实践案例
- DB37T5312-2025 建筑施工安全防护设施技术标准
- 2026年高考政治一轮复习:统编版选择性必修二《法律与生活》主观题 专项练习题汇编(含答案解析)
- DRG付费下医院成本管控数据策略
- 物理青海会考真题及答案
评论
0/150
提交评论