你好学弟!这里是学长向你展现他们在2019年夏天花了大价钱购入一台平衡小车之家的风力摆,一直想照着搭一个,结果刚研究完就比赛了。
老师让咱们把这堆破烂留给大家(有些零件缺了大家要本身买 -_-),这边怕大家不懂,彻底自愿的给大家写了一篇教程,规避一些咱们走过的弯路,也但愿大家能把这份精神传承下去,替下下届的接班人们开山铺路。话很少说,先上个实物图。
还有一个电源:
web
这根杆是很是软质的那种,颇有弹性,咱们以前买过一根碳纤维杆彻底不适合。
其次它全部重量全都集中在底部,惯性至关好。总共分三层,下面一一拆解开来看一下:app
硬件层:
这一层有一块MPU6050用于姿态测量,一块蓝牙模块用于使用配套的APP,还有从顶部接入的主电源。输出方面有四路电机插槽,不知道是怎么驱动空心杯电机的,由于并无看到任何驱动器件,还有一个激光头输出。
svg
机械层:
最底层是四路空心杯电机和一个激光头用于指示路径。
函数
用Keil v5建的工程,用Keil v4要装一个Keil v5,并且Keil v4要卸载掉,否则会起冲突。
先看主函数部分:spa
int main(void) { MY_NVIC_PriorityGroupConfig(2); //=====设置中断分组 uart1_init(128000); //=====串口1初始化 uart2_init(9600); //=====串口2初始化 delay_init(); //=====延时函数初始化 // JTAG_Set(JTAG_SWD_DISABLE); //=====关闭JTAG接口 // JTAG_Set(SWD_ENABLE); //=====打开SWD接口 LED_Init(); //=====初始化LED KEY_Init(); //=====按键初始化 MiniBalance_PWM_Init(7199,0); //=====初始化PWM10KHZ,用于驱动电机 OLED_Init(); //=====OLED初始化 delay_ms(1000); //=====延时 IIC_Init(); //=====IIC初始化 MPU6050_initialize(); //=====MPU6050初始化 DMP_Init(); //=====初始化DMP Adc_Init(); //=====adc初始化 MiniBalance_EXTI_Init(); //=====MPU6050 5ms定时中断初始化 200Hz定时 Laser=1; //=====开启激光灯 PA12 if(KEY==0)Flash_Read(); //=====开机长按用户按键读取flash参数运行 while(1) { if(Debug_key==7&&Flag_Zero) {Read_AngleZero(Flag_Zero,10);}//调试界面按键7(第三排第一个)零点读取 if(Debug_key==4&&Flag_Zero==0) {Flag_Zero=1,count_Zero=0,LED=0;}//调试界面按键4(第二排第一个)零点读取标志位,建议4,7重复两次 if(Flag_Show==0) //默认开启APP和OLED显示屏,长安按键3S切换上位机 { APP_Show(); // APP显示数据 oled_show(); //===显示屏打开 } else DataScope(); //开启上位机 if(Flash_Send==1) //写入PID参数到Flash,由app控制该指令 { Flash_WritePID(); //将PID参数写入Flash保存 Flash_Send=0; } delay_flag=1; delay_50=0; while(delay_flag); //经过MPU6050的INT中断实现精准的50ms延时 } }
其余的就大体讲解一下各个文件的内容:
.net
main.c: 包含所有变量的定义,初始化与主循环函数,全部文件经过调用sys.h来使用变量 sys.c: 包含全部系统相关初始化函数的定义,如时钟初始化,配置JTAG模式,配置外部中断等 usart.c: 包含uart1与uart2的初始化。uart2的中断处理函数,用于处理蓝牙传过来的数据。fputc函数的重定义,这里同时使用了串口1和2。 LED.c: LED的初始化与闪烁函数 key.c: 按键的初始化与双击,单击,长按函数 oled.c: oled的初始化与各类使用函数 adc.c: ADC1的初始化与使用,用于获取电池电压 motor.c: 定义用于驱动四个电机的PWM,初始化TIM3的四个PWM输出脚 IOI2C.c: 用于定义一个模拟IIC协议,是给MPU6050使用的 exti.c: 将PB6定义为一个外部触发的中断,由MPU6050给出中断信号,获得一个精确的5ms时钟 stmflash.c: 对stm32的内部flash进行初始化与读写操做函数,主要用于存取预设的PID参数 control.c: 是整个工程的主要控制逻辑部分,包含 ------------------------------------------------------------------------------------ int EXTI9_5_IRQHandler(void) //由MPU6050触发的5ms定时中断处理函数 //包括姿态更新Read_DMP(),控制模式更新Get_RC(),PID计算,按键扫描,电机的PWM赋值 int Position_PID_X (float value,float Target) //PID的的计算,这里采用的就是传统的PID, int Position_PID_Y (float value,float Target) //关于PID的相关说明与各类PID,见https://blog.csdn.net/foxclever/article/category/9281151,这是一个系列,建议从第一篇到结尾都看一遍 void Get_RC(void) //处理APP传入的控制模式信息 //根据uart2中断里置位的各类标志位进行一系列的switch-case操做 ------------------------------------------------------------------------------------ inv_mpu.c: inv_mpu_dmp_motion_driver.c: MPU6050的dmp单元相关库,若是要使用MPU内置的dmp单元则须要包含 MPU6050.c 包含MPU6050的初始化与内部信息的读取函数 filter.c (未使用) 定义了卡尔曼滤波与一阶滤波的相关函数 show.c 包含 void oled_show(void)用于在oled显示屏上显示数据。 void APP_Show(void)用于向串口2 APP发送数据。 void DataScope(void)用于向串口1 上位机发送数据
店家给的资料其实还挺多的,然而你不买根本不会给你。
腾讯微云:https://share.weiyun.com/5kC2VAe 密码:bt5u5c
源码连接:https://download.csdn.net/download/qq_43243338/11939899调试