
Arduino 与无刷直流电机(BLDC)结合实现基于电流环的力矩控制,是一种在低成本嵌入式平台上逼近工业伺服性能的先进控制策略。其核心思想是:通过精确调节 BLDC 电机的相电流,直接控制输出电磁转矩,从而实现对机械系统力/力矩的精准调控。以下从专业工程视角,系统阐述该技术的主要特点、典型应用场景及关键注意事项。
一、主要特点
- 力矩与电流的线性关系
在理想条件下,BLDC 电机的电磁转矩 T e 与相电流幅值 I 成正比:
为转矩常数(单位:N·m/A)。因此,精确控制电流即可直接控制输出力矩,这是力矩控制的理论基础。 - 内环为电流闭环,外环可扩展
系统以电流环作为最内层高速闭环(通常控制频率 ≥ 5–10 kHz),外层可叠加位置、速度或力/阻抗控制环。
Arduino 需配合支持电流采样与 PWM 调制的驱动电路(如带电流检测的半桥/全桥驱动器),实时调节占空比以跟踪目标电流。 - 高动态响应与力控精度潜力
相较于仅控制电压或速度的传统方案,电流环能快速抑制负载扰动(如突加阻力、碰撞),实现“柔顺”或“刚性”力输出。
在合理硬件支持下,可实现 ±5% 甚至更高的稳态力矩控制精度。 - 依赖高带宽电流检测
常用电流传感器包括:
低侧电流采样电阻 + 差分放大器(成本低,但无法检测续流电流);
高侧或三相电流检测(需多路 ADC,更精确);
集成电流检测的驱动芯片(如 TI DRV8313、Infineon IFX007T + 外部运放);
霍尔效应电流传感器(如 ACS712、ACS770,隔离性好但带宽有限)。
采样频率与 ADC 分辨率直接影响控制性能。 - 需配合先进换向策略
传统六步换向难以实现平滑力矩输出(存在转矩脉动);
磁场定向控制(FOC, Field-Oriented Control) 是实现高性能力矩控制的关键,它将三相电流解耦为直轴(Id)与交轴(Iq)分量,其中 Iq 直接对应输出转矩。
开源库如 SimpleFOC 已支持在 Arduino(ESP32/STM32)上实现 FOC + 电流环。
二、典型应用场景 - 协作机器人(Cobot)关节
实现人机安全交互,当机械臂接触人体时自动降低力矩,避免伤害;
支持拖动示教(Backdrivability),用户可手动引导机器人学习轨迹。 - 康复与辅助外骨骼
根据患者肌力状态提供自适应辅助力矩(如助力行走、手臂支撑);
力矩控制可模拟弹簧-阻尼特性,实现柔顺康复训练。 - 精密装配与打磨机器人
在插入、拧紧、抛光等操作中维持恒定接触力,避免过压损坏工件;
替代昂贵的六维力传感器,通过电机电流间接估算接触力(需标定)。 - 仿生假肢与灵巧手
模拟人体肌肉的力输出特性,实现抓取力自适应调节(如握鸡蛋不碎、握瓶不滑);
多指协同需各关节独立力矩控制。 - 教学与科研平台
用于验证阻抗控制、导纳控制、力位混合控制等高级算法;
低成本替代商业伺服电机,便于高校实验室开展机器人控制研究。
三、需要注意的事项 - Arduino 平台性能限制
标准 Arduino Uno/Nano(8-bit AVR, 16 MHz)无法实时运行 FOC + 电流环;
必须选用高性能 MCU:
ESP32(双核 240 MHz,支持硬件浮点);
STM32F4/F7/H7 系列(Cortex-M4/M7,支持 FPU、高级定时器、多路 ADC);
Teensy 4.0/4.1(600 MHz Cortex-M7)。
控制周期建议 ≤ 200 μs(即 ≥5 kHz)以保证电流环稳定性。 - 电流采样同步性与噪声
电流采样必须与 PWM 开关同步(通常在 PWM 中心对齐模式下采样),否则引入严重纹波;
BLDC 高频开关噪声易耦合至模拟信号,需:
使用 RC 低通滤波;
采用差分输入与屏蔽线;
在软件中加入数字滤波(如滑动平均、卡尔曼滤波)。 - 驱动电路设计要求高
驱动器需支持:
三相桥臂独立 PWM 控制;
电流检测通道(至少两相,用于重构第三相);
过流保护与死区时间设置;
推荐使用集成预驱+MOSFET 的模块(如 VESC、SimpleFOC Shield、TI DRV8305EVM)。 - 参数辨识与标定不可忽视电机参数影响控制性能;
需通过实验(如阶跃电流测试、堵转测试)进行标定;
温度变化会导致电阻漂移,长期运行需考虑温补。 - 安全性与故障保护
电流环失控可能导致电机过热、驱动器烧毁或机械结构损坏;
必须设置:
软件电流限幅;
硬件过流切断(如比较器触发 shutdown 引脚);
温度监控(NTC 或 MOSFET 结温估算);
看门狗与紧急停止机制。 - 力矩控制 ≠ 实际输出力
电机输出力矩需经减速器、连杆等传动机构传递至末端,存在摩擦、间隙、惯量耦合等非理想因素;
若需精确控制末端作用力,仍需结合力传感器或进行动力学补偿。

1、工业传送带恒张力控制
#include <PID_v2.h>
const float Kp = 0.8, Ki = 0.2, Kd = 0.05; // PID参数
float targetCurrent = 5.0; // 目标电流(A)
float currentScale = 0.1f; // 电流采样比例系数
// 硬件相关定义
#define CURRENT_PIN A0
#define PWM_PIN 9
#define MOTOR_EN 7
void setup() {
pinMode(PWM_PIN, OUTPUT);
pinMode(MOTOR_EN, OUTPUT);
digitalWrite(MOTOR_EN, HIGH); // 启用电机驱动
}
void loop() {
// 电流采样 (假设使用分流电阻+运放)
float adcValue = analogRead(CURRENT_PIN);
float actualCurrent = (adcValue * 5.0 / 1023.0) / currentScale;
// PID计算
static float integral = 0, lastError = 0;
float error = targetCurrent - actualCurrent;
integral += error * 0.01;
float derivative = (error - lastError) / 0.01;
float pwmDuty = constrain(Kp*error + Ki*integral + Kd*derivative, 0, 255);
lastError = error;
// 输出控制
analogWrite(PWM_PIN, pwmDuty);
delay(10); // 10ms控制周期
}
要点解读:
电流采样处理:通过ADC读取分流电阻电压,需根据实际硬件校准currentScale
抗饱和设计:constrain()限制PWM范围防止积分溢出
安全机制:独立使能引脚便于紧急停机
典型应用:传送带、卷绕设备等需保持物料张力的场景
2、协作机器人关节力控
#include <Filter.h>
#define NUM_READINGS 10
float currentSum = 0;
int sampleCount = 0;
void setup() {
// 初始化滤波数组
for(int i=0; i<NUM_READINGS; i++){
currentBuffer[i] = 0;
}
}
void loop() {
// 滑动平均滤波
float newSample = readPhaseCurrent();
currentSum = currentSum - currentBuffer[sampleCount] + newSample;
currentBuffer[sampleCount] = newSample;
sampleCount = (sampleCount + 1) % NUM_READINGS;
float filteredCurrent = currentSum / NUM_READINGS;
// 力矩映射表 (角度-电流)
const float torqueTable[6][2] = {
{0, 0}, {30, 2.5}, {60, 4.0},
{90, 3.5}, {120, 2.0}, {150, 0}
};
// 根据当前位置查表设置目标电流
float currentAngle = readEncoder();
float targetCurrent = mapLookup(torqueTable, currentAngle);
// 双环控制 (外层位置环+内层电流环)
float posError = targetAngle - currentAngle;
float torqueCmd = posError * 0.1; // 位置环输出转矩指令
float currentError = torqueCmd - filteredCurrent;
// PI控制输出
static float iTerm = 0;
iTerm += currentError * 0.001;
float pwmOut = constrain(currentError * 1.5 + iTerm, 0, 255);
analogWrite(9, pwmOut);
}
要点解读:
多级滤波:滑动平均消除电流采样噪声
力矩映射表:实现不同角度下的差异化力矩输出
双闭环架构:位置外环生成力矩指令,电流内环快速响应
安全特性:可添加if(overcurrent()) emergencyStop();实现过流保护
3、无人机动力系统过热保护
#define THERMAL_LIMIT 70 // 温度阈值(℃)
#define OVERCURRENT_LIMIT 15 // 过流阈值(A)
float tempCoeff = 0.02; // 温度补偿系数
void loop() {
// 获取实时数据
float phaseCurrent = readShuntVoltage() / shuntResistance;
float motorTemp = readNTCThermistor();
// 温度补偿
float compensatedCurrent = phaseCurrent * (1 + tempCoeff * (motorTemp - 25));
// 智能限幅
float safeCurrent = min(OVERCURRENT_LIMIT, OVERCURRENT_LIMIT * (THERMAL_LIMIT - motorTemp)/THERMAL_LIMIT);
float currentError = min(safeCurrent, targetCurrent) - compensatedCurrent;
// 自适应PI控制
float adaptiveKp = map(abs(currentError), 0, 10, 0.5, 2.0);
float pwmOutput = currentError * adaptiveKp;
// 故障诊断
if(motorTemp > THERMAL_LIMIT || abs(currentError) > 5){
reducePowerGradually(); // 渐进式降功率
setStatusLED(RED);
} else {
analogWrite(ESC_PWM_PIN, pwmOutput);
}
}
要点解读:
温度补偿:修正铜损随温度变化的影响
动态限幅:根据温升自动降低允许电流
自适应控制:误差大时增强响应速度
故障管理:分级处理过热/过流异常

4、恒力输出设备(如弹簧模拟器)
#include <SimpleFOC.h>
// 硬件配置
BLDCMotor motor(7);
BLDCDriver3PWM driver(9, 10, 11, 8);
InlineCurrentSense current_sense(A0, A1, A2); // 三相电流采样
// 控制参数
float target_torque = 0.5; // 目标力矩(归一化值,范围-1~1)
float Kp = 0.5; // 电流环比例系数
void setup() {
Serial.begin(115200);
// 初始化电流检测
current_sense.init();
current_sense.gain *= 0.5; // 调整增益(根据硬件)
// 电机配置
driver.init();
motor.linkDriver(&driver);
motor.linkCurrentSense(¤t_sense);
motor.torque_controller = TorqueControlType::current; // 电流控制模式
motor.controller = MotionControlType::torque;
motor.init();
motor.initFOC();
}
void loop() {
// 1. 直接设定目标电流(对应目标力矩)
motor.target = target_torque * motor.current_limit;
// 2. 执行FOC控制(自动闭环)
motor.loopFOC();
motor.move();
// 3. 监控实际电流
PhaseCurrent_s current = current_sense.getPhaseCurrents();
float actual_current = current.a + current.b + current.c; // 三相合成
Serial.print("Target: "); Serial.print(target_torque);
Serial.print(" Actual: "); Serial.println(actual_current);
delay(10);
}
要点解读:
电流采样:使用InlineCurrentSense实现三相电流检测,需根据硬件调整增益
归一化控制:target_torque范围通常设为[-1, 1],对应±current_limit
直接力矩模式:TorqueControlType::current表示通过电流实现力矩控制
5、力矩跟随曲线(如电动助力系统)
#include <SimpleFOC.h>
#include <Encoder.h>
BLDCMotor motor(7);
BLDCDriver3PWM driver(9, 10, 11, 8);
InlineCurrentSense current_sense(A0, A1, A2);
Encoder encoder(2, 3); // 位置传感器
// 力矩映射表(角度→目标力矩)
const float torque_map[5] = {0.2, 0.8, 1.0, 0.6, 0.1}; // 示例值
const float angle_points[5] = {0, 90, 180, 270, 360};
void setup() {
Serial.begin(115200);
encoder.init();
current_sense.init();
driver.init();
motor.linkDriver(&driver);
motor.linkCurrentSense(¤t_sense);
motor.linkSensor(&encoder);
motor.torque_controller = TorqueControlType::current;
motor.controller = MotionControlType::torque;
motor.init();
motor.initFOC();
}
void loop() {
// 1. 获取当前角度(映射到0~360°)
float angle = fmod(encoder.getAngle() * RAD_TO_DEG, 360);
// 2. 查表插值计算目标力矩
float target_torque = 0;
for (int i=0; i<4; i++) {
if (angle >= angle_points[i] && angle <= angle_points[i+1]) {
float ratio = (angle - angle_points[i]) / (angle_points[i+1] - angle_points[i]);
target_torque = torque_map[i] + ratio * (torque_map[i+1] - torque_map[i]);
break;
}
}
// 3. 执行力矩控制
motor.target = target_torque * motor.current_limit;
motor.loopFOC();
motor.move();
// 4. 监控数据
PhaseCurrent_s current = current_sense.getPhaseCurrents();
Serial.print("Angle: "); Serial.print(angle);
Serial.print(" Torque: "); Serial.println(current.a + current.b + current.c);
delay(10);
}
要点解读:
查表插值:通过角度映射实现非线性力矩输出(如助力曲线)
三相电流合成:实际监控时可取三相电流之和(需考虑方向)
闭环稳定性:电流环通常需要较高频率(建议≥5kHz)
6、安全力矩限制(如协作机器人)
#include <SimpleFOC.h>
BLDCMotor motor(7);
BLDCDriver3PWM driver(9, 10, 11, 8);
InlineCurrentSense current_sense(A0, A1, A2);
// 安全参数
float max_torque = 1.2; // 最大允许力矩(归一化)
float emergency_limit = 1.5; // 紧急保护阈值
void setup() {
Serial.begin(115200);
current_sense.init();
driver.init();
motor.linkDriver(&driver);
motor.linkCurrentSense(¤t_sense);
motor.torque_controller = TorqueControlType::current;
motor.controller = MotionControlType::torque;
motor.current_limit = 3.0; // 硬件电流限制(安培)
motor.init();
motor.initFOC();
}
void loop() {
// 1. 模拟外部输入(如传感器或上位机指令)
static float external_input = 0;
external_input += 0.01;
if (external_input > 1.5) external_input = -1.0;
// 2. 软限制(正常控制逻辑)
float target_torque = constrain(external_input, -max_torque, max_torque);
// 3. 硬件级保护(检测实际电流)
PhaseCurrent_s current = current_sense.getPhaseCurrents();
float actual_current = fabs(current.a + current.b + current.c);
if (actual_current > emergency_limit * motor.current_limit) {
motor.target = 0; // 紧急制动
Serial.println("EMERGENCY STOP!");
} else {
motor.target = target_torque * motor.current_limit;
}
// 4. 执行控制
motor.loopFOC();
motor.move();
Serial.print("Input: "); Serial.print(external_input);
Serial.print(" Current: "); Serial.println(actual_current);
delay(5);
}
要点解读:
分层保护:
软件限制:constrain()实现正常工况限制
硬件保护:实时检测电流超限后强制制动
紧急处理:检测到过流时直接设置target=0,避免硬件损坏
电流绝对值:使用fabs()确保正反方向超限均能触发保护
注意,以上案例只是为了拓展思路,仅供参考。它们可能有错误、不适用或者无法编译。您的硬件平台、使用场景和Arduino版本可能影响使用方法的选择。实际编程时,您要根据自己的硬件配置、使用场景和具体需求进行调整,并多次实际测试。您还要正确连接硬件,了解所用传感器和设备的规范和特性。涉及硬件操作的代码,您要在使用前确认引脚和电平等参数的正确性和安全性。

1060

被折叠的 条评论
为什么被折叠?



