在这里插入图片描述

基于模糊逻辑的Arduino BLDC避障机器人是一种不依赖精确数学模型,而是利用人类驾驶经验(语言规则)来实现复杂环境下智能导航的控制系统。
一、 主要特点
•鲁棒性强:面对未知或不确定的复杂环境(如光照变化、地面纹理),系统表现稳定。
•无需精确建模:不需要建立繁琐的环境数学模型,通过设定“如果…那么…”规则即可控制。
•非线性与适应性:能很好地处理传感器数据与环境反应之间的非线性关系,适应动态障碍。
•实时性高:算法计算量相对较小,适合Arduino等微控制器进行快速决策。

二、 应用场景
•智能仓储AGV:在货架林立、人员走动的非结构化仓库中自主避障运输。
•家庭服务机器人:在家具布局复杂、存在宠物或儿童的室内环境中安全导航。
•野外勘探机器人:适应崎岖、非结构化地形,避开石块或坑洼。
•动态密集环境:如商场、医院等人群密集且移动轨迹不可预测的场所。

三、 注意事项
•规则库设计:模糊规则的质量和数量直接决定避障效果,需结合实际场景反复调试。
•传感器布局:需合理配置超声波或红外传感器的数量与角度,消除探测盲区。
•计算资源限制:Arduino内存和处理能力有限,需优化模糊算法代码,防止控制周期过长。
•电机响应匹配:BLDC电机的高转速特性要求模糊控制器输出的动态响应必须精准,避免震荡。

在这里插入图片描述
1、未知静态环境自主探索机器人(废墟搜救模拟)
场景说明:针对废墟、洞穴等无预设地图的未知环境,机器人需自动避障并生成探索路径,实现区域覆盖。硬件配置为Arduino Mega 2560、L298N驱动板、超声波传感器HC-SR04(3路环形分布)、12V BLDC减速电机。

#include <FuzzyLogic.h>  // 模糊逻辑核心库(需提前安装Arduino Fuzzy Logic库)

// 硬件引脚定义
#define TRIG_LEFT 9    // 左超声波触发引脚
#define ECHO_LEFT 10   // 左超声波回响引脚
#define TRIG_FRONT 11  // 前方超声波触发引脚
#define ECHO_FRONT 12  // 前方超声波回响引脚
#define TRIG_RIGHT 13  // 右超声波触发引脚
#define ECHO_RIGHT 14  // 右超声波回响引脚
#define IN1 2          // BLDC左电机正转引脚
#define IN2 3          // BLDC左电机反转引脚
#define IN3 4          // BLDC右电机正转引脚
#define IN4 5          // BLDC右电机反转引脚
#define PWM_LEFT 6     // 左电机PWM调速引脚
#define PWM_RIGHT 7    // 右电机PWM调速引脚

// 模糊输入输出变量定义(核心:将距离、转向需求转化为模糊量)
FuzzyVariable distanceFront;  // 前方障碍物距离
FuzzyVariable distanceLeft;   // 左侧障碍物距离
FuzzyVariable distanceRight;  // 右侧障碍物距离
FuzzyVariable turnAngle;      // 转向角度

// 隶属度函数:将0-200cm的距离划分为"Near"(近)、"Medium"(中)、"Far"(远)
void setupDistanceMembership() {
  distanceFront.addTerm("Near", 0, 50, 100);      // 0-100cm为近,隶属度线性下降
  distanceFront.addTerm("Medium", 50, 100, 150);  // 50-150cm为中,峰值100cm
  distanceFront.addTerm("Far", 100, 200, 200);     // 100cm以上为远,隶属度线性上升
  
  distanceLeft.addTerm("Near", 0, 50, 100);
  distanceLeft.addTerm("Medium", 50, 100, 150);
  distanceLeft.addTerm("Far", 100, 200, 200);
  
  distanceRight.addTerm("Near", 0, 50, 100);
  distanceRight.addTerm("Medium", 50, 100, 150);
  distanceRight.addTerm("Far", 100, 200, 200);
  
  // 转向角度:-90°(左转最大)、0°(直行)、90°(右转最大),隶属度函数为三角型
  turnAngle.addTerm("LeftMax", -90, -45, 0);
  turnAngle.addTerm("Left", -45, -22.5, 0);
  turnAngle.addTerm("Straight", -22.5, 0, 22.5);
  turnAngle.addTerm("Right", 0, 22.5, 45);
  turnAngle.addTerm("RightMax", 0, 45, 90);
}

// 模糊规则库:根据距离输入制定转向规则
FuzzyRuleSet ruleSet;
void setupRules() {
  // 核心规则:前方近需避障,侧方近决定转向方向,前方远可直行
  ruleSet.addRule("(distanceFront == Near) && (distanceLeft == Far)", "turnAngle == RightMax");
  ruleSet.addRule("(distanceFront == Near) && (distanceRight == Far)", "turnAngle == LeftMax");
  ruleSet.addRule("(distanceFront == Near) && (distanceLeft == Medium) && (distanceRight == Medium)", "turnAngle == Right");
  ruleSet.addRule("(distanceFront == Medium) && (distanceLeft == Far) && (distanceRight == Far)", "turnAngle == Straight");
  ruleSet.addRule("(distanceFront == Medium) && (distanceLeft == Medium) && (distanceRight == Far)", "turnAngle == Left");
  ruleSet.addRule("(distanceFront == Medium) && (distanceLeft == Far) && (distanceRight == Medium)", "turnAngle == Right");
}

// 硬件初始化
void setup() {
  pinMode(TRIG_LEFT, OUTPUT); pinMode(ECHO_LEFT, INPUT);
  pinMode(TRIG_FRONT, OUTPUT); pinMode(ECHO_FRONT, INPUT);
  pinMode(TRIG_RIGHT, OUTPUT); pinMode(ECHO_RIGHT, INPUT);
  pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT);
  pinMode(PWM_LEFT, OUTPUT); pinMode(PWM_RIGHT, OUTPUT);
  
  Serial.begin(9600);
  setupDistanceMembership();
  setupRules();
  
  analogWrite(PWM_LEFT, 150);  // 初始基础转速(PWM范围0-255,对应0-100%占空比)
  analogWrite(PWM_RIGHT, 150);
}

// 超声波测距函数(单位:cm)
int getDistance(int trigPin, int echoPin) {
  long duration = pulseIn(echoPin, HIGH);
  return duration * 0.0343 / 2;  // 声速343m/s,转换为cm
}

// 模糊推理主逻辑
void fuzzyObstacleAvoidance() {
  int frontDist = getDistance(TRIG_FRONT, ECHO_FRONT);
  int leftDist = getDistance(TRIG_LEFT, ECHO_LEFT);
  int rightDist = getDistance(TRIG_RIGHT, ECHO_RIGHT);
  
  // 输入模糊化:将实际距离映射到模糊集合
  distanceFront.setInput(frontDist);
  distanceLeft.setInput(leftDist);
  distanceRight.setInput(rightDist);
  
  // 执行模糊推理
  ruleSet.evaluate();
  
  // 输出清晰化:将模糊角度转化为具体PWM差值
  float angle = turnAngle.getOutput();
  int diff = map(angle, -90, 90, -80, 80);  // 角度映射为PWM差值
  
  // 控制BLDC电机:根据转向角度调整左右电机转速
  int leftSpeed = 150 + diff / 2;
  int rightSpeed = 150 - diff / 2;
  
  analogWrite(PWM_LEFT, constrain(leftSpeed, 50, 255));
  analogWrite(PWM_RIGHT, constrain(rightSpeed, 50, 255));
}

void loop() {
  fuzzyObstacleAvoidance();
  delay(50);  // 控制周期50ms,保证实时性
}

2、动态人流跟随避障机器人(商场/工厂场景)
场景说明:在商场、工厂等人流动态变化的场景中,机器人需跟随前方目标(人)并避开其他障碍物,硬件增加红外循迹传感器和人体红外传感器,适配动态目标追踪。

#include <FuzzyLogic.h>

// 硬件引脚定义(新增人体红外传感器和红外循迹)
#define PIR_FRONT 8   // 前方人体红外传感器
#define IR_LEFT 15    // 左红外循迹
#define IR_RIGHT 16   // 右红外循迹
// BLDC电机引脚同案例1(省略重复定义)

// 模糊变量:新增"目标距离"(跟随目标的远近)、"跟随偏角"(目标偏移方向)
FuzzyVariable targetDistance;
FuzzyVariable targetAngle;

void setupMembership() {
  // 目标距离:跟随目标0-150cm,划分为"TooClose"(过近)、"Close"(近)、"Good"(适宜)、"Far"(远)
  targetDistance.addTerm("TooClose", 0, 30, 50);
  targetDistance.addTerm("Close", 30, 50, 80);
  targetDistance.addTerm("Good", 50, 80, 120);
  targetDistance.addTerm("Far", 80, 120, 150);
  
  // 目标偏角:-60°~60°,划分为"LeftBig"(左偏大)、"Left"(左偏)、"Center"(正中)、"Right"(右偏)、"RightBig"(右偏大)
  targetAngle.addTerm("LeftBig", -60, -30, 0);
  targetAngle.addTerm("Left", -30, -15, 0);
  targetAngle.addTerm("Center", -15, 0, 15);
  targetAngle.addTerm("Right", 0, 15, 30);
  targetAngle.addTerm("RightBig", 0, 30, 60);
}

void setupFollowRules() {
  // 跟随逻辑:距离适宜时保持跟随,距离过近减速,距离过远加速;偏角决定转向
  ruleSet.addRule("(targetDistance == TooClose)", "turnAngle == Straight && speed == Low");
  ruleSet.addRule("(targetDistance == Close) && (targetAngle == Center)", "turnAngle == Straight && speed == Medium");
  ruleSet.addRule("(targetDistance == Good) && (targetAngle == Center)", "turnAngle == Straight && speed == High");
  ruleSet.addRule("(targetDistance == Far)", "turnAngle == Straight && speed == Max");
  ruleSet.addRule("(targetDistance == Good) && (targetAngle == Left)", "turnAngle == Left");
  ruleSet.addRule("(targetDistance == Good) && (targetAngle == LeftBig)", "turnAngle == LeftMax");
  ruleSet.addRule("(targetDistance == Good) && (targetAngle == Right)", "turnAngle == Right");
  ruleSet.addRule("(targetDistance == Good) && (targetAngle == RightBig)", "turnAngle == RightMax");
}

// 目标距离测量(结合超声波与人体红外触发)
int getTargetDistance() {
  if (digitalRead(PIR_FRONT) == HIGH) {  // 检测到目标
    return getDistance(TRIG_FRONT, ECHO_FRONT);
  } else {
    return 200;  // 未检测到目标,距离设为最大
  }
}

// 目标偏角计算(通过左右红外传感器差值估算)
float getTargetAngle() {
  int leftIR = analogRead(IR_LEFT);
  int rightIR = analogRead(IR_RIGHT);
  // 差值映射到偏角,差值越大偏角越大
  float diff = leftIR - rightIR;
  return map(diff, -500, 500, -60, 60);
}

void setup() {
  // 硬件初始化(新增传感器引脚)
  pinMode(PIR_FRONT, INPUT);
  pinMode(IR_LEFT, INPUT);
  pinMode(IR_RIGHT, INPUT);
  // 电机引脚初始化同案例1
  
  setupMembership();
  setupFollowRules();
  analogWrite(PWM_LEFT, 100);
  analogWrite(PWM_RIGHT, 100);
}

void loop() {
  int dist = getTargetDistance();
  float angle = getTargetAngle();
  
  // 输入模糊化
  targetDistance.setInput(dist);
  targetAngle.setInput(angle);
  
  // 模糊推理
  ruleSet.evaluate();
  
  // 输出控制:结合转向和速度
  float outAngle = turnAngle.getOutput();
  int diff = map(outAngle, -60, 60, -50, 50);
  int baseSpeed = (targetDistance.getOutput() > 80) ? 180 : (targetDistance.getOutput() < 50) ? 80 : 150;
  
  int leftSpeed = baseSpeed + diff / 2;
  int rightSpeed = baseSpeed - diff / 2;
  
  analogWrite(PWM_LEFT, constrain(leftSpeed, 50, 255));
  analogWrite(PWM_RIGHT, constrain(rightSpeed, 50, 255));
  
  delay(40);
}

3、非结构化农田作业避障机器人(智能喷洒/巡检)
场景说明:针对农田非规则地形(沟渠、作物、土块),机器人需实现行间导航与避障,硬件增加GPS模块和IMU,支持路径规划与地形适配。

#include <FuzzyLogic.h>
#include <TinyGPS++.h>  // GPS定位库
#include <Wire.h>       // IMU通信库
#include <MPU6050.h>    // 陀螺仪传感器库

// 硬件引脚定义(新增GPS和IMU)
#define GPS_RX 17
#define GPS_TX 18
#define IMU_ADDR 0x68  // MPU6050地址

TinyGPSPlus gps;
MPU6050 mpu;

// 模糊变量:新增"地形倾斜度"(IMU获取)、"路径偏差"(GPS与预设路径的偏差)
FuzzyVariable terrainSlope;
FuzzyVariable pathDeviation;

void setupTerrainMembership() {
  // 地形倾斜度:-30°~30°,划分为"LeftSteep"(左陡坡)、"LeftSlope"(左坡)、"Flat"(平坦)、"RightSlope"(右坡)、"RightSteep"(右陡坡)
  terrainSlope.addTerm("LeftSteep", -30, -15, 0);
  terrainSlope.addTerm("LeftSlope", -15, -5, 0);
  terrainSlope.addTerm("Flat", -5, 0, 5);
  terrainSlope.addTerm("RightSlope", 0, 5, 15);
  terrainSlope.addTerm("RightSteep", 0, 15, 30);
  
  // 路径偏差:-50cm~50cm(假设行距100cm),划分为"LeftBig"(左偏离大)、"Left"(左偏离)、"Center"(对齐)、"Right"(右偏离)、"RightBig"(右偏离大)
  pathDeviation.addTerm("LeftBig", -50, -25, 0);
  pathDeviation.addTerm("Left", -25, -10, 0);
  pathDeviation.addTerm("Center", -10, 0, 10);
  pathDeviation.addTerm("Right", 0, 10, 25);
  pathDeviation.addTerm("RightBig", 0, 25, 50);
}

void setupFarmRules() {
  // 农田规则:路径对齐优先,地形倾斜调整重心(陡坡减速,平坦加速)
  ruleSet.addRule("(pathDeviation == Center) && (terrainSlope == Flat)", "turnAngle == Straight && speed == High");
  ruleSet.addRule("(pathDeviation == Left) && (terrainSlope == Flat)", "turnAngle == Left");
  ruleSet.addRule("(pathDeviation == LeftBig) && (terrainSlope == Flat)", "turnAngle == LeftMax");
  ruleSet.addRule("(pathDeviation == Right) && (terrainSlope == Flat)", "turnAngle == Right");
  ruleSet.addRule("(pathDeviation == RightBig) && (terrainSlope == Flat)", "turnAngle == RightMax");
  ruleSet.addRule("(terrainSlope == LeftSteep)", "turnAngle == Right && speed == Low");  // 左陡坡向右转平衡重心,减速
  ruleSet.addRule("(terrainSlope == RightSteep)", "turnAngle == Left && speed == Low");
  ruleSet.addRule("(pathDeviation == Center) && (terrainSlope == LeftSlope)", "turnAngle == Center && speed == Medium");
}

// 获取地形倾斜度(IMU陀螺仪数据)
float getTerrainSlope() {
  mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  // 通过加速度计算倾斜角(简化算法,实际应用需滤波)
  return atan2(ay, az) * 180 / PI;  // 单位:度,范围-90°~90°
}

// 计算路径偏差(GPS与预设路径的差值)
float getPathDeviation(float targetLat, float targetLng) {
  if (gps.location.isValid()) {
    float deltaLat = (gps.location.lat() - targetLat) * 111320;  // 纬度差转米
    float deltaLng = (gps.location.lng() - targetLng) * 111320 * cos(gps.location.lat() * PI / 180);
    return sqrt(deltaLat*deltaLat + deltaLng*deltaLng);  // 计算距离偏差
  }
  return 0;
}

void setup() {
  // 硬件初始化
  Serial1.begin(9600, SERIAL_8N1, GPS_RX, GPS_TX);  // GPS串口初始化
  Wire.begin();
  mpu.initialize();
  
  setupTerrainMembership();
  setupFarmRules();
  analogWrite(PWM_LEFT, 120);
  analogWrite(PWM_RIGHT, 120);
}

void loop() {
  while (Serial1.available() > 0) {
    gps.encode(Serial1.read());  // 读取GPS数据
  }
  
  float slope = getTerrainSlope();
  float deviation = getPathDeviation(31.230416, 121.473701);  // 预设目标坐标(示例)
  
  // 模糊化输入
  terrainSlope.setInput(slope);
  pathDeviation.setInput(deviation);
  
  // 推理与控制
  ruleSet.evaluate();
  float outAngle = turnAngle.getOutput();
  int baseSpeed = (slope > 15 || slope < -15) ? 80 : 140;  // 陡坡减速
  
  int diff = map(outAngle, -90, 90, -60, 60);
  int leftSpeed = baseSpeed + diff / 2;
  int rightSpeed = baseSpeed - diff / 2;
  
  analogWrite(PWM_LEFT, constrain(leftSpeed, 50, 255));
  analogWrite(PWM_RIGHT, constrain(rightSpeed, 50, 255));
  
  delay(100);
}

要点解读

  1. 模糊逻辑的“不确定性建模”本质:破解复杂环境的核心
    模糊逻辑避障的核心不是追求精确控制,而是模拟人类应对复杂环境的决策逻辑——将传感器数据(如距离、角度)转化为“近/中/远”“左偏/正中/右偏”等模糊概念,通过隶属度函数量化不确定性,再用“如果-那么”的规则库映射决策。例如,当超声波检测到“前方30cm+左侧80cm+右侧150cm”时,系统会同时激活“前方近、左侧中、右侧远”的隶属度,触发“向右转向”的规则,避免了传统阈值控制的“非此即彼”的死板。
  2. 规则库的“经验-适配”双驱动设计:平衡性能与灵活性
    规则库是模糊逻辑的“大脑”,其质量直接决定避障效果:
    经验驱动:规则源于人类对避障的直观认知(如“前方近需避障、侧方近决定转向方向”),无需复杂的数学建模,开发周期短。
    适配迭代:规则库必须根据场景动态调整,比如农田场景需增加地形相关规则,人流跟随场景需加入目标追踪规则。通过反复测试修改规则(如调整隶属度函数范围、补充边缘规则),可避免机器人陷入死循环(如反复转向)或漏判(如对低矮障碍物无响应)。
  3. BLDC电机与模糊控制的“响应性匹配”:实现实时动态控制
    模糊逻辑的优势是快速决策,但优势的落地依赖BLDC电机的高动态响应:
    硬件匹配:BLDC电机的低惯量、高扭矩特性,能快速响应模糊控制器输出的转速差和转向指令,避免传统舵机的延迟导致的碰撞。案例中通过PWM实时调整转速,控制周期控制在50ms以内,与模糊推理的实时性匹配。
    控制精度适配:模糊输出的模糊角度需通过清晰化算法转化为具体的PWM值,且需通过constrain()函数限制速度范围,避免电机堵转或超速,保证控制的平滑性。
  4. 多传感器“信息互补融合”:弥补单一传感器缺陷
    复杂环境中单一传感器必然存在盲区或局限,模糊逻辑的包容性为多传感器融合提供了天然框架:
    静态+动态传感器互补:案例1的超声波(测距)与案例2的人体红外(目标检测)、案例3的IMU(地形感知)结合,分别捕捉障碍物位置、目标动态、地形信息,避免单一传感器因盲区或干扰(如超声波对透明障碍物失效、红外受光照影响)导致决策错误。
    输入维度扩展:将不同传感器的数据转化为模糊输入变量,通过模糊推理整合信息,例如案例3中同时输入路径偏差和地形倾斜度,既实现路径对齐,又保证地形适应性,比单一输入的避障效果更可靠。
  5. 系统“低功耗与可靠性”的工程化设计:适配嵌入式场景
    模糊逻辑避障机器人多运行在电池供电的嵌入式环境,硬件与程序设计需兼顾效率与稳定性:
    硬件层面:选择低功耗的MCU(如Arduino Mega的低功耗模式),匹配高效的BLDC驱动板,通过PWM调速降低不必要的功耗;同时增加电源滤波电路,减少电机启停对传感器的电磁干扰。
    软件层面:采用非阻塞编程(如案例3的GPS串口轮询),避免程序卡顿;合理设置控制周期(50-100ms),既保证实时性,又避免过度占用算力;对传感器数据进行简单的滤波处理(如均值滤波),减少噪声对模糊输入的影响,提升系统可靠性。

在这里插入图片描述
4、基础模糊避障控制器(三向感知机器人)
功能描述:
这是最经典的模糊逻辑应用。机器人通过左、中、右三个超声波传感器获取距离信息,模糊控制器根据这三个输入,直接输出左右两个BLDC电机的速度差,实现平滑转向。

#include <Fuzzy.h>
#include <FuzzySet.h>
#include <FuzzyRule.h>
#include <Consequent.h>
#include <Antecedent.h>
#include <FuzzyRuleConsequent.h>
#include <FuzzyRuleAntecedent.h>

// --- 1. 模糊控制器定义 ---
Fuzzy *fuzzy = new Fuzzy();

// 输入变量:距离 (左、右)
FuzzyVariable *distLeft = new FuzzyVariable("distLeft", 0, 100, "cm");
FuzzyVariable *distRight = new FuzzyVariable("distRight", 0, 100, "cm");

// 输出变量:转向力度 (Turn)
FuzzyVariable *turn = new FuzzyVariable("turn", -100, 100, "power");

// --- 2. 硬件引脚定义 ---
const int trigPinL = 2, echoPinL = 3;
const int trigPinR = 4, echoPinR = 5;
// 假设使用简单的PWM控制BLDC速度(实际需FOC或电调)
const int motorLeftPWM = 9;
const int motorRightPWM = 10;

void setup() {
  Serial.begin(9600);
  
  // 初始化模糊集
  // 距离:近 (Near), 远 (Far)
  distLeft->addFuzzySet(new FuzzySet(0, 0, 20, 40, "Near"));
  distLeft->addFuzzySet(new FuzzySet(20, 60, 100, 100, "Far"));
  
  distRight->addFuzzySet(new FuzzySet(0, 0, 20, 40, "Near"));
  distRight->addFuzzySet(new FuzzySet(20, 60, 100, 100, "Far"));

  // 转向:左转 (Left), 直行 (Straight), 右转 (Right)
  turn->addFuzzySet(new FuzzySet(-100, -100, -50, 0, "Left"));
  turn->addFuzzySet(new FuzzySet(-50, 0, 50, 100, "Straight")); 
  turn->addFuzzySet(new FuzzySet(0, 50, 100, 100, "Right"));

  // 添加变量到控制器
  fuzzy->addFuzzyVariable(distLeft);
  fuzzy->addFuzzyVariable(distRight);
  fuzzy->addFuzzyVariable(turn);

  // 定义规则
  // 规则1: 左近右远 -> 右转
  FuzzyRuleAntecedent *ifLeftNearRightFar = new FuzzyRuleAntecedent();
  ifLeftNearRightFar->joinWithAND(distLeft->getFuzzySet("Near"), distRight->getFuzzySet("Far"));
  FuzzyRuleConsequent *thenTurnRight = new FuzzyRuleConsequent();
  thenTurnRight->addOutput(turn->getFuzzySet("Right"));
  fuzzy->addFuzzyRule(new FuzzyRule(1, ifLeftNearRightFar, thenTurnRight));

  // 规则2: 左远右近 -> 左转
  FuzzyRuleAntecedent *ifLeftFarRightNear = new FuzzyRuleAntecedent();
  ifLeftFarRightNear->joinWithAND(distLeft->getFuzzySet("Far"), distRight->getFuzzySet("Near"));
  FuzzyRuleConsequent *thenTurnLeft = new FuzzyRuleConsequent();
  thenTurnLeft->addOutput(turn->getFuzzySet("Left"));
  fuzzy->addFuzzyRule(new FuzzyRule(2, ifLeftFarRightNear, thenTurnLeft));
  
  // 规则3: 都远 -> 直行
  FuzzyRuleAntecedent *ifBothFar = new FuzzyRuleAntecedent();
  ifBothFar->joinWithAND(distLeft->getFuzzySet("Far"), distRight->getFuzzySet("Far"));
  FuzzyRuleConsequent *thenStraight = new FuzzyRuleConsequent();
  thenStraight->addOutput(turn->getFuzzySet("Straight"));
  fuzzy->addFuzzyRule(new FuzzyRule(3, ifBothFar, thenStraight));

  pinMode(motorLeftPWM, OUTPUT);
  pinMode(motorRightPWM, OUTPUT);
}

long getDistance(int trig, int echo) {
  digitalWrite(trig, LOW); delayMicroseconds(2);
  digitalWrite(trig, HIGH); delayMicroseconds(10);
  digitalWrite(trig, LOW);
  return pulseIn(echo, HIGH) / 58.2;
}

void loop() {
  // 1. 获取输入
  float dL = getDistance(trigPinL, echoPinL);
  float dR = getDistance(trigPinR, echoPinR);
  
  // 2. 模糊化
  fuzzy->setInput("distLeft", dL);
  fuzzy->setInput("distRight", dR);
  
  // 3. 推理
  fuzzy->fuzzify();
  
  // 4. 解模糊化 (获取具体数值)
  float output = fuzzy->defuzzify("turn");
  
  // 5. 执行 (差速转向)
  int baseSpeed = 150; // 基础速度
  int leftSpeed = baseSpeed - output;
  int rightSpeed = baseSpeed + output;
  
  // 限制范围 0-255
  leftSpeed = constrain(leftSpeed, 0, 255);
  rightSpeed = constrain(rightSpeed, 0, 255);
  
  analogWrite(motorLeftPWM, leftSpeed);
  analogWrite(motorRightPWM, rightSpeed);
  
  delay(100);
}

5、动态速度调节模糊控制器
功能描述:
在复杂环境中,不仅要控制方向,还要控制速度。当障碍物很近时,机器人应减速以确保安全;当路径开阔时,加速通过。本案例引入“距离”作为速度控制的输入。

#include <Fuzzy.h>
// ... (引用同上)

Fuzzy *fuzzySpeed = new Fuzzy();
FuzzyVariable *distFront = new FuzzyVariable("distFront", 0, 200, "cm");
FuzzyVariable *motorSpeed = new FuzzyVariable("motorSpeed", 0, 255, "pwm");

// 假设中间传感器控制速度
const int trigPinF = 6, echoPinF = 7;
const int motorEnable = 9; // 简化为单电机或双电机同步

void setupFuzzySpeed() {
  // 距离:极近 (VeryNear), 近 (Near), 远 (Far)
  distFront->addFuzzySet(new FuzzySet(0, 0, 10, 30, "VeryNear"));
  distFront->addFuzzySet(new FuzzySet(10, 30, 60, 100, "Near"));
  distFront->addFuzzySet(new FuzzySet(60, 100, 200, 200, "Far"));

  // 速度:停 (Stop), 慢 (Slow), 快 (Fast)
  motorSpeed->addFuzzySet(new FuzzySet(0, 0, 0, 50, "Stop"));
  motorSpeed->addFuzzySet(new FuzzySet(0, 50, 150, 200, "Slow"));
  motorSpeed->addFuzzySet(new FuzzySet(150, 200, 255, 255, "Fast"));

  fuzzySpeed->addFuzzyVariable(distFront);
  fuzzySpeed->addFuzzyVariable(motorSpeed);

  // 规则
  // 极近 -> 停
  FuzzyRuleAntecedent *ifVeryNear = new FuzzyRuleAntecedent();
  ifVeryNear->joinSingle(distFront->getFuzzySet("VeryNear"));
  FuzzyRuleConsequent *thenStop = new FuzzyRuleConsequent();
  thenStop->addOutput(motorSpeed->getFuzzySet("Stop"));
  fuzzySpeed->addFuzzyRule(new FuzzyRule(10, ifVeryNear, thenStop));

  // 远 -> 快
  FuzzyRuleAntecedent *ifFar = new FuzzyRuleAntecedent();
  ifFar->joinSingle(distFront->getFuzzySet("Far"));
  FuzzyRuleConsequent *thenFast = new FuzzyRuleConsequent();
  thenFast->addOutput(motorSpeed->getFuzzySet("Fast"));
  fuzzySpeed->addFuzzyRule(new FuzzyRule(11, ifFar, thenFast));
}

void loop() {
  // 结合案例一的方向控制和本案的速度控制
  // 1. 计算方向 (略,参考案例一) -> 得到 turnOutput
  // 2. 计算速度
  float dF = getDistance(trigPinF, echoPinF);
  fuzzySpeed->setInput("distFront", dF);
  fuzzySpeed->fuzzify();
  int speedVal = (int)fuzzySpeed->defuzzify("motorSpeed");
  
  // 3. 应用速度和方向到BLDC
  // 这里简化处理:速度影响整体PWM占空比
  analogWrite(motorEnable, speedVal);
}

6、带“安全本能”的混合模糊控制
功能描述:
模糊逻辑虽然平滑,但在极端危险情况下(如突然出现的墙壁),推理过程可能有微小延迟或输出不够果断。本案例采用“混合控制”:底层保留硬性的安全阈值(本能),上层运行模糊逻辑(大脑)。

// ... (引用同上)
Fuzzy *fuzzyHybrid = new Fuzzy();
// ... (模糊变量定义同上)

const int SAFETY_DIST = 15; // 硬性安全距离 cm
const int BLDC_BRAKE_PIN = 8; // 刹车引脚

void loop() {
  float dL = getDistance(trigPinL, echoPinL);
  float dR = getDistance(trigPinR, echoPinR);
  float dF = getDistance(trigPinF, echoPinF);

  // --- 1. 安全本能层 (优先级最高) ---
  if (dF < SAFETY_DIST || (dL < SAFETY_DIST && dR < SAFETY_DIST)) {
    // 紧急刹车:直接拉低PWM,切断电机动力
    analogWrite(motorLeftPWM, 0);
    analogWrite(motorRightPWM, 0);
    digitalWrite(BLDC_BRAKE_PIN, HIGH); // 激活电子刹车
    Serial.println("⚠️ 紧急制动触发!");
    return; // 跳过模糊逻辑
  }
  digitalWrite(BLDC_BRAKE_PIN, LOW); // 释放刹车

  // --- 2. 模糊逻辑层 (正常运行) ---
  fuzzy->setInput("distLeft", dL);
  fuzzy->setInput("distRight", dR);
  fuzzy->fuzzify();
  
  float turnOutput = fuzzy->defuzzify("turn");
  
  // 平滑驱动 BLDC
  // 注意:BLDC有最低启动电压,需处理死区
  int baseSpeed = 180;
  int leftS = baseSpeed - turnOutput;
  int rightS = baseSpeed + turnOutput;
  
  // 死区处理:如果速度太低,电机可能不转或啸叫,需设为0
  if (leftS < 50) leftS = 0;
  if (rightS < 50) rightS = 0;

  analogWrite(motorLeftPWM, leftS);
  analogWrite(motorRightPWM, rightS);
}

要点解读
模糊逻辑的核心优势是“平滑性”:
传统的避障算法(如if dist < 30 turn_right)会导致机器人在障碍物边缘产生震荡(来回急转)。模糊逻辑通过隶属度函数(Membership Functions),允许机器人处于“稍微左转”或“中度左转”的状态,使得BLDC电机的速度变化是线性的、平滑的,极大地减少了机械磨损和能耗。
BLDC电机的低速控制挑战:
在案例中,我们直接输出了PWM值。但在实际BLDC控制中,必须注意启动死区。BLDC电机通常需要一定的初始电压(如占空比>10%)才能克服静摩擦力开始转动。如果模糊逻辑输出过小的数值,电机可能不转或发出啸叫。因此,代码中必须包含死区补偿或最小速度限制逻辑。
规则库的设计决定了智能程度:
模糊控制器的“智商”完全取决于规则库(Rule Base)的设计。例如,仅凭“左近右远->右转”可能不够,还需要处理“左近右近->后退”或“左远右远->加速”的情况。规则越完善,机器人在复杂迷宫中的通过能力越强。
计算资源的权衡:
Fuzzy 库虽然方便,但涉及大量的浮点运算。在Arduino Uno(AVR架构)上运行复杂的模糊系统可能会占用较多CPU周期,导致传感器读取频率下降。对于高速移动的机器人,建议使用 Arduino Due 或 ESP32,或者手动将模糊算法优化为定点数运算。
混合控制策略的必要性:
案例6强调了“安全本能”的重要性。模糊逻辑是一种近似推理,存在不确定性。在工程实践中,绝不能完全依赖AI算法来保障安全。必须保留一层基于硬性阈值的“看门狗”逻辑,一旦检测到极度危险(如距离<10cm),立即接管控制权进行急停,这是工业级机器人的基本设计原则。

请注意:以上案例仅作为思路拓展的参考示例,不保证完全正确、适配所有场景或可直接编译运行。由于硬件平台、实际使用场景、Arduino 版本的差异,均可能影响代码的适配性与使用方法的选择。在实际编程开发时,请务必根据自身硬件配置、使用场景及具体功能需求进行针对性调整,并通过多次实测验证效果;同时需确保硬件接线正确,充分了解所用传感器、执行器等设备的技术规范与核心特性。对于涉及硬件操作的代码,使用前务必核对引脚定义、电平参数等关键信息的准确性与安全性,避免因参数错误导致硬件损坏或运行异常。

在这里插入图片描述

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐