舵机与电机控制
舵机和电机是机器人执行器的两大基石。本章从物理原理讲起,介绍两者的控制方式,并重点说明 GSRL 中 CAN 总线电机的控制架构。
上一篇:定时器与 PWM
1. 舵机(Servo)
1.1 物理结构
舵机是一个闭环角度伺服系统,内部集成了:
┌─────────────────────────────────────────┐
│ 舵机内部 │
│ │
│ PWM 信号 ──→ ┌─────────┐ │
│ │ 控制电路 │ │
│ └────┬────┘ │
│ │ │
│ ┌────▼────┐ │
│ │ 直流电机 │──→ 齿轮组 ──→ 输出轴
│ └─────────┘ │
│ │ │
│ ┌────▼────┐ │
│ │ 电位器 │←── 反馈角度 │
│ │(位置反馈)│ │
│ └─────────┘ │
└─────────────────────────────────────────┘
- 直流电机:提供动力
- 齿轮组:减速增扭,同时放大了位置精度
- 电位器:实时测量输出轴的角度
- 控制电路:比较目标位置(PWM 信号)和实际位置(电位器),驱动电机消除误差
1.2 控制方式
舵机通过 PWM 信号的脉宽控制角度(见上一章)。重要的是:
- 舵机内部自带 PID 控制(PID 算法详见 GSRL Algorithm 层),只需要给定目标位置信号
- 普通舵机角度范围约 180°,旋转角度由内部机械限位决定
- 总线舵机(如 Dynamixel)通过 UART/RS485 收发数字指令,可反馈位置、速度、电流
1.3 关键参数
| 参数 | 典型值 | 含义 |
|---|---|---|
| 工作电压 | 4.8V ~ 7.4V | 供电电压越高,扭矩和速度越大 |
| 堵转扭矩 | 15 ~ 40 kg·cm | 输出轴能承受的最大负载 |
| 响应速度 | 0.1 ~ 0.2 s/60° | 转动 60° 所需时间 |
| 死区 | 1~2 μs | 脉宽变化小于死区时舵机不响应 |
| 控制频率 | 50Hz (20ms) | 大部分舵机的标准控制频率 |
2. 直流有刷电机
2.1 基本原理
直流有刷电机通过电刷和换向器使转子线圈中的电流方向不断切换,从而在永磁体磁场中持续旋转。
简化模型:
N N N
┌─────┐ ┌─────┐ ┌─────┐
│ →→→ │ │ ↑↑↑ │ │ ←←← │ ← 转子线圈(电流方向随换向器翻转)
└─────┘ └─────┘ └─────┘
S S S
换向器 (换角度后电流反向,维持同一方向的电磁力)
2.2 控制方式:H 桥驱动
H 桥通过 4 个开关管(MOSFET)控制电机的转向和转速:
VCC
│
┌────┴────┐
│ S1 S3 │ S1+S4 导通 → 正转
│ M │ S2+S3 导通 → 反转
│ S2 S4 │ S1+S2 或 S3+S4 同时导通 → 短路(禁止!)
└────┬────┘ 占空比 0% ~ 100% → 调速
│
GND
PWM 信号控制 H 桥开关管的导通时间,实现电压调速。
3. 无刷直流电机(BLDC)
3.1 为什么要无刷
有刷电机的电刷是磨损件(接触摩擦、产生火花),高速高功率场景下寿命短、EMI 大。此外,电刷与换向器之间的火花会产生电气噪声(电弧),干扰传感器和无线电通信——在机器人中,这可能导致 IMU 数据抖动或遥控信号丢包。无刷电机效率约 85%~90%,远高于有刷电机的 70%~75%,同等电池容量下续航更长。同时,无刷电机功率密度更高——相同体积下能输出更大的扭矩,这对于空间紧张的机器人关节至关重要。
无刷电机将永磁体放在转子上,线圈放在定子上,通过电子换向代替机械换向。
无刷电机结构:
┌──────────┐
│ 定子线圈 │ ← 固定不动
┌─────┼──────────┼─────┐
│ │ ┌──┐ │ │
│ │ │永│ │ │ ← 转子旋转
│ │ │磁│ │ │
│ │ │体│ │ │
│ │ └──┘ │ │
└─────┴──────────┴─────┘
3.2 FOC(磁场定向控制)原理简述
比赛机器人中常用的高性能电机(大疆 M3508、达妙 DM4310 等)都使用 FOC 控制:
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ 目标扭矩 │ → │ PID 控制 │ → │ 坐标变换 │ → │ SVPWM │ → 三相桥 → 电机
│ (电流) │ │ (电流环) │ │ Clarke │ │ (空间矢量)│
└──────────┘ └──────────┘ │ Park │ └──────────┘
└──────────┘
↑
┌──────────┐
│ 角度传感器│ ← 编码器/霍尔
└──────────┘
FOC 的核心思想:通过数学变换(Clarke + Park),将三相交流电流转化为等效的直流电流进行控制(转矩电流 Iq 和励磁电流 Id),大幅简化了控制模型。
3.3 为什么用 FOC 而不是简单的六步换相
六步换相(方波驱动)是最简单的 BLDC 控制方式:依次给三相线圈中的两相通电,每 60° 电角度切换一次。它实现简单,但存在固有缺陷——每次换相时刻,电流方向突变导致转矩脉动,电机会产生明显的振动和噪音。
FOC(磁场定向控制)则完全不同:它通过实时测量转子角度,用数学变换(Clarke + Park)将三相交流电流分解为转矩电流 Iq 和励磁电流 Id,然后像控制直流电机一样分别控制它们。FOC 的电流矢量连续平滑旋转,产生的转矩也连续平滑——没有换相突变,没有振动。
在云台(gimbal)应用中,这一差异至关重要:六步换相的振动会导致相机画面抖动,而 FOC 的平滑转矩是实现稳定拍摄的基础。这就是为什么大疆 M3508、达妙 DM4310 等比赛电机全部采用 FOC 的原因。
关键认知:FOC 控制中的电机驱动器(如大疆 C620 电调、达妙电机内置驱动板)已经实现了电流环 FOC,用户只需通过 CAN 总线发送目标电流值。这意味着我们不需要自己写 FOC,只需要做好通信层和控制层。
3.4 为什么用 CAN 总线电机而不是 PWM 电机
传统 PWM 电机控制是单向的——MCU 通过 PWM 占空比告诉电机"转多快",但电机无法向 MCU 返回任何信息。想获得位置反馈?需要额外接编码器线。想知道电流和温度?需要额外接传感器。一个电机至少需要 3 根线(PWM + 编码器 A + 编码器 B),6 个电机就是 18 根线。
CAN 总线电机是双向的——MCU 发送目标电流/位置/速度指令,电机同时回报当前角度、转速、转矩电流、温度。这种反馈是实现闭环控制的前提——PID 控制器需要知道当前位置才能计算下一步输出。此外,CAN 总线只需 CAN_H 和 CAN_L 两根线,就能菊花链串联数十个电机,大幅简化布线。在 RoboMaster 机器人中,8 个关节电机通过两根 CAN 线即可全部连接,如果用 PWM + 编码器方案,线缆数量将超过 30 根。
4. GSRL 中的电机控制架构
4.1 电机控制的三层结构
GSRL 中的电机控制是一个经典的闭环控制系统:
┌──────────────────────────────────────────────────┐
│ 控制层 (Control) │
│ │
│ 目标位置/速度 ─→ PID 控制器 ─→ 目标电流/电压 │
│ ↑ │ │
│ │ │ │
│ 实际位置/速度 (反馈) │ │
│ │ │ │
├───────┼──────────────────────────────┼───────────┤
│ │ 通信层 (CAN) │ │
│ │ │ │
│ CAN 反馈帧 ←──────────────→ CAN 控制帧 │
│ │ │ │
├───────┼──────────────────────────────┼───────────┤
│ │ 物理层 (电机驱动板) │ │
│ │
│ 编码器 → 驱动板 → 三相桥 → BLDC 电机 │
└──────────────────────────────────────────────────┘
4.2 Motor 基类的设计
GSRL 的 Motor 类(dvc_motor.hpp)封装了所有电机共有的控制逻辑:
class Motor {
protected:
// 通信
uint32_t m_motorControlMessageID; // CAN 控制帧 ID
uint32_t m_motorFeedbackMessageID; // CAN 反馈帧 ID
uint8_t m_motorControlData[8]; // CAN 控制数据(发送)
uint8_t m_motorFeedbackData[8]; // CAN 反馈数据(接收)
// 当前状态(从 CAN 反馈中解析)
fp32 m_currentAngle; // 当前角度 (rad)
fp32 m_currentAngularVelocity; // 当前角速度 (rad/s)
int16_t m_currentTorqueCurrent; // 当前转矩电流
int8_t m_temperature; // 温度
bool m_isMotorConnected; // 是否在线
// 目标状态(由上层控制算法设定)
fp32 m_targetAngle;
fp32 m_targetAngularVelocity;
int16_t m_targetTorqueCurrent;
// 控制器
Controller *m_controller; // PID 控制器接口
fp32 m_controllerOutput; // 控制器输出
public:
// 闭环控制(多种模式)
fp32 angleClosedloopControl(); // 位置闭环
fp32 angularVelocityClosedloopControl(); // 速度闭环
int16_t torqueCurrentClosedloopControl(); // 电流闭环
fp32 revolutionsClosedloopControl(); // 圈数闭环
void openloopControl(fp32 controlValue); // 开环控制
};
4.3 支持的电机类型
GSRL 通过继承 Motor 基类,支持多种 CAN 总线电机:
| 类名 | 电机型号 | 通信协议 |
|---|---|---|
MotorGM6020 |
大疆 GM6020 | 大疆 CAN 协议,一控多(电压控制) |
MotorM3508 |
大疆 M3508 | 大疆 CAN 协议(电流控制) |
MotorM2006 |
大疆 M2006 | 与 M3508 协议兼容 |
MotorDM4310 |
达妙 DMJ4310 | 达妙 MIT 模式(力矩控制) |
MotorDM2325 |
达妙 DM-S2325 | 与 DMJ4310 协议兼容 |
MotorDMmulti |
达妙一控四固件 | 达妙力位混控模式 |
MotorLKMG |
瓴控 MG 系列 | 瓴控协议 |
4.4 完整控制流程示例
以 tsk_test.cpp 中的达妙电机控制为例:
// 1. 声明 PID 控制器
SimplePID::PIDParam param = {
10.0f, // Kp
0.0f, // Ki
0.0f, // Kd
100.0f, // outputLimit
0.0f // intergralLimit
};
SimplePID myPID(SimplePID::PID_POSITION, param);
// 2. 声明电机对象(ID=1, MasterID=3, PMAX=PI, VMAX=40, TMAX=15)
MotorDM4310 motor(1, 3, 3.1415926f, 40, 15, &myPID);
// 3. 在任务中初始化 CAN
CAN_Init(&hcan1, can1RxCallback);
// 4. 主循环:1ms 周期
while (1) {
motor.openloopControl(sinf(2 * PI * 0.5f * xTaskGetTickCount() / 1000));
// 将控制数据通过 CAN 发送给电机
const uint8_t *data = motor.getMotorControlData();
HAL_CAN_AddTxMessage(&hcan1, motor.getMotorControlHeader(), data, &send_mail_box);
vTaskDelayUntil(&taskLastWakeTime, 1);
}
// 5. ISR 中接收反馈
void can1RxCallback(can_rx_message_t *pRxMsg) {
motor.decodeCanRxMessageFromISR(pRxMsg);
}
数据流:
1ms 任务循环:
motor.openloopControl() ← 计算控制量
→ motor.getMotorControlHeader() ← 获取 CAN 帧头
→ motor.getMotorControlData() ← 获取 CAN 数据
→ HAL_CAN_AddTxMessage() ← 通过 CAN1 发出
CAN 中断:
CAN1_RX0_IRQHandler()
→ HAL_CAN_RxFifo0MsgPendingCallback()
→ can1RxCallback()
→ motor.decodeCanRxMessageFromISR() ← 更新电机当前状态
5. 舵机 vs 电机对比
| 特性 | 舵机 | 直流有刷电机 | CAN 总线 BLDC |
|---|---|---|---|
| 控制接口 | PWM 脉宽 | PWM 占空比(H 桥) | CAN 总线数字指令 |
| 控制量 | 角度(位置) | 电压/转速 | 转矩电流(FOC) |
| 反馈 | 无(内部闭环) | 无(需编码器) | 角度/速度/电流/温度 |
| 精度 | ±1° | 取决于编码器 | 编码器精度(可达 0.01°) |
| 使用的控制器 | 舵机内置 | 需要外部 PID | 电机内置电流环 + 外置位置/速度 PID |
| GSRL 中的角色 | 较少使用 | 较少使用 | 主力执行器 |
6. 总结
| 要点 | 说明 |
|---|---|
| 舵机 | 内置闭环的角位置伺服,PWM 脉宽控制角度 |
| 直流有刷电机 | H 桥驱动,PWM 占空比调速,电刷是磨损件 |
| BLDC + FOC | 电子换向,CAN 总线控制,驱动器内置电流环 |
| GSRL Motor 体系 | 基类封装闭环控制,继承类适配不同 CAN 协议 |
| 控制流程 | 任务中 PID 计算 → CAN 发送 → ISR 中接收反馈 → 更新状态 |
与 GSRL 的关系
GSRL 中几乎所有机器人关节都由 CAN 总线电机驱动。Motor 基类定义了位置/速度/电流闭环的接口,SimplePID / CascadePID 作为控制器实现,CAN Driver 负责数据传输。这种分层设计使得同一控制算法可以无缝切换不同品牌的电机——只需替换继承类。
下一篇:UART 通信原理与实践
作者: Qing | 修改日期: 2026-07-18