# 2021控制组单片机方向线上测试
**Repository Path**: wangchunzheng/ControlGroupSCMOnlineTest2021
## Basic Information
- **Project Name**: 2021控制组单片机方向线上测试
- **Description**: 北航机器人队2021控制组单片机方向线上测试题发布
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 4
- **Created**: 2021-10-27
- **Last Updated**: 2021-10-27
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 2021控制组单片机方向线上测试
## 第一周测试题
### 1.git基本操作
#### 任务简介
> Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目,可以帮助你进行自动的版本管理。控制组单片机端**之后的线上测试都是通过`gitee`发布**,在多人协作的情况下,使用`git`就会相当的方便,能够有效地协调多位开发者对不同地方的改动。
#### 任务要求
- 安装git,并且注册好`gitee`账户与`git`绑定,并且点击[**邀请链接**](https://gitee.com/buaarobot_admin/ControlGroupSCMOnlineTest2021/invite_link?invite=5da7ad7eb3b3136be9a91b408883ac5d3590bbbcfaa0f7b4b7993663152babc5d6e1b161aee09dd55f318cd36bbddc3a)加入本远程仓库
- 注意邀请链接的有效期为3天
- 在想要克隆本仓库的地方,右键菜单点击“**`Git Bash Here`**”,输入以下代码,即可实现将远程仓库克隆到本地的操作,注意**之后的任务会放置在任务文件夹中**
```c
>>> git clone https://gitee.com/buaarobot_admin/ControlGroupSCMOnlineTest2021.git
```
- 创建一个markdown文件,命名格式为**{你的名字}.md**,如`李明.md` 撰写你对本周题目的难度的看法,创建一个简述自己对**git组成以及常见命令使用原理的理解**的markdown文件,命名格式为**{你的名字ToMarkDown}.md**。
两个文件统一放到`ControlGroupSCMOnlineTest2021/第一周测试题/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文本文件中写明原因以及完成的进度情况。
- 本任务提交方式为**邮箱提交**,地址为`bhjqrdkzz2021@163.com`(与其他需要邮箱提交的任务放在**同一个zip文件**中,zip文件命名格式为**{你的名字}第一周测试题.zip)**
#### 参考资料
- [初识PID-搞懂PID概念](https://zhuanlan.zhihu.com/p/74131690)
### 3. 无刷电机控制
#### 任务简介
##### 无刷直流电机
- 机器人的驱动通常有电动、气动和液动三种,电机驱动是三种方式中功率密度最大、功能方式最简、伺服精度最高的控制方式。在移动式机器人中,常用直流电源(如航模电池)给电机供电,实现机器人的能源-驱动系统。
- 电动机一般分为同步电机和异步电机,其共同点是都需要旋转的磁场来产生驱动力。为了产生旋转的磁场,就需要交变的电流。因此,直流电机控制的核心技术是将直流电压逆变为交流电压,进而产生交变电流。逆变技术有很多种,最简单的是通过电刷换向,应用此技术的电机称为有刷直流电机(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"文件中,放在`/task3`目录下。
- 若未及时完成任务,也请一并提交;若对题目理解有困难,可在微信群讨论。
- 本任务提交方式为**邮箱提交**,地址为`bhjqrdkzz2021@163.com`(与其他需要邮箱提交的任务放在**同一个zip文件**中,zip文件命名格式为**{你的名字}第一周测试题.zip**)
#### 参考资料
- [【自制FOC驱动器】深入浅出讲解FOC算法与SVPWM技术](https://zhuanlan.zhihu.com/p/147659820)
- [一文了解BLDC与PMSM的区别](https://blog.csdn.net/sphinz1/article/details/109265584)
### 任务预告
下周可能会用到C++编写QT。请没有基础的同学提前学习一下关于C++的知识
[学习网站](https://www.runoob.com/cplusplus/cpp-tutorial.html)
## 第二周测试题
### 4.底盘运动学
#### 任务简介
- Robocon比赛中的机器人绝大部分都是依靠轮式底盘完成运动,进而在赛场上完成各类任务的。当前活跃在Robocon赛场上的底盘主要有全向轮底盘与舵轮底盘。接下来的两周各位将通过任务熟悉两种底盘的运动学与控制方式。
#### 任务要求
- 子任务1:推导如图1所示四轮全向轮将**车体坐标系**下的目标速度大小、速度方向与角速度大小(方向默认俯视顺时针为正)解算到四个轮子转动**角速度**的公式,写出推导过程并说明各个参数的含义。部分说明与设定参数如下:
*车体坐标系是与机器人底盘固连的坐标系,不论机器人处在场地上的什么位置,车体坐标系始终与车体姿态一致;
*车轮半径r为30mm;
*底盘半径R为200mm(说明:底盘半径此处指轮子到底盘中心的距离,如图2所示;
*图中四个轮子中心连线构成一个正方形;
*图中四个轮子所在平面与车体坐标系夹角(锐角)均为45°;
*轮子编号如图2所示,橙色箭头表示轮子正转时使底盘产生的运动方向。
图1 全向轮底盘(图片来自网络)
图2 全向轮底盘与车体坐标系
- 子任务2:在上一问的基础上,考虑当给出**世界坐标系**下的机器人期望速度矢量与角速度矢量时,如何解算出四个轮子转动的角速度。给出公式,写出推导过程并说明参数含义。
*世界坐标系是与场地固连的坐标系,被认为静止不动的、作为参考的坐标系。在机器人运动过程中,由于机器人底盘的旋转,车体坐标系会相对于世界坐标系转动一定的角度。
*图中给出的速度矢量是在世界坐标系下描述的。
图3 车体坐标系与世界坐标系
- 子任务3:在ChassisMotion.c 与 ChassisMotion.h 中,根据注释提示补全代码,实现四轮全向轮底盘各轮所需转速的解算任务。
- 任务提交:将本任务中的子任务1、2写在word文档中,word命名为“**{你的名字}+第二周底盘运动学**”,将子任务3的.c/h文件下载到本地进行修改、保存。上述word文件与.c/h文件与其他任务的文件一起打包为zip文件,命名为"**{你的名字}+控制组测试题第二周**"发送至指定邮箱(bhjqrdkzz2021@163.com)
#### 任务提示
- 注意速度的合成与分解。一个刚体在做平移运动时其上各点速度是相同的。
- 注意世界坐标系与车体坐标系的关系,一般情况下Robocon比赛用的底盘只需完成平面运动,故只需要用一个角度便可表示车体坐标系相对世界坐标系的**姿态**。
- 车体坐标系原点在世界坐标系下的**位置**对求解速度没有影响。
- 参考资料中给出了三轮全向轮底盘的运动学公式,可以作为参考思考本题中四轮全向轮运动公式的解算。
#### 参考资料
- [几种移动机器人底盘类型及其运动学](https://blog.csdn.net/qq_24706659/article/details/88342626)
### 5. 串口的使用
#### 任务要求
- 任务实现过程为:串口调试助手**通过串口**发送字符'a',下位机开始通过相同串口循环打印数字1-10(**Simple帧编码**),发送字符'b',下位机开始通过相同串口循环打印数字11-20(**Normal帧编码**),发送字符'c',下位机开始通过相同串口循环打印数字21-30(**Trigger帧编码**)
- **要求**
- 与下位机STM32F407之间的通信使用给定的三种数据帧(由操作手**在串口助手上**进行指定)
- **仅需要**编写**下位机**程序
- 将编写好的KEIL工程文件放在task5文件夹下与其他任务的文件一起打包为zip文件,命名为"**{你的名字}+控制组测试题第二周**"发送至指定邮箱(bhjqrdkzz2021@163.com)
#### 任务提示
- 三种数据帧示意图如下所示
- 参数说明
- 帧头:0x7E
- 类型位:Simple:0,Normal:1,Trigger:2
- Simple:
- 长度位:5
- 编号位:简单帧ID(uint8_t)
- 数据位:
- size:4
- type:float(4字节)
- Normal
- 长度位:sizeof('buaarobotteam')+5
- 名称位:(char \*)('buaarobotteam')
- 数据位:
- size:4
- type:float(4字节)
- Trigger
- 长度位:{数量位}\*4+2
- 编号位:ID位(uint8_t)
- 数量位:uint8_t
- 参数位:
- size:{数量位}\*4
- type:float(4字节)
- 校验位:0x03
- 帧尾:0x04
- 对于三种数据帧的ID位可均设置为1.
- 数据帧编码采用**小端模式**,STM32采用的是**小端模式**
#### 参考资料
- [经典永流传](https://www.bilibili.com/video/BV1kx411k7JT)
- [知识宝库](https://space.bilibili.com/394620890)
### 6. 无刷电机控制
#### 任务简介
- 上周学习了PMSM的基本控制概念以及基本控制方法,这周我们将结合北航机器人队使用的无刷电机控制器学习一些实用的技巧。
- 机器人队通常使用的驱动器有以下几个:
- 适配大疆M2006电机和M3508电机的C610及C620
- 开源驱动器Odrvie
- 开源驱动器VESC
- C610和C620驱动器只封装了电流环,无需调参,需外置控制器实现速度或位置环控制,可以通过CAN通信回发转子位置信息。VESC和Odrive驱动器封装了三环控制,使用时需要配置电机和编码器属性,以及速度、位置环PID控制器参数。上周已经了解了PID参数的调试方法,但实际配置过程中,在没有计算辅助的情况下硬调参数比较困难,因此通常先根据机器参数和系统指标理论分析设计PID控制器,然后在分析结果附近调参。
#### 任务要求
1. PI控制器有两种形式,如以下图示
- 常见形式

- 级联形式

请叙述这两种PI控制器形式的区别。提示:可以但不限于从数学形式、代码形式、参数关系等方面分析。
2. 分析实际情况PID参数配置。假设四轮舵轮底盘机器人(4轮方向相同),总重20kg,轮胎与场地摩擦系数0.3,车轮半径5cm,电机扭矩常数(扭矩与电流之比)为0.1。只考虑平动不考虑机器人自转,请通过分析得出速度环PI控制器参数值,并完成task6文件夹下的Simulink仿真,将分析过程及最终结果图像整理成word文档。若还未学过自动控制原理,可不改变Simulink中的其它参数,只按照上周查找的调参方法整定速度环PI控制器参数。
**提示:**需要根据参数修改Current to Acceleration模块和Acceleration Saturation模块,然后配置PI控制器参数,将计算和配置分析过程写在文档中,Bode图可拍照或用绘图工具绘制。
**注:**电流闭环可通过电流环PI控制器参数配置,转化为一阶系统。该一阶系统可通过设置控制器电流环的带宽完全确定。在本题中,假设电流环传递函数为$\displaystyle\frac{1}{\displaystyle\frac{s}{100}+1}$。Simulink中使用级联式PID,可将PID模块的Form选项设置为Ideal。
#### 任务要求
- 将文字内容整理在"第二周电机控制.md"文件中,放在`/task6`目录下,将完成的Simulink文件也放在`/task6`目录下。
- 若未及时完成任务,也请一并提交;若对题目理解有困难,可在微信群讨论。
- 本任务提交方式为**邮箱提交**,地址为`bhjqrdkzz2021@163.com`(与其他需要邮箱提交的任务放在**同一个zip文件**中,zip文件命名格式为**{你的名字}第二周测试题.zip**)
#### 参考资料
- [Teaching Your PI Controller to Behave (Part I)](https://e2e.ti.com/blogs_/b/industrial_strength/posts/teaching-your-pi-controller-to-behave-part-i?keyMatch=TEACHING%20YOUR%20PI%20CONTROLLER%20TO%20BEHAVE&tisearch=search-everything)
- [Teaching Your PI Controller to Behave (Part II)](https://e2e.ti.com/blogs_/b/industrial_strength/posts/teaching-your-pi-controller-to-behave-part-ii)
### 任务预告
下周可能会用到FreeRTOS。没有基础的同学可以提前学习一下相关知识
[官网](https://freertos.org/)
## 第三周测试题
### 7.CAN通信
#### 任务简介
- 除上周用到的串口通信外,STM32还可以使用SPI、IIC、SDIO、CAN、USB、以太网等通信方式,其中CAN是一种比较可靠的通信方式,也是Robocon赛场上常用的一种机器人内部有线通信方式。
#### 任务说明
- 子任务1:通过查阅资料,总结CAN通信相比于其它有线通信方式的特点,并从软件和硬件两个方面分析使用CAN通信时需要注意的点,写成一个TXT文档,字数不超过200字,以自己的名字命名即可。
- 子任务2:任选一款有至少两路CAN的STM32芯片,新建keil工程,编写STM32程序,要求实现以下功能:
1. 用CAN1接收设备A和设备B的反馈信息,反馈的CAN报文均为标准帧,数据长度均为8字节。设备A反馈的标准帧ID为0x01,反馈数据第1-4个字节为float型的数据DataA1,第5-8个字节为float型的数据DataA2;设备B反馈的标准帧ID为0x02,反馈数据第1-4个字节为float型的数据DataB1,第5-8个字节为float型的数据DataB2。
2. 拟定数值为0~1之间的float型权重WeightsA和WeightsB,算出float型数据:
DataA=(WeightsA)DataA1+(1-WeightsA)DataA2
DataB=(WeightsB)DataB1+(1-WeightsB)DataB2
3. 用CAN2接收来自上位机的信息,上位机下发报文有两种,均为标准帧。第一种帧的标准帧ID为0xA1,数据长度为8字节,下发数据第1-4个字节为float型的数据WeightsA,第5-8个字节为float型的数据WeightsB,根据接收到的数据更新第2点中提到的两个权重。第二种帧的标准帧ID为0xA2,数据长度为4字节,下发数据第1-2个字节为uint16_t型的CommandA,第3-4个字节为uint16_t型的CommandB,接收并保存这两个数据。
4. 将第2点中提到的数据DataA和DataB分别以两种标准帧定时上发给上位机,第一种格式为0x01+0x00+0x00+0x00+4个字节float型数据DataA,每20ms上发一次;第二种格式为0x02+0x00+0x00+0x00+4个字节float型数据DataB,每100ms上发一次。假设上位机只能接受帧ID为0x01的帧。
5. 将从上位机收到的CommandA尽快转发给设备A,设备A仅支持接收帧ID为0x01且长度为2个字节的标准帧,发给设备A的2个字节为uint16_t型的CommandA;将从上位机收到的CommandB尽快转发给设备B,设备B仅支持接收帧ID为0x02且长度为2个字节的标准帧,发给设备B的2个字节为uint16_t型的CommandB。
#### 任务要求
- 与设备A和设备B通信的波特率为1Mbps,与上位机通信的波特率为100Kbps。
- 程序有一定可读性,包含适当的注释;**即使没能完成任务,也请提交上来**,并且写明原因以及完成的进度情况。
- 本任务提交方式为**邮箱提交**,地址为`bhjqrdkzz2021@163.com`(与其他需要邮箱提交的任务放在**同一个zip文件**中,zip文件命名格式为**{你的名字}第三周测试题.zip)**。
#### 参考资料
- [正点原子各型号STM32开发板资料汇总](http://47.111.11.73/docs/boards/stm32/index.html)
### 8、舵轮底盘运动学
#### 任务简介:
在上一周的任务中,大家已经了解并实现了四轮全向轮的运动学原理与代码实现方式。本周将需要大家完成舵轮底盘运动学的代码编写。
所谓舵轮,便是可以同时控制单个驱动轮转速与方向的轮子,具有两个自由度。其中,常用一个电机作为驱动电机,另一个电机作为舵向电机,对驱动轮的方向进行控制。大家可以在任务的参考链接中对舵轮有一个更直观的印象。
#### 任务要求:
于gitee上下载task8文件中的ChassisMotion.c/h并根据注释补全代码。题目中的舵轮底盘如下图所示:
#### 任务提示:
1、当希望底盘完成平移运动的时候,显然,四个舵轮的转速与朝向都必须是一样的。
2、当希望底盘完成自转的时候,有两种解决方案,其一为在不改变四个轮子朝向的前提下改变驱动轮各自的速度,利用差速进行车体旋转;其二为各轮转动到合适角度,各轮速度矢量所在直线均为同一圆的切线。
3、当车体同时需要平移和转动时,可综合考虑每个轮子使车体产生平移以及旋转的速度大小与方向,将两个速度矢量叠加后作为此轮的实际速度矢量。
#### 参考资料:
- [东北大学舵轮]( https://www.bilibili.com/video/BV1aK4y1Q72J )
- [东京大学2020RoboFestival视频](https://www.bilibili.com/video/BV1ah411R7T9?from=search&seid=3560252799842215741)
### 9. FreeRTOS
#### 任务简介
- 在robocon的赛场中一般对机器人同时处理多项任务的能力的要求较高,在这种情况下裸机编程已不再合适,需要引入嵌入式操作系统的概念。
- 在北航机器人队中采用的嵌入式操作系统为FreeRTOS,因此在FreeRTOS平台上进行编程是控制组单片机方向的队员们必须要掌握的一项技能。
- 单片机与传感器之间的通讯方式有很多种,除去上周的串口通讯,还有SPI、CAN、IIC等通讯方式。本周任务需要完成单片机和某种传感器之间的通讯,单片机通过SPI总线与传感器进行通讯。
- 中文版资料(视频和例程以及书籍等)主要参考正点原子(FreeRTOS开发手册)与野火哥(FreeRTOS内核实现与应用开发实战),英文原版资料可参考[FreeRTOS官网](https://freertos.org/)和官方手册。
#### 任务前提
- 使用STM32F4的SPI1与传感器进行通讯,片选信号(CSn)引脚为GPIOA8。
- 片选信号为**低电平**的时候才能开始进行数据传输。完整的Command帧传输完毕之后,片选信号为**高电平**时,**Command帧生效**。如下图所示
- ADD[x]为某个寄存器的地址,也就是下文中的ADDR
- 存储原始值的寄存器地址为0x3fff
- EF位默认为0
- 数据的读取可直接利用按位与操作
- 命令帧格式如下
| Bit | Name | Description |
| ---- | ---- | ------------------------------------------------------------ |
| 15 | PARC | Parity bit(even) calculated on the lower 15 bits of command frame |
| 14 | R/W | 0:Write
1:Read |
| 13:0 | ADDR | Address to read or write |
- 数据帧的格式如下:
| Bit | Name | Description |
| ---- | ---- | ----------------------------------------------------- |
| 15 | PARD | Parity bit(even) calculated on the lower 15 bits |
| 14 | EF | 0:No command frame error occurred
1:Error occurred |
| 13:0 | DATA | Data |
#### 任务要求
- 查阅相关资料,谈谈嵌入式操作系统的功能和原理,目前主要有分为哪几种,各有什么特点,以及为什么要使用嵌入式操作系统?
- 使用STM32的SPI1与传感器进行通讯,片选信号(CSn)引脚为GPIOA8
- 在SensorController.c/h中完成传感器交互任务和传感器数据处理任务的编写,在工程中的合适地方进行任务的建立,传感器交互任务负责与传感器进行通信获取数据,运行频率设置为约100Hz即可,当接收到完整的一帧,并且将原始值取出(即实际数据,类型为uint16_t)后,交互任务将实际数据发送给数据处理任务,传感器数据处理任务开始运行进行数据处理,在未收到实际距离数据时,数据处理任务处于阻塞状态(数据处理任务具体内容可以自拟,如进行一个简单的滤波)。
- 与第二周设计的串口调试助手配合,将原始数据通过串口打印出来(可以考虑新建串口发送与接收任务)。
- 如果实在无法完成任务请将已完成部分提交上来,并附上无法完成任务的原因
- 只需要完成**下位机**的编写
- 本次任务的提交方式为邮箱提交将编写好的KEIL工程文件放在task9文件夹下与其他任务的文件一起打包为zip文件,命名为"**{你的名字}+控制组测试题第三周**"发送至指定邮箱(bhjqrdkzz2021@163.com)