跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

Arduino BLDC 超声波与 PID 控制跟随机器人实战

基于 Arduino 的 BLDC 电机跟随机器人项目,通过超声波传感器采集环境数据,利用 PID 算法解算运动指令。内容涵盖三角测量感知逻辑、双环串级控制架构、多场景应用及核心代码实现。重点解析传感器抗干扰设计、PID 参数整定技巧与电源隔离方案,提供从单点跟随到自适应控制的完整工程参考。

栈溢出发布于 2026/3/28更新于 2026/6/1619 浏览
Arduino BLDC 超声波与 PID 控制跟随机器人实战

Arduino BLDC 超声波与 PID 控制跟随机器人实战

基于 Arduino 的无刷直流电机(BLDC)跟随机器人,是自动控制理论与现代驱动技术结合的典型项目。系统通过超声波传感器获取环境距离信息,利用 PID 算法实时解算运动指令,由 Arduino 驱动 BLDC 电机执行,实现对目标物体的稳定、平滑跟随。

系统特性

感知架构:三角测量与单发双收

这是实现'定向'跟随而非'盲目'避障的核心逻辑。系统通常采用一个手持式超声波发射模块和两个安装在机器人前端左右两侧的接收模块(单发双收)。这种布局构成了一个简单的三角形测量系统。当目标正对机器人时,左右两个接收模块测得的距离相等,系统可精确判断目标的偏航角度,从而实现方向控制。

控制策略:双环 PID 串级控制

为了实现平稳的跟随效果,系统采用速度环(内环)与方向环(外环)的串级 PID 控制结构。

  • 方向环(外环):以左右超声波距离差为输入,通过 PD 或 PID 算法计算出所需的转向角速度(或左右轮速差),负责消除方向偏差,使机器人对准目标。
  • 速度环(内环):以当前与目标的距离为输入,调节整体行进速度。

动力响应:BLDC 电机优势

相较于传统有刷电机,BLDC 电机为跟随机器人的动态响应和续航提供了坚实基础。

  • 快速动态响应:高扭矩密度和快速的电磁时间常数,能迅速响应 PID 控制器发出的频繁加减速和转向指令,轨迹平滑无滞后。
  • 长续航与低维护:无电刷磨损,效率高,发热量小,配合电子调速器(ESC)的高效驱动,适合长时间连续作业。

图片

典型应用场景

  • 智能行李箱与随行载具:在机场、车站或校园中,机器人底盘可作为智能行李车,自动跟随主人身后,解放双手。超声波方案成本低廉,且不受光线条件影响,适合室内外通用。
  • 农业辅助与物料搬运:在农场或仓库,工人可以利用该机器人搬运工具或货物。通过简单的手持发射器,机器人能稳定地跟在工人身后,适应复杂的地形和环境变化。
  • 教育与创客实践平台:作为高校《自动控制原理》、《传感器技术》和《机电一体化》课程的经典实验项目,学生可以通过搭建该系统,直观理解三角测量原理、PID 参数整定方法以及 BLDC 电机的控制特性。
  • 展厅导览与广告跟随:在大型展会中,机器人可以搭载广告屏或展品,自动跟随讲解员移动,确保观众始终能清晰地看到展示内容,提升互动体验。

工程实践建议

传感器选型与安装

  • 抗干扰设计:超声波传感器易受环境温度、湿度及气流影响,且多个超声波模块同时工作时可能产生串扰。建议在软件中加入时间片轮询机制或频率编码技术,并对采样数据进行滑动平均滤波或卡尔曼滤波,以剔除异常值。
  • 安装位置:两个接收探头之间的基线距离应尽可能长(在结构允许范围内),以提高角度测量的分辨率。同时,探头应安装在机器人前端较高位置,避免地面反射干扰。

PID 参数整定与系统稳定性

  • 积分饱和(Integral Windup):在跟随过程中,若机器人因障碍物或机械卡死无法到达目标位置,积分项会持续累积,导致解除卡死后机器人疯狂加速。必须加入积分限幅或积分分离策略。
  • 微分项噪声:微分项对测量噪声敏感,容易引起电机抖动。可以适当降低微分增益,或在微分环节前加入一阶低通滤波器。
  • 采样周期一致性:PID 控制的稳定性高度依赖于固定的控制周期。必须使用硬件定时器中断来触发 PID 计算,严禁使用 delay() 函数导致控制周期抖动。

电机驱动与电源管理

  • 驱动器匹配:Arduino 的 IO 口无法直接驱动 BLDC 电机,必须通过电子调速器(ESC)。需确保 ESC 支持所需的通信协议(如 DShot、PWM),并正确配置其刹车和响应参数。
  • 电源隔离:大电流的电机回路会产生电压波动,容易导致 Arduino 复位。建议使用独立的稳压模块(如 LM2596)为逻辑电路和电机电路分别供电,并共地处理。

代码实现示例

以下代码展示了不同场景下的核心逻辑,实际使用时请根据硬件引脚调整。

1. 单点超声波基本跟随

场景:固定跟随一个移动目标,保持设定距离。核心逻辑:超声波测距 + 单路 PID 速度控制。

#include <SimpleFOC.h>
#include <NewPing.h>
#include <PID_v1.h>

#define TRIG_PIN 9
#define ECHO_PIN 10
#define MAX_DISTANCE 200

NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DISTANCE);

// BLDC 电机对象
BLDCMotor motorL(11);
BLDCMotor motorR(11);

// PID 参数
double setpoint = 30.0; // 目标跟随距离:30cm
double input, output;
double Kp = 0.5, Ki = 0.1, Kd = 0.05;
PID myPID(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);

void setup() {
  Serial.begin(115200);
  // 初始化 PID
  myPID.SetMode(AUTOMATIC);
  myPID.SetOutputLimits(-0.5, 0.5); // 输出限制在 -0.5~0.5
  
  // 电机初始化
  motorL.init();
  motorR.init();
  motorL.initFOC();
  motorR.initFOC();
}

void loop() {
  // 1. 超声波测距
  input = sonar.ping_cm();
  if (input == 0) input = 100; // 无信号时设为远距离

  // 2. PID 计算输出
  myPID.Compute();

  // 3. 根据 PID 输出控制电机
  // output 为正:向前追赶;为负:后退拉开
  float speedL = 0.2 + output;
  float speedR = 0.2 + output;

  // 4. 输出限制
  speedL = constrain(speedL, -0.5, 0.5);
  speedR = constrain(speedR, -0.5, 0.5);
  
  motorL.move(speedL);
  motorR.move(speedR);
  motorL.loopFOC();
  motorR.loopFOC();
  
  Serial.print("Distance:");
  Serial.print(input);
  Serial.print(" PIDout:");
  Serial.println(output);
}

2. 双超声波差速转向跟随

场景:不仅能前后跟随,还能在目标横向移动时自动转向。核心逻辑:左右双超声波 + 双路 PID(距离 PID + 角度 PID)。

#include <SimpleFOC.h>
#include <NewPing.h>
#include <PID_v1.h>

#define SONAR_L_TRIG 2
#define SONAR_L_ECHO 3
#define SONAR_R_TRIG 4
#define SONAR_R_ECHO 5

NewPing sonarL(SONAR_L_TRIG, SONAR_L_ECHO, 200);
NewPing sonarR(SONAR_R_TRIG, SONAR_R_ECHO, 200);

BLDCMotor motorL(11);
BLDCMotor motorR(11);

// 双路 PID:距离控制和角度控制
double setpointDist = 30.0, setpointAngle = 0.0;
double distInput, distOutput, angleInput, angleOutput;
PID pidDist(&distInput, &distOutput, &setpointDist, 0.4, 0.05, 0.02, DIRECT);
PID pidAngle(&angleInput, &angleOutput, &setpointAngle, 0.3, 0.01, 0.01, DIRECT);

void setup() {
  Serial.begin(115200);
  // 初始化 PID
  pidDist.SetMode(AUTOMATIC);
  pidDist.SetOutputLimits(-0.4, 0.4);
  pidAngle.SetMode(AUTOMATIC);
  pidAngle.SetOutputLimits(-0.3, 0.3);
  
  // 电机初始化
  motorL.init();
  motorR.init();
  motorL.initFOC();
  motorR.initFOC();
}

void loop() {
  // 1. 读取左右距离
  float distL = sonarL.ping_cm();
  float distR = sonarR.ping_cm();
  if (distL == 0) distL = 100;
  if (distR == 0) distR = 100;

  // 2. 计算距离输入(平均距离)和角度输入(距离差)
  distInput = (distL + distR) / 2.0;
  angleInput = distL - distR; // 正值为目标偏左

  // 3. 计算 PID 输出
  pidDist.Compute();
  pidAngle.Compute();

  // 4. 混合控制:差速转向
  // 左轮速度 = 距离控制 + 角度控制
  // 右轮速度 = 距离控制 - 角度控制
  float speedL = 0.2 + distOutput + angleOutput;
  float speedR = 0.2 + distOutput - angleOutput;

  // 5. 限幅
  speedL = constrain(speedL, -0.6, 0.6);
  speedR = constrain(speedR, -0.6, 0.6);
  
  motorL.move(speedL);
  motorR.move(speedR);
  motorL.loopFOC();
  motorR.loopFOC();
}

3. 自适应 PID 跟随(带死区与饱和保护)

场景:工业级应用,加入非线性处理和异常保护。核心逻辑:死区控制 + PID 自适应 + 安全保护。

#include <SimpleFOC.h>
#include <NewPing.h>
#include <PID_v1.h>

// ... 引脚定义与案例一类似
double setpoint = 30.0;
double input, output;
PID myPID(&input, &output, &setpoint, 0.5, 0.1, 0.05, DIRECT);

// 自适应参数
float errorDeadZone = 2.0; // 死区±2cm
float errorThreshold = 20.0; // 误差超过 20cm 时启用强 PID
float maxSpeed = 0.4;

void setup() {
  // 初始化...
  myPID.SetMode(AUTOMATIC);
  myPID.SetOutputLimits(-maxSpeed, maxSpeed);
}

void loop() {
  input = sonar.ping_cm();
  if (input == 0) { safetyStop(); return; }
  
  float error = input - setpoint;

  // 1. 死区控制:误差在死区内不调节
  if (abs(error) < errorDeadZone) {
    motorL.move(0);
    motorR.move(0);
    return;
  }

  // 2. 自适应 PID:大误差时增强 P 项
  if (abs(error) > errorThreshold) {
    myPID.SetTunings(1.0, 0.0, 0.0); // 纯 P 控制
  } else {
    myPID.SetTunings(0.5, 0.1, 0.05); // 正常 PID
  }

  // 3. PID 计算
  myPID.Compute();

  // 4. 前馈补偿
  float feedForward = 0.0;
  if (error > 0) feedForward = 0.1; // 距离过远,给予基础前向速度
  
  float speedL = output + feedForward;
  float speedR = output + feedForward;

  // 5. 软限制
  speedL = constrain(speedL, -0.5, 0.5);
  speedR = constrain(speedR, -0.5, 0.5);
  
  motorL.move(speedL);
  motorR.move(speedR);
  motorL.loopFOC();
  motorR.loopFOC();
}

void safetyStop() {
  // 软停止
  static float speedL = 0, speedR = 0;
  speedL *= 0.9;
  speedR *= 0.9;
  motorL.move(speedL);
  motorR.move(speedR);
}

关键要点解读

超声波传感器的局限与应对

回波干扰在狭小空间或面对吸音材料时可能发生。代码中应加入有效性校验,连续多次无效读数时紧急停车。此外,超声波锥形波束(约 15°)可能同时检测到障碍物和目标,双超声波方案可提供简单的横向定位,避免目标偏离中线时机器人'视而不见'。

PID 控制的三重调校

  • P(比例):决定响应速度。P 值过小会导致跟随迟缓,过大则会在目标距离附近震荡。
  • I(积分):消除稳态误差。如果机器人最终停在 32cm 而非 30cm,需增加 Ki。但 I 值过大会导致'积分饱和',响应滞后。
  • D(微分):抑制超调。当目标突然靠近,微分项可提前减速。案例三的自适应 PID 在大误差时切为纯 P 控制,避免积分项累积造成危险。

'差速转向'是实现横向跟随的关键

angleInput = distL - distR 是核心。当目标偏左时,左声纳距离更近,angleInput 为负,pidAngle 输出负值,使左轮减速、右轮加速,从而实现转向。这种双 PID 混控是轮式机器人跟踪移动目标的经典方案。

非线性的必要处理

  • 死区(Dead Zone):如案例三,±2cm 内不响应,避免机器人在目标距离附近'抽搐'。这是节省能量、减少机械磨损的关键。
  • 输出限幅:PID 输出必须限制在电机安全范围内。案例一通过 SetOutputLimits() 限制,案例三通过 constrain() 实现平滑限幅,避免急启急停。

BLDC 闭环控制是精度保障

使用 analogWrite() 的开环控制,负载变化时速度会漂移,导致跟随距离波动。采用 SimpleFOC 库的闭环控制,电机速度严格跟随 motor.move() 的指令,这是 PID 算法能稳定工作的基础。编码器反馈的实时速度信息还可用于速度前馈,进一步提升响应。

图片

其他参考方案

4. 超声波跟随小车(单传感器避障跟随)

适用于基础入门,核心在于 PWM 映射与基础 PID。

#include <NewPing.h>
#include <PID_v1.h>

#define TRIG_PIN 12
#define ECHO_PIN 11
#define MAX_DISTANCE 200

NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DISTANCE);
double setpoint = 30.0;
double input, output;
PID myPID(&input, &output, &setpoint, 2.0, 5.0, 1.0, DIRECT);

const int motorL_PWM = 5;
const int motorR_PWM = 6;

void setup() {
  Serial.begin(9600);
  myPID.SetMode(AUTOMATIC);
  pinMode(motorL_PWM, OUTPUT);
  pinMode(motorR_PWM, OUTPUT);
}

void loop() {
  input = sonar.ping_cm();
  if (input == 0) input = MAX_DISTANCE;
  
  myPID.Compute();
  
  int speed = constrain(output, -255, 255);
  if (speed > 0) {
    analogWrite(motorL_PWM, speed);
    analogWrite(motorR_PWM, speed);
  } else {
    analogWrite(motorL_PWM, 0);
    analogWrite(motorR_PWM, 0);
  }
  
  Serial.print("Distance: ");
  Serial.print(input);
  Serial.print(" -> Speed: ");
  Serial.println(speed);
  delay(50);
}

5. 双超声波传感器差速跟随

通过左右轮速度差实现转向,需确保电机极性一致。

#include <NewPing.h>
#include <PID_v1.h>

#define LEFT_TRIG 12
#define LEFT_ECHO 11
#define RIGHT_TRIG 10
#define RIGHT_ECHO 9
#define MAX_DISTANCE 100

NewPing leftSonar(LEFT_TRIG, LEFT_ECHO, MAX_DISTANCE);
NewPing rightSonar(RIGHT_TRIG, RIGHT_ECHO, MAX_DISTANCE);

double leftDist, rightDist, error, output;
PID myPID(&error, &output, &setpoint, 1.5, 0.1, 0.5, DIRECT);

const int motorL_PWM = 5;
const int motorR_PWM = 6;
const int baseSpeed = 150;

void setup() {
  Serial.begin(9600);
  myPID.SetMode(AUTOMATIC);
  pinMode(motorL_PWM, OUTPUT);
  pinMode(motorR_PWM, OUTPUT);
}

void loop() {
  leftDist = leftSonar.ping_cm();
  rightDist = rightSonar.ping_cm();
  if (leftDist == 0) leftDist = MAX_DISTANCE;
  if (rightDist == 0) rightDist = MAX_DISTANCE;
  
  error = leftDist - rightDist;
  myPID.Compute();
  
  int leftSpeed = constrain(baseSpeed - output, 0, 255);
  int rightSpeed = constrain(baseSpeed + output, 0, 255);
  
  analogWrite(motorL_PWM, leftSpeed);
  analogWrite(motorR_PWM, rightSpeed);
  
  Serial.print("Left: ");
  Serial.print(leftDist);
  Serial.print(" Right: ");
  Serial.print(rightDist);
  Serial.print(" -> L/R Speed: ");
  Serial.print(leftSpeed);
  Serial.print("/");
  Serial.println(rightSpeed);
  delay(50);
}

6. 带速度限制的智能跟随

根据距离动态调整基础速度,提升跟随平滑性。

#include <NewPing.h>
#include <PID_v1.h>

#define TRIG_PIN 12
#define ECHO_PIN 11
#define MAX_DISTANCE 150

NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DISTANCE);
double setpoint = 40.0;
double input, output;
PID myPID(&input, &output, &setpoint, 1.8, 0.5, 0.2, DIRECT);

const int motorL_PWM = 5;
const int motorR_PWM = 6;
const int maxSpeed = 200;

void setup() {
  Serial.begin(9600);
  myPID.SetMode(AUTOMATIC);
  myPID.SetOutputLimits(-maxSpeed, maxSpeed);
  pinMode(motorL_PWM, OUTPUT);
  pinMode(motorR_PWM, OUTPUT);
}

void loop() {
  input = sonar.ping_cm();
  if (input == 0) input = MAX_DISTANCE;
  
  myPID.Compute();
  
  int baseSpeed = map(constrain(input, 20, 100), 20, 100, 80, 200);
  int leftSpeed = baseSpeed + output;
  int rightSpeed = baseSpeed - output;
  
  leftSpeed = constrain(leftSpeed, 0, maxSpeed);
  rightSpeed = constrain(rightSpeed, 0, maxSpeed);
  
  analogWrite(motorL_PWM, leftSpeed);
  analogWrite(motorR_PWM, rightSpeed);
  
  Serial.print("Distance: ");
  Serial.print(input);
  Serial.print(" -> L/R Speed: ");
  Serial.print(leftSpeed);
  Serial.print("/");
  Serial.println(rightSpeed);
  delay(30);
}

以上案例仅供参考,实际编程时需根据自己的硬件配置、使用场景和具体需求进行调整。涉及硬件操作的代码,要在使用前确认引脚和电平等参数的正确性和安全性。

目录

  1. Arduino BLDC 超声波与 PID 控制跟随机器人实战
  2. 系统特性
  3. 感知架构:三角测量与单发双收
  4. 控制策略:双环 PID 串级控制
  5. 动力响应:BLDC 电机优势
  6. 典型应用场景
  7. 工程实践建议
  8. 传感器选型与安装
  9. PID 参数整定与系统稳定性
  10. 电机驱动与电源管理
  11. 代码实现示例
  12. 1. 单点超声波基本跟随
  13. 2. 双超声波差速转向跟随
  14. 3. 自适应 PID 跟随(带死区与饱和保护)
  15. 关键要点解读
  16. 超声波传感器的局限与应对
  17. PID 控制的三重调校
  18. “差速转向”是实现横向跟随的关键
  19. 非线性的必要处理
  20. BLDC 闭环控制是精度保障
  21. 其他参考方案
  22. 4. 超声波跟随小车(单传感器避障跟随)
  23. 5. 双超声波传感器差速跟随
  24. 6. 带速度限制的智能跟随
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Arduino BLDC 机器人 IMU 角度读取与 PID 互补滤波控制
  • Python Pandas 库超详细教程
  • ESP32 + 大功率双向 ESC 机器人底盘动力控制方案
  • Python 基础语法入门:顺序、条件与循环
  • ESP32 + MimiClaw 组合机器人 BLDC 驱动与智能控制方案
  • Jetson 平台 OpenClaw 联动 Ollama 与 llama.cpp 部署大模型
  • ESP32 结合 MimiClaw 的 BLDC 无刷电机控制与本地智能机器人方案
  • Arduino BLDC 驱动方案:MimiClaw + ESP32 嵌入式机器人实战
  • HUSKYLENS 2 AI 相机视觉传感器识别条形码输出数据
  • 拆解 DDSM400 伺服轮毂电机:结构原理与选型实战
  • 前端面试亮点:微前端架构实战与原理深度解析
  • 基于 SSM 框架的儿童物品置换网站设计与实现
  • Python 数据清洗实战:缺失值、异常值与特征工程
  • PostgreSQL PostGIS 安装配置及现有数据库启用方法
  • 无人机 AI 算法全景图:7 大场景 50+ 算法详解
  • 基于 Leaflet Trackplayer 的 WebGIS 高速轨迹可视化实战
  • 基于 Leaflet-Trackplayer 的 WebGIS 高速轨迹可视化实战
  • MixAIHub 提供 ChatGPT Claude Sora 等 AI 官网镜像服务
  • Xilinx 7 系列 FPGA 收发器架构与时钟设计
  • 基于 Leaflet Trackplayer 的高速公路轨迹 WebGIS 可视化

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online