【花雕学编程】Arduino BLDC 之机器人分布式模糊调度(多MCU协同)

基于 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;
// 发送接管指令
}
};
要点解读
- 模糊调度在分布式系统的核心价值
不确定信息处理:能够处理节点状态、网络质量、负载等不确定信息
自适应决策:根据实时情况动态调整调度策略,无需精确数学模型
多目标优化:同时考虑响应时间、能耗、可靠性等多个目标
容错能力:在部分节点故障时仍能维持系统功能
人机交互友好:调度规则用自然语言描述,易于理解和调整 - CAN总线在实时系统的优势
确定性延迟:消息传递时间可预测,适合实时控制
优先级仲裁:支持消息优先级,确保关键指令及时传递
多主架构:任何节点都可以发送消息,支持分布式决策
错误检测:内置CRC校验和错误帧重发机制
物理层可靠:差分信号抗干扰能力强,适合工业环境 - 无线Mesh网络的协同控制策略
自组织网络:节点自动发现和组网,无需固定基础设施
多跳通信:通过中继扩大通信范围,适应大范围部署
动态路由:根据网络状况动态选择最优路径
负载均衡:在多条路径间分配流量,避免拥塞
容错拓扑:节点故障时自动重建通信路径 - 时间触发架构的精确同步
全局时钟:所有节点共享统一的时间基准
时分多址:为每个节点分配专用时隙,避免冲突
确定性调度:所有通信和计算的时间可预先确定
容错设计:支持时钟漂移补偿和时隙动态调整
资源预留:为关键任务预留带宽,保证服务质量 - 分布式系统的容错机制
心跳检测:定期检查节点存活状态
冗余设计:关键节点配备备份,支持热切换
故障隔离:故障节点不影响整个系统运行
自动恢复:故障恢复后自动重新加入系统
状态同步:备份节点与主节点状态保持同步
注意,以上案例只是为了拓展思路,仅供参考。它们可能有错误、不适用或者无法编译。您的硬件平台、使用场景和Arduino版本可能影响使用方法的选择。实际编程时,您要根据自己的硬件配置、使用场景和具体需求进行调整,并多次实际测试。您还要正确连接硬件,了解所用传感器和设备的规范和特性。涉及硬件操作的代码,您要在使用前确认引脚和电平等参数的正确性和安全性。

更多推荐


所有评论(0)