【花雕学编程】Arduino BLDC 之机器人三级制动状态机控制(平稳分级制动)

Arduino BLDC之机器人三级制动状态机控制(平稳分级制动)的核心在于利用有限状态机(FSM)将刹车过程解耦为滑行缓冲、电气降速与位置锁死三个平滑递进阶段,以消除机械冲击并实现“无超调”精准停靠。 该方案在算力受限的嵌入式平台上,通过多传感器融合与分层决策,解决了传统BLDC电机刹车生硬、易损坏机械结构及无法精准定位的痛点。以下从主要特点、应用场景及注意事项三个维度进行专业解析。
主要特点
- 三级制动状态机架构(核心控制逻辑)
这是系统的“决策大脑”,通过有限状态机(FSM)将刹车过程解耦为三个平滑递进的状态,避免传统急停带来的机械冲击。
第一级:滑行缓冲态(Coasting / Deceleration Phase):当系统接收到刹车指令或检测到障碍物时,不立即施加制动力,而是先切断电机动力输出(motor.move(0)),让机器人依靠惯性自然滑行。此阶段可设置定时器或距离阈值,避免误触发,同时让电机转速自然衰减,为后续电气制动做准备。
第二级:电气降速态(Electrical Braking Phase):当速度降至预设阈值(如额定转速的20%-30%)时,状态机切换至电气制动模式。此时采用回馈制动(再生制动)或短接制动,通过调节PWM占空比动态控制制动力矩。中高速时PWM占空比控制在30%以内以限制短路电流,中低速时再切换为满占空比短接,实现平稳减速。
第三级:位置锁死态(Position Hold / Locked Phase):当速度接近零时,状态机进入位置保持模式。此时BLDC电机切换至FOC位置环控制,通过PID算法输出维持力矩,抵抗外部扰动(如斜坡重力、碰撞力),实现“停得准、hold得住”的精准停靠。 - 多传感器融合的风险评估与分级响应
制动决策不仅依赖单一信号,而是融合多源数据进行智能判断。
距离感知层:激光雷达/超声波用于远距离预警(触发第一级滑行),红外/触碰传感器用于近距离确认(触发第二级电气制动)。
姿态感知层:IMU监测机器人倾斜角和加速度,防止在斜坡上制动时发生倾覆或溜车。
力矩/电流感知层:通过电流环实时监测BLDC电机输出力矩,当检测到异常碰撞或堵转时,电流急剧上升可作为最后一道防线,直接触发紧急制动。
分级响应机制:不同风险等级触发不同制动级别。例如,远处静态障碍只需滑行减速,快速接近的动态障碍需立即电气制动,而碰撞或倾覆风险则直接锁死电机并切断使能。 - 基于FOC的平滑转矩控制与S曲线规划
BLDC电机配合FOC(磁场定向控制)是实现平稳制动的物理基础。
低转矩脉动:FOC通过正弦电流驱动消除换相阶跃,转矩纹波降低70%以上,确保制动过程中无抖动、无冲击。
S形速度曲线(S-curve Trajectory):在制动过程中引入加加速度(jerk)限制,使加速度连续变化,避免梯形速度曲线中加速度突变导致的机械谐振和跟踪误差。
力矩线性控制:FOC的q轴电流(Iq)与输出转矩呈线性关系,使得制动力矩可精确调节,实现“踩多少刹多少”的拟人化制动体验。
应用场景
该系统凭借其平稳性、精准性和高安全性,主要应用于以下场景:
服务机器人与人机共融场景:在餐厅、酒店、商场等人流密集环境中,机器人需要与人类安全共存。三级制动确保机器人在检测到行人时先平滑减速(避免惊吓),再精准停靠(避免碰撞),最后保持静止(防止被推倒)。
精密定位与自动化设备:如3D打印机、CNC机床、激光雕刻机等,要求打印头或刀头在高速运动后精准停靠在指定位置,无超调、无振荡。三级制动中的位置锁死态通过PID位置环实现亚毫米级定位精度。
物流搬运机器人(AGV/AMR):在仓储物流中,重载AGV需要在货架前精准停靠以进行货物存取。三级制动可有效抑制重载惯性带来的停车超调,同时位置锁死态可防止在斜坡上溜车。
机械臂关节伺服驱动:多自由度机械臂的每个关节都需要快速、准确地到达指定角度。三级制动确保关节在高速运动后无冲击地停在目标位置,并通过力矩保持抵抗重力矩和外部扰动。
教育与科研验证平台:高校在机器人学、自动控制原理课程中,利用该平台演示状态机编程、PID调参、FOC控制等核心概念,是学习嵌入式运动控制的理想载体。
需要注意的事项
在实现该系统时,需重点关注以下技术细节与工程红线:
- MCU选型与控制周期(算力瓶颈)
MCU性能要求:标准Arduino Uno(ATmega328P, 16MHz)无法高效运行FOC+状态机+多传感器融合。强烈推荐ESP32(双核240MHz,支持硬件浮点)、STM32F4/F7(Cortex-M4/M7,支持高级定时器)或Teensy 4.1(600MHz)。
控制周期:FOC电流环需≥1kHz(建议10-20kHz),速度环/位置环≥200Hz,状态机判断≥50Hz。所有控制回路必须使用硬件定时器中断,严禁使用delay()函数。 - 传感器校准与数据滤波
编码器分辨率:关节定位精度直接取决于传感器分辨率。12-bit磁编码器(如AS5600)分辨率约0.088°,14-bit(如MA730)约0.022°。编码器应安装在关节输出轴而非电机轴,以补偿减速器齿隙。
数据滤波:传感器信号易受电磁干扰。建议对编码器数据进行滑动平均或卡尔曼滤波处理;对电流数据进行低通滤波,以剔除尖峰干扰。 - 严格的电源管理与电磁兼容(EMC)
隔离供电:BLDC电机在制动时会产生反向电动势和电流尖峰,极易导致MCU复位。必须使用独立DC-DC模块为控制电路供电,并在电机驱动端并联大容量低ESR电容(1000μF-4700μF)吸收反电动势。
共地连接:MCU的GND必须与电机驱动模块的GND物理连接,否则控制信号无法形成回路。
信号屏蔽:编码器、IMU等敏感信号线需使用屏蔽线,并远离动力线布线,PCB布局时注意AGND与DGND单点连接。 - 制动参数整定与安全冗余
速度阈值标定:第一级到第二级的切换速度阈值需通过实验标定,过高会导致滑行距离过长,过低会导致电气制动时电流冲击过大。
PID参数整定:位置锁死态的PID参数需精细标定。Kp过大会导致振荡,Kd过小会导致超调,Ki用于消除稳态误差但需防止积分饱和。建议采用增量式PID或带限幅的积分分离PID。
硬件急停:必须设置独立的硬件急停电路(如物理急停按钮),采用中断级处理,可强切电机使能(EN),确保在状态机失控时能瞬间切断动力。
死区时间控制:在驱动BLDC电机的三相全桥逆变电路中,必须插入短暂的“死区时间”(通常0.5-2μs),防止上下桥臂MOSFET同时导通造成短路。

1、基础三级制动状态机(减速 → 软停 → 抱闸保持)
适用场景:轮式机器人精准停机、路径跟踪终点制动、移动作业停机等场景,特点是要求制动平稳、无顿挫、无过冲,避免因制动过急导致货物倾倒或人员晃动。
/**
* 三级制动状态机 - 平稳分级制动
* 硬件假设:Arduino Mega, BLDC + 编码器, 电机驱动板(PWM+方向), 电磁抱闸(BRAKE_PIN)
* 状态流转:RUNNING -> DECEL -> SOFT_STOP -> HOLD
*/
#include <SimpleFOC.h>
BLDCMotor motor(7);
Encoder encoder(2, 4, 2048);
#define BRAKE_PIN 9
#define DECEL_THRESHOLD 30 // 进入减速制动的速度阈值 (cm/s)
#define SOFT_STOP_THRESHOLD 5 // 进入软停车的速度阈值 (cm/s)
#define HOLD_SPEED_THRESHOLD 0.5 // 进入抱闸的速度阈值 (cm/s)
#define DECEL_RATE 8.0 // 减速阶段减速度 (cm/s²)
#define SOFT_DECEL_RATE 3.0 // 软停车阶段减速度 (cm/s²)
// 状态定义
typedef enum {
STATE_RUNNING, // 正常运行
STATE_DECEL, // 一级:减速制动
STATE_SOFT_STOP, // 二级:软停车
STATE_HOLD, // 三级:抱闸保持
STATE_ERROR // 异常状态
} BrakeState;
BrakeState currentState = STATE_RUNNING;
float currentSpeed = 0.0;
float targetSpeed = 0.0;
unsigned long lastUpdate = 0;
// 编码器中断(4倍频)
volatile long encCount = 0;
void encoderISR() {
bool a = digitalRead(2);
bool b = digitalRead(4);
if (a && !b) encCount++;
else if (!a && b) encCount--;
}
float readSpeed() {
static long lastEnc = 0;
static unsigned long lastTime = 0;
unsigned long now = micros();
if (now - lastTime < 5000) return currentSpeed; // 200Hz更新
long deltaEnc = encCount - lastEnc;
float dt = (now - lastTime) / 1000000.0;
// 假设编码器2048线,轮径10cm,4倍频 -> 8192脉冲/圈
currentSpeed = (deltaEnc / 8192.0) * PI * 10.0 / dt; // cm/s
lastEnc = encCount;
lastTime = now;
return currentSpeed;
}
void setup() {
Serial.begin(115200);
pinMode(BRAKE_PIN, OUTPUT);
digitalWrite(BRAKE_PIN, LOW); // 抱闸初始释放
attachInterrupt(digitalPinToInterrupt(2), encoderISR, CHANGE);
motor.linkSensor(&encoder);
motor.init();
motor.initFOC();
motor.controller = MotionControlType::velocity;
targetSpeed = 20.0; // 初始巡航速度
Serial.println("三级制动状态机就绪");
}
void loop() {
motor.loopFOC();
currentSpeed = readSpeed();
switch (currentState) {
case STATE_RUNNING:
motor.move(targetSpeed / 10.0); // 简化的速度映射
if (Serial.available() && Serial.readStringUntil('\n') == "STOP") {
currentState = STATE_DECEL;
Serial.println("进入一级减速制动");
}
break;
case STATE_DECEL:
// 一级:按 DECEL_RATE 减速
targetSpeed -= DECEL_RATE * 0.02; // 50Hz循环
if (targetSpeed < 0) targetSpeed = 0;
motor.move(targetSpeed / 10.0);
if (currentSpeed < DECEL_THRESHOLD && currentSpeed >= SOFT_STOP_THRESHOLD) {
currentState = STATE_SOFT_STOP;
Serial.println("进入二级软停车");
}
if (currentSpeed < SOFT_STOP_THRESHOLD) {
currentState = STATE_SOFT_STOP;
}
break;
case STATE_SOFT_STOP:
// 二级:更慢的减速度,精细逼近零速
targetSpeed -= SOFT_DECEL_RATE * 0.02;
if (targetSpeed < 0) targetSpeed = 0;
motor.move(targetSpeed / 10.0);
if (currentSpeed < HOLD_SPEED_THRESHOLD) {
currentState = STATE_HOLD;
digitalWrite(BRAKE_PIN, HIGH); // 抱闸锁死
Serial.println("进入三级抱闸保持");
}
break;
case STATE_HOLD:
motor.move(0); // 电机零力矩
// 保持抱闸
break;
case STATE_ERROR:
digitalWrite(BRAKE_PIN, HIGH);
motor.move(0);
break;
}
lastUpdate = millis();
Serial.print("速度:"); Serial.print(currentSpeed, 1);
Serial.print(" 状态:"); Serial.println(currentState);
delay(20); // 50Hz
}
要点:该代码的核心是基于速度阈值的状态自动流转。减速阶段以 8.0 cm/s² 的减速度快速降速,当速度进入 5~30 cm/s 区间时切换到软停车阶段,以更低的 3.0 cm/s² 减速度精细逼近零速,最后在速度低于 0.5 cm/s 时触发抱闸。这种“先快后慢”的策略避免了高速下直接抱闸对机械结构的冲击。
2、硬件中断急停 + 三级制动(优先级仲裁)
适用场景:工业 AGV、商用服务机器人等对安全性要求极高的场景,急停信号必须绕过常规逻辑直接响应,同时分级制动平衡制动速度与机械冲击。
/**
* 硬件中断急停 + 三级制动状态机
* 硬件假设:Arduino Mega, BLDC + 编码器, 驱动板, 电磁抱闸, 急停按钮(NC常闭)
* 核心:ISR极简响应(仅置位标志+硬件断电) -> 主循环执行分级制动
*/
#include <SimpleFOC.h>
BLDCMotor motor(7);
Encoder encoder(2, 4, 2048);
#define BRAKE_PIN 9
#define ESTOP_PIN 3 // 外部中断引脚,接常闭急停按钮
// 制动阈值
#define DECEL_THRESHOLD 40
#define SOFT_STOP_THRESHOLD 8
#define HOLD_THRESHOLD 1.0
// 状态定义
typedef enum {
STATE_RUNNING,
STATE_PRE_WARN, // 预警减速
STATE_DECEL, // 动态制动
STATE_SOFT_STOP, // 软停车
STATE_HOLD, // 抱闸保持
STATE_EMERGENCY // 急停(不可逆)
} BrakeState;
volatile bool emergencyFlag = false;
BrakeState currentState = STATE_RUNNING;
float currentSpeed = 0.0;
float targetSpeed = 0.0;
void estopISR() {
emergencyFlag = true;
// ISR中极简操作:仅置位标志,禁止delay/Serial
}
void setup() {
Serial.begin(115200);
pinMode(BRAKE_PIN, OUTPUT);
digitalWrite(BRAKE_PIN, LOW);
pinMode(ESTOP_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(ESTOP_PIN), estopISR, FALLING);
attachInterrupt(digitalPinToInterrupt(2), []() {
bool a = digitalRead(2); bool b = digitalRead(4);
if (a && !b) encCount++;
else if (!a && b) encCount--;
}, CHANGE);
motor.linkSensor(&encoder);
motor.init(); motor.initFOC();
motor.controller = MotionControlType::velocity;
targetSpeed = 25.0;
}
void loop() {
motor.loopFOC();
currentSpeed = readSpeed();
// 最高优先级:急停信号检查
if (emergencyFlag) {
currentState = STATE_EMERGENCY;
emergencyFlag = false;
}
switch (currentState) {
case STATE_RUNNING:
motor.move(targetSpeed / 10.0);
// 可添加其他触发条件进入PRE_WARN
break;
case STATE_PRE_WARN: // 预警减速 (低强度)
targetSpeed -= 4.0 * 0.02;
if (targetSpeed < 0) targetSpeed = 0;
motor.move(targetSpeed / 10.0);
if (currentSpeed < DECEL_THRESHOLD) currentState = STATE_DECEL;
break;
case STATE_DECEL: // 动态制动 (中强度,能耗制动)
// 通过反向电流产生制动转矩,同时监测电流防止过流
targetSpeed -= 10.0 * 0.02; // 更快减速
if (targetSpeed < -5.0) targetSpeed = -5.0; // 限制反向速度
motor.move(targetSpeed / 10.0);
if (currentSpeed < SOFT_STOP_THRESHOLD) {
currentState = STATE_SOFT_STOP;
}
break;
case STATE_SOFT_STOP:
targetSpeed -= 3.0 * 0.02;
if (targetSpeed < 0) targetSpeed = 0;
motor.move(targetSpeed / 10.0);
if (currentSpeed < HOLD_THRESHOLD) currentState = STATE_HOLD;
break;
case STATE_HOLD:
motor.move(0);
digitalWrite(BRAKE_PIN, HIGH);
break;
case STATE_EMERGENCY: // 急停:不可逆,仅硬件复位可恢复
motor.move(0);
digitalWrite(BRAKE_PIN, HIGH);
// 此处保持,直到系统复位
break;
}
Serial.print("速度:"); Serial.print(currentSpeed, 1);
Serial.print(" 状态:"); Serial.println(currentState);
delay(20);
}
要点:该案例体现了安全优先级仲裁的设计原则。急停信号通过外部中断直接响应,ISR 仅置位 emergencyFlag,不做任何耗时操作。主循环检测到标志后,进入不可逆的 STATE_EMERGENCY,强制抱闸并等待硬件复位。三级制动的核心价值在于:动态制动阶段允许电机以反向转矩快速降速,但限制反向速度防止过流;软停车阶段以更低减速度逼近零速,避免顿挫;抱闸阶段最终锁定位置。
3、基于 SimpleFOC 力矩控制的平滑制动(FOC 力矩感知 + 分级响应)
适用场景:对制动力矩精度要求高的协作机器人或精密移动平台,利用 FOC 的力矩控制能力实现更柔顺的减速曲线。
/**
* 基于 SimpleFOC 力矩控制的平滑分级制动
* 核心:利用 FOC 的力矩控制模式,以力矩指令替代速度指令实现制动
* 优势:力矩平滑,无速度环超调,适合对顿挫敏感的场景
*/
#include <SimpleFOC.h>
BLDCMotor motor(7);
Encoder encoder(2, 4, 2048);
BLDCDriver3PWM driver(5, 6, 9, 8);
#define BRAKE_PIN 10
#define TORQUE_DECEL 0.3 // 减速力矩 (Nm)
#define TORQUE_SOFT 0.1 // 软停力矩 (Nm)
#define HOLD_THRESHOLD 1.0
typedef enum {
STATE_RUNNING,
STATE_TORQUE_BRAKE, // 力矩制动
STATE_SOFT_BRAKE, // 软力矩制动
STATE_HOLD
} BrakeState;
BrakeState state = STATE_RUNNING;
float currentSpeed = 0.0;
void setup() {
Serial.begin(115200);
pinMode(BRAKE_PIN, OUTPUT);
digitalWrite(BRAKE_PIN, LOW);
driver.voltage_power_supply = 24;
driver.init();
motor.linkDriver(&driver);
motor.linkSensor(&encoder);
motor.init();
motor.initFOC();
// 力矩控制模式,配合电流检测
motor.controller = MotionControlType::torque;
motor.torque_controller = TorqueControlType::voltage;
// 先以速度模式启动
motor.controller = MotionControlType::velocity;
motor.move(3.0);
delay(2000);
Serial.println("开始制动...");
state = STATE_TORQUE_BRAKE;
}
void loop() {
motor.loopFOC();
currentSpeed = readSpeed();
switch (state) {
case STATE_RUNNING:
motor.move(3.0);
break;
case STATE_TORQUE_BRAKE:
// 施加反向力矩制动
// FOC力矩控制下,负力矩即为制动
motor.move(-TORQUE_DECEL);
if (abs(currentSpeed) < 10.0) {
state = STATE_SOFT_BRAKE;
Serial.println("切换到软力矩制动");
}
break;
case STATE_SOFT_BRAKE:
// 更小的制动力矩,精细逼近零速
motor.move(-TORQUE_SOFT);
if (abs(currentSpeed) < HOLD_THRESHOLD) {
state = STATE_HOLD;
digitalWrite(BRAKE_PIN, HIGH);
Serial.println("抱闸保持");
}
break;
case STATE_HOLD:
motor.move(0); // 零力矩
break;
}
Serial.print("速度:"); Serial.print(currentSpeed, 1);
Serial.print(" 状态:"); Serial.println(state);
delay(20);
}
float readSpeed() {
static long lastEnc = 0;
static unsigned long lastTime = 0;
unsigned long now = micros();
if (now - lastTime < 5000) return currentSpeed;
long delta = encCount - lastEnc;
float dt = (now - lastTime) / 1000000.0;
currentSpeed = (delta / 8192.0) * PI * 10.0 / dt;
lastEnc = encCount; lastTime = now;
return currentSpeed;
}
要点:该案例展示了 FOC 力矩控制在制动场景中的独特优势。传统速度环制动在接近零速时容易出现积分饱和和超调,而力矩控制直接指定制动力矩大小,物理意义更明确。TORQUE_DECEL = 0.3 Nm 和 TORQUE_SOFT = 0.1 Nm 的两级力矩配置实现了自然的“先强后弱”减速曲线,无需复杂的速度规划。SimpleFOC 的 TorqueControlType::voltage 模式无需电流传感器即可实现近似力矩控制。
要点解读
-
三级制动的本质是“用时间换平稳”,而不是“用力量换速度”。 从减速到软停再到抱闸,每一级都在降低制动强度,代价是制动距离延长。如果机器人需要从 30 cm/s 完全停止,三级制动可能需要 2~3 秒,而直接抱闸可能只需 0.5 秒。选择三级制动的场景,一定是“平稳性优先于制动距离”的场景——如搬运易碎品的 AGV、载人的服务机器人、精密定位平台。如果场景要求“最短制动距离”,应该选择直接动态制动甚至机械抱闸,而不是三级制动。
-
减速阈值和减速率必须与负载惯量匹配,否则会顿挫或过冲。 案例一中的 DECEL_THRESHOLD = 30 和 SOFT_STOP_THRESHOLD = 5 不是通用值,而是根据机器人质量、轮径和电机扭矩估算的。如果负载惯量大而减速率设置过小,机器人会在软停阶段“滑行”很久;如果减速率设置过大,则会产生反向冲击。实践中,减速率应从保守值(如 5 cm/s²)开始,逐步调大直到观察到轻微顿挫,再回调 20% 作为最终值。
-
硬件中断急停与分级制动是互补而非替代关系。 急停按钮通过硬件中断直接切断动力,是最后的安全防线,响应时间在微秒级。但急停是“一刀切”的粗暴制动,对机械结构和负载都有冲击。分级制动适用于“计划内的平稳停机”——如到达终点、收到正常停止指令。两者应该共存:正常停机走三级制动状态机,异常情况走硬件急停。
-
FOC 力矩控制让制动更“柔性”,但需要解决零速附近的转矩控制精度。 案例三用 motor.move(-TORQUE_DECEL) 直接指定制动力矩,避免了速度环在低速时的积分饱和问题。但 SimpleFOC 在极低转速(<1 rad/s)下的力矩控制精度会下降,因为反电动势过小,电压模式力矩控制的近似误差增大。如果需要在零速附近精确控制抱闸时机,建议在软停阶段切换回速度模式,用速度环的积分项来精细逼近零速。
-
抱闸时序是三级制动的“最后一厘米”,也是最容易被忽视的细节。 案例中 digitalWrite(BRAKE_PIN, HIGH) 在速度低于 HOLD_THRESHOLD 时触发。如果抱闸过早(速度仍较高),会对抱闸片和电机轴产生冲击;如果抱闸过晚(速度已接近零但电机仍在输出力矩),则会产生“电机与抱闸对抗”。理想的抱闸时机是:电机力矩降至接近零(motor.move(0)),等待 50~100ms 让机械系统稳定,再闭合抱闸。案例一直接在 STATE_HOLD 中同时执行 motor.move(0) 和抱闸,可以进一步优化为先零力矩、延时、再抱闸。

4、常规作业路径终点三级平稳制动程序(核心:路径终点精准停靠)
适用场景:巡检、搬运等常规作业机器人,在路径终点实现平稳分级制动,避免急停的冲击力与定位偏差。
核心逻辑
基于预设距离,划分三级制动区间,匹配不同制动策略
通过状态机切换巡航、一级制动、二级制动、三级制动四个状态,逐步降低速度与扭矩
三级制动完成后触发停机,实现精准停靠
// 常规作业终点三级平稳制动程序
// 硬件:BLDC驱动、光电编码器(速度反馈)、霍尔定位传感器、蜂鸣器
// 功能:路径终点分级制动,精准停靠,降低停车冲击
#include <Arduino.h>
// ========== 硬件定义 ==========
const byte PWM_PIN = 9; // BLDC转速控制
const byte DIR_PIN = 8; // BLDC方向控制
const byte BRK_PIN = 7; // 硬件制动引脚(可选,辅助制动)
const byte PIN_ENC = 2; // 编码器中断引脚
const byte PIN_HOME = 4; // 终点定位传感器
const byte SND_PIN = 13; // 蜂鸣器(到位提示)
// ========== 制动参数 ==========
enum BrakeStage { CRUISE, FIRST_BRAKE, SECOND_BRAKE, THIRD_BRAKE, PARKING }; // 0巡航,1-3三级制动,4停放
BrakeStage stage = CRUISE;
const float DIST_THRESHOLD[3] = {200.0, 80.0, 20.0}; // 三级制动触发距离(cm)
const uint8_t CRUISE_SPEED = 180; // 巡航速度(0-255)
const uint8_t SPEED_1 = 140; // 一级制动目标速度
const uint8_t SPEED_2 = 80; // 二级制动目标速度
const uint8_t SPEED_3 = 30; // 三级制动目标速度
float speed = CRUISE_SPEED; // 当前实际速度
uint16_t dist = 300; // 当前距离终点距离,模拟值
bool parkingComplete = false;
// ========== 函数声明 ==========
void speedPID(uint8_t target);
void applyBrake(uint8_t spd);
void enterStage(BrakeStage s);
long readEncoder();
void setup() {
Serial.begin(115200);
Serial.println("三级制动系统启动");
pinMode(PWM_PIN, OUTPUT);
pinMode(DIR_PIN, OUTPUT);
pinMode(BRK_PIN, OUTPUT);
pinMode(PIN_HOME, INPUT);
pinMode(SND_PIN, OUTPUT);
digitalWrite(BRK_PIN, HIGH); // 释放制动
attachInterrupt(digitalPinToInterrupt(PIN_ENC), readEncoder, LOW);
}
void loop() {
// 模拟距离递减(实际可通过编码器/定位计算)
if (dist > 0) dist--;
// 1. 状态机触发与切换
switch (stage) {
case CRUISE:
speed = CRUISE_SPEED;
if (dist < DIST_THRESHOLD[0]) {
stage = FIRST_BRAKE;
enterStage(stage);
}
break;
case FIRST_BRAKE:
// 距离降低则切换至二级制动
if (dist < DIST_THRESHOLD[1]) {
stage = SECOND_BRAKE;
enterStage(stage);
} else {
speedPID(SPEED_1);
// 缓慢降速,避免落差过大
speed = lerp(speed, SPEED_1, 0.2f);
}
break;
case SECOND_BRAKE:
if (dist < DIST_THRESHOLD[2]) {
stage = THIRD_BRAKE;
enterStage(stage);
} else {
speedPID(SPEED_2);
speed = lerp(speed, SPEED_2, 0.15f);
}
break;
case THIRD_BRAKE:
// 距离终点足够近,进入最终停靠
if (dist < 5 || digitalRead(PIN_HOME) == HIGH) {
stage = PARKING;
enterStage(stage);
parkingComplete = true;
} else {
speedPID(SPEED_3);
speed = lerp(speed, SPEED_3, 0.1f);
}
break;
case PARKING:
// 缓慢降速至0,完成停靠
speed = max((int)(speed - 5), 0);
applyBrake(speed);
if (speed == 0) {
digitalWrite(BRK_PIN, LOW); // 启用硬件制动,锁定位置
digitalWrite(SND_PIN, HIGH);
Serial.println("制动完成,已精准停靠");
}
break;
}
Serial.print("当前阶段:");Serial.print(stage);
Serial.print(" 距离终点:");Serial.println(dist);
delay(20);
}
// 简易PID调速,快速逼近目标速度
void speedPID(uint8_t target) {
int error = target - speed;
int output = speed + error * 0.1; // 比例控制
output = constrain(output, 0, 255);
applyBrake(output);
}
// 应用电机驱动,驱动BLDC
void applyBrake(uint8_t spd) {
digitalWrite(DIR_PIN, HIGH); // 保持运行方向
analogWrite(PWM_PIN, spd);
}
// 进入新制动阶段,打印提示
void enterStage(BrakeStage s) {
const char* stageName[] = {"巡航", "一级制动", "二级制动", "三级制动", "停放"};
Serial.print("切换制动阶段:");Serial.println(stageName[s]);
}
// 读取编码器脉冲,计算实际速度(简化)
long readEncoder() {
// 累积脉冲数,用于速度计算,此处简化处理
return 0;
}
适用场景优化
加入里程累积功能,精准计算剩余距离,适配长距离作业场景
优化制动区间阈值,根据作业总距离动态调整三级区间长度,提升制动平滑度
增加加速度限幅,避免阶段切换时速度突变,进一步降低冲击
5、复合场景下的三级制动与应急响应程序(核心:动态场景制动适配)
适用场景:仓储物流、复杂地形机器人,在正常停靠与紧急避障双重需求下,实现动态切换制动策略,兼顾平稳性与安全性。
核心逻辑
基于距离划分为三级制动区间,对应不同制动强度
结合避障传感器触发应急制动,紧急情况下跳过分级,直接急停
避障解除后,平滑回归正常分级制动流程,实现平顺过渡
// 复合场景三级制动+应急响应程序
// 硬件:BLDC、避障红外、距离传感器、蜂鸣器、状态指示灯
// 功能:正常分级制动,紧急避障急停,场景动态适配
#include <Arduino.h>
// ========== 硬件定义 ==========
const byte PWM_PIN = 9, DIR_PIN = 8, BRK_PIN = 7;
const byte IR_AVOID = 2; // 前方避障传感器
const byte DIST_SENSOR = A0;// 距离传感器(红外测距)
const byte LED_RED = 13, LED_GREEN = 12; // 状态指示灯
// ========== 制动参数 ==========
enum BrakeMode { NORMAL_BRAKE, EMERGENCY_STOP };
enum State { IDLE, CRUISE, FIRST_BRAKE, SECOND_BRAKE, THIRD_BRAKE, PARKING };
State state = IDLE;
BrakeMode mode = NORMAL_BRAKE;
const int DIST_LEVEL[3] = {250, 100, 40}; // 三级制动距离阈值
const uint8_t BASE_SPEED = 200;
const uint8_t SPEED_SET[3] = {150, 90, 40}; // 三级制动目标速度
int currentSpeed = 0;
bool emergencyFlag = false;
// ========== 函数声明 ==========
void checkEmergency();
void normalBrake(int level);
void emergencyStop();
uint16_t readDistance();
void setup() {
Serial.begin(115200);
Serial.println("复合制动系统启动");
pinMode(PWM_PIN, OUTPUT);
pinMode(DIR_PIN, OUTPUT);
pinMode(BRK_PIN, OUTPUT);
pinMode(IR_AVOID, INPUT);
pinMode(DIST_SENSOR, INPUT);
pinMode(LED_RED, OUTPUT);
pinMode(LED_GREEN, OUTPUT);
digitalWrite(BRK_PIN, HIGH);
digitalWrite(LED_GREEN, LOW);
digitalWrite(LED_RED, LOW);
}
void loop() {
uint16_t dist = readDistance(); // 1. 读取当前距离
checkEmergency(); // 2. 检测紧急避障
// 3. 紧急制动模式
if (mode == EMERGENCY_STOP) {
emergencyStop();
// 紧急解除后恢复正常制动
if (!emergencyFlag && dist > 50) {
mode = NORMAL_BRAKE;
state = CRUISE;
Serial.println("紧急解除,恢复分级制动");
digitalWrite(LED_RED, LOW);
}
return;
}
// 4. 正常分级制动
switch (state) {
case IDLE:
digitalWrite(LED_GREEN, HIGH);
state = CRUISE;
break;
case CRUISE:
currentSpeed = BASE_SPEED;
applyMotor(currentSpeed, HIGH);
if (dist < DIST_LEVEL[0]) {
state = FIRST_BRAKE;
Serial.println("进入一级制动");
}
break;
case FIRST_BRAKE:
normalBrake(0);
if (dist < DIST_LEVEL[1]) {
state = SECOND_BRAKE;
Serial.println("进入二级制动");
}
break;
case SECOND_BRAKE:
normalBrake(1);
if (dist < DIST_LEVEL[2]) {
state = THIRD_BRAKE;
Serial.println("进入三级制动");
}
break;
case THIRD_BRAKE:
normalBrake(2);
if (dist < 15) {
state = PARKING;
Serial.println("进入停靠阶段");
}
break;
case PARKING:
// 缓慢降速到0,平滑停靠
currentSpeed = max(currentSpeed - 10, 0);
applyMotor(currentSpeed, HIGH);
if (currentSpeed == 0) {
digitalWrite(BRK_PIN, LOW); // 锁定制动
digitalWrite(LED_GREEN, LOW);
Serial.println("停靠完成");
}
break;
}
delay(15);
}
// 检测紧急避障,触发急停
void checkEmergency() {
bool obs = digitalRead(IR_AVOID) == HIGH;
if (obs) {
emergencyFlag = true;
mode = EMERGENCY_STOP;
Serial.println("检测到紧急障碍,触发应急制动");
} else {
emergencyFlag = false;
}
}
// 正常分级制动,逐级降速
void normalBrake(int level) {
int target = SPEED_SET[level];
// 线性缓降,避免速度突变
if (currentSpeed > target) {
currentSpeed -= (level + 2); // 制动强度随等级提升
}
applyMotor(currentSpeed, HIGH);
digitalWrite(LED_GREEN, currentSpeed > 0 ? HIGH : LOW);
}
// 应急急停
void emergencyStop() {
// 快速降速,切断动力并启用制动
currentSpeed = max(currentSpeed - 30, 0);
applyMotor(currentSpeed, LOW); // 方向拉低,辅助减速
digitalWrite(LED_RED, HIGH);
if (currentSpeed == 0) {
digitalWrite(BRK_PIN, LOW); // 锁定位置
}
}
// 读取距离值
uint16_t readDistance() {
uint16_t raw = analogRead(DIST_SENSOR);
return map(raw, 0, 1023, 0, 500); // 映射为0-500cm
}
// 驱动电机
void applyMotor(uint8_t spd, bool dir) {
digitalWrite(DIR_PIN, dir);
analogWrite(PWM_PIN, spd);
}
适用场景优化
增加场景识别,根据场景类型(空旷/狭窄)调整制动阈值,适配不同地形
优化应急恢复机制,加入速度平滑过渡,避免急停后重启的冲击
加入速度上限动态调整,狭窄区域提前降速,减少紧急制动触发概率
6、重载机器人三级制动与防溜坡控制程序(核心:重载平稳制动)
适用场景:重载搬运、坡地作业机器人,重载条件下实现平稳制动,同时防止停靠后溜坡,保障作业安全。#### 核心逻辑
结合负载参数,调整三级制动的减速速率,避免重载惯性导致的制动不足
三级制动后,启用反扭矩与硬件制动双重锁定,防止溜坡
制动过程中实时监控速度,异常时自动升级制动等级
// 重载机器人三级制动+防溜坡控制程序
// 硬件:BLDC、编码器、倾角传感器、负载检测、硬件制动器
// 功能:重载分级制动,速度自适应调节,溜坡防护,安全停靠
#include <Arduino.h>
// ========== 硬件定义 ==========
const byte PWM_PIN = 9, DIR_PIN = 8, BRK_PIN = 7;
const byte ENC_PIN = 2;
const byte ANGLE_PIN = A0; // 倾角传感器
const byte LOAD_PIN = A1; // 负载检测(压力传感器)
// ========== 制动参数 ==========
enum BrakeStage { CRUISE, B1, B2, B3, LOCKED };
BrakeStage stage = CRUISE;
// 距离阈值(根据负载动态调整,此处简化)
const int DIST_T[3] = {300, 150, 60};
// 基础速度与负载系数
const uint8_t BASE_SPD = 180;
uint8_t loadFactor = 100; // 负载系数,0-100,越大负载越重
int targetSpeed[3] = {160, 90, 40}; // 三级目标速度(可随负载调整)
int currentSpeed = 0;
float pitchAngle = 0; // 坡度角度
bool slopeFlag = false; // 是否存在坡度
// ========== 函数声明 ==========
void calcLoadFactor();
float readAngle();
void slopeProtection();
void heavyBrake(int level);
void setup() {
Serial.begin(115200);
Serial.println("重载制动系统启动");
pinMode(PWM_PIN, OUTPUT);
pinMode(DIR_PIN, OUTPUT);
pinMode(BRK_PIN, OUTPUT);
pinMode(LOAD_PIN, INPUT);
pinMode(ANGLE_PIN, INPUT);
digitalWrite(BRK_PIN, HIGH);
}
void loop() {
calcLoadFactor(); // 1. 读取负载,计算系数
float angle = readAngle(); // 2. 读取坡度 pitchAngle = angle;
slopeFlag = (angle > 3.0f); // 坡度大于3°判定为坡地
static int dist = 400;
if (dist > 0) dist--; // 模拟距离递减
// 3. 状态机:分级制动
switch (stage) {
case CRUISE:
// 巡航阶段,坡地适度降速
int cruiseSpd = BASE_SPEED - loadFactor / 20;
cruiseSpd = constrain(cruiseSpd, 120, BASE_SPEED);
currentSpeed = cruiseSpd;
applyMotor(currentSpeed, HIGH);
if (dist < DIST_T[0]) {
stage = B1;
Serial.println("重载一级制动启动");
}
break;
case B1:
heavyBrake(0);
if (dist < DIST_T[1]) {
stage = B2;
Serial.println("重载二级制动启动");
}
break;
case B2:
heavyBrake(1);
if (dist < DIST_T[2]) {
stage = B3;
Serial.println("重载三级制动启动");
}
break;
case B3:
heavyBrake(2);
if (dist < 20) { // 接近终点
stage = LOCKED;
Serial.println("进入锁停阶段");
}
break;
case LOCKED:
// 低速滑行至停,坡地加大制动力
if (slopeFlag) {
currentSpeed = max(currentSpeed - 15, 0);
applyMotor(currentSpeed, LOW); // 反扭矩制动
} else {
currentSpeed = max(currentSpeed - 8, 0);
applyMotor(currentSpeed, HIGH);
}
slopeProtection(); // 溜坡监测
if (currentSpeed == 0) {
digitalWrite(BRK_PIN, LOW); // 启用硬件锁定
Serial.println("重载制动完成,已锁定,防溜坡生效");
}
break;
}
Serial.print("负载:");Serial.print(loadFactor);Serial.print("°坡度:");Serial.print(pitchAngle);
Serial.print(" 当前速度:");Serial.println(currentSpeed);
delay(20);
}
// 计算负载系数
void calcLoadFactor() {
uint16_t loadRaw = analogRead(LOAD_PIN);
loadFactor = map(loadRaw, 0, 1023, 30, 100); // 映射为30-100
}
// 读取坡度角度(简化,直接读取电压映射)
float readAngle() {
uint16_t raw = analogRead(ANGLE_PIN);
return (raw - 512) * 0.1f; // 转换为角度,±50°
}
// 重载分级制动,根据负载调整减速速率
void heavyBrake(int level) {
// 负载越大,降速越慢,避免惯性冲击
int decRate = 5 + (100 - loadFactor) * (level + 1) / 10;
if (currentSpeed > targetSpeed[level]) {
currentSpeed -= decRate;
currentSpeed = constrain(currentSpeed, targetSpeed[level], 255);
}
// 坡地额外增加制动力
if (slopeFlag) {
currentSpeed -= 3;
}
applyMotor(currentSpeed, level >= 1 ? HIGH : LOW);
}
// 溜坡防护:检测到位置偏移或速度反弹,立即锁死制动
void slopeProtection() {
// 简化逻辑:速度为0时,若坡度存在,立即锁死
if (currentSpeed == 0 && slopeFlag) {
digitalWrite(BRK_PIN, LOW);
Serial.print("检测到坡度,已锁死制动防溜坡,角度:"); Serial.println(pitchAngle);
}
}
// 驱动电机
void applyMotor(int spd, bool dir) {
spd = constrain(spd, 0, 255);
digitalWrite(DIR_PIN, dir);
analogWrite(PWM_PIN, spd);
}
适用场景优化
增加编码器实时反馈,精准计算实际速度与位移,提升制动精度
优化负载检测精度,多传感器融合判断负载等级,适配不同重载场景
加入溜坡预警,检测到轻微位移时提前加大制动力,进一步降低溜坡风险
要点解读
要点1:三级制动区间需“按负载与路径精准划分”,奠定平稳基础
制动区间的合理划分是平稳分级的前提,需结合工况动态适配。
距离层级匹配:根据作业总距离、速度合理划分三级制动区间,一级制动负责大幅降速,二级负责精细调速,三级负责精准停靠,各区间互补覆盖
负载自适应调整:重载机器人需延长制动区间、降低目标速度,预留足够减速距离,匹配大惯性特性,避免制动不足
场景差异化设定:平坦路面制动区间紧凑,坡地作业延长制动距离、提升低等级制动力,适配不同地形的制动需求,保障基础平稳性
要点2:状态机切换需“平滑过渡无跳变”,避免速度冲击
状态机的平滑切换直接决定制动的连贯性,需优化过渡逻辑。
状态触发阈值精确:一级、二级、三级制动的触发距离精准设置,避免区间交叉或间隔过大,确保制动无间隙、不突兀- 速度缓变控制:阶段切换时采用线性插值、限幅降速,避免速度突变,通过PID算法快速且平滑地逼近目标速度,降低切换冲击
状态锁定机制:每个状态设置执行阈值,未达标不切换,如三级制动需将速度降至预设范围再进入停靠,保障过渡连贯
要点3:制动力需“分级量化+动态补偿”,匹配不同制动阶段
制动强度的精准控制是分级制动的核心,需分阶段量化与补偿。
制动强度分级:一级制动减速平缓,二级适中,三级精准微调,逐级提升制动强度,遵循“先缓后微”的原则,实现平稳降速
环境动态补偿:坡地、重载、强风等场景下,提升低等级制动力,或增加反向扭矩补偿,抵消惯性、重力、外力的影响
执行器协同控制:结合PWM调速与硬件制动,三级制动后期启用硬件制动辅助,最后锁定位置,既保证平稳又实现可靠停靠
要点4:传感器反馈需“实时精准”,支撑闭环控制
实时准确的数据反馈是闭环制动的关键,直接影响制动精度。
多传感器融合:融合编码器(速度)、距离传感器(位置)、倾角传感器(坡度)、负载传感器(重量),全面感知机器人状态,为制动提供多维度数据支撑
数据快速采样:缩短传感器采样周期,一般控制在15-20ms,实时捕捉速度、距离变化,及时调整制动力,避免滞后
数据滤波优化:对传感器数据进行中值、均值滤波,过滤噪声干扰,避免异常数据导致制动误判,提升制动稳定性
要点5:安全防护需“全覆盖”,保障制动过程与停靠稳定
制动系统需兼顾过程安全与停靠安全,设置多重防护机制。
应急制动兜底:设置独立紧急制动通道,遇障碍或系统异常时触发急停,跳过分级直接锁定,保障安全优先级最高
防溜坡保护:重载、坡地场景停靠后,启用硬件制动锁定+反扭矩保持,监测到溜坡趋势立即加大制动力,防止装甲移位
故障自检与异常处理:检测到传感器失效、电机堵转、制动力不足等异常,自动切断动力并锁死制动,记录故障信息,避免危险发生,适配复杂工况的稳定运行要求
请注意:以上案例仅作为思路拓展的参考示例,不保证完全正确、适配所有场景或可直接编译运行。由于硬件平台、实际使用场景、Arduino 版本的差异,均可能影响代码的适配性与使用方法的选择。在实际编程开发时,请务必根据自身硬件配置、使用场景及具体功能需求进行针对性调整,并通过多次实测验证效果;同时需确保硬件接线正确,充分了解所用传感器、执行器等设备的技术规范与核心特性。对于涉及硬件操作的代码,使用前务必核对引脚定义、电平参数等关键信息的准确性与安全性,避免因参数错误导致硬件损坏或运行异常。

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


所有评论(0)