同步操作将从 yssickjgd/RoboMaster2023新架构 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
[toc]
感谢RoboWalker战队的Glorill学长, 以及华南虎战队的SRML库文件
drv_bsp
dvc_motor
根据华南虎战队的motor.h文件, 改编形成dvc_motor系列cpp与h文件
在其基础上额外实现了自动分配CAN ID以及CAN滤波器等操作, 顶层操作起来更方便, 不需过度考虑底层实现原理
PID算法类在底层定义后, 其调用并入motor类中, 无需额外声明PID对象. 使用者配置好PID后即可自动在上层调用, 无需同以前一样显式调用PID调整函数, 更符合架构分层的逻辑. 只需在上层设定角度或速度即可
代码风格更统一, 电机类继承的逻辑更直观, 有助于后续战队同学们的理解与维护
dvc_serialplot
根据Glorill学长的SerialPlot文件进行优化
利用可变数量传参, 且传的是指针, 大大增强了代码的独立性
相较于旧版串口绘图, 初始化配置后调用更少的函数即可实现串口绘图数据传输与接收指令, 使用起来更方便
dvc_dr16
对拨码开关以及按键操作的状态更加细分, 新增上升沿, 下降沿等检测, 有助于不同操作继续细化
初始化配置后只需利用各个Get函数, 即可实现对内容的读取, 更易于找到自己想要的参数
词语 | 解释 |
---|---|
drv | Driver, 驱动, 一般指底层配置 |
bsp | Board Supportive Pack, 板级支持包 |
can | Controller Area Network, 一种通信协议, 常用于电机控制 |
alg | Algorithm, 算法, 包含控制算法, 滤波等 |
pid | 一种带有反馈的控制算法 |
dvc | Device, 设备 |
motor | 电机, 顾名思义 |
chariot | 战车, 一般指车整体, 包含底盘, 云台, 发射机构等 |
chassis | 底盘, 进行战车的整体移动 |
pantilt | 云台, 控制枪口相对底盘运动的机构 |
shoot | 发射机构, 主要包括拨盘和摩擦轮 |
pitch、yaw、roll | 欧拉角, 分别是俯仰角, 航向角, 滚转角, 在云台和姿态传感器中描述角度. 形象理解分别对应点头, 摇头, 晃头 |
... | ... |
Keil v5 MDK-ARM工程, 使用STM32CubeMX生成, 使用STM32F427IIH芯片. 如需使用vscode开发, 请安装vscode插件并配置keil环境, 然后你就可以在vscode中使用git版本管理工具进行本项目的开发
值得注意的时, 想要使用vscode中的keil插件开发, 你应当在MDK-ARM文件夹下, 右键“通过Code打开”, 而不是在根目录下
CubeMX生成的代码, 你需要在开发时遵循CubeMX的一切规则. 包括但不限于, 在CubeMX生成的文件中, 你必须在如下两行注释之间写你自己的代码
/* USER CODE BEGIN ...*/
/* USER CODE END ...*/
否则, 在CubeMX中重新生成工程时, 你写的代码将会消失
DMA不生产数据, 只是数据的搬运工. 一般情况下, 外设收发数据与内存交互, 需要通过内核作为中介. 这种情况下, 内核无法处理其他事情. DMA可以让外设对内存直接访问, 减少了内核的工作量. 而且同时内核可以处理其他事务
DMA1
DMA2
引脚使用情况, 与其他外设直接相关, 故不赘述
中断向量, 与其他外设直接相关, 故不赘述.
但需要注意, 自己新建的中断, 抢占优先级是5, 子优先级是0
系统时钟, 此处用到HSE高速外部时钟, 来源于晶振. 配置时选择锁相环PLL通道, HCLK设置为180后自动生成解决方案即可
调试线默认Disable不动就行, 时钟源选择TIM14
arr = 65535
channel2, 加热电阻, 为保证AHRS正常工作, 陀螺仪需要外接加热电阻防止温漂. 该PWM波用来控制加热温度
2700Hz
channel1, 蜂鸣器
下文按照自底向上的顺序介绍
只有一个文件: startup_stm32f427xx.s. 这是stm32的启动文件, 包括初始化堆栈、初始化PC、LR寄存器等功能. 除非你对ARM指令集理解较为深刻并极其确定这个文件出现了问题, 否则不要对这个文件进行任何修改. 也不要在这个文件目录下添加任何的文件
STM32 HAL(Hardware Abstraction Layer)库文件. CubeMX自动生成了这些文件. 你写的代码应当符合HAL库的规则, 而不是ST官方固件库. 不要对这些文件进行任何修改
STM32的驱动文件. 不要修改
用来进行各种外设初始化配置的文件
main.c
stm32f4xx_it.c
详见代码架构.md
裁判系统与电源管理模块
DR16
底盘
云台
发射机构
超级电容
妙算视觉
串口绘图
函数命名, 变量命名, 文件命名要有描述性; 少用缩写
尽可能使用描述性的命名, 别心疼空间, 毕竟相比之下让代码易于新读者理解更重要. 不要用只有项目开发者能理解的缩写, 也不要通过砍掉几个字母来缩写单词
int price_count_reader; // 无缩写
int num_errors; // "num" 是一个常见的写法
int num_dns_connections; // 人人都知道 "DNS" 是什么
int n; // 毫无意义.
int nerr; // 含糊不清的缩写.
int n_comp_conns; // 含糊不清的缩写.
int wgc_connections; // 只有贵团队知道是什么意思.
int pc_reader; // "pc" 有太多可能的解释了.
int cstmr_id; // 删减了若干字母.
注意, 一些特定的广为人知的缩写是允许的, 例如用 i
表示迭代变量和用 T
表示模板参数
绝大多数变量与函数, 用大驼峰+下划线命名全称
函数内的内部变量以及文件内的内部函数, 用小写+下划线命名全称
结构体, 枚举类型命名如下, 注意变量类型是大驼峰, 元素名前面是大驼峰, 后面是全大写
/**
* @brief CAN电机的ID分配情况
*
*/
enum Enum_CAN_Motor_ID_Status
{
CAN_Motor_ID_Status_FREE = 0,
CAN_Motor_ID_Status_ALLOCATED,
};
Enum_CAN_Motor_ID_Status CAN_Motor_ID_Status;
宏定义, 全大写
类的命名规则较复杂, 只可意会, 下方摘自dvc_motor.h, 有删减. 初始化变量是除去初始化外不可更改的变量; 常量是不可更改的默认变量; 内部变量是不可Get也不可Set的变量; 读变量是仅可Get的变量; 写变量是仅可Set的变量; 读写变量是可Get和Set的变量
class Class_Motor_CAN
{
public:
//PID控制
Class_PID *PID_Angle;
Class_PID *PID_Speed;
void Init(CAN_HandleTypeDef *__hcan, Enum_CAN_Motor_ID __CAN_ID);
float Get_Now_Angle();
float Get_Target_Speed();
void Set_Control_Method(Enum_Control_Method __Control_Method);
void Set_Target_Speed(float __Target_Speed);
void Output();
protected:
//初始化相关变量
//绑定的CAN总线
CAN_HandleTypeDef *hcan;
//常量
//一圈编码器刻度
uint16_t Encoder_Num_Per_Round = 8192;
//内部变量
//接收的编码器位置, 0~8191
uint16_t Rx_Encoder = 0;
//读变量
//当前的角度, rad
float Now_Angle = 0;
//写变量
//电机控制方式
Enum_Control_Method Control_Method = Control_Method_ANGLE;
};
库文件本身就是小写加下划线, 例如
system_stm32f4xx.c
用户文件小写加下划线, 例如
dvc_motor.cpp
.h与对应的.c同名
对于代码模板, 本仓库已经给出xxx.cpp和xxx.h两个模板用于进行套用, 希望尽量遵循该模板的内容
如有必要, 需要进一步注释. 一行语句或多行语句用单行注释. 多行语句需要注释时, 如有必要可以用双回车进行分段. 函数前如有必要可以用多行注释解释. 例如
/**
* @brief 设定预期速度,底盘坐标系
* @param V 三轴速度
* @note 将底盘运动速度解算为四个电机的运动速度
* @retval null
*/
void C_Chassis ::SetSpeed(SpeedTypeDef V)
{
float vx=V.vx, vy=V.vy, omega=V.omega;
//速度限制
//x方向
_Constrain(&vx, -SpeedMax.vx, SpeedMax.vx);
//y方向
_Constrain(&vy, -SpeedMax.vy, SpeedMax.vy);
//角速度
_Constrain(&omega, -SpeedMax.omega, SpeedMax.omega);
TargetSpeed.vx = vx;
TargetSpeed.vy = vy;
TargetSpeed.omega = omega;
//更新底盘速度变量
WheelSpeed[0].Target = (OMEGA_TO_MS * omega + vx - vy) / RPM_TO_MS;
WheelSpeed[1].Target = (OMEGA_TO_MS * omega + vx + vy) / RPM_TO_MS;
WheelSpeed[2].Target = (OMEGA_TO_MS * omega - vx + vy) / RPM_TO_MS;
WheelSpeed[3].Target = (OMEGA_TO_MS * omega - vx - vy) / RPM_TO_MS;
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。