AI 传感器融合:多源异构数据的边缘实时处理架构

AI 传感器融合:多源异构数据的边缘实时处理架构

一、单一传感器的感知盲区

工业设备的状态监测,靠单一传感器远远不够。振动传感器能捕捉机械磨损,但对电气故障无感;温度传感器能发现过热,但响应慢,等温度异常时轴承可能已经损坏;电流传感器能检测电机负载,但无法区分正常负载波动和早期故障。三个传感器各看各的,漏报率居高不下。

传感器融合的核心价值是:多个传感器的信息互补,1+1+1>3。振动突然增大+温度缓慢上升+电流纹波增加,单独看每个信号都在正常范围内,但组合起来就是轴承早期故障的典型模式。问题在于,三个传感器的采样率不同(振动 10kHz、温度 1Hz、电流 1kHz),数据格式不同(加速度、摄氏度、安培),时间戳精度不同。在 MCU 上做实时融合,必须解决时间对齐、特征同步和决策聚合三个核心问题。

二、多传感器融合的架构设计

2.1 三级融合模型

传感器融合分为数据级、特征级、决策级三个层次。

数据级融合:原始数据直接拼接,送入模型。信息保留最完整,但对时间对齐和采样率匹配要求最高。适合传感器同质、采样率接近的场景。

特征级融合:每个传感器独立提取特征,特征向量拼接后送入融合模型。对时间对齐要求降低,但特征提取可能丢失信息。适合传感器异质、采样率差异大的场景。

决策级融合:每个传感器独立推理,输出概率,再通过加权投票或贝叶斯融合得到最终决策。最灵活,但信息损失最大。适合传感器完全独立、通信带宽受限的场景。

2.2 边缘融合系统架构

flowchart TD subgraph 传感器层 A1[振动传感器 10kHz] A2[温度传感器 1Hz] A3[电流传感器 1kHz] end subgraph 数据采集层 B1[DMA缓冲区] B2[环形缓冲区] B3[DMA缓冲区] end subgraph 特征提取层 C1[FFT频谱提取] C2[滑动窗口均值] C3[谐波分析] end subgraph 融合推理层 D1[时间对齐模块] D2[特征向量拼接] D3[轻量推理模型] end subgraph 决策输出层 E1[故障概率输出] E2[告警等级判定] E3[结果上报] end A1 --> B1 --> C1 A2 --> B2 --> C2 A3 --> B3 --> C3 C1 & C2 & C3 --> D1 D1 --> D2 --> D3 D3 --> E1 --> E2 --> E3 style A1 fill:#4dabf7,color:#fff style A2 fill:#4dabf7,color:#fff style A3 fill:#4dabf7,color:#fff style D3 fill:#ffd43b,color:#333 style E2 fill:#ff6b6b,color:#fff

三、边缘传感器融合的工程实现

3.1 多速率数据采集与时间对齐

c 复制代码
#include <stdint.h>
#include <string.h>
#include <math.h>

/* 传感器数据包头 */
typedef struct __attribute__((packed)) {
    uint32_t timestamp_ms;    /* 毫秒级时间戳 */
    uint8_t  sensor_type;     /* 传感器类型 */
    uint8_t  sample_rate_hz;  /* 采样率标识 */
    uint16_t payload_len;     /* 负载长度 */
} SensorHeader;

/* 振动传感器采样数据 */
typedef struct {
    float accel_x;   /* X轴加速度 (m/s²) */
    float accel_y;   /* Y轴加速度 */
    float accel_z;   /* Z轴加速度 */
} VibrationSample;

/* 温度传感器采样数据 */
typedef struct {
    float temperature;  /* 温度 (°C) */
} TemperatureSample;

/* 电流传感器采样数据 */
typedef struct {
    float current_rms;  /* 电流有效值 (A) */
    float thd;          /* 总谐波失真 (%) */
} CurrentSample;

/* 多速率环形缓冲区
 * 每个传感器独立的环形缓冲区,
 * 支持不同采样率的数据存储
 */
#define RING_BUFFER_SIZE 4096

typedef struct {
    uint8_t  data[RING_BUFFER_SIZE];
    uint32_t head;         /* 写入位置 */
    uint32_t tail;         /* 读取位置 */
    uint32_t count;        /* 当前数据量 */
    uint32_t sample_size;  /* 单个采样大小 */
} RingBuffer;

void ring_buffer_init(RingBuffer *rb, uint32_t sample_size) {
    memset(rb, 0, sizeof(RingBuffer));
    rb->sample_size = sample_size;
}

/* 写入一个采样(DMA中断中调用) */
int ring_buffer_write(RingBuffer *rb, const void *sample) {
    if (rb->count + rb->sample_size > RING_BUFFER_SIZE) {
        return -1;  /* 缓冲区满 */
    }

    memcpy(rb->data + rb->head, sample, rb->sample_size);
    rb->head = (rb->head + rb->sample_size) % RING_BUFFER_SIZE;
    rb->count += rb->sample_size;
    return 0;
}

/* 读取一个采样 */
int ring_buffer_read(RingBuffer *rb, void *sample) {
    if (rb->count < rb->sample_size) {
        return -1;  /* 缓冲区空 */
    }

    memcpy(sample, rb->data + rb->tail, rb->sample_size);
    rb->tail = (rb->tail + rb->sample_size) % RING_BUFFER_SIZE;
    rb->count -= rb->sample_size;
    return 0;
}

/* 时间对齐模块
 * 核心问题:不同采样率的传感器数据如何对齐到同一时间轴?
 * 策略:以最低采样率传感器的时间戳为基准,
 * 高采样率传感器在基准时刻取最近邻采样
 */
typedef struct {
    uint32_t target_timestamp_ms;  /* 目标对齐时间戳 */
    /* 各传感器最近一次采样的缓存 */
    VibrationSample  vibration;    /* 振动:取目标时刻前最近的采样 */
    TemperatureSample temperature; /* 温度:线性插值 */
    CurrentSample    current;      /* 电流:取目标时刻前最近的采样 */
    /* 时间戳记录 */
    uint32_t vib_timestamp;
    uint32_t temp_timestamp_prev;
    uint32_t temp_timestamp_curr;
    uint32_t curr_timestamp;
    bool     data_ready;           /* 所有传感器数据就绪标志 */
} AlignedData;

/* 时间对齐处理
 * 每次温度传感器有新数据时触发(最低采样率)
 * 收集其他传感器在对应时刻的数据
 */
void align_sensor_data(
    AlignedData *aligned,
    const RingBuffer *vib_rb,
    const RingBuffer *temp_rb,
    const RingBuffer *curr_rb,
    uint32_t current_time_ms
) {
    /* 以温度采样周期为对齐基准 */
    TemperatureSample temp_sample;
    if (ring_buffer_read((RingBuffer *)temp_rb, &temp_sample) != 0) {
        return;  /* 温度数据未就绪 */
    }

    aligned->target_timestamp_ms = current_time_ms;
    aligned->temperature = temp_sample;

    /* 振动传感器:取最近的采样 */
    VibrationSample vib_sample;
    /* 从环形缓冲区读取最新的一个采样 */
    if (ring_buffer_read((RingBuffer *)vib_rb, &vib_sample) == 0) {
        aligned->vibration = vib_sample;
        aligned->vib_timestamp = current_time_ms;
    }

    /* 电流传感器:取最近的采样 */
    CurrentSample curr_sample;
    if (ring_buffer_read((RingBuffer *)curr_rb, &curr_sample) == 0) {
        aligned->current = curr_sample;
        aligned->curr_timestamp = current_time_ms;
    }

    aligned->data_ready = true;
}

3.2 特征提取与融合推理

c 复制代码
/* 特征提取:从原始采样中提取统计特征 */

typedef struct {
    /* 振动特征 */
    float vib_rms;           /* RMS值 */
    float vib_peak;          /* 峰值 */
    float vib_crest_factor;  /* 峭度系数 */
    float vib_dominant_freq; /* 主频 */

    /* 温度特征 */
    float temp_value;        /* 当前温度 */
    float temp_delta;        /* 温度变化率 */

    /* 电流特征 */
    float curr_rms;          /* 电流RMS */
    float curr_thd;          /* 谐波失真 */
} FusedFeatures;

/* 从振动缓冲区提取特征 */
void extract_vibration_features(
    const VibrationSample *samples,
    int num_samples,
    float sample_rate_hz,
    FusedFeatures *features
) {
    float sum_sq = 0.0f;
    float peak = 0.0f;

    /* 计算RMS和峰值 */
    for (int i = 0; i < num_samples; i++) {
        float magnitude = sqrtf(
            samples[i].accel_x * samples[i].accel_x +
            samples[i].accel_y * samples[i].accel_y +
            samples[i].accel_z * samples[i].accel_z
        );
        sum_sq += magnitude * magnitude;
        if (magnitude > peak) {
            peak = magnitude;
        }
    }

    features->vib_rms = sqrtf(sum_sq / num_samples);
    features->vib_peak = peak;
    features->vib_crest_factor = peak / features->vib_rms;

    /* 简化的主频检测:找RMS最大的频段
     * 生产环境应使用完整的FFT
     */
    features->vib_dominant_freq = 0.0f;
    /* FFT计算省略,使用ARM CMSIS-DSP的arm_rfft_fast_f64 */
}

/* 从温度历史提取特征 */
void extract_temperature_features(
    const TemperatureSample *current,
    const TemperatureSample *previous,
    float interval_sec,
    FusedFeatures *features
) {
    features->temp_value = current->temperature;
    if (interval_sec > 0.0f) {
        features->temp_delta =
            (current->temperature - previous->temperature) / interval_sec;
    } else {
        features->temp_delta = 0.0f;
    }
}

/* 从电流数据提取特征 */
void extract_current_features(
    const CurrentSample *sample,
    FusedFeatures *features
) {
    features->curr_rms = sample->current_rms;
    features->curr_thd = sample->thd;
}

/* 融合推理:基于规则的轻量决策(MCU上不用深度模型) */
typedef struct {
    float normal_prob;      /* 正常概率 */
    float warning_prob;     /* 预警概率 */
    float fault_prob;       /* 故障概率 */
    uint8_t fault_type;     /* 故障类型编码 */
} FusionResult;

/* 基于阈值的融合决策
 * 在MCU上,规则引擎比神经网络更可靠
 * 规则可解释、延迟确定、不依赖训练数据
 */
FusionResult fuse_and_decide(const FusedFeatures *features) {
    FusionResult result = {0};

    /* 振动异常评分 */
    float vib_score = 0.0f;
    if (features->vib_rms > 5.0f) vib_score += 0.4f;
    if (features->vib_crest_factor > 6.0f) vib_score += 0.3f;
    if (features->vib_dominant_freq > 1000.0f) vib_score += 0.3f;

    /* 温度异常评分 */
    float temp_score = 0.0f;
    if (features->temp_value > 80.0f) temp_score += 0.5f;
    if (features->temp_delta > 2.0f) temp_score += 0.5f;

    /* 电流异常评分 */
    float curr_score = 0.0f;
    if (features->curr_rms > 15.0f) curr_score += 0.4f;
    if (features->curr_thd > 10.0f) curr_score += 0.6f;

    /* 加权融合:振动权重最高(对机械故障最敏感) */
    float total_score =
        vib_score * 0.5f + temp_score * 0.2f + curr_score * 0.3f;

    /* 映射到概率 */
    result.normal_prob = fmaxf(1.0f - total_score * 2.0f, 0.0f);
    result.warning_prob = fmaxf(total_score - 0.3f, 0.0f) * 0.6f;
    result.fault_prob = fmaxf(total_score - 0.5f, 0.0f);

    /* 归一化 */
    float sum = result.normal_prob + result.warning_prob + result.fault_prob;
    if (sum > 0.0f) {
        result.normal_prob /= sum;
        result.warning_prob /= sum;
        result.fault_prob /= sum;
    }

    /* 故障类型判定 */
    if (result.fault_prob > 0.5f) {
        if (vib_score > 0.5f && temp_score > 0.3f) {
            result.fault_type = 1;  /* 轴承故障 */
        } else if (curr_score > 0.5f) {
            result.fault_type = 2;  /* 电气故障 */
        } else {
            result.fault_type = 3;  /* 综合故障 */
        }
    }

    return result;
}

四、边缘融合的可靠性挑战

4.1 传感器故障的级联影响

传感器融合的一个隐含假设是:所有传感器都在正常工作。如果某个传感器故障(比如振动传感器松动导致数据全零),融合结果会被严重误导。温度正常+电流正常+振动为零,融合模型可能判定设备完全正常,实际上振动传感器已经坏了。

应对方法是传感器健康监测:对每个传感器的原始数据做自检(方差是否为零、是否长时间不变、是否超出物理范围),异常传感器的数据在融合时降权或排除。这增加了系统复杂度,但避免了"传感器坏了比设备坏了更危险"的悖论。

4.2 时间对齐的精度瓶颈

以最低采样率传感器为对齐基准,意味着高采样率传感器的大量数据被丢弃。振动传感器 10kHz 采样,温度传感器 1Hz,对齐后每秒只取一个振动采样,信息利用率只有万分之一。

改进方案是特征级对齐:振动传感器在本地完成 FFT 和统计特征提取,每秒输出一个特征向量,与温度数据对齐。这样既保留了振动信号的频域信息,又解决了采样率差异问题。代价是 MCU 上需要额外的 FFT 计算资源。

4.3 适用与禁用场景

适用场景:工业设备状态监测、智能楼宇环境感知、可穿戴设备健康监测、自动驾驶多传感器感知。

禁用场景:安全关键系统(如医疗诊断,需要确定性保证)、传感器高度耦合的场景(一个传感器故障影响所有传感器)、需要亚毫秒级同步的实时控制系统。

五、总结

多传感器融合在边缘设备上的核心挑战是时间对齐和资源约束。三级融合模型(数据级、特征级、决策级)提供了从紧耦合到松耦合的灵活选择。特征级融合是 MCU 上最务实的方案:每个传感器本地提取特征,避免传输原始数据,降低对时间对齐的精度要求。规则引擎比深度模型更适合 MCU 上的融合决策------可解释、延迟确定、不依赖训练数据。传感器健康监测是融合系统可靠性的底线,不能假设传感器永远正常。最后,融合的价值不在于传感器数量多,而在于信息互补------三个看同一方向的传感器,不如三个看不同方向的传感器。