# 2022控制组方向线上测试
**Repository Path**: buaarobot_admin/ControlGroupOnlineTest2022
## Basic Information
- **Project Name**: 2022控制组方向线上测试
- **Description**: 北航机器人队2022控制组方向线上测试题发布
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 7
- **Forks**: 1
- **Created**: 2022-07-16
- **Last Updated**: 2025-05-11
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 2022控制组单片机方向线上测试
## 第一周测试题
### 1.git基本操作
#### 任务简介
> Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目,可以帮助你进行自动的版本管理。控制组单片机端**之后的线上测试都是通过`gitee`发布**,在多人协作的情况下,使用`git`就会相当的方便,能够有效地协调多位开发者对不同地方的改动。
#### 任务要求
- 安装git,并且注册好`gitee`账户与`git`绑定,并且点击[**邀请链接**]([2022控制组线上测试题 (gitee.com)](https://gitee.com/buaarobot_admin/ControlGroupOnlineTest2022/invite_link?invite=7600632b845df338c29945b4076b0cacf366c75cc061dd04b7993663152babc5b5bb6a8590dff59e5f318cd36bbddc3a))加入本远程仓库
- 注意邀请链接的有效期为3天
- 在想要克隆本仓库的地方,右键菜单点击“**`Git Bash Here`**”,输入以下代码,即可实现将远程仓库克隆到本地的操作,注意**之后的任务会放置在任务文件夹中**
```c
>>> git clone https://gitee.com/buaarobot_admin/ControlGroupOnlineTest2022.git
```
- 创建一个markdown文件,命名格式为{**{你的名字}.md**},如`李明.md` 撰写你对本周题目的难度的看法,创建一个简述自己对**git组成以及常见命令使用原理的理解**的markdown文件,命名格式为 **{你的名字ToMarkDown}.md** 。
两个文件统一放到`ControlGroupSCMOnlineTest2022/第一周测试题/task1`下面
- `git commit -m {改动的内容}` 在这里写清这次提交改动的内容:**{你的名字}提交task1**
- 本任务结果提交方式为**git提交**
##### 提示信息
- 可以使用`git push` 将本地所有未上传的提交推送到远程仓库
- 此时有可能会提示推送失败,这是因为远程仓库里面有本地未获取的提交
- 此时需要先`git pull`获取当前远程仓库的最新版本, 将远程仓库的最新版本和本地最新版本合并(`merge`)后,才能够推送
- 第一次进行提交操作时需要登记提交者信息,提交时`git`会有相关的操作说明
- 更多详细的`git`用法请查询参考资料或借助网络搜索
##### 注意
**不是**所有任务都需要利用git进行提交,第一周以及以后的其它任务提交方式**请以对应的任务说明为准**
#### 参考资料
- [git入门教程](https://www.cnblogs.com/imyalost/p/8762522.html)
- [菜鸟教程yyds](https://www.runoob.com/git/git-tutorial.html)
- 一个可以打开md文件的软件:[Typora](https://www.typora.io/windows/dev_release.html)
### 2.PID控制程序编写及封装
#### 任务简介
- PID算法是控制领域应用最广泛的算法,其计算流程与其应用场景并无关系,为了避免重复编写同样的代码,我们往往会将PID算法进行封装,初始化过后直接调用即可。
#### 任务说明
- 1.请完善`PID.c`中的两个空白函数,函数的功能已经在注释中写出。
`void PID_StructInit(void PID_StructInit(PID_t *pid, float p, float i, float d, float integral_limit, float max_output))`
`static void Calculate(PID_t *pid, float current_value, float target_value)`
- 2.请根据自己编写好的函数进行对`PID.c`的封装。
需要达到的要求是用户在定义 `PID_t` 结构体后(例如 `PID_t TestPID`),先运行`PID_StructInit`函数,再使用`TestPID.f_Calculate(&TestPID, Current_value, Target_value)`即可完成计算,计算的结果保存在结构体中。
- 3.通过查阅关于`PID`的资料,说一说P、I、D分别有什么作用,如果让你调节PID参数,你会如何开始调节。写成一个TXT文档,字数不超过100字,以自己的名字命名即可。
- 4.本任务的代码均放在 `第一周测试题/task2`文件夹下。
#### 任务要求
- 需要提交的文件:`PID.c`和`PID.h`和`PID参数说明文档`。将这些文件放在`第一周任务/task2`目录下即可。
- 程序有一定可读性,包含适当的注释;**即使没能完成任务,也请提交上来**,并且在同目录下创建一个README文本文件中写明原因以及完成的进度情况。
- 本任务提交方式为**邮箱提交**,地址为`bhjqrdkzz2022@163.com`(与其他需要邮箱提交的任务放在**同一个zip文件**中,zip文件命名格式为 **{你的名字}第一周测试题.zip)**
#### 参考资料
- [初识PID-搞懂PID概念](https://zhuanlan.zhihu.com/p/74131690)
### 3. 串口的使用
#### 任务要求
- 任务实现过程为:串口调试助手**通过串口**发送字符'a'(char类型数据,不用数据帧编码),下位机开始通过相同串口循环打印数字1-10(**Simple帧编码**),发送字符'b'(char类型数据,不用数据帧编码),下位机开始通过相同串口循环打印数字11-20(**Normal帧编码**),发送字符'c'(char类型数据,不用数据帧编码),下位机开始通过相同串口循环打印数字21-30(**Trigger帧编码**)
- **要求**
- 与下位机STM32F407之间的通信使用给定的三种数据帧(由操作手**在串口助手上**进行指定)
- **仅需要**编写**下位机**程序
- 将编写好的KEIL工程文件放在task3文件夹下与其他任务的文件一起打包为zip文件,命名为"**{你的名字}+控制组测试题第一周**"发送至指定邮箱bhjqrdkzz2022@163.com
#### 任务提示
- 三种数据帧示意图如下所示
- 参数说明
- 帧头:0x7E(type: uint8_t)
- 类型位:Simple:0,Normal:1,Trigger:2(type: uint8_t)
- Simple:
- 长度位:5(type: uint8_t)
- 编号位:简单帧ID(type: uint8_t)
- 数据位:
- size:4
- type:float(4字节)
- Normal
- 长度位:sizeof(“buaarobotteam”)+4
- 名称位:(char[])(“buaarobotteam”)
- 数据位:
- size:4
- type:float(4字节)
- Trigger
- 长度位:{数量位}*4+2(type: uint8_t)
- 编号位:ID位(type: uint8_t)
- 数量位:uint8_t
- 参数位:
- size:{数量位}*4
- type:float(4字节)
- 校验位:0x03(type: uint8_t)
- 帧尾:0x04(type: uint8_t)
例:Simple帧数字1:7E0005010000803F0304
- 对于三种数据帧的ID位可均设置为1.
- 数据帧编码采用**小端模式**,STM32采用的是**小端模式**
**参考资料**
- [经典永流传](https://gitee.com/link?target=https%3A%2F%2Fwww.bilibili.com%2Fvideo%2FBV1kx411k7JT)
- [知识宝库](https://gitee.com/link?target=https%3A%2F%2Fspace.bilibili.com%2F394620890)
### 4.串口调试助手
#### 任务要求
- 利用Qt实现能够按数据帧格式编码数据的串口调试助手
- **要求**
- 需要实现串口调试助手的基本功能,如选择串口,设置波特率、停止位等(注:此处的校验位、停止位等视为不影响数据帧的编码,可任意实现)
- 除正常串口调试的基本功能外,要对发送的数据(单个或多个float类型数据,取决于数据帧类型)进行编码,编码数据帧格式按任务3所述
- **仅需要**编写**串口调试助手**程序
- 将编写好的Qt工程文件放在task4文件夹下与其他任务的文件一起打包为zip文件,命名为"**{你的名字}+控制组测试题第一周**"发送至指定邮箱bhjqrdkzz2022@163.com
## 第二周测试题
### 5.CAN通信
#### 任务说明
- 子任务1:查阅相关资料,简述CAN通信相比于其他有线通信方式的优点。试从物理层和协议层,谈谈自己对CAN通信“简便、可靠”的理解。写成一个txt文档,字数不超过200字,以自己名字命名即可。
- 子任务2:阅读参考资料“RM C610无刷电机调速器使用说明 发布版”中的“CAN通信协议”内容,任选一款含有CAN的STM32芯片,新建Keil工程尝试编写程序,利用STM32控制板与C610电调进行通信,并利用“第一周测试题”中封装好的“PID控制程序”控制1个C610电调及电机工作在固定速度。具体提示如下:
1. 阅读参考资料“RM C610无刷电机调速器使用说明 发布版”中的“电调反馈报文格式”内容,配置CAN过滤器,接收C610电调(认为帧ID为1)向总线上发送的反馈信息。
2. 接收到C610电调反馈的信息,提取数据域中的“转子转速”内容,作为输入项输入到封装好的“PID控制程序”中,并将“PID控制程序”的输出作为控制电流,准备向CAN总线上发送。
3. 阅读参考资料“RM C610无刷电机调速器使用说明 发布版”中“电调接收报文格式”,配置CAN发送格式,将2中控制电流发送给电调。
#### 任务要求
- 与C610电调通信的波特率为1Mbps。
- 将以上内容放在task5文件夹下与其他任务的文件一起打包为zip文件地址为zip文件命名格式为**{你的名字}第二周测试题.zip**),提交到邮箱`bhjqrdkzz2022@163.com`
#### 参考资料
[RM C610无刷电机调速器使用说明 发布版](https://rm-static.djicdn.com/tem/RM%20C610%E6%97%A0%E5%88%B7%E7%94%B5%E6%9C%BA%E8%B0%83%E9%80%9F%E5%99%A8%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E%20%E5%8F%91%E5%B8%83%E7%89%88.pdf)
[正点原子STM32开发板 — 正点原子资料下载中心 1.0.0 文档](http://47.111.11.73/docs/boards/stm32/index.html)
### 6. 无刷电机控制
#### 任务简介
##### 无刷直流电机
- 机器人的驱动通常有电动、气动和液动三种,电机驱动是三种方式中功率密度最大、功能方式最简、伺服精度最高的控制方式。在移动式机器人中,常用直流电源(如航模电池)给电机供电,实现机器人的能源-驱动系统。
- 电动机一般分为同步电机和异步电机,其共同点是都需要旋转的磁场来产生驱动力。为了产生旋转的磁场,就需要交变的电流。因此,直流电机控制的核心技术是将直流电压逆变为交流电压,进而产生交变电流。逆变技术有很多种,最简单的是通过电刷换向,应用此技术的电机称为有刷直流电机(BDC: Brush Direct Current Motor)。直流有刷电机的优点为驱动电路简单、工作稳定、力矩大。其缺点为能量转换效率低、需要维护更换电刷、转速一般较低。
- 相应的,使用电子管换向而取代电刷换向的电机,称为无刷直流电机(BLDC: Brushless Direct Current Motor)。随着无刷电机控制技术的发展,更多的半导体公司推出了成熟的无刷电机控制方案。而由于无刷电机能量密度高、无需维护、效率高、伺服精度高的优点,移动机器人中使用无刷电机成为主流趋势。传统的BLDC控制方法是通过霍尔传感器以及换向电子管,因此其通过生产时对磁隙的调制,使反电动势为方波。而由于控制方法的精进,使得我们不仅可以用直流电源驱动BLDC,还可以直接使用直流电源驱动一些交流电机,比如永磁同步电机(PMSM: Permanent-Magnet Synchronous Motor),对其控制方法称为空间矢量控制(FOC: Field-Oriented Control)。
- 在北航机器人队中,我们通常使用PMSM作为机器人驱动器。
##### 电机编码器
- 电机位置的传感对电机控制与机器人控制都有重要意义,编码器是常用的电机位置传感器。常见的编码器的种类有光电编码器和磁编码器等,按照反馈信息形式,又分为增量式编码器与绝对式编码器。
#### 任务说明
1. 以下为北航机器人队常用的M3508电机,请根据下图,查阅资料,简述机器人驱动电机的3个主要组成部分,并分别简述其作用,不超过200字。
2. 请通过查阅资料,简述BLDC与PMSM的区别,并简述PMSM的控制原理,不超过300字。
3. 无刷电机的控制方式常见为三环控制,即电流环、速度环和位置环通过级联的方式实现控制。常见的FOC控制器或电调通常会封装电流环,机器人队使用的控制器带有三环的封装,其中电流环参数会通过测量电机绕组的电阻和电感参数自动计算,而速度环和位置环参数与外部负载有关。请简述三环分别的输入量与输出量的物理意义,以及三环控制的作用,不超过100字。
#### 任务要求
- 将简述内容整理在"无刷电机控制.md"文件中,放在`/task4`目录下。
- 若未及时完成任务,也请一并提交;若对题目理解有困难,可在微信群讨论。
- 将以上内容放在task6文件夹下与其他任务的文件一起打包为zip文件地址为zip文件命名格式为**{你的名字}第二周测试题.zip**),提交到邮箱`bhjqrdkzz2022@163.com`
#### 参考资料
- [【自制FOC驱动器】深入浅出讲解FOC算法与SVPWM技术](https://zhuanlan.zhihu.com/p/147659820)
- [一文了解BLDC与PMSM的区别](https://blog.csdn.net/sphinz1/article/details/109265584)
### 7.全场定位基础
#### 任务简介:
全场定位模块是整个机器人中必不可少的一部分,通过陀螺仪、[正交轮](https://www.mfcad.com/tuzhi/1658/1082371.html)与激光,机器人可以知晓自己在场地中的位置,从而更好地完成一系列自动任务,底盘正交轮1,2和世界坐标系如下图所示。
#### 任务说明:
- 子任务1:推导依靠正交轮与陀螺仪实现全场定位的基本方法。已知正交轮的基本结构如上图所示,假定每个轮子顺时针转动为正,假定陀螺仪的欧拉角已经得到,并且偏航角顺时针为正。
- 子任务2:在Location.c与Location.h中,根据注释提示补全代码,实现定位信息的获取。
- 子任务3:请简要叙述陀螺仪、光纤陀螺、激光陀螺的区别与联系,不超过500字
- 将以上内容放在task7文件夹下与其他任务的文件一起打包为zip文件地址为zip文件命名格式为**{你的名字}第二周测试题.zip**),提交到邮箱`bhjqrdkzz2022@163.com`
#### 参考资料
- 王志君. 移动机器人全场定位系统的研究[D].电子科技大学,2015.
## 第三周测试题
### 8.PI校正
#### 任务简介
根据控制模型,得出最优的PI控制参数
#### 任务说明
FOC三环控制模型中,为减小控制量,获得稳定的控制量,将电机A、B、C三相静止坐标系通过Park变换和Clack变换后得到随定子旋转的d-q坐标系,得到电机电压电压与电流关系如下式所示,其中 $u_d,u_q$ 为定子电压d-q轴分量, $i_d,i_q$为定子电流d-q轴分量,$L_d,L_q$为定子电感d-q轴分量,$\omega_e$为电机电角速度(rad/s),$\phi_s$为电机永磁体磁链(Wb)。
$$
\begin{align}
u_{q}=&R_{s} \times i_{q}+L_{q} \frac{d i_{q}}{d t}+\omega_{e}( \phi_s+L_{d} i_{d})
\\
u_d=&R_s \times i_{d}+L_d \frac{d i_d}{d t}-\omega_e L_q i_q
\end{align}
$$
可以看出上式中电流电压是耦合的,在电机转速较低时$\omega_e$近似为0(高速时通过对电机参数辨识,实现前馈解耦),对于表贴式电机(SPM)$L_d=L_q=L$,上式可简化为
$$
\begin{align}u_{q}=&R_{{s}} \times i_{q}+L \frac{d i_{q}}{d t}\\
u_d=&R_s \times i_{d}+L\frac{d i_{d}}{d t}\end{align}
$$
此时d-q系控制相互解耦,很容易可以得到电压与电流传递函数满足
$$
G(S)=\frac{I(S)}{U(S)}=\frac{1}{R+LS}
$$
于是可以在simulink中搭建电机控制结构框图如下图所示,由PI控制环节、由单片机定时器装载产生的滞后环节和电机模型共三个环节;其中$T_S=\frac{1}{30000}s$为电流环执行周期,取电机参数$L=6.27e^{-6}H,R=0.017\Omega$
当Kp=1,Ki=0时,阶跃响应效果如图所示,
#### 任务要求:
- 子任务1:根据task8文件夹中的.slx文件,调整PI控制参数,使其单位阶跃响应调节时间小于0.5ms,超调小于5%,无稳态误差。
- 子任务2:根据自控原理所学知识给出PI控制器设计思路,没学过自控的同学可以结合第一周任务“PID控制程序编写及封装”中的调节方法,给出手动调节思路。
- 子任务3:将调整后的示波器图像和任务2中的设计思路以PDF 形式提交到邮箱。
- 将以上内容放在task8文件夹下与其他任务的文件一起打包为zip文件地址为zip文件命名格式为**{你的名字}第三周测试题.zip**),提交到邮箱`bhjqrdkzz2022@163.com`
### 9.运动学解算
#### 任务简介:
底盘运动学分解是控制组必备技能。在今年的Robocon比赛中,北航机器人队采用了3舵轮运动底盘,我们需要对底盘进行运动学分解,以便控制机器人进行运动
#### 任务说明:
- 子任务1:推导如图1所示三舵轮底盘将**车体坐标系**下的目标速度大小、速度方向与角速度大小(方向默认俯视顺时针为正)解算到三舵轮转动**角速度和角度**的公式,写出推导过程并说明各个参数的含义。部分说明与设定参数如下:
- 子任务2:在上一问的基础上,考虑当给出**世界坐标系**下的机器人期望速度矢量与角速度矢量时,解算出三舵轮转动的**角速度和角度**。给出公式,写出推导过程并说明参数含义。
- 子任务3:在ChassisMotion.c 与 ChassisMotion.h 中,根据注释提示补全代码,实现三轮全向轮底盘各轮所需转速的解算任务。
- 将以上内容放在task9文件夹下与其他任务的文件一起打包为zip文件地址为zip文件命名格式为**{你的名字}第三周测试题.zip**),提交到邮箱`bhjqrdkzz2022@163.com`
### 10.FreeRTOS
#### 任务简介:
Robocon的赛场上,机器人同时处理的任务、同时传递的消息繁多,这时候继续采用前后端的编程模式和全局变量的消息形式,就存在一定的局限性,不利于机器人控制逻辑的实现和代码的可维护性。这时候就需要使用嵌入式操作系统。在北航机器人队中,采用的嵌入式操作系统为FreeRTOS,几乎所有控制组的成员都需要掌握FreeRTOS的使用方法。
在之前,我们已经学习过了电机驱动的FOC控制方式,其中的巧妙深入人心。但是在此类伺服驱动能够运行三环控制之前,校准环节是必不可少的。本周的任务需要使用FreeRTOS简单实现编码器校准的工作。
中文版资料(视频和例程以及书籍等)主要参考正点原子(FreeRTOS开发手册)与野火哥(FreeRTOS内核实现与应用开发实战),英文原版资料科参考FreeRTOS官网和官方手册。
#### 任务前提:
##### 编码器校准流程:
①控制电机转向指定电角度$\theta_e$,当电机稳定指向该角度时,记录编码器数值。
②小量改变指定电角度为$\theta_e+\Delta\theta$,重复上述过程。
③由于编码器数值是离散的整数(大小范围为0~1024),因此只要电角度改变足够小,可以做到1个编码器数值对应多个电角度数值。此时,对相同编码器数值$i$对应的多个编码器数值$\theta_{ei}$取平均值$\hat\theta_{e}$,得到$encoder[i]=\hat\theta_{e}$
④处理完全部数据,得到数组encoder[1024]。
##### 定向电流环任务:
①根据$i_{a},i_{b},i_{c}$和$\theta_{e}$,利用Park变换和Clark变换,得到$i_{d},i_{q}$。
②将$i_{d},i_{q}$带入PID中计算(2个PID分别计算,得到输出$u_{d},u_{q}$)。
③高频运行,通常运行频率为校准任务20倍以上。
##### 校准任务:
①迭代期望电角度值$\theta_e+\Delta\theta$。
②读出此时编码器数值$i$。
③重复以上两步,直到电角度值全部遍历。处理所有数据,得到encoder[1024]。
#### 任务说明:
- 子任务1:查阅相关资料,简要谈谈为什么要使用嵌入式操作系统?谈谈你对操作系统FreeRTOS中信号量的功能的理解?字数不超过200字。
- 子任务2:任选一款STM32芯片,新建Keil工程并编写STM32程序,尝试移植FreeRTOS操作系统。然后根据上述流程图,创建2个任务,实现编码器校准的大致过程。具体提示如下:
- 校准任务
1. 创建“校准任务”,运行频率约为50Hz,任务优先级自选,较低即可。
校准任务每次循环时,更新全局变量$\theta_{e}$:(设极对数为1,编码器数值范围0~1024,相同i对应约20个点角度值)
$$
\theta_{e}(n+1)=\theta_{e}(n)+\Delta\theta(\Delta\theta=\frac{2\times\pi\times 1}{1024\times20}=3\times10^{-4})
$$
2. 更新全局变量$\theta_ e$后,“校准任务”进入阻塞态,延时为20ms。
3. 延时20ms后,调用GetRawAngle()函数,该函数不用编写,直接调用即可。其返回值为uint16_t类型,含义为当前编码器数值i。
4. 重复以上过程,直到当$\theta_{e}>2\pi$时,停止循环。此时计算encoder[1024]值:
$$
encoder[i]=\frac{\sum_{j=1}^n\theta_{e}(对应编码器为i的电角度值)}{n}
$$
5. 计算完毕后挂起该任务。
- 定向电流任务
1. 创建“定向电流环任务”,运行频率约1kHz,任务优先级需高于“校准任务”。
2. 调用函数GetCurrent()得到三相电流$i_a,i_b,i_c$。再根据和$i_a,i_b,i_c$和$\theta_ e$,根据前几周学习的FOC内容,调用提供的ClarkTransform()、ParkTransform()函数,得到$i_d,i_q$。接着将分别带入$i_d,i_q$各自的PID运算中,以PID计算的结果为输出$u_d,u_q$(Kp、Ki数值任取)。最后调用函数ApplyVoltDQ()输出$u_d,u_q$。输出$u_d,u_q$后,认为该次循环结束,该任务进入阻塞态,延时为1ms。
- 需注意:当“校准任务”要挂起时,先挂起“定向电流任务”。
#### 任务要求
程序要有一定的可读性,包含适当的注释;即使没能完成任务,也请提交上来,并且写明原因以及完成的进度情况。
可直接调用而无需编写的函数如下
| 返回类型 | 函数名称 | 调用方式 |
| -------- | --------------------------------- | ------------------------------------------------------------ |
| float * | GetCurrent() | float cur = GetCurrent(); $i_a$=cur; $i_b$=(cur + 1); $i_c$=(cur + 2); |
| float * | ParkTransform() ClarkTransform() | 与上函数类似 |
| void | ApplyVoltDQ() | ApplyVoltDQ($u_d$,$u_q$); |
| uint16_t | GetRawAngle() | i = GetRawAngle(); |
将以上内容放在task10文件夹下与其他任务的文件一起打包为zip文件地址为zip文件命名格式为**{你的名字}第三周测试题.zip**),提交到邮箱`bhjqrdkzz2022@163.com`