在这里插入图片描述
基于 Arduino 平台实现 BLDC 机器人分布式模糊调度(多MCU协同),是解决复杂机器人系统中“实时性”与“智能性”矛盾的高级架构方案。该系统摒弃了单片机处理所有任务的集中式模式,采用多个 Arduino(或 MCU)构成主从或对等网络,利用模糊逻辑(Fuzzy Logic)在节点间动态分配控制优先级和资源,实现多电机或多功能的协同运作。

1、主要特点
分布式异构计算架构
这是系统的硬件基础,实现了计算能力的扩展与分工。
物理拓扑:系统通常采用 “一主多从” 或 “多主对等” 的 CAN 总线/串口网络。主控节点(如 Arduino Mega, ESP32)负责高层决策与模糊调度;从控节点(如 Arduino Nano, STM32)负责底层 BLDC 电机的实时闭环控制。
任务卸载:将计算密集型的模糊推理、路径规划与实时性要求极高的电机电流环/速度环控制分离。主控进行毫秒级(ms)的调度决策,从控进行微秒级(μs)的 PWM 更新,互不干扰。
模糊逻辑驱动的动态资源调度
这是系统的核心“大脑”,解决了传统固定优先级调度的僵化问题。
输入变量模糊化:主控 MCU 采集各子系统的状态(如:避障传感器距离、电池电量、目标接近度、电机温度)。这些数值被转换为模糊集合,如“距离:很近/较远”、“电量:充足/低”。
动态优先级仲裁:通过预设的模糊规则库进行推理。例如规则:“IF (前方距离 = 很近) AND (电量 = 充足) THEN (避障任务优先级 = 最高), (巡航任务优先级 = 零)”。
输出平滑过渡:相较于传统操作系统的硬切换,模糊逻辑输出的是连续的权重值。这使得多个 BLDC 关节或任务之间的协同动作更加平滑,避免了因任务抢占导致的机械冲击。
高可靠性实时通信
这是系统的“神经网络”,确保多 MCU 间指令与反馈的同步。
工业级总线:推荐使用 CAN 总线。它具备非破坏性仲裁机制,高优先级节点可自动抢占总线,完美契合模糊调度中“优先级动态变化”的需求。
同步机制:主控周期性广播“心跳包”或同步帧,各从控节点根据该时间戳统一更新 PWM 输出,防止因通信延迟导致的多电机动作不同步(“拉扯”现象)。

2、应用场景
多足仿生机器人(如四足、六足机器人)
在复杂的步态切换(如从“行走”切换到“小跑”)过程中,主控 Arduino 根据 IMU 姿态数据和模糊规则,动态调整每条腿(由从控 Arduino 驱动)的运动优先级,确保在崎岖地形下身体姿态的稳定性。
模块化冗余机械臂
对于具有冗余自由度的机械臂,多个关节电机需要协同避障并到达目标点。分布式模糊调度器根据各关节的当前负载和角度限制,动态分配运动权重,实现能耗最优的协同运动。
多机器人协作系统(Swarm Robotics)
在群体机器人探索任务中,每个机器人作为一个独立的 MCU 节点。通过模糊逻辑评估自身电量(“低”)和任务紧迫度(“发现目标”),动态决定是继续探索还是返航充电,实现群体层面的资源最优分配。
高动态人机协作机械臂
在协作场景中,当操作员触碰机器人的末端时,力矩传感器信号触发模糊控制器,瞬间将“柔顺控制”任务的优先级提升至最高,并通过 CAN 总线下发指令,让各关节电机立即进入低刚度模式,确保人员安全。

3、注意事项
通信延迟与实时性瓶颈
确定性延迟:模糊调度依赖于实时的状态反馈。若使用普通 UART 或低速 I2C,通信延迟会导致调度决策滞后。必须选用实时性高的 CAN 总线 或 高速 SPI,并严格规定数据帧的优先级。
总线负载率:随着节点增多,总线负载率上升。需精简通信协议,仅传输关键状态量(如“优先级权重”而非原始大数据),避免总线拥塞。
模糊规则库的设计与调试
维数灾难:随着输入变量(如距离、速度、温度、电量)的增加,模糊规则数量呈指数级增长,极易超出 Arduino 的 Flash 存储空间。
对策:采用分层模糊控制。先用粗规则确定大致状态(如“紧急/正常”),再用细规则进行微调。或使用查表法(Look-Up Table)固化规则,避免在线进行复杂的数学运算。
硬件平台的算力匹配
主控算力:模糊推理涉及大量的 MIN/MAX 运算和查表,8 位 AVR 单片机(如 Uno)处理速度较慢。建议主控选用 32 位 ARM Cortex-M 内核的 MCU(如 STM32F4, Teensy 4.1)或带 FPU 的 ESP32,以保证调度周期的稳定性(建议 < 10ms)。
从控实时性:从控节点必须专注于底层电机控制,严禁在从机代码中加入复杂的延时或浮点运算,确保 PWM 波形的纯净。
系统安全与故障冗余
看门狗与超时保护:必须为每个 MCU 启用独立的硬件看门狗。若主控因模糊逻辑死循环而停机,从控应能在超时后自动进入安全模式(如保持当前位置或缓慢停止)。
硬线急停:模糊调度属于软件层逻辑,存在失效风险。对于“急停”、“碰撞”等最高安全等级的事件,必须设计硬线中断电路(如物理急停按钮直接切断 MOS 管驱动),绕过 MCU 直接切断动力电源。

在这里插入图片描述
1、基于模糊逻辑的双轮差速机器人避障调度(主从式架构)
场景:主MCU(ESP32)运行模糊调度算法,从MCU(Arduino Uno)控制BLDC电机驱动。
功能:通过超声波传感器检测障碍物距离,模糊规则动态调整电机速度实现避障。

// 主MCU (ESP32) - 模糊调度核心
#include <WiFi.h>
#include <PubSubClient.h> // MQTT通信(可选)

// 模糊输入:障碍物距离(0-100cm)
float distance = 0;
// 模糊输出:电机速度调整量(-100到100)
float speedAdjust = 0;

// 模糊隶属度函数(简化版)
float fuzzyDistance(float d) {
    if (d <= 20) return 1.0; // 近
    else if (d <= 50) return (50 - d) / 30; // 中
    else return 0.0; // 远
}

void fuzzyInference() {
    float near = fuzzyDistance(distance);
    float medium = fuzzyDistance(distance - 30); // 偏移模拟重叠
    
    // 模糊规则(示例)
    if (near > 0.7) speedAdjust = -80; // 急停
    else if (near > 0.3) speedAdjust = -40; // 减速
    else if (medium > 0.5) speedAdjust = 20; // 微调
    else speedAdjust = 0; // 直行
}

void setup() {
    Serial.begin(115200);
    Serial2.begin(9600); // 与从MCU通信(如UART)
}

void loop() {
    // 模拟读取传感器(实际替换为超声波/红外数据)
    distance = analogRead(34) / 10.23; // 0-100cm映射
    
    fuzzyInference();
    Serial2.print(speedAdjust); // 发送调整量到从MCU
    delay(100);
}
// 从MCU (Arduino Uno) - BLDC电机控制
#include <Servo.h>
Servo motorLeft, motorRight;

void setup() {
    Serial.begin(9600);
    motorLeft.attach(9);
    motorRight.attach(10);
}

void loop() {
    if (Serial.available()) {
        int adjust = Serial.parseInt(); // 接收主MCU的调整量
        // 基础速度(示例:100) + 模糊调整
        int leftSpeed = 100 + adjust;
        int rightSpeed = 100 - adjust; // 差速转向
        motorLeft.writeMicroseconds(map(leftSpeed, -100, 100, 1000, 2000));
        motorRight.writeMicroseconds(map(rightSpeed, -100, 100, 1000, 2000));
    }
}

2、多关节机械臂模糊轨迹规划(CAN总线通信)
场景:主MCU(STM32)运行模糊调度,多个从MCU(Arduino Nano)分别控制BLDC关节电机。
功能:通过模糊逻辑优化关节加速度,避免机械振动。

// 主MCU (STM32) - 模糊调度核心(伪代码,需适配HAL库)
#include <CAN.h>

struct JointCommand {
    uint8_t id;
    float targetPos;
    float fuzzyAdjust; // 模糊输出:加速度调整系数
};

void fuzzyAccelerationControl(float currentPos, float targetPos, float &adjust) {
    float error = targetPos - currentPos;
    // 模糊规则:误差大时高加速度,误差小时低加速度
    if (abs(error) > 50) adjust = 1.5; // 高增益
    else if (abs(error) > 20) adjust = 1.0; // 中增益
    else adjust = 0.5; // 低增益
}

void setup() {
    CAN.begin(CAN_500KBPS);
}

void loop() {
    static float jointPos[3] = {0}; // 模拟关节位置
    JointCommand cmd;
    for (int i = 0; i < 3; i++) {
        fuzzyAccelerationControl(jointPos[i], /* 目标位置 */, cmd.fuzzyAdjust);
        cmd.id = i;
        CAN.sendMessage(&cmd, sizeof(cmd)); // 发送到对应从MCU
    }
    delay(20);
}
// 从MCU (Arduino Nano) - 单关节BLDC控制
#include <CAN.h>
#include <SimpleFOC.h>
BLDCMotor motor(7); // 7极对数
BLDCDriver3PWM driver(9, 10, 11);

void setup() {
    Serial.begin(115200);
    CAN.begin(CAN_500KBPS);
    motor.linkDriver(&driver);
    motor.controller = MotionControlType::position;
    driver.init();
    motor.init();
}

void loop() {
    if (CAN.available()) {
        struct JointCommand cmd;
        CAN.readMessage(&cmd, sizeof(cmd));
        // 应用模糊调整系数到PID参数
        motor.PID_velocity.Kp *= cmd.fuzzyAdjust;
        motor.move(cmd.targetPos); // 执行位置控制
    }
}

3、AGV小车模糊负载均衡调度(无线通信)
场景:主MCU(ESP32)通过模糊逻辑分配动力,多个从MCU(Arduino Uno)控制驱动轮BLDC电机。
功能:根据电池电压和负载电流模糊调整各电机输出功率。

// 主MCU (ESP32) - 模糊调度核心
#include <ESPNow.h>

struct MotorCommand {
    uint8_t id;
    float powerAdjust; // 模糊输出:功率调整百分比
};

void fuzzyPowerAllocation(float voltage, float current, float &adjust) {
    // 模糊规则:电压低或电流高时降低功率
    if (voltage < 11.0 && current > 5.0) adjust = 0.6; // 严重限制
    else if (voltage < 11.5 || current > 3.0) adjust = 0.8; // 轻度限制
    else adjust = 1.0; // 全力输出
}

void setup() {
    ESPNow.begin();
    // 绑定从MCU的MAC地址(需预先配置)
}

void loop() {
    float batteryVoltage = analogRead(35) * 0.00488; // 模拟电压读取
    float motorCurrent = analogRead(34) * 0.00122; // 模拟电流读取
    
    MotorCommand cmd;
    fuzzyPowerAllocation(batteryVoltage, motorCurrent, cmd.powerAdjust);
    cmd.id = 1; // 发送到所有从MCU(广播或单独地址)
    ESPNow.send(NULL, (uint8_t*)&cmd, sizeof(cmd));
    delay(500);
}
// 从MCU (Arduino Uno) - 单驱动轮控制
#include <Servo.h>
Servo motor;

void setup() {
    Serial.begin(115200);
    motor.attach(9);
    // 初始化ESPNow接收(需适配库)
}

void loop() {
    // 模拟接收主MCU命令(实际替换为ESPNow回调)
    if (Serial.available()) {
        float adjust = Serial.parseFloat();
        int basePower = 150; // 基础PWM值(0-255)
        motor.writeMicroseconds(map(basePower * adjust, 0, 255, 1000, 2000));
    }
}

要点解读
分布式架构设计
主从分工:主MCU负责高计算量的模糊调度(如规则推理、隶属度计算),从MCU专注实时控制(如PWM输出、传感器读取)。
通信协议选择:
短距离:UART(简单)、I2C(低速)、SPI(高速)。
长距离/多节点:CAN总线(抗干扰强)、无线(ESPNow/LoRa,灵活但需考虑延迟)。
代码体现:案例一使用UART,案例二使用CAN,案例三使用ESPNow。
模糊逻辑的实时性优化
查表法替代实时计算:预计算模糊规则表存储在Flash中,运行时查表而非实时计算隶属度函数。
简化规则集:减少输入维度(如仅用距离而非距离+速度)和规则数量(如从9条减至3条)。
代码体现:案例一中fuzzyDistance()函数通过分段线性近似替代复杂高斯函数。
多MCU同步与容错
心跳机制:从MCU定期发送状态信号,主MCU检测超时后重启或切换备用从机。
看门狗定时器:防止单个MCU死机导致整个系统瘫痪。
代码体现:案例二中主MCU循环发送命令,从MCU需在固定时间内响应。
资源受限环境下的实现技巧
定点数运算:用整数替代浮点数(如int16_t代替float),适合Arduino Uno等无FPU的MCU。
任务调度:通过定时器中断分割模糊推理和控制任务,避免阻塞。
代码体现:案例三中从MCU使用map()函数快速缩放PWM值,而非复杂数学运算。
模糊参数的自适应调整
在线学习:根据历史数据动态调整模糊规则(如强化学习优化隶属度函数参数)。
环境适配:通过额外传感器(如温度、湿度)扩展模糊输入,适应不同工况。
代码体现:案例二中从MCU根据fuzzyAdjust动态修改PID参数,实现自适应控制。

在这里插入图片描述
4、CAN总线主从控制系统
场景:多关节机械臂,每个关节独立MCU控制
核心逻辑:CAN总线通信 + 主控制器调度 + 分布式模糊控制

// 主控制器代码 (Master)
#include <SimpleFOC.h>
#include <mcp2515_can.h>
#include <SPI.h>

// CAN总线设置
#define CAN_CS_PIN 10
#define CAN_INT_PIN 2
MCP2515 can(CAN_CS_PIN);

// 从节点定义
#define NODE_COUNT 4
#define CAN_MASTER_ID 0x100
#define CAN_BROADCAST_ID 0x7FF

// 从节点状态
struct SlaveNode {
  uint8_t nodeId;
  uint8_t canId;
  float currentPosition;
  float targetPosition;
  float velocity;
  float current;
  float temperature;
  uint8_t status;
  uint32_t lastHeartbeat;
  float healthScore;  // 健康度评分
};
SlaveNode nodes[NODE_COUNT];

// 模糊调度器
class FuzzyScheduler {
private:
  // 模糊规则
  struct FuzzyRule {
    float positionError;      // 位置误差
    float velocity;           // 速度
    float current;           // 电流
    float priority;          // 优先级输出
  };
  
  std::vector<FuzzyRule> rules;
  
  // 隶属度函数参数
  struct MembershipFunc {
    float low[3];    // {min, center, max}
    float medium[3];
    float high[3];
  };
  
  MembershipFunc errorMF, velocityMF, currentMF, priorityMF;
  
public:
  FuzzyScheduler() {
    initMembershipFunctions();
    initFuzzyRules();
  }
  
  void calculatePriorities(SlaveNode* nodes, int count) {
    // 计算各节点优先级
    
    for (int i = 0; i < count; i++) {
      if (nodes[i].status == 0) continue;  // 节点离线
      
      // 模糊化输入
      float errorDegree[3];  // 位置误差隶属度
      float velocityDegree[3];  // 速度隶属度
      float currentDegree[3];  // 电流隶属度
      
      fuzzify(nodes[i], errorDegree, velocityDegree, currentDegree);
      
      // 模糊推理
      float priority = fuzzyInference(errorDegree, velocityDegree, currentDegree);
      
      // 记录优先级
      nodes[i].healthScore = priority;
      
      // 计算控制周期
      uint32_t controlPeriod = calculateControlPeriod(priority);
      
      // 发送调度指令
      sendControlCommand(nodes[i].canId, controlPeriod, priority);
    }
  }
  
private:
  void initMembershipFunctions() {
    // 初始化隶属度函数
    
    // 位置误差隶属度
    errorMF.low[0] = 0; errorMF.low[1] = 0; errorMF.low[2] = 0.1;
    errorMF.medium[0] = 0.05; errorMF.medium[1] = 0.15; errorMF.medium[2] = 0.25;
    errorMF.high[0] = 0.2; errorMF.high[1] = 0.3; errorMF.high[2] = 0.5;
    
    // 速度隶属度
    velocityMF.low[0] = 0; velocityMF.low[1] = 1; velocityMF.low[2] = 3;
    velocityMF.medium[0] = 2; velocityMF.medium[1] = 5; velocityMF.medium[2] = 8;
    velocityMF.high[0] = 6; velocityMF.high[1] = 10; velocityMF.high[2] = 15;
    
    // 电流隶属度
    currentMF.low[0] = 0; currentMF.low[1] = 1; currentMF.low[2] = 2;
    currentMF.medium[0] = 1.5; currentMF.medium[1] = 2.5; currentMF.medium[2] = 3.5;
    currentMF.high[0] = 3; currentMF.high[1] = 4; currentMF.high[2] = 5;
    
    // 优先级隶属度
    priorityMF.low[0] = 0; priorityMF.low[1] = 0.3; priorityMF.low[2] = 0.5;
    priorityMF.medium[0] = 0.4; priorityMF.medium[1] = 0.6; priorityMF.medium[2] = 0.8;
    priorityMF.high[0] = 0.7; priorityMF.high[1] = 0.9; priorityMF.high[2] = 1.0;
  }
  
  void initFuzzyRules() {
    // 初始化模糊规则
    // 格式: 如果 位置误差 且 速度 且 电流 则 优先级
    
    // 规则1: 误差大、速度高、电流大 -> 高优先级
    rules.push_back({0.3, 8.0, 4.0, 0.9});
    
    // 规则2: 误差中、速度中、电流中 -> 中优先级
    rules.push_back({0.15, 5.0, 2.5, 0.6});
    
    // 规则3: 误差小、速度低、电流小 -> 低优先级
    rules.push_back({0.05, 1.0, 1.0, 0.3});
    
    // 规则4: 误差大、速度低、电流大 -> 中高优先级
    rules.push_back({0.3, 1.0, 4.0, 0.7});
    
    // 规则5: 误差小、速度高、电流小 -> 中优先级
    rules.push_back({0.05, 8.0, 1.0, 0.5});
  }
  
  void fuzzify(const SlaveNode& node, float* errorDegree, 
               float* velocityDegree, float* currentDegree) {
    // 计算位置误差
    float posError = abs(node.targetPosition - node.currentPosition);
    
    // 计算隶属度
    errorDegree[0] = triangularMF(posError, errorMF.low);     // 低
    errorDegree[1] = triangularMF(posError, errorMF.medium);  // 中
    errorDegree[2] = triangularMF(posError, errorMF.high);    // 高
    
    velocityDegree[0] = triangularMF(node.velocity, velocityMF.low);
    velocityDegree[1] = triangularMF(node.velocity, velocityMF.medium);
    velocityDegree[2] = triangularMF(node.velocity, velocityMF.high);
    
    currentDegree[0] = triangularMF(node.current, currentMF.low);
    currentDegree[1] = triangularMF(node.current, currentMF.medium);
    currentDegree[2] = triangularMF(node.current, currentMF.high);
  }
  
  float triangularMF(float x, float* params) {
    // 三角隶属度函数
    if (x <= params[0] || x >= params[2]) return 0;
    if (x <= params[1]) return (x - params[0]) / (params[1] - params[0]);
    return (params[2] - x) / (params[2] - params[1]);
  }
  
  float fuzzyInference(float* errorDegree, float* velocityDegree, 
                      float* currentDegree) {
    // 模糊推理
    float numerator = 0;
    float denominator = 0;
    
    for (const auto& rule : rules) {
      // 计算规则激活度
      float activation = 1.0;
      
      // 位置误差匹配度
      float errorMatch = 0;
      if (rule.positionError < 0.1) errorMatch = errorDegree[0];  // 低
      else if (rule.positionError < 0.2) errorMatch = errorDegree[1];  // 中
      else errorMatch = errorDegree[2];  // 高
      
      // 速度匹配度
      float velocityMatch = 0;
      if (rule.velocity < 3) velocityMatch = velocityDegree[0];
      else if (rule.velocity < 6) velocityMatch = velocityDegree[1];
      else velocityMatch = velocityDegree[2];
      
      // 电流匹配度
      float currentMatch = 0;
      if (rule.current < 2) currentMatch = currentDegree[0];
      else if (rule.current < 3) currentMatch = currentDegree[1];
      else currentMatch = currentDegree[2];
      
      // 取最小值作为激活度
      activation = min(errorMatch, min(velocityMatch, currentMatch));
      
      // 累加
      numerator += activation * rule.priority;
      denominator += activation;
    }
    
    if (denominator == 0) return 0.5;  // 默认优先级
    return numerator / denominator;  // 重心法解模糊
  }
  
  uint32_t calculateControlPeriod(float priority) {
    // 根据优先级计算控制周期
    // 优先级越高,控制周期越短
    
    uint32_t minPeriod = 1000;  // 1ms
    uint32_t maxPeriod = 10000; // 10ms
    
    return maxPeriod - (uint32_t)((maxPeriod - minPeriod) * priority);
  }
  
  void sendControlCommand(uint8_t canId, uint32_t period, float priority) {
    // 通过CAN发送控制指令
    uint8_t data[8];
    
    data[0] = 0x01;  // 控制指令
    data[1] = (period >> 8) & 0xFF;
    data[2] = period & 0xFF;
    data[3] = (uint8_t)(priority * 100);
    
    can.sendMsgBuf(canId, 0, 4, data);
  }
};

FuzzyScheduler scheduler;

// 分布式状态管理器
class DistributedStateManager {
private:
  enum SystemMode {
    MODE_IDLE,
    MODE_HOMING,
    MODE_MOVING,
    MODE_FAULT,
    MODE_RECOVERY
  };
  
  SystemMode currentMode = MODE_IDLE;
  uint32_t modeStartTime = 0;
  
  // 系统状态
  struct SystemState {
    uint8_t onlineNodes = 0;
    float systemHealth = 1.0;
    float loadBalance = 0.5;
    uint32_t totalRuntime = 0;
  };
  SystemState systemState;
  
public:
  void update() {
    // 更新系统状态
    
    // 统计在线节点
    int online = 0;
    for (int i = 0; i < NODE_COUNT; i++) {
      if (nodes[i].status > 0) online++;
    }
    systemState.onlineNodes = online;
    
    // 计算系统健康度
    calculateSystemHealth();
    
    // 计算负载均衡
    calculateLoadBalance();
    
    // 状态机
    stateMachine();
  }
  
  void stateMachine() {
    // 状态机
    
    switch (currentMode) {
      case MODE_IDLE:
        idleState();
        break;
      case MODE_HOMING:
        homingState();
        break;
      case MODE_MOVING:
        movingState();
        break;
      case MODE_FAULT:
        faultState();
        break;
      case MODE_RECOVERY:
        recoveryState();
        break;
    }
  }
  
private:
  void idleState() {
    // 空闲状态
    if (systemState.onlineNodes >= NODE_COUNT) {
      // 所有节点在线,进入回零状态
      changeMode(MODE_HOMING);
    }
  }
  
  void homingState() {
    // 回零状态
    static bool homingComplete[NODE_COUNT] = {false};
    
    // 检查是否所有节点都回零完成
    bool allHomed = true;
    for (int i = 0; i < NODE_COUNT; i++) {
      if (nodes[i].status > 0 && !homingComplete[i]) {
        allHomed = false;
        
        // 发送回零指令
        sendHomingCommand(nodes[i].canId);
      }
    }
    
    if (allHomed) {
      changeMode(MODE_MOVING);
    }
  }
  
  void movingState() {
    // 运动状态
    // 主控制逻辑
    
    // 模糊调度
    scheduler.calculatePriorities(nodes, NODE_COUNT);
    
    // 检查故障
    if (systemState.systemHealth < 0.3) {
      changeMode(MODE_FAULT);
    }
  }
  
  void faultState() {
    // 故障状态
    // 停止所有节点
    broadcastStopCommand();
    
    // 尝试恢复
    if (millis() - modeStartTime > 5000) {  // 5秒后尝试恢复
      changeMode(MODE_RECOVERY);
    }
  }
  
  void recoveryState() {
    // 恢复状态
    // 逐个恢复节点
    static int recoveryIndex = 0;
    
    if (millis() - modeStartTime > 1000) {  // 每秒恢复一个节点
      if (recoveryIndex < NODE_COUNT) {
        sendRecoveryCommand(nodes[recoveryIndex].canId);
        recoveryIndex++;
        modeStartTime = millis();
      } else {
        recoveryIndex = 0;
        changeMode(MODE_IDLE);
      }
    }
  }
  
  void changeMode(SystemMode newMode) {
    Serial.print("状态切换: ");
    Serial.print(currentMode);
    Serial.print(" -> ");
    Serial.println(newMode);
    
    currentMode = newMode;
    modeStartTime = millis();
  }
  
  void calculateSystemHealth() {
    // 计算系统健康度
    float healthSum = 0;
    int count = 0;
    
    for (int i = 0; i < NODE_COUNT; i++) {
      if (nodes[i].status > 0) {
        healthSum += nodes[i].healthScore;
        count++;
      }
    }
    
    if (count > 0) {
      systemState.systemHealth = healthSum / count;
    } else {
      systemState.systemHealth = 0;
    }
  }
  
  void calculateLoadBalance() {
    // 计算负载均衡
    float loadSum = 0;
    float loadSqSum = 0;
    int count = 0;
    
    for (int i = 0; i < NODE_COUNT; i++) {
      if (nodes[i].status > 0) {
        float load = nodes[i].current / 5.0;  // 归一化
        loadSum += load;
        loadSqSum += load * load;
        count++;
      }
    }
    
    if (count > 0) {
      float avgLoad = loadSum / count;
      float variance = (loadSqSum / count) - (avgLoad * avgLoad);
      systemState.loadBalance = 1.0 / (1.0 + variance);
    } else {
      systemState.loadBalance = 0;
    }
  }
  
  void broadcastStopCommand() {
    // 广播停止指令
    uint8_t data[8] = {0x02};  // 停止指令
    can.sendMsgBuf(CAN_BROADCAST_ID, 0, 1, data);
  }
  
  void sendHomingCommand(uint8_t canId) {
    uint8_t data[8] = {0x03};  // 回零指令
    can.sendMsgBuf(canId, 0, 1, data);
  }
  
  void sendRecoveryCommand(uint8_t canId) {
    uint8_t data[8] = {0x04};  // 恢复指令
    can.sendMsgBuf(canId, 0, 1, data);
  }
};

DistributedStateManager stateManager;

void setup() {
  Serial.begin(115200);
  Serial.println("===== 分布式模糊调度主控制器 =====");
  
  // 初始化CAN总线
  initCAN();
  
  // 初始化从节点
  initSlaveNodes();
  
  // 发送发现广播
  discoverNodes();
  
  Serial.println("主控制器就绪");
}

void loop() {
  static unsigned long lastUpdate = 0;
  
  // 接收CAN消息
  receiveCANMessages();
  
  // 更新系统状态
  stateManager.update();
  
  // 发送心跳
  if (millis() - lastUpdate >= 100) {  // 10Hz
    sendHeartbeat();
    lastUpdate = millis();
  }
}

void initCAN() {
  SPI.begin();
  can.initCAN(CAN_500KBPS);
  can.setNormalMode();
  
  // 设置过滤器
  can.init_Mask(0, 0, 0x7FF);  // 接收所有消息
  can.init_Filt(0, 0, CAN_MASTER_ID);
  
  Serial.println("CAN总线初始化完成");
}

void discoverNodes() {
  Serial.println("开始发现从节点...");
  
  // 发送发现广播
  uint8_t data[8] = {0x00};  // 发现指令
  can.sendMsgBuf(CAN_BROADCAST_ID, 0, 1, data);
  
  delay(100);
  
  // 等待响应
  unsigned long start = millis();
  while (millis() - start < 2000) {
    if (can.checkReceive()) {
      receiveCANMessages();
    }
  }
  
  Serial.print("发现 ");
  Serial.print(getOnlineNodeCount());
  Serial.println(" 个从节点");
}
// 从控制器代码 (Slave)
#include <SimpleFOC.h>
#include <mcp2515_can.h>
#include <SPI.h>

// CAN设置
#define CAN_CS_PIN 10
#define CAN_INT_PIN 2
#define NODE_ID 0x101  // 节点ID
MCP2515 can(CAN_CS_PIN);

// BLDC电机
BLDCMotor motor(7);
Encoder encoder(2, 3, 2048);
void doA() { encoder.handleA(); }
void doB() { encoder.handleB(); }

// 本地模糊控制器
class LocalFuzzyController {
private:
  // 模糊集合
  enum FuzzySet { LOW, MEDIUM, HIGH };
  
  // 输入变量
  float positionError = 0;
  float velocity = 0;
  float current = 0;
  float temperature = 25;
  
  // 输出变量
  float controlOutput = 0;
  float adaptiveKp = 0.5;
  float adaptiveKi = 10.0;
  float adaptiveKd = 0.0;
  
  // 模糊规则表
  struct FuzzyRule {
    FuzzySet error;
    FuzzySet velocity;
    FuzzySet current;
    float kpFactor;
    float kiFactor;
    float kdFactor;
  };
  
  std::vector<FuzzyRule> rules;
  
public:
  LocalFuzzyController() {
    initFuzzyRules();
  }
  
  void update(float targetPos, float currentPos, 
              float currentVel, float motorCurrent,
              float motorTemp, float dt) {
    // 更新输入
    positionError = targetPos - currentPos;
    velocity = currentVel;
    current = motorCurrent;
    temperature = motorTemp;
    
    // 模糊推理
    fuzzyInference();
    
    // 自适应PID
    adaptivePIDControl(targetPos, currentPos, currentVel, dt);
  }
  
  float getControlOutput() { return controlOutput; }
  float getKp() { return adaptiveKp; }
  float getKi() { return adaptiveKi; }
  float getKd() { return adaptiveKd; }
  
private:
  void initFuzzyRules() {
    // 初始化模糊规则
    
    // 规则1: 误差大、速度低、电流小 -> 高增益
    rules.push_back({HIGH, LOW, LOW, 1.5, 1.2, 0.8});
    
    // 规则2: 误差中、速度中、电流中 -> 中增益
    rules.push_back({MEDIUM, MEDIUM, MEDIUM, 1.0, 1.0, 1.0});
    
    // 规则3: 误差小、速度高、电流大 -> 低增益
    rules.push_back({LOW, HIGH, HIGH, 0.8, 0.8, 1.2});
    
    // 规则4: 误差大、速度高、电流中 -> 中高增益
    rules.push_back({HIGH, HIGH, MEDIUM, 1.2, 1.0, 0.9});
    
    // 规则5: 误差小、速度低、电流大 -> 中增益
    rules.push_back({LOW, LOW, HIGH, 1.0, 0.9, 1.1});
  }
  
  void fuzzyInference() {
    // 模糊推理
    
    float numeratorKp = 0, denominatorKp = 0;
    float numeratorKi = 0, denominatorKi = 0;
    float numeratorKd = 0, denominatorKd = 0;
    
    for (const auto& rule : rules) {
      // 计算规则激活度
      float activation = 1.0;
      
      // 计算各输入隶属度
      float errorDegree = getErrorMembership(rule.error);
      float velocityDegree = getVelocityMembership(rule.velocity);
      float currentDegree = getCurrentMembership(rule.current);
      
      // 取最小值
      activation = min(errorDegree, min(velocityDegree, currentDegree));
      
      // 累加
      numeratorKp += activation * rule.kpFactor;
      denominatorKp += activation;
      
      numeratorKi += activation * rule.kiFactor;
      denominatorKi += activation;
      
      numeratorKd += activation * rule.kdFactor;
      denominatorKd += activation;
    }
    
    // 解模糊
    if (denominatorKp > 0) {
      adaptiveKp = 0.5 * (numeratorKp / denominatorKp);
    }
    if (denominatorKi > 0) {
      adaptiveKi = 10.0 * (numeratorKi / denominatorKi);
    }
    if (denominatorKd > 0) {
      adaptiveKd = 0.0 * (numeratorKd / denominatorKd);
    }
  }
  
  float getErrorMembership(FuzzySet set) {
    float errorAbs = abs(positionError);
    
    switch(set) {
      case LOW: return triangularMF(errorAbs, 0, 0, 0.1);
      case MEDIUM: return triangularMF(errorAbs, 0.05, 0.15, 0.25);
      case HIGH: return triangularMF(errorAbs, 0.2, 0.3, 0.5);
      default: return 0;
    }
  }
  
  float getVelocityMembership(FuzzySet set) {
    float velAbs = abs(velocity);
    
    switch(set) {
      case LOW: return triangularMF(velAbs, 0, 1, 3);
      case MEDIUM: return triangularMF(velAbs, 2, 5, 8);
      case HIGH: return triangularMF(velAbs, 6, 10, 15);
      default: return 0;
    }
  }
  
  float getCurrentMembership(FuzzySet set) {
    switch(set) {
      case LOW: return triangularMF(current, 0, 1, 2);
      case MEDIUM: return triangularMF(current, 1.5, 2.5, 3.5);
      case HIGH: return triangularMF(current, 3, 4, 5);
      default: return 0;
    }
  }
  
  float triangularMF(float x, float a, float b, float c) {
    if (x <= a || x >= c) return 0;
    if (x <= b) return (x - a) / (b - a);
    return (c - x) / (c - b);
  }
  
  void adaptivePIDControl(float target, float current, float vel, float dt) {
    // 自适应PID控制
    
    static float integral = 0;
    static float lastError = 0;
    
    float error = target - current;
    
    // 积分项
    integral += error * dt;
    integral = constrain(integral, -1.0, 1.0);
    
    // 微分项
    float derivative = (error - lastError) / dt;
    lastError = error;
    
    // 计算输出
    controlOutput = adaptiveKp * error + 
                   adaptiveKi * integral + 
                   adaptiveKd * derivative;
    
    // 温度补偿
    if (temperature > 50) {
      controlOutput *= 0.9;  // 过热时降低输出
    }
  }
};

LocalFuzzyController fuzzyCtrl;

// CAN消息处理器
class CANMessageHandler {
private:
  struct Command {
    uint8_t type;
    uint32_t data1;
    uint32_t data2;
    uint32_t timestamp;
  };
  
  Command lastCommand;
  uint32_t commandCount = 0;
  
  // 调度参数
  uint32_t controlPeriod = 5000;  // 默认5ms
  float priority = 0.5;
  
public:
  void processMessage(uint8_t* data, uint8_t len) {
    if (len < 1) return;
    
    uint8_t cmdType = data[0];
    
    switch(cmdType) {
      case 0x01:  // 控制指令
        if (len >= 4) {
          controlPeriod = (data[1] << 8) | data[2];
          priority = data[3] / 100.0;
          Serial.print("收到调度: 周期=");
          Serial.print(controlPeriod);
          Serial.print("us, 优先级=");
          Serial.println(priority);
        }
        break;
        
      case 0x02:  // 停止指令
        emergencyStop();
        break;
        
      case 0x03:  // 回零指令
        startHoming();
        break;
        
      case 0x04:  // 恢复指令
        recover();
        break;
    }
    
    lastCommand.type = cmdType;
    lastCommand.timestamp = millis();
    commandCount++;
  }
  
  uint32_t getControlPeriod() { return controlPeriod; }
  float getPriority() { return priority; }
  
private:
  void emergencyStop() {
    // 紧急停止
    motor.disable();
    Serial.println("紧急停止");
  }
  
  void startHoming() {
    // 开始回零
    Serial.println("开始回零");
    // 回零逻辑...
  }
  
  void recover() {
    // 恢复运行
    motor.enable();
    Serial.println("恢复运行");
  }
};

CANMessageHandler canHandler;

void setup() {
  Serial.begin(115200);
  Serial.print("从节点 ");
  Serial.print(NODE_ID, HEX);
  Serial.println(" 启动");
  
  // 初始化电机
  initMotor();
  
  // 初始化CAN
  initCAN();
  
  // 发送上线消息
  sendOnlineMessage();
  
  Serial.println("从节点就绪");
}

void loop() {
  static unsigned long lastControlTime = 0;
  static unsigned long lastHeartbeat = 0;
  
  // 接收CAN消息
  if (can.checkReceive()) {
    uint8_t len = 0;
    uint8_t buf[8];
    
    if (can.readMsgBuf(&len, buf) == CAN_OK) {
      canHandler.processMessage(buf, len);
    }
  }
  
  // 控制循环
  unsigned long now = micros();
  uint32_t period = canHandler.getControlPeriod();
  
  if (now - lastControlTime >= period) {
    float dt = (now - lastControlTime) / 1000000.0;
    
    // 1. 读取传感器
    float currentPos = motor.shaft_angle;
    float currentVel = motor.shaft_velocity;
    float currentCur = getMotorCurrent();
    float temperature = getTemperature();
    
    // 2. 获取目标(从CAN或本地)
    float targetPos = getTargetPosition();
    
    // 3. 模糊控制
    fuzzyCtrl.update(targetPos, currentPos, currentVel, currentCur, temperature, dt);
    
    // 4. 应用控制
    motor.move(fuzzyCtrl.getControlOutput());
    
    // 5. 执行FOC
    motor.loopFOC();
    
    // 6. 发送状态报告
    if (now - lastHeartbeat >= 100000) {  // 100ms
      sendStatusReport(currentPos, currentVel, currentCur, temperature);
      lastHeartbeat = now;
    }
    
    lastControlTime = now;
  }
}

void sendOnlineMessage() {
  uint8_t data[8];
  data[0] = 0x80;  // 上线消息
  data[1] = NODE_ID;
  
  can.sendMsgBuf(CAN_MASTER_ID, 0, 2, data);
  Serial.println("发送上线消息");
}

5、无线Mesh网络协同控制
场景:移动机器人集群,无线通信
核心逻辑:ESP-NOW Mesh网络 + 分布式共识算法

// Mesh网络主节点
#include <SimpleFOC.h>
#include <esp_now.h>
#include <WiFi.h>

// 网络配置
#define MAX_NODES 8
#define CHANNEL 1
uint8_t broadcastMac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

// 网络节点
struct MeshNode {
  uint8_t mac[6];
  uint8_t nodeId;
  float position[3];  // x, y, theta
  float velocity[3];
  float battery;
  int8_t rssi;
  uint32_t lastSeen;
  float trustScore;  // 信任度评分
};
std::vector<MeshNode> meshNodes;

// 分布式共识算法
class DistributedConsensus {
private:
  // 共识状态
  struct ConsensusState {
    float targetPosition[3];
    float formationError;
    float consensusError;
    int iteration;
    bool converged;
  };
  ConsensusState consensus;
  
  // 通信图
  float adjacencyMatrix[MAX_NODES][MAX_NODES];
  
  // 模糊一致性
  struct FuzzyConsensusRule {
    float distance;
    float velocityDiff;
    float trustScore;
    float weight;
  };
  std::vector<FuzzyConsensusRule> consensusRules;
  
public:
  DistributedConsensus() {
    initConsensusRules();
    initCommunicationGraph();
  }
  
  void updateConsensus(std::vector<MeshNode>& nodes) {
    // 更新分布式共识
    
    if (nodes.empty()) return;
    
    // 计算一致性误差
    calculateConsensusError(nodes);
    
    // 模糊加权平均
    calculateTargetPosition(nodes);
    
    // 检查收敛
    checkConvergence();
    
    // 迭代计数
    consensus.iteration++;
  }
  
  void calculateTargetPosition(std::vector<MeshNode>& nodes) {
    // 计算目标位置
    
    float sumX = 0, sumY = 0, sumTheta = 0;
    float totalWeight = 0;
    
    for (int i = 0; i < nodes.size(); i++) {
      float weight = calculateNodeWeight(nodes[i], i);
      
      sumX += nodes[i].position[0] * weight;
      sumY += nodes[i].position[1] * weight;
      sumTheta += nodes[i].position[2] * weight;
      totalWeight += weight;
    }
    
    if (totalWeight > 0) {
      consensus.targetPosition[0] = sumX / totalWeight;
      consensus.targetPosition[1] = sumY / totalWeight;
      consensus.targetPosition[2] = sumTheta / totalWeight;
    }
  }
  
private:
  void initConsensusRules() {
    // 初始化模糊共识规则
    
    // 规则1: 距离近、速度差小、信任度高 -> 高权重
    consensusRules.push_back({0.5, 0.2, 0.9, 1.0});
    
    // 规则2: 距离中、速度差中、信任度中 -> 中权重
    consensusRules.push_back({1.0, 0.5, 0.7, 0.7});
    
    // 规则3: 距离远、速度差大、信任度低 -> 低权重
    consensusRules.push_back({2.0, 1.0, 0.4, 0.3});
  }
  
  void initCommunicationGraph() {
    // 初始化通信图
    for (int i = 0; i < MAX_NODES; i++) {
      for (int j = 0; j < MAX_NODES; j++) {
        if (i == j) {
          adjacencyMatrix[i][j] = 1.0;
        } else {
          adjacencyMatrix[i][j] = 0.5;  // 默认连接强度
        }
      }
    }
  }
  
  float calculateNodeWeight(const MeshNode& node, int index) {
    // 计算节点权重
    
    float weightSum = 0;
    float activationSum = 0;
    
    for (const auto& rule : consensusRules) {
      // 计算匹配度
      float distanceMatch = triangularMF(node.trustScore, rule.trustScore - 0.2, 
                                       rule.trustScore, rule.trustScore + 0.2);
      
      // 这里简化计算
      float activation = distanceMatch;
      
      weightSum += activation * rule.weight;
      activationSum += activation;
    }
    
    if (activationSum > 0) {
      return weightSum / activationSum;
    }
    return 0.5;  // 默认权重
  }
  
  void calculateConsensusError(std::vector<MeshNode>& nodes) {
    // 计算一致性误差
    
    if (nodes.size() < 2) {
      consensus.consensusError = 0;
      return;
    }
    
    float errorSum = 0;
    int pairCount = 0;
    
    for (int i = 0; i < nodes.size(); i++) {
      for (int j = i + 1; j < nodes.size(); j++) {
        float dx = nodes[i].position[0] - nodes[j].position[0];
        float dy = nodes[i].position[1] - nodes[j].position[1];
        float distance = sqrt(dx*dx + dy*dy);
        
        float desiredDistance = 1.0;  // 期望间距
        errorSum += abs(distance - desiredDistance);
        pairCount++;
      }
    }
    
    if (pairCount > 0) {
      consensus.consensusError = errorSum / pairCount;
    }
  }
  
  void checkConvergence() {
    // 检查共识收敛
    consensus.converged = (consensus.consensusError < 0.1 && 
                          consensus.iteration > 10);
  }
  
  float triangularMF(float x, float a, float b, float c) {
    if (x <= a || x >= c) return 0;
    if (x <= b) return (x - a) / (b - a);
    return (c - x) / (c - b);
  }
};

// 模糊任务调度器
class FuzzyTaskScheduler {
private:
  // 任务定义
  struct Task {
    uint8_t taskId;
    uint8_t priority;
    float deadline;
    float executionTime;
    float resourceNeed[3];  // CPU, 内存, 带宽
    uint8_t assignedNode;
  };
  
  std::vector<Task> taskQueue;
  
  // 模糊调度规则
  struct SchedulingRule {
    float urgency;
    float complexity;
    float resourceAvailability;
    float schedulingScore;
  };
  std::vector<SchedulingRule> schedulingRules;
  
public:
  void scheduleTasks(std::vector<MeshNode>& nodes) {
    // 调度任务
    
    for (auto& task : taskQueue) {
      if (task.assignedNode != 0) continue;  // 已分配
      
      // 计算最佳节点
      int bestNode = findBestNode(task, nodes);
      if (bestNode >= 0) {
        task.assignedNode = bestNode;
        sendTaskAssignment(task, nodes[bestNode]);
      }
    }
  }
  
private:
  int findBestNode(Task& task, std::vector<MeshNode>& nodes) {
    // 寻找最佳节点
    
    int bestNode = -1;
    float bestScore = -1;
    
    for (int i = 0; i < nodes.size(); i++) {
      float score = calculateNodeScore(task, nodes[i]);
      
      if (score > bestScore) {
        bestScore = score;
        bestNode = i;
      }
    }
    
    return bestNode;
  }
  
  float calculateNodeScore(Task& task, MeshNode& node) {
    // 计算节点得分
    
    // 计算紧急度
    float urgency = 1.0 - (task.deadline / 10.0);  // 简化计算
    
    // 计算复杂度
    float complexity = task.executionTime / 1.0;
    
    // 计算资源可用性
    float batteryAvailability = node.battery / 100.0;
    float signalAvailability = (node.rssi + 100) / 50.0;  // RSSI转可用性
    
    // 模糊推理
    float score = fuzzyScheduling(urgency, complexity, 
                                 batteryAvailability, signalAvailability);
    
    return score;
  }
  
  float fuzzyScheduling(float urgency, float complexity, 
                       float battery, float signal) {
    // 模糊调度
    
    // 简化实现
    float score = 0;
    
    if (urgency > 0.8 && battery > 0.7) {
      score = 0.9;  // 紧急且电量足
    } else if (complexity < 0.5 && signal > 0.8) {
      score = 0.8;  // 简单且信号好
    } else if (urgency > 0.6 && battery > 0.5) {
      score = 0.7;
    } else {
      score = 0.5;
    }
    
    return score;
  }
  
  void sendTaskAssignment(Task& task, MeshNode& node) {
    // 发送任务分配
    uint8_t data[32];
    
    data[0] = 0xA0;  // 任务分配指令
    data[1] = task.taskId;
    data[2] = task.priority;
    
    // 发送到指定节点
    esp_now_send(node.mac, data, 32);
  }
};

6、时间触发架构协同控制
场景:高实时性要求的同步系统
核心逻辑:时间触发协议 + 精确时钟同步 + 容错调度

// 时间触发主节点
#include <SimpleFOC.h>
#include <TimeLib.h>
#include <vector>

// 时间触发参数
#define TDMA_SLOTS 16
#define SLOT_DURATION 1000  // 1ms
#define SYNC_PERIOD 10000   // 10ms同步一次

// TDMA时隙分配
struct TimeSlot {
  uint8_t slotId;
  uint8_t nodeId;
  uint32_t startTime;
  uint32_t duration;
  uint8_t priority;
  bool allocated;
};
TimeSlot timeSlots[TDMA_SLOTS];

// 精确时钟同步
class PreciseClockSync {
private:
  struct SyncData {
    uint32_t localTime;
    uint32_t masterTime;
    int32_t offset;
    float drift;
    uint32_t syncCount;
  };
  SyncData sync;
  
  // 卡尔曼滤波
  float P = 1.0;  // 估计误差协方差
  float Q = 0.01; // 过程噪声
  float R = 0.1;  // 测量噪声
  
public:
  void synchronize(uint32_t masterTime) {
    // 时钟同步
    uint32_t localTime = micros();
    
    // 计算偏移
    int32_t measuredOffset = masterTime - localTime;
    
    // 卡尔曼滤波
    float K = P / (P + R);  // 卡尔曼增益
    sync.offset += K * (measuredOffset - sync.offset);
    P = (1 - K) * P + Q;
    
    // 计算漂移
    if (sync.syncCount > 0) {
      int32_t offsetChange = measuredOffset - sync.offset;
      uint32_t timeChange = localTime - sync.localTime;
      
      if (timeChange > 0) {
        sync.drift = offsetChange / (float)timeChange;
      }
    }
    
    sync.localTime = localTime;
    sync.masterTime = masterTime;
    sync.syncCount++;
  }
  
  uint32_t getGlobalTime() {
    // 获取全局时间
    uint32_t currentLocal = micros();
    uint32_t elapsed = currentLocal - sync.localTime;
    
    // 应用偏移和漂移
    uint32_t globalTime = sync.masterTime + sync.offset + 
                         (uint32_t)(elapsed * (1.0 + sync.drift));
    
    return globalTime;
  }
  
  float getSyncAccuracy() {
    // 获取同步精度
    return 1.0 / (1.0 + P);  // 协方差越小,精度越高
  }
};

PreciseClockSync clockSync;

// 模糊时隙调度器
class FuzzySlotScheduler {
private:
  // 节点需求
  struct NodeRequirement {
    uint8_t nodeId;
    float bandwidthNeed;
    float latencyNeed;
    float reliabilityNeed;
    float urgency;
  };
  
  // 时隙质量
  struct SlotQuality {
    uint8_t slotId;
    float signalQuality;
    float interference;
    float historicalReliability;
  };
  
  // 模糊匹配规则
  struct MatchingRule {
    float bandwidthMatch;
    float latencyMatch;
    float reliabilityMatch;
    float allocationScore;
  };
  std::vector<MatchingRule> matchingRules;
  
public:
  void allocateSlots(std::vector<NodeRequirement>& requirements, 
                     SlotQuality* slotQualities) {
    // 分配时隙
    
    // 清空时隙分配
    for (int i = 0; i < TDMA_SLOTS; i++) {
      timeSlots[i].allocated = false;
    }
    
    // 按紧急度排序
    std::sort(requirements.begin(), requirements.end(),
              [](const NodeRequirement& a, const NodeRequirement& b) {
                return a.urgency > b.urgency;
              });
    
    // 为每个节点分配时隙
    for (auto& req : requirements) {
      allocateSlotForNode(req, slotQualities);
    }
  }
  
private:
  void allocateSlotForNode(NodeRequirement& req, SlotQuality* qualities) {
    // 为单个节点分配时隙
    
    int bestSlot = -1;
    float bestScore = -1;
    
    for (int i = 0; i < TDMA_SLOTS; i++) {
      if (timeSlots[i].allocated) continue;
      
      // 计算匹配度
      float score = calculateMatchScore(req, qualities[i]);
      
      if (score > bestScore) {
        bestScore = score;
        bestSlot = i;
      }
    }
    
    if (bestSlot >= 0) {
      // 分配时隙
      timeSlots[bestSlot].nodeId = req.nodeId;
      timeSlots[bestSlot].allocated = true;
      timeSlots[bestSlot].priority = (uint8_t)(req.urgency * 10);
      
      // 计算开始时间
      timeSlots[bestSlot].startTime = calculateStartTime(bestSlot);
      
      // 发送分配指令
      sendSlotAllocation(req.nodeId, bestSlot);
    }
  }
  
  float calculateMatchScore(NodeRequirement& req, SlotQuality& quality) {
    // 计算匹配度
    
    float scoreSum = 0;
    float activationSum = 0;
    
    for (const auto& rule : matchingRules) {
      // 计算各维度匹配度
      float bandwidthMatch = triangularMF(req.bandwidthNeed, 
                                         rule.bandwidthMatch - 0.2,
                                         rule.bandwidthMatch,
                                         rule.bandwidthMatch + 0.2);
      
      float reliabilityMatch = triangularMF(quality.historicalReliability,
                                           rule.reliabilityMatch - 0.2,
                                           rule.reliabilityMatch,
                                           rule.reliabilityMatch + 0.2);
      
      // 取最小值作为激活度
      float activation = min(bandwidthMatch, reliabilityMatch);
      
      scoreSum += activation * rule.allocationScore;
      activationSum += activation;
    }
    
    if (activationSum > 0) {
      return scoreSum / activationSum;
    }
    return 0.5;
  }
  
  uint32_t calculateStartTime(uint8_t slotId) {
    // 计算时隙开始时间
    uint32_t currentTime = clockSync.getGlobalTime();
    uint32_t cycleTime = TDMA_SLOTS * SLOT_DURATION;
    
    // 对齐到时隙边界
    uint32_t cycleStart = (currentTime / cycleTime) * cycleTime;
    uint32_t slotStart = cycleStart + slotId * SLOT_DURATION;
    
    // 如果已经过了这个时隙,安排到下一个周期
    if (slotStart < currentTime) {
      slotStart += cycleTime;
    }
    
    return slotStart;
  }
  
  float triangularMF(float x, float a, float b, float c) {
    if (x <= a || x >= c) return 0;
    if (x <= b) return (x - a) / (b - a);
    return (c - x) / (c - b);
  }
  
  void sendSlotAllocation(uint8_t nodeId, uint8_t slotId) {
    // 发送时隙分配
    uint8_t data[8];
    
    data[0] = 0xB0;  // 时隙分配指令
    data[1] = nodeId;
    data[2] = slotId;
    data[3] = (timeSlots[slotId].startTime >> 24) & 0xFF;
    data[4] = (timeSlots[slotId].startTime >> 16) & 0xFF;
    data[5] = (timeSlots[slotId].startTime >> 8) & 0xFF;
    data[6] = timeSlots[slotId].startTime & 0xFF;
    
    // 通过CAN或无线发送
  }
};

// 容错调度管理器
class FaultTolerantScheduler {
private:
  // 故障检测
  struct FaultDetection {
    uint8_t nodeId;
    uint32_t lastHeartbeat;
    uint8_t missedBeats;
    float faultProbability;
    uint8_t faultType;  // 0=无故障, 1=通信, 2=控制, 3=电源
  };
  std::vector<FaultDetection> faultStates;
  
  // 模糊故障规则
  struct FaultRule {
    float missedBeats;
    float signalQuality;
    float voltageLevel;
    float faultLevel;
  };
  std::vector<FaultRule> faultRules;
  
  // 冗余配置
  struct RedundancyConfig {
    uint8_t primaryNode;
    uint8_t backupNode;
    uint8_t takeoverMode;  // 0=热备份, 1=冷备份, 2=温备份
    float switchThreshold;
  };
  std::vector<RedundancyConfig> redundancyConfigs;
  
public:
  void monitorNodes(std::vector<MeshNode>& nodes) {
    // 监控节点状态
    
    for (auto& node : nodes) {
      FaultDetection* detection = getFaultDetection(node.nodeId);
      
      if (!detection) {
        // 新节点
        detection = addFaultDetection(node.nodeId);
      }
      
      // 更新心跳
      uint32_t currentTime = millis();
      uint32_t timeSinceLast = currentTime - detection->lastHeartbeat;
      
      if (timeSinceLast > 100) {  // 100ms
        detection->missedBeats++;
      } else {
        detection->missedBeats = 0;
      }
      
      // 计算故障概率
      detection->faultProbability = calculateFaultProbability(*detection, node);
      
      // 检查是否需要切换
      if (detection->faultProbability > 0.8) {
        triggerRedundancySwitch(node.nodeId);
      }
      
      detection->lastHeartbeat = currentTime;
    }
  }
  
private:
  float calculateFaultProbability(FaultDetection& detection, MeshNode& node) {
    // 计算故障概率
    
    float probability = 0;
    
    for (const auto& rule : faultRules) {
      // 计算匹配度
      float beatsMatch = triangularMF(detection.missedBeats,
                                     rule.missedBeats - 1,
                                     rule.missedBeats,
                                     rule.missedBeats + 1);
      
      float signalMatch = triangularMF((node.rssi + 100) / 50.0,
                                      rule.signalQuality - 0.2,
                                      rule.signalQuality,
                                      rule.signalQuality + 0.2);
      
      float voltageMatch = triangularMF(node.battery / 100.0,
                                       rule.voltageLevel - 0.1,
                                       rule.voltageLevel,
                                       rule.voltageLevel + 0.1);
      
      // 模糊推理
      float activation = min(beatsMatch, min(signalMatch, voltageMatch));
      probability += activation * rule.faultLevel;
    }
    
    return min(probability, 1.0);
  }
  
  void triggerRedundancySwitch(uint8_t faultyNode) {
    // 触发冗余切换
    
    for (auto& config : redundancyConfigs) {
      if (config.primaryNode == faultyNode) {
        // 切换到备份节点
        switchToBackup(config);
        
        // 记录故障
        logFault(faultyNode, config.backupNode);
        break;
      }
    }
  }
  
  void switchToBackup(RedundancyConfig& config) {
    // 切换到备份节点
    
    Serial.print("切换: 主节点");
    Serial.print(config.primaryNode);
    Serial.print(" -> 备份节点");
    Serial.println(config.backupNode);
    
    // 更新时隙分配
    for (int i = 0; i < TDMA_SLOTS; i++) {
      if (timeSlots[i].nodeId == config.primaryNode) {
        timeSlots[i].nodeId = config.backupNode;
        
        // 通知备份节点
        notifyBackupTakeover(config.backupNode, i);
      }
    }
  }
  
  FaultDetection* getFaultDetection(uint8_t nodeId) {
    for (auto& detection : faultStates) {
      if (detection.nodeId == nodeId) {
        return &detection;
      }
    }
    return nullptr;
  }
  
  FaultDetection* addFaultDetection(uint8_t nodeId) {
    FaultDetection detection = {nodeId, millis(), 0, 0.0, 0};
    faultStates.push_back(detection);
    return &faultStates.back();
  }
  
  void logFault(uint8_t faultyNode, uint8_t backupNode) {
    // 记录故障日志
    Serial.print("故障记录: 节点");
    Serial.print(faultyNode);
    Serial.print(" 切换到 ");
    Serial.println(backupNode);
  }
  
  void notifyBackupTakeover(uint8_t backupNode, uint8_t slotId) {
    // 通知备份节点接管
    uint8_t data[8];
    
    data[0] = 0xC0;  // 接管指令
    data[1] = backupNode;
    data[2] = slotId;
    
    // 发送接管指令
  }
};

要点解读

  1. 模糊调度在分布式系统的核心价值
    不确定信息处理:能够处理节点状态、网络质量、负载等不确定信息
    自适应决策:根据实时情况动态调整调度策略,无需精确数学模型
    多目标优化:同时考虑响应时间、能耗、可靠性等多个目标
    容错能力:在部分节点故障时仍能维持系统功能
    人机交互友好:调度规则用自然语言描述,易于理解和调整
  2. CAN总线在实时系统的优势
    确定性延迟:消息传递时间可预测,适合实时控制
    优先级仲裁:支持消息优先级,确保关键指令及时传递
    多主架构:任何节点都可以发送消息,支持分布式决策
    错误检测:内置CRC校验和错误帧重发机制
    物理层可靠:差分信号抗干扰能力强,适合工业环境
  3. 无线Mesh网络的协同控制策略
    自组织网络:节点自动发现和组网,无需固定基础设施
    多跳通信:通过中继扩大通信范围,适应大范围部署
    动态路由:根据网络状况动态选择最优路径
    负载均衡:在多条路径间分配流量,避免拥塞
    容错拓扑:节点故障时自动重建通信路径
  4. 时间触发架构的精确同步
    全局时钟:所有节点共享统一的时间基准
    时分多址:为每个节点分配专用时隙,避免冲突
    确定性调度:所有通信和计算的时间可预先确定
    容错设计:支持时钟漂移补偿和时隙动态调整
    资源预留:为关键任务预留带宽,保证服务质量
  5. 分布式系统的容错机制
    心跳检测:定期检查节点存活状态
    冗余设计:关键节点配备备份,支持热切换
    故障隔离:故障节点不影响整个系统运行
    自动恢复:故障恢复后自动重新加入系统
    状态同步:备份节点与主节点状态保持同步

注意,以上案例只是为了拓展思路,仅供参考。它们可能有错误、不适用或者无法编译。您的硬件平台、使用场景和Arduino版本可能影响使用方法的选择。实际编程时,您要根据自己的硬件配置、使用场景和具体需求进行调整,并多次实际测试。您还要正确连接硬件,了解所用传感器和设备的规范和特性。涉及硬件操作的代码,您要在使用前确认引脚和电平等参数的正确性和安全性。

在这里插入图片描述

Logo

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

更多推荐