前言
你好学弟!这里是学长向你展示他们在2019年夏天花了大价钱购入一台平衡小车之家的风力摆,一直想照着搭一个,结果刚研究完就比赛了。
老师让我们把这堆破烂留给你们(有些零件缺了你们要自己买 -_-),这边怕你们不懂,完全自愿的给你们写了一篇教程,规避一些我们走过的弯路,也希望你们能把这份精神传承下去,替下下届的接班人们开山铺路。话不多说,先上个实物图。
还有一个电源:
硬件部分
这根杆是非常软质的那种,很有弹性,我们之前买过一根碳纤维杆完全不适合。
其次它所有重量全都集中在底部,惯性相当好。总共分三层,下面一一拆解开来看一下:
- 主控层:
主控为一块F103,左边5个排母是OLED接口,如果插上的话可以看到输出的调试信息。右边有四根排针为SWD调试接口,可以用J-link调试器进行调试。下面是一个串口IO,可以通过串口查看信息。
-
硬件层:
这一层有一块MPU6050用于姿态测量,一块蓝牙模块用于使用配套的APP,还有从顶部接入的主电源。输出方面有四路电机插槽,不知道是怎么驱动空心杯电机的,因为并没有看到任何驱动器件,还有一个激光头输出。
-
机械层:
最底层是四路空心杯电机和一个激光头用于指示路径。
代码部分
用Keil v5建的工程,用Keil v4要装一个Keil v5,而且Keil v4要卸载掉,不然会起冲突。
先看主函数部分:
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延时
}
}
其他的就大致讲解一下各个文件的内容:
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