【花雕学编程】Arduino BLDC 之协作机器人关节力控

Arduino BLDC之协作机器人关节力控,该系统的目标是利用Arduino微控制器作为下位机或协处理器,结合无刷直流(BLDC)电机、精密减速器和力/力矩传感器(或间接估计算法),在协作机器人的单个关节或整个机械臂上实现高精度的力与力矩控制。其核心在于使机器人能够感知与环境的交互力,并据此调整自身行为,实现安全、柔顺的人机协作。
一、 主要特点 (Key Characteristics)
力/力矩感知能力 (Force/Torque Sensing Capability):
直接测量 (Direct Measurement): 在关节输出端或机器人末端执行器(End-Effector)安装六维力/力矩传感器(6-DOF F/T Sensor)。这是最准确的方法,能同时测量三个方向的力(Fx, Fy, Fz)和三个方向的力矩(Mx, My, Mz)。传感器数据通过I2C、SPI或模拟接口传给Arduino。
间接估计 (Indirect Estimation - 扭矩观测器): 成本更低但更复杂。通过实时监测BLDC电机的相电流(需使用精密电流采样电阻和ADC),结合已知的电机反电动势常数(Kv)、电枢电阻(R)、电感(L)以及机械模型(包括减速比、转动惯量),利用扩展卡尔曼滤波(EKF) 或滑模观测器(SMO) 等算法,在软件中估算出作用在关节上的外部扰动力矩。这要求精确的系统辨识和复杂的数学运算。
“协作”的基石: 力感知是实现柔顺控制、碰撞检测和人机交互的前提。
基于Arduino的实时力控环 (Arduino as Real-Time Force Control Loop Executor):
角色: Arduino(必须使用高性能型号,如ESP32或Due)在此架构中通常扮演底层实时控制器的角色:
高速数据采集: 以极高的频率(>1kHz)读取编码器位置、电机相电流(用于扭矩观测)和/或F/T传感器原始数据。
扭矩观测器运行: 如果采用间接法,需在中断服务程序(ISR)中执行扭矩估算算法。
力/力矩PID控制: 将期望的力/力矩指令(来自上位机)与实际测量/估算的力/力矩进行比较,运行力PID控制环,生成所需的关节扭矩指令。
扭矩到电流的转换: 根据电机模型(τ = Kt * I,其中Kt为扭矩常数),将扭矩指令转换为目标相电流。
FOC(磁场定向控制)实现: 为了精确控制BLDC电机的转矩,必须实现FOC算法。Arduino需要执行Clarke变换、Park变换、PI电流环调节、反Park/Clarke变换和SVPWM(空间矢量脉宽调制)生成。这是计算量极大的任务。
紧急响应: 处理过流、过热、急停等硬件信号,确保毫秒级的安全切断。
分层架构的必要性: 如此复杂的实时控制任务,几乎不可能由单一Arduino独立完成。它通常是更大系统的一部分。
BLDC电机与精密驱动 (BLDC Motor with Precision Drive):
执行机构: BLDC电机是产生所需关节力矩的动力源。通常搭配谐波减速器或行星减速器,以提供高扭矩密度和平稳的输出。
高动态响应: 协作机器人要求快速、精确地响应力的变化,这对电机和驱动器的带宽提出了很高要求。
低齿槽效应与平滑运行: 选用低齿槽效应的BLDC电机,并配合FOC控制,确保在低速和零速时也能平稳、无抖动地输出力矩。
柔顺与安全的协作特性 (Compliant and Safe Collaboration):
核心价值: 力控使得机器人具备了“感觉”。当与人或环境发生意外接触时,它可以立即检测到异常的力并做出反应(如停止、后退或顺应推动),从根本上保证了人机共存的安全性。
应用模式: 支持“拖拽示教”(Lead-through Programming),操作员可以直接用手引导机器人学习新路径;支持精密装配,机器人能感知微小的装配力,避免损坏零件。
二、 应用场景 (Application Scenarios)
该方案主要定位于研究、教育和高端原型开发,而非成熟的工业产品:
学术研究与算法验证 (Academic Research & Algorithm Validation):
高校和研究机构用于开发和测试新的力控算法、阻抗控制、导纳控制、人机协作策略等。
高级机器人教学平台 (Advanced Robotics Education Platform):
作为机电一体化、现代控制理论、机器人学的综合性实验设备,让学生深入理解从传感器到执行器的完整闭环控制链。
定制化轻型协作机器人原型 (Customized Lightweight Cobot Prototypes):
为特定应用场景(如实验室自动化、小型精密制造)设计和构建功能验证机,当商用协作机器人成本过高或不满足特殊需求时。
康复机器人与外骨骼 (Rehabilitation Robots & Exoskeletons):
在辅助行走或上肢康复训练中,需要精确感知用户施加的力并提供恰当的助力。Arduino平台可用于开发低成本的原型系统。
艺术与互动装置 (Art & Interactive Installations):
创造能与观众进行物理互动的智能雕塑或表演机器人。
三、 需要注意的事项 (Critical Considerations & Challenges)
极端的计算性能与实时性要求 (Extreme Computational Power & Real-Time Requirements):
最大挑战: 同时运行FOC算法(含SVPWM)、扭矩观测器(如EKF)、力PID控制环和通信协议,对MCU的算力和实时性是毁灭性的考验。即使是ESP32,在处理多轴系统时也极其吃力。
解决方案 (严格的分层架构):
主控 (Master): 使用高性能嵌入式PC(如NVIDIA Jetson系列、Intel NUC)或实时操作系统(RTOS)工控机。负责高层任务:运动规划、轨迹生成、整体协调、人机交互、复杂的控制律(如阻抗控制)计算,并将分解后的关节力矩/电流指令下发给下位机。
下位机 (Slave - Arduino): ESP32/Due专注于最底层的、硬实时的伺服循环(Servo Loop),周期通常要求≤1ms。只接收来自主控的“目标电流”或“目标扭矩”指令,然后执行FOC和PWM生成。两者通过EtherCAT、CAN总线或高速UART通信。
绝对避免: 试图在单一Arduino上完成从轨迹规划到FOC的所有工作。
FOC算法的复杂性与实现难度 (Complexity of FOC Implementation):
门槛高: FOC涉及大量的浮点运算、坐标变换和实时PI调节。需要深厚的电机控制理论知识和嵌入式编程经验。
库的选择: 可以使用开源库(如SimpleFOC for Arduino),但必须深刻理解其原理才能调试和优化。
传感器精度与噪声 (Sensor Accuracy & Noise):
电流采样: 相电流的测量精度直接影响力矩估算的准确性。需要使用低阻值、高精度的采样电阻和高分辨率、高采样率的ADC(最好在MCU内部)。
编码器: 需要高分辨率(如17位以上)的绝对式或增量式编码器,以精确测量位置和速度。
F/T传感器: 商用六维力传感器价格昂贵,且需要复杂的标定。
抗干扰: 电机驱动产生的强EMI会严重污染微弱的传感器信号。必须使用屏蔽线、差分信号、隔离放大器和精心的PCB布局。
系统建模与参数辨识 (System Modeling & Parameter Identification):
基础: 无论是直接力还是间接力控,都需要相对准确的电机和机械系统模型(Kt, Kv, R, L, J, B等)。这些参数需要通过实验进行辨识,且可能随温度变化。
机械结构与背隙 (Mechanical Structure & Backlash):
关键影响: 减速器和传动链中的背隙(Backlash) 是力控的最大敌人。它会导致力控环出现死区和非线性,严重降低控制精度和稳定性。
解决方案: 必须使用零背隙或超低背隙的减速器(如谐波减速器)。机械结构需极其坚固,避免柔性变形。
安全性与功能安全 (Safety & Functional Safety):
最高优先级: 协作机器人直接与人交互,任何失控都可能导致严重伤害。
措施:
多重冗余: 硬件急停回路(独立于软件)、软件看门狗、电流/温度监控。
安全标准: 设计需参考ISO 10218(工业机器人安全)和ISO/TS 15066(协作机器人专用标准),限制功率和力。
安全PLC: 在严肃应用中,应有独立的安全PLC或安全控制器负责监控所有安全相关信号。
开发工具与调试 (Development Tools & Debugging):
复杂性: 调试一个包含机械、电气、控制算法的系统非常困难。
工具: 需要示波器观察PWM和电流波形,使用逻辑分析仪抓取通信数据,通过串口或网络实时绘制控制变量(位置、速度、电流、力)的波形图。

1、基于SimpleFOC库的电机电流环控制示例
#include <SimpleFOC.h>
// 定义BLDCMotor对象,参数为电机极对数和电阻等
BLDCMotor motor = BLDCMotor(11, 2.0); // 假设有11个极对数,相电阻为2.0欧姆
// 定义Driver对象,用于驱动电机
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 10, 11, 8);
// 定义CurrentSense对象,用于电流检测
InlineCurrentSense current_sense = InlineCurrentSense(0.01, 50.0, A2, A3, A4);
void setup() {
// 初始化通信串口
Serial.begin(115200);
// 初始化driver电源
driver.init();
// 连接电机与驱动器、电流传感器
motor.linkDriver(&driver);
motor.useMonitoring(current_sense);
// 设置运动控制类型为扭矩控制模式
motor.controller = MotionControlType::torque;
// 初始化电机
motor.init();
// 使用监测功能校准电流传感器零点
current_sense.calibrate(motor);
// 启动电机
motor.start();
}
void loop() {
// 从串口读取目标扭矩值
if (Serial.available()) {
float target_torque = Serial.parseFloat();
// 设置电机的目标扭矩
motor.move(target_torque);
}
}
要点解读:
库的使用:借助SimpleFOC库简化了BLDC电机的控制流程,该库提供了丰富的功能,如磁场定向控制(FOC)、电流环控制等,方便开发者快速搭建电机控制系统。
硬件连接:明确指定了电机、驱动器和电流传感器的引脚连接,确保硬件电路的正确连接是实现电机控制的基础。在实际应用中,需根据具体的硬件设备和开发板进行相应的引脚配置。
控制模式选择:将电机的控制器设置为扭矩控制模式,这是实现关节力控的关键步骤。在该模式下,通过给定目标扭矩值,电机能够自动调整输出以匹配设定的扭矩。
电流传感器校准:在使用电流传感器之前,需要进行零点校准,以提高电流测量的准确性。这对于精确控制电机扭矩至关重要,因为电机的电磁转矩与相电流成正比,准确的电流测量是实现精准扭矩控制的前提。
通信接口:利用串口通信接收外部设定的目标扭矩值,这种方式便于用户实时调整电机的输出扭矩,增加了系统的灵活性和可操作性。
2、简易的模拟量输入控制电机扭矩示例
const int torquePotPin = A0; // 连接到电位器,用于模拟扭矩输入
const int motorEnablePin = 9; // PWM输出使能引脚
void setup() {
pinMode(motorEnablePin, OUTPUT);
}
void loop() {
// 读取电位器的值,范围为0-1023
int potValue = analogRead(torquePotPin);
// 将电位器的值映射到电机的扭矩范围,例如0-255
int torqueValue = map(potValue, 0, 1023, 0, 255);
// 根据计算得到的扭矩值设置PWM占空比,从而控制电机扭矩
analogWrite(motorEnablePin, torqueValue);
delay(10); // 延时一段时间,避免过于频繁地更新PWM值
}
要点解读:
模拟量输入:通过电位器产生模拟量输入信号来模拟扭矩设定值,这种方式简单直观,适用于一些简单的实验和测试场景,能够帮助开发者快速验证电机扭矩控制的基本原理。
PWM控制:使用PWM(脉冲宽度调制)技术来控制电机的扭矩。通过改变PWM信号的占空比,可以调节电机的平均电压,进而控制电机的输出扭矩。这种方法成本较低且易于实现,但精度相对有限。
数据映射:将电位器的原始读数映射到合适的电机扭矩范围,使得输入信号与电机的实际输出相匹配。合理的数据映射能够充分利用电位器的动态范围,提高控制的精度和效果。
软件滤波:在循环中添加适当的延时可以减少PWM值的频繁更新,起到一定的软件滤波作用,使电机的运行更加平稳。然而,过长的延时可能会影响系统的响应速度,需要根据实际情况进行调整。
局限性:此方法仅适用于对扭矩控制精度要求不高的场合,对于复杂的应用场景可能无法满足需求。由于没有采用闭环控制,电机的实际输出扭矩可能会受到负载变化等因素的影响,导致控制精度下降。
3、结合编码器反馈的电机位置与扭矩复合控制示例
#include <Encoder.h>
Encoder myEnc(2, 3); // 创建编码器对象,连接到数字引脚2和3
int currentPosition = 0;
int targetPosition = 1000; // 设定目标位置
int maxTorque = 100; // 最大允许扭矩限制
void setup() {
Serial.begin(9600);
pinMode(9, OUTPUT); // 电机使能引脚
}
void loop() {
// 获取当前编码器的位置值
long newPosition = myEnc.read();
// 计算位置误差
int error = targetPosition - newPosition;
// 根据位置误差计算所需的扭矩值,这里使用了简单的比例控制算法
int torque = constrain(error * 0.1, -maxTorque, maxTorque);
// 根据计算出的扭矩值设置PWM占空比
analogWrite(9, abs(torque));
// 如果接近目标位置且扭矩较小,则停止电机并记录当前位置
if (abs(error) < 10 && torque == 0) {
digitalWrite(9, LOW);
myEnc.write(0); // 重置编码器位置为零点
currentPosition = newPosition;
}
// 每隔一定时间打印一次相关信息用于调试
static unsigned long lastTime = millis();
if (millis() - lastTime > 1000) {
Serial.print("Current Position: ");
Serial.println(newPosition);
Serial.print("Target Position: ");
Serial.println(targetPosition);
Serial.print("Error: ");
Serial.println(error);
Serial.print("Torque: ");
Serial.println(torque);
lastTime = millis();
}
}
要点解读:
编码器反馈:引入编码器作为位置传感器,实时获取电机的位置信息。编码器的高精度位置反馈为实现精确的位置控制和扭矩控制提供了基础数据,有助于提高整个系统的控制精度和稳定性。
复合控制策略:采用了位置与扭矩的复合控制方式。一方面,根据目标位置与实际位置之间的误差来计算所需的扭矩值;另一方面,通过对扭矩的限制避免了因过大的扭矩而导致的设备损坏或失控情况发生。这种复合控制策略既保证了系统的位置跟踪性能,又实现了对电机输出扭矩的有效管控。
比例控制算法:使用了简单的比例控制算法来计算扭矩值,即扭矩与位置误差成正比关系。这种算法具有响应速度快的优点,能够在较短时间内使系统朝着减小误差的方向调整。然而,它也存在稳态误差较大的缺点,对于一些高精度的应用可能需要进一步优化或结合其他控制算法。
安全保护机制:设置了最大允许扭矩限制以及当接近目标位置且扭矩较小时自动停止电机的保护措施。这些机制可以防止意外情况下电机过度运转或承受过大的负载,保障了人员和设备的安全。
调试信息输出:定期向串口打印当前的电机位置、目标位置、误差以及扭矩等信息,方便开发者进行调试和分析系统的性能表现。通过对这些数据的观察和分析,可以及时发现潜在问题并进行相应的调整和改进。

4、阻抗控制(Impedance Control)
功能:模拟虚拟弹簧-阻尼系统,外力作用下关节产生顺应性位移。
应用场景:康复外骨骼、人机协作拖动示教。
#include <SimpleFOC.h>
// 电机与编码器配置
BLDCMotor motor = BLDCMotor(7);
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 10, 11, 8);
Encoder encoder = Encoder(2, 3, 500);
void doA() { encoder.handleA(); }
void doB() { encoder.handleB(); }
// 阻抗参数
float K_virtual = 0.5; // 虚拟刚度 (N·m/rad)
float B_virtual = 0.01; // 虚拟阻尼 (N·m·s/rad)
float target_angle = 0; // 期望角度
void setup() {
encoder.init();
encoder.enableInterrupts(doA, doB);
driver.init();
motor.linkDriver(&driver);
motor.linkSensor(&encoder);
motor.controller = MotionControlType::torque; // 力矩控制模式
motor.init();
motor.initFOC();
}
void loop() {
motor.loopFOC();
// 获取当前角度与速度
float angle = encoder.getAngle();
float velocity = encoder.getVelocity();
// 阻抗控制律: T = K*(θ_d - θ) + B*(ω_d - ω)
float torque = K_virtual * (target_angle - angle) + B_virtual * (0 - velocity);
motor.move(torque);
// 更新目标角度(例如通过外部输入)
// target_angle = ...;
}
解读要点:
虚拟参数调节:K_virtual和B_virtual需根据负载惯量调整,避免系统振荡。
传感器依赖:需高分辨率编码器(如AS5048A)实现低延迟反馈。
安全限制:应加入最大输出力矩限制(motor.torque_limit)。
5、导纳控制(Admittance Control)
功能:将外部力转换为运动轨迹,实现人机交互。
应用场景:表面打磨、装配力控。
#include <SimpleFOC.h>
// 硬件配置(同案例1)
BLDCMotor motor = BLDCMotor(7);
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 10, 11, 8);
Encoder encoder = Encoder(2, 3, 500);
// 导纳参数
float M_virtual = 0.1; // 虚拟质量 (kg·m²)
float B_virtual = 0.05; // 虚拟阻尼 (N·m·s/rad)
float force_input = 0; // 外部力输入(需通过传感器获取)
void setup() {
// 初始化同案例1
motor.controller = MotionControlType::velocity; // 速度控制模式
}
void loop() {
motor.loopFOC();
// 模拟外部力输入(实际应接六维力传感器或电流突变检测)
force_input = analogRead(A0) * 0.1; // 示例:电位器模拟力输入
// 导纳控制律: ω = (F - B*ω)/M
float velocity = (force_input - B_virtual * encoder.getVelocity()) / M_virtual;
motor.move(velocity);
}
解读要点:
力输入来源:实际应用需替换为力传感器(如HX711)或电流估算(motor.current_sp)。
参数整定:M_virtual过小会导致运动过于敏感,需结合负载调试。
防抖处理:对force_input加入低通滤波(如force_input = 0.9prev + 0.1current)。
6、力/位置混合控制
功能:在接近目标位置时切换为力控,避免冲击。
应用场景:精密装配、物体抓取。
#include <SimpleFOC.h>
// 硬件配置(同案例1)
BLDCMotor motor = BLDCMotor(7);
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 10, 11, 8);
Encoder encoder = Encoder(2, 3, 500);
// 控制参数
float target_angle = 1.57; // 目标角度 (rad)
float force_threshold = 0.2; // 力控阈值 (N·m)
float current_force = 0;
void setup() {
// 初始化同案例1
motor.controller = MotionControlType::angle; // 默认位置控制
}
void loop() {
motor.loopFOC();
// 估算当前力矩(通过电流)
current_force = motor.current_sp * motor.phase_resistance * motor.KV_rating;
// 混合控制逻辑
if (abs(target_angle - encoder.getAngle()) < 0.1 && current_force > force_threshold) {
motor.controller = MotionControlType::torque; // 切换为力控
motor.move(force_threshold); // 维持恒定力
} else {
motor.controller = MotionControlType::angle; // 位置控制
motor.move(target_angle);
}
}
解读要点:
切换条件:需根据任务调整位置误差阈值(如0.1 rad)和力阈值。
力估算精度:电流-力转换需校准电机参数(phase_resistance, KV_rating)。
平滑过渡:可加入加权混合(如control_output = 0.7pos + 0.3force)。
注意,以上案例只是为了拓展思路,仅供参考。它们可能有错误、不适用或者无法编译。您的硬件平台、使用场景和Arduino版本可能影响使用方法的选择。实际编程时,您要根据自己的硬件配置、使用场景和具体需求进行调整,并多次实际测试。您还要正确连接硬件,了解所用传感器和设备的规范和特性。涉及硬件操作的代码,您要在使用前确认引脚和电平等参数的正确性和安全性。

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)