汽车自动雨刷与雨量感应系统全解析——从光学原理到控制算法

前言

前阵子做一个汽车雨刷控制模块的项目,从雨量传感器选型到控制算法都过了一遍。自动雨刷看起来简单,但要做到"智能"------根据雨量大小自动调节频率、避免误触发、响应迅速又不抖动------还是有不少技术细节的。

今天把雨量感应和自动雨刷的技术整理出来,从传感器原理到控制代码,希望对做汽车电子的朋友有帮助。

系统整体架构

复制代码
┌─────────────────────────────────────────────────────────────────────────────┐
│                      自动雨刷系统架构                                        │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   ┌─────────────────────────────────────────────────────────────────────┐  │
│   │                      雨量传感器模块                                  │  │
│   │                      (贴装于前挡风玻璃内侧)                          │  │
│   │                                                                     │  │
│   │   ┌───────────────┐  ┌───────────────┐  ┌───────────────┐          │  │
│   │   │   红外LED     │  │   光电二极管   │  │   信号处理    │          │  │
│   │   │   发射阵列    │  │   接收阵列    │  │   MCU         │          │  │
│   │   └───────┬───────┘  └───────┬───────┘  └───────┬───────┘          │  │
│   │           │                  │                  │                   │  │
│   │           │    全内反射      │                  │                   │  │
│   │           └────────●─────────┘                  │                   │  │
│   │                    │ 挡风玻璃                    │                   │  │
│   │                    ▼                            │                   │  │
│   │              雨滴改变反射                        │                   │  │
│   └────────────────────┼────────────────────────────┼───────────────────┘  │
│                        │                            │                      │
│                        │ 雨量信号                   │ LIN/CAN              │
│                        ▼                            ▼                      │
│   ┌─────────────────────────────────────────────────────────────────────┐  │
│   │                      车身控制器 (BCM)                                │  │
│   │                                                                     │  │
│   │   ┌───────────────┐  ┌───────────────┐  ┌───────────────┐          │  │
│   │   │ 雨量等级判断  │  │ 雨刷速度决策  │  │ 联动控制      │          │  │
│   │   │               │  │               │  │ - 自动大灯    │          │  │
│   │   │ - 无雨        │  │ - 间歇档位    │  │ - 自动关窗    │          │  │
│   │   │ - 小雨        │  │ - 低速连续    │  │ - 后视镜加热  │          │  │
│   │   │ - 中雨        │  │ - 高速连续    │  │ - 空调除雾    │          │  │
│   │   │ - 大雨        │  │               │  │               │          │  │
│   │   └───────────────┘  └───────────────┘  └───────────────┘          │  │
│   └──────────────────────────────┬──────────────────────────────────────┘  │
│                                  │                                         │
│                                  ▼                                         │
│   ┌─────────────────────────────────────────────────────────────────────┐  │
│   │                      雨刷执行机构                                    │  │
│   │                                                                     │  │
│   │   ┌───────────────┐  ┌───────────────┐  ┌───────────────┐          │  │
│   │   │  雨刷电机     │  │  位置传感器   │  │  继电器/驱动  │          │  │
│   │   │  (直流/步进)  │  │  (霍尔/电位器)│  │               │          │  │
│   │   └───────────────┘  └───────────────┘  └───────────────┘          │  │
│   │                                                                     │  │
│   └─────────────────────────────────────────────────────────────────────┘  │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

雨量传感器原理

光学式雨量传感器(主流方案)

复制代码
┌─────────────────────────────────────────────────────────────────────────────┐
│                    光学式雨量传感器工作原理                                  │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   【无雨状态 - 全内反射】                                                   │
│                                                                             │
│        空气 (n=1.0)                                                        │
│   ═══════════════════════════════════════  挡风玻璃外表面                  │
│        玻璃 (n≈1.5)                                                        │
│                                                                             │
│            ┌─────────────────────────┐                                     │
│            │    全内反射区域          │                                     │
│            │                         │                                     │
│        LED ●━━━━━━━━━━━━━━━━━━━━━━━━●→ 光电二极管                         │
│         发射 ╲        反射         ╱  接收                                 │
│              ╲                   ╱                                         │
│               ╲    θ > θc      ╱    θc = arcsin(1/1.5) ≈ 41.8°           │
│                ╲             ╱                                             │
│   ═══════════════════════════════════════  传感器-玻璃界面                  │
│            │   硅胶耦合层   │                                              │
│            └─────────────────────────┘                                     │
│                    传感器模块                                               │
│                                                                             │
│   原理: 入射角θ > 临界角θc时,光线在玻璃-空气界面发生全内反射              │
│         接收端收到强信号                                                    │
│                                                                             │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   【有雨状态 - 反射被破坏】                                                 │
│                                                                             │
│        水滴 (n≈1.33)     空气                                              │
│          💧    💧                                                           │
│   ═══════════════════════════════════════  挡风玻璃外表面                  │
│        玻璃 (n≈1.5)                                                        │
│                                                                             │
│            ┌─────────────────────────┐                                     │
│            │                         │                                     │
│            │    部分光线折射出去      │                                     │
│        LED ●━━━━━━━╲   ╱━━━━━━━━━━━━●→ 光电二极管                         │
│         发射        ╲ ╱ 💧          接收 (信号减弱)                        │
│                      ╳   折射                                              │
│                     ↗ ╲                                                    │
│                   ↗    ╲  光线穿过水滴                                     │
│   ═══════════════════════════════════════                                  │
│                                                                             │
│   原理: 水滴改变了界面折射率,部分光线折射进入水滴                          │
│         接收端信号减弱,减弱程度与水滴大小/数量相关                         │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

传感器结构设计

c 复制代码
/**
 * 光学雨量传感器结构
 * 
 * 典型配置: 多组LED+光电二极管阵列
 * 覆盖不同检测区域,提高准确性
 */

/*
传感器阵列布局 (俯视图):

    ┌─────────────────────────────────┐
    │                                 │
    │    LED1 ●───────────● PD1       │  区域1: 中心区
    │              ╲                  │
    │    LED2 ●─────╲─────● PD2       │  区域2: 左侧
    │              ╲ ╲                │
    │    LED3 ●─────╲─╲───● PD3       │  区域3: 右侧
    │                ╲ ╲              │
    │    LED4 ●───────╲─╲─● PD4       │  区域4: 边缘
    │                                 │
    │         发射端      接收端       │
    │                                 │
    └─────────────────────────────────┘

多区域设计优势:
1. 提高检测覆盖面积
2. 通过多点数据提高可靠性
3. 可检测雨滴分布和移动方向
4. 区分局部污渍和真实雨滴
*/

// 传感器通道定义
typedef enum {
    RAIN_CHANNEL_CENTER = 0,    // 中心区域
    RAIN_CHANNEL_LEFT,          // 左侧区域
    RAIN_CHANNEL_RIGHT,         // 右侧区域
    RAIN_CHANNEL_EDGE,          // 边缘区域
    RAIN_CHANNEL_COUNT
} RainChannel_t;

// 单通道配置
typedef struct {
    uint8_t led_pin;            // LED控制引脚
    uint8_t adc_channel;        // ADC通道
    uint16_t baseline;          // 基线值(无雨时)
    uint16_t threshold;         // 检测阈值
    float sensitivity;          // 灵敏度系数
} RainChannelConfig_t;

// 传感器整体配置
typedef struct {
    RainChannelConfig_t channels[RAIN_CHANNEL_COUNT];
    uint16_t sample_interval_ms;    // 采样间隔
    uint8_t samples_per_read;       // 每次读取采样数
    uint8_t led_pulse_width_us;     // LED脉冲宽度
} RainSensorConfig_t;

// 默认配置
static RainSensorConfig_t rain_config = {
    .channels = {
        {.led_pin = GPIO_PIN_0, .adc_channel = 0, .baseline = 3000, .threshold = 200, .sensitivity = 1.0f},
        {.led_pin = GPIO_PIN_1, .adc_channel = 1, .baseline = 2900, .threshold = 200, .sensitivity = 1.0f},
        {.led_pin = GPIO_PIN_2, .adc_channel = 2, .baseline = 2950, .threshold = 200, .sensitivity = 1.0f},
        {.led_pin = GPIO_PIN_3, .adc_channel = 3, .baseline = 2800, .threshold = 250, .sensitivity = 0.8f},
    },
    .sample_interval_ms = 50,
    .samples_per_read = 4,
    .led_pulse_width_us = 100
};

电容式雨量传感器

c 复制代码
/**
 * 电容式雨量传感器
 * 
 * 原理: 水滴改变电极间介电常数,导致电容变化
 * 优点: 结构简单,成本低
 * 缺点: 易受温度影响,灵敏度较低
 */

/*
电容式传感器结构:

    ═══════════════════════════════════  挡风玻璃
         │                     │
         │  💧  💧  💧        │  水滴
         │                     │
    ─────┴─────────────────────┴─────  玻璃外表面
    
    ─────┬─────────────────────┬─────  玻璃内表面
         │░░░░░░░░░░░░░░░░░░░░░│  
         │░░░ 感应电极阵列 ░░░░│  ITO透明导电膜
         │░░░░░░░░░░░░░░░░░░░░░│
    ═════╧═════════════════════╧═════  传感器基板

电极布局 (叉指电容):

    ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
    │A│B│A│B│A│B│A│B│A│B│
    └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘
    
    A-B间电容: C = ε × A / d
    水滴覆盖时: ε增大 → C增大
*/

typedef struct {
    uint32_t base_capacitance;      // 基准电容值 (pF × 100)
    uint32_t current_capacitance;   // 当前电容值
    int32_t delta_capacitance;      // 电容变化量
    float temperature;              // 温度(用于补偿)
} CapacitiveSensorState_t;

/**
 * 电容测量 (使用RC充放电法)
 */
uint32_t measure_capacitance(uint8_t channel)
{
    // 放电
    HAL_GPIO_WritePin(CAP_PORT, CAP_PIN, GPIO_PIN_RESET);
    HAL_Delay(1);
    
    // 开始充电,测量时间
    uint32_t start = DWT->CYCCNT;
    HAL_GPIO_WritePin(CAP_PORT, CAP_PIN, GPIO_PIN_SET);
    
    // 等待电压达到阈值
    while (HAL_GPIO_ReadPin(CAP_SENSE_PORT, CAP_SENSE_PIN) == GPIO_PIN_RESET) {
        if (DWT->CYCCNT - start > TIMEOUT_CYCLES) {
            return 0xFFFFFFFF;  // 超时
        }
    }
    
    uint32_t cycles = DWT->CYCCNT - start;
    
    // 周期数转电容值 (需要标定)
    // C = t / R, t = cycles / SystemCoreClock
    uint32_t capacitance = cycles * CAP_SCALE_FACTOR / SystemCoreClock;
    
    return capacitance;
}

/**
 * 温度补偿
 */
float capacitance_temp_compensate(uint32_t raw_cap, float temperature)
{
    // 电容温度系数约 200ppm/°C
    float temp_coef = 1.0f + 0.0002f * (temperature - 25.0f);
    return raw_cap / temp_coef;
}

信号处理与雨量检测

ADC采样与滤波

c 复制代码
/**
 * 雨量传感器信号采集
 */

#include "stm32f1xx_hal.h"
#include <string.h>
#include <math.h>

// 采样缓冲区
#define SAMPLE_BUFFER_SIZE 16

typedef struct {
    uint16_t raw_values[RAIN_CHANNEL_COUNT];
    uint16_t filtered_values[RAIN_CHANNEL_COUNT];
    uint16_t sample_buffer[RAIN_CHANNEL_COUNT][SAMPLE_BUFFER_SIZE];
    uint8_t buffer_index;
    
    // 差值(相对于基线)
    int16_t delta_values[RAIN_CHANNEL_COUNT];
    
    // 检测标志
    uint8_t rain_detected[RAIN_CHANNEL_COUNT];
} RainSensorData_t;

static RainSensorData_t rain_data;

/**
 * 单通道ADC采样(带LED脉冲同步)
 * 
 * 使用同步检测减少环境光干扰:
 * 1. LED关闭,采样背景光
 * 2. LED开启,采样信号光
 * 3. 信号 = 开启值 - 关闭值
 */
uint16_t rain_sensor_read_channel(RainChannel_t channel)
{
    RainChannelConfig_t *ch_cfg = &rain_config.channels[channel];
    
    // 关闭所有LED
    for (int i = 0; i < RAIN_CHANNEL_COUNT; i++) {
        HAL_GPIO_WritePin(GPIOA, rain_config.channels[i].led_pin, GPIO_PIN_RESET);
    }
    delay_us(50);
    
    // 采样背景光
    ADC_ChannelConfTypeDef sConfig = {0};
    sConfig.Channel = ch_cfg->adc_channel;
    sConfig.Rank = 1;
    sConfig.SamplingTime = ADC_SAMPLETIME_28CYCLES_5;
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);
    
    HAL_ADC_Start(&hadc1);
    HAL_ADC_PollForConversion(&hadc1, 10);
    uint16_t background = HAL_ADC_GetValue(&hadc1);
    
    // 开启对应LED
    HAL_GPIO_WritePin(GPIOA, ch_cfg->led_pin, GPIO_PIN_SET);
    delay_us(rain_config.led_pulse_width_us);
    
    // 采样信号光
    HAL_ADC_Start(&hadc1);
    HAL_ADC_PollForConversion(&hadc1, 10);
    uint16_t signal = HAL_ADC_GetValue(&hadc1);
    
    // 关闭LED
    HAL_GPIO_WritePin(GPIOA, ch_cfg->led_pin, GPIO_PIN_RESET);
    
    // 计算差值(消除背景光)
    if (signal > background) {
        return signal - background;
    } else {
        return 0;
    }
}

/**
 * 多次采样取中值滤波
 */
uint16_t rain_sensor_read_filtered(RainChannel_t channel)
{
    uint16_t samples[8];
    
    for (int i = 0; i < 8; i++) {
        samples[i] = rain_sensor_read_channel(channel);
        delay_us(200);
    }
    
    // 排序
    for (int i = 0; i < 7; i++) {
        for (int j = i + 1; j < 8; j++) {
            if (samples[j] < samples[i]) {
                uint16_t tmp = samples[i];
                samples[i] = samples[j];
                samples[j] = tmp;
            }
        }
    }
    
    // 取中间4个值的平均
    uint32_t sum = samples[2] + samples[3] + samples[4] + samples[5];
    
    return sum / 4;
}

/**
 * 更新所有通道数据
 */
void rain_sensor_update(void)
{
    for (int ch = 0; ch < RAIN_CHANNEL_COUNT; ch++) {
        // 读取原始值
        rain_data.raw_values[ch] = rain_sensor_read_filtered(ch);
        
        // 存入滑动窗口
        rain_data.sample_buffer[ch][rain_data.buffer_index] = rain_data.raw_values[ch];
        
        // 滑动平均滤波
        uint32_t sum = 0;
        for (int i = 0; i < SAMPLE_BUFFER_SIZE; i++) {
            sum += rain_data.sample_buffer[ch][i];
        }
        rain_data.filtered_values[ch] = sum / SAMPLE_BUFFER_SIZE;
        
        // 计算与基线的差值
        rain_data.delta_values[ch] = (int16_t)rain_config.channels[ch].baseline - 
                                     (int16_t)rain_data.filtered_values[ch];
        
        // 判断是否检测到雨滴
        rain_data.rain_detected[ch] = (rain_data.delta_values[ch] > 
                                       rain_config.channels[ch].threshold);
    }
    
    rain_data.buffer_index = (rain_data.buffer_index + 1) % SAMPLE_BUFFER_SIZE;
}

雨量等级判断

c 复制代码
/**
 * 雨量等级定义
 */

typedef enum {
    RAIN_LEVEL_NONE = 0,        // 无雨
    RAIN_LEVEL_MIST,            // 雾/毛毛雨
    RAIN_LEVEL_LIGHT,           // 小雨
    RAIN_LEVEL_MODERATE,        // 中雨
    RAIN_LEVEL_HEAVY,           // 大雨
    RAIN_LEVEL_STORM            // 暴雨
} RainLevel_t;

// 雨量等级阈值 (基于信号衰减百分比)
typedef struct {
    float min_attenuation;      // 最小衰减率 (%)
    float max_attenuation;      // 最大衰减率 (%)
    uint8_t min_channels;       // 最少触发通道数
} RainLevelThreshold_t;

static const RainLevelThreshold_t rain_thresholds[] = {
    [RAIN_LEVEL_NONE]     = {0.0f,  3.0f,  0},
    [RAIN_LEVEL_MIST]     = {3.0f,  8.0f,  1},
    [RAIN_LEVEL_LIGHT]    = {8.0f,  15.0f, 2},
    [RAIN_LEVEL_MODERATE] = {15.0f, 30.0f, 2},
    [RAIN_LEVEL_HEAVY]    = {30.0f, 50.0f, 3},
    [RAIN_LEVEL_STORM]    = {50.0f, 100.0f, 3},
};

typedef struct {
    RainLevel_t current_level;
    RainLevel_t raw_level;          // 未滤波的等级
    float attenuation_percent;      // 平均衰减率
    uint8_t active_channels;        // 触发的通道数
    uint32_t level_stable_time;     // 等级稳定时间
    uint32_t last_change_time;      // 上次变化时间
    
    // 趋势分析
    float attenuation_history[10];
    uint8_t history_index;
    float attenuation_trend;        // 变化趋势 (正=雨增大)
} RainLevelState_t;

static RainLevelState_t rain_state;

/**
 * 计算信号衰减率
 */
float calc_attenuation(RainChannel_t channel)
{
    RainChannelConfig_t *cfg = &rain_config.channels[channel];
    
    if (cfg->baseline == 0) return 0;
    
    float attenuation = (float)rain_data.delta_values[channel] / cfg->baseline * 100.0f;
    
    // 应用灵敏度系数
    attenuation *= cfg->sensitivity;
    
    // 限制范围
    if (attenuation < 0) attenuation = 0;
    if (attenuation > 100) attenuation = 100;
    
    return attenuation;
}

/**
 * 判断雨量等级
 */
RainLevel_t calc_rain_level(void)
{
    // 计算各通道衰减率
    float attenuations[RAIN_CHANNEL_COUNT];
    float max_attenuation = 0;
    float sum_attenuation = 0;
    uint8_t active_count = 0;
    
    for (int ch = 0; ch < RAIN_CHANNEL_COUNT; ch++) {
        attenuations[ch] = calc_attenuation(ch);
        
        if (attenuations[ch] > rain_thresholds[RAIN_LEVEL_MIST].min_attenuation) {
            active_count++;
            sum_attenuation += attenuations[ch];
        }
        
        if (attenuations[ch] > max_attenuation) {
            max_attenuation = attenuations[ch];
        }
    }
    
    // 平均衰减率(仅计算激活的通道)
    float avg_attenuation = (active_count > 0) ? 
                            (sum_attenuation / active_count) : 0;
    
    rain_state.attenuation_percent = avg_attenuation;
    rain_state.active_channels = active_count;
    
    // 判断等级
    RainLevel_t level = RAIN_LEVEL_NONE;
    
    for (int i = RAIN_LEVEL_STORM; i >= RAIN_LEVEL_MIST; i--) {
        if (avg_attenuation >= rain_thresholds[i].min_attenuation &&
            active_count >= rain_thresholds[i].min_channels) {
            level = i;
            break;
        }
    }
    
    return level;
}

/**
 * 雨量等级滤波(防止频繁跳变)
 */
void rain_level_filter(RainLevel_t raw_level)
{
    uint32_t now = HAL_GetTick();
    
    rain_state.raw_level = raw_level;
    
    // 更新衰减历史
    rain_state.attenuation_history[rain_state.history_index] = 
        rain_state.attenuation_percent;
    rain_state.history_index = (rain_state.history_index + 1) % 10;
    
    // 计算趋势(简单差分)
    float oldest = rain_state.attenuation_history[(rain_state.history_index + 1) % 10];
    rain_state.attenuation_trend = rain_state.attenuation_percent - oldest;
    
    // 等级变化滞后处理
    if (raw_level != rain_state.current_level) {
        // 等级上升(雨变大): 快速响应
        // 等级下降(雨变小): 延迟响应
        
        uint32_t required_stable_time;
        
        if (raw_level > rain_state.current_level) {
            // 雨变大,快速响应
            required_stable_time = 200;  // 200ms
        } else {
            // 雨变小,延迟响应(避免雨刷停得太快)
            required_stable_time = 2000; // 2秒
        }
        
        if (now - rain_state.last_change_time > required_stable_time) {
            rain_state.current_level = raw_level;
            rain_state.last_change_time = now;
        }
    } else {
        rain_state.last_change_time = now;
    }
}

/**
 * 雨量传感器主处理函数
 */
void rain_sensor_process(void)
{
    // 更新传感器数据
    rain_sensor_update();
    
    // 计算原始雨量等级
    RainLevel_t raw_level = calc_rain_level();
    
    // 滤波
    rain_level_filter(raw_level);
}

/**
 * 获取当前雨量等级
 */
RainLevel_t rain_sensor_get_level(void)
{
    return rain_state.current_level;
}

/**
 * 获取雨量详细信息
 */
void rain_sensor_get_info(float *attenuation, uint8_t *active_channels, 
                          float *trend)
{
    *attenuation = rain_state.attenuation_percent;
    *active_channels = rain_state.active_channels;
    *trend = rain_state.attenuation_trend;
}

自动基线校准

c 复制代码
/**
 * 自动基线校准
 * 
 * 基线会随温度、玻璃老化等因素漂移
 * 需要在无雨时自动校准
 */

typedef struct {
    uint16_t calibration_values[RAIN_CHANNEL_COUNT];
    uint32_t calibration_time;
    uint8_t calibration_valid;
    float temperature_at_cal;
} CalibrationData_t;

static CalibrationData_t cal_data;

// 校准状态
typedef enum {
    CAL_STATE_IDLE,
    CAL_STATE_COLLECTING,
    CAL_STATE_VALIDATING,
    CAL_STATE_COMPLETE
} CalibrationState_t;

static CalibrationState_t cal_state = CAL_STATE_IDLE;
static uint32_t cal_sample_count = 0;
static uint32_t cal_accumulator[RAIN_CHANNEL_COUNT];

/**
 * 开始校准
 */
void rain_sensor_start_calibration(void)
{
    cal_state = CAL_STATE_COLLECTING;
    cal_sample_count = 0;
    
    for (int i = 0; i < RAIN_CHANNEL_COUNT; i++) {
        cal_accumulator[i] = 0;
    }
}

/**
 * 校准过程(需要多次调用)
 */
int rain_sensor_calibration_process(void)
{
    switch (cal_state) {
    case CAL_STATE_IDLE:
        return 0;
        
    case CAL_STATE_COLLECTING:
        // 采集样本
        for (int ch = 0; ch < RAIN_CHANNEL_COUNT; ch++) {
            cal_accumulator[ch] += rain_sensor_read_filtered(ch);
        }
        cal_sample_count++;
        
        if (cal_sample_count >= 100) {  // 采集100个样本
            cal_state = CAL_STATE_VALIDATING;
        }
        return 1;  // 进行中
        
    case CAL_STATE_VALIDATING:
        // 验证数据有效性
        {
            uint8_t valid = 1;
            
            for (int ch = 0; ch < RAIN_CHANNEL_COUNT; ch++) {
                uint16_t avg = cal_accumulator[ch] / cal_sample_count;
                
                // 检查是否在合理范围
                if (avg < 1000 || avg > 3800) {
                    valid = 0;
                    break;
                }
                
                cal_data.calibration_values[ch] = avg;
            }
            
            if (valid) {
                // 应用校准值
                for (int ch = 0; ch < RAIN_CHANNEL_COUNT; ch++) {
                    rain_config.channels[ch].baseline = 
                        cal_data.calibration_values[ch];
                }
                
                cal_data.calibration_time = HAL_GetTick();
                cal_data.calibration_valid = 1;
                cal_data.temperature_at_cal = get_temperature();  // 假设有温度传感器
                
                cal_state = CAL_STATE_COMPLETE;
                return 0;  // 完成
            } else {
                // 校准失败,重新开始
                cal_state = CAL_STATE_IDLE;
                return -1;  // 失败
            }
        }
        
    case CAL_STATE_COMPLETE:
        cal_state = CAL_STATE_IDLE;
        return 0;
    }
    
    return 0;
}

/**
 * 自动校准触发条件判断
 */
int should_auto_calibrate(void)
{
    // 条件1: 长时间无雨(>10分钟)
    static uint32_t no_rain_start = 0;
    
    if (rain_state.current_level == RAIN_LEVEL_NONE) {
        if (no_rain_start == 0) {
            no_rain_start = HAL_GetTick();
        } else if (HAL_GetTick() - no_rain_start > 10 * 60 * 1000) {
            // 条件2: 距上次校准超过1小时
            if (HAL_GetTick() - cal_data.calibration_time > 60 * 60 * 1000) {
                no_rain_start = 0;
                return 1;
            }
        }
    } else {
        no_rain_start = 0;
    }
    
    // 条件3: 温度变化超过10度
    float current_temp = get_temperature();
    if (cal_data.calibration_valid && 
        fabsf(current_temp - cal_data.temperature_at_cal) > 10.0f) {
        return 1;
    }
    
    return 0;
}

雨刷控制系统

雨刷电机驱动

c 复制代码
/**
 * 雨刷电机控制
 * 
 * 雨刷电机类型:
 * 1. 双速直流电机(高速/低速两个绕组)
 * 2. PWM调速直流电机
 * 3. 步进电机(高端车型)
 */

// 雨刷状态
typedef enum {
    WIPER_STATE_PARKED,         // 停止位置
    WIPER_STATE_MOVING_UP,      // 向上摆动
    WIPER_STATE_MOVING_DOWN,    // 向下摆动
    WIPER_STATE_PARKING         // 正在归位
} WiperState_t;

// 雨刷速度档位
typedef enum {
    WIPER_SPEED_OFF = 0,
    WIPER_SPEED_INT,            // 间歇
    WIPER_SPEED_LOW,            // 低速连续
    WIPER_SPEED_HIGH            // 高速连续
} WiperSpeed_t;

// 雨刷电机配置(双速电机)
typedef struct {
    GPIO_TypeDef *low_speed_port;
    uint16_t low_speed_pin;
    GPIO_TypeDef *high_speed_port;
    uint16_t high_speed_pin;
    GPIO_TypeDef *park_sense_port;  // 停止位置传感器
    uint16_t park_sense_pin;
} WiperMotorConfig_t;

// 雨刷控制状态
typedef struct {
    WiperState_t state;
    WiperSpeed_t target_speed;
    WiperSpeed_t current_speed;
    
    uint32_t cycle_count;           // 摆动次数
    uint32_t last_cycle_time;       // 上次摆动时间
    uint32_t interval_ms;           // 间歇时间
    
    uint8_t is_parked;              // 是否在停止位
    uint8_t park_requested;         // 请求归位
    
    // 安全保护
    uint32_t motor_on_time;         // 电机运行时间
    uint8_t overcurrent;            // 过流标志
    uint8_t stall_detected;         // 堵转检测
} WiperControlState_t;

static WiperMotorConfig_t wiper_config;
static WiperControlState_t wiper_state;

/**
 * 初始化雨刷控制
 */
void wiper_init(void)
{
    // GPIO初始化
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    // 低速控制引脚
    GPIO_InitStruct.Pin = wiper_config.low_speed_pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(wiper_config.low_speed_port, &GPIO_InitStruct);
    
    // 高速控制引脚
    GPIO_InitStruct.Pin = wiper_config.high_speed_pin;
    HAL_GPIO_Init(wiper_config.high_speed_port, &GPIO_InitStruct);
    
    // 停止位传感器(输入)
    GPIO_InitStruct.Pin = wiper_config.park_sense_pin;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(wiper_config.park_sense_port, &GPIO_InitStruct);
    
    // 初始化状态
    memset(&wiper_state, 0, sizeof(wiper_state));
    wiper_state.state = WIPER_STATE_PARKED;
}

/**
 * 检测停止位
 */
uint8_t wiper_is_parked(void)
{
    // 停止位传感器:低电平表示在停止位
    return (HAL_GPIO_ReadPin(wiper_config.park_sense_port, 
                             wiper_config.park_sense_pin) == GPIO_PIN_RESET);
}

/**
 * 设置电机速度
 */
void wiper_motor_set(WiperSpeed_t speed)
{
    switch (speed) {
    case WIPER_SPEED_OFF:
        HAL_GPIO_WritePin(wiper_config.low_speed_port, 
                          wiper_config.low_speed_pin, GPIO_PIN_RESET);
        HAL_GPIO_WritePin(wiper_config.high_speed_port, 
                          wiper_config.high_speed_pin, GPIO_PIN_RESET);
        break;
        
    case WIPER_SPEED_INT:
    case WIPER_SPEED_LOW:
        HAL_GPIO_WritePin(wiper_config.low_speed_port, 
                          wiper_config.low_speed_pin, GPIO_PIN_SET);
        HAL_GPIO_WritePin(wiper_config.high_speed_port, 
                          wiper_config.high_speed_pin, GPIO_PIN_RESET);
        break;
        
    case WIPER_SPEED_HIGH:
        HAL_GPIO_WritePin(wiper_config.low_speed_port, 
                          wiper_config.low_speed_pin, GPIO_PIN_RESET);
        HAL_GPIO_WritePin(wiper_config.high_speed_port, 
                          wiper_config.high_speed_pin, GPIO_PIN_SET);
        break;
    }
    
    wiper_state.current_speed = speed;
    
    if (speed != WIPER_SPEED_OFF) {
        wiper_state.motor_on_time = HAL_GetTick();
    }
}

/**
 * 雨刷归位控制
 * 
 * 特殊逻辑:关闭时需要运行到停止位才停机
 */
void wiper_park(void)
{
    if (wiper_is_parked()) {
        // 已在停止位,直接停机
        wiper_motor_set(WIPER_SPEED_OFF);
        wiper_state.state = WIPER_STATE_PARKED;
        wiper_state.park_requested = 0;
    } else {
        // 继续低速运行直到停止位
        wiper_state.park_requested = 1;
        wiper_motor_set(WIPER_SPEED_LOW);
        wiper_state.state = WIPER_STATE_PARKING;
    }
}

/**
 * 雨刷控制主循环
 */
void wiper_control_loop(void)
{
    uint32_t now = HAL_GetTick();
    
    // 更新停止位状态
    wiper_state.is_parked = wiper_is_parked();
    
    // 归位处理
    if (wiper_state.park_requested) {
        if (wiper_state.is_parked) {
            wiper_motor_set(WIPER_SPEED_OFF);
            wiper_state.state = WIPER_STATE_PARKED;
            wiper_state.park_requested = 0;
        }
        return;
    }
    
    // 正常运行
    switch (wiper_state.target_speed) {
    case WIPER_SPEED_OFF:
        // 请求停止,归位
        wiper_park();
        break;
        
    case WIPER_SPEED_INT:
        // 间歇模式
        if (wiper_state.current_speed == WIPER_SPEED_OFF) {
            // 当前停止,检查是否到间歇时间
            if (now - wiper_state.last_cycle_time >= wiper_state.interval_ms) {
                // 开始一个摆动周期
                wiper_motor_set(WIPER_SPEED_LOW);
                wiper_state.state = WIPER_STATE_MOVING_UP;
            }
        } else {
            // 正在运行,等待回到停止位
            if (wiper_state.is_parked && 
                wiper_state.state == WIPER_STATE_MOVING_DOWN) {
                // 完成一个周期
                wiper_motor_set(WIPER_SPEED_OFF);
                wiper_state.cycle_count++;
                wiper_state.last_cycle_time = now;
                wiper_state.state = WIPER_STATE_PARKED;
            }
        }
        break;
        
    case WIPER_SPEED_LOW:
        // 低速连续
        if (wiper_state.current_speed != WIPER_SPEED_LOW) {
            wiper_motor_set(WIPER_SPEED_LOW);
        }
        break;
        
    case WIPER_SPEED_HIGH:
        // 高速连续
        if (wiper_state.current_speed != WIPER_SPEED_HIGH) {
            wiper_motor_set(WIPER_SPEED_HIGH);
        }
        break;
    }
    
    // 状态机更新
    if (wiper_state.current_speed != WIPER_SPEED_OFF) {
        // 简单的上下摆动状态跟踪
        static uint8_t last_parked = 0;
        
        if (wiper_state.is_parked && !last_parked) {
            // 刚到达停止位
            if (wiper_state.state == WIPER_STATE_MOVING_DOWN) {
                wiper_state.state = WIPER_STATE_MOVING_UP;
            }
        } else if (!wiper_state.is_parked && last_parked) {
            // 刚离开停止位
            wiper_state.state = WIPER_STATE_MOVING_UP;
        }
        
        last_parked = wiper_state.is_parked;
    }
    
    // 安全保护:堵转检测
    if (wiper_state.current_speed != WIPER_SPEED_OFF) {
        // 如果电机运行超过5秒还没有位置变化,可能堵转
        // 实际需要更复杂的检测逻辑
        if (now - wiper_state.motor_on_time > 5000) {
            // 检测电流或位置变化
            // ...
        }
    }
}

/**
 * 设置雨刷速度
 */
void wiper_set_speed(WiperSpeed_t speed)
{
    wiper_state.target_speed = speed;
}

/**
 * 设置间歇时间
 */
void wiper_set_interval(uint32_t interval_ms)
{
    // 限制范围
    if (interval_ms < 500) interval_ms = 500;
    if (interval_ms > 10000) interval_ms = 10000;
    
    wiper_state.interval_ms = interval_ms;
}

自动雨刷控制逻辑

c 复制代码
/**
 * 自动雨刷控制算法
 * 
 * 根据雨量等级自动调节雨刷速度和间歇时间
 */

// 自动雨刷配置
typedef struct {
    // 各雨量等级对应的雨刷设置
    struct {
        WiperSpeed_t speed;
        uint32_t interval_ms;       // 间歇时间(仅间歇档有效)
    } level_config[6];
    
    // 灵敏度调节(用户可调)
    uint8_t sensitivity;            // 0-10, 默认5
    
    // 车速相关
    uint8_t speed_adaptive;         // 是否根据车速调节
    float vehicle_speed_factor;     // 车速影响因子
    
} AutoWiperConfig_t;

static AutoWiperConfig_t auto_wiper_config = {
    .level_config = {
        [RAIN_LEVEL_NONE]     = {WIPER_SPEED_OFF, 0},
        [RAIN_LEVEL_MIST]     = {WIPER_SPEED_INT, 8000},     // 8秒间歇
        [RAIN_LEVEL_LIGHT]    = {WIPER_SPEED_INT, 4000},     // 4秒间歇
        [RAIN_LEVEL_MODERATE] = {WIPER_SPEED_INT, 2000},     // 2秒间歇
        [RAIN_LEVEL_HEAVY]    = {WIPER_SPEED_LOW, 0},        // 低速连续
        [RAIN_LEVEL_STORM]    = {WIPER_SPEED_HIGH, 0},       // 高速连续
    },
    .sensitivity = 5,
    .speed_adaptive = 1,
    .vehicle_speed_factor = 0.1f
};

// 自动雨刷状态
typedef struct {
    uint8_t enabled;                // 自动模式使能
    RainLevel_t last_rain_level;
    WiperSpeed_t commanded_speed;
    uint32_t commanded_interval;
    
    // 延迟启动(避免误触发)
    uint32_t first_detect_time;
    uint8_t startup_delay_active;
    
    // 平滑过渡
    uint32_t transition_start_time;
    WiperSpeed_t transition_from_speed;
    WiperSpeed_t transition_to_speed;
} AutoWiperState_t;

static AutoWiperState_t auto_wiper_state;

/**
 * 根据灵敏度调整雨量等级
 */
RainLevel_t adjust_rain_level_by_sensitivity(RainLevel_t raw_level)
{
    int8_t sensitivity_offset = (int8_t)auto_wiper_config.sensitivity - 5;
    
    // 灵敏度高时,低等级雨也触发高档
    // 灵敏度低时,需要更大的雨才触发
    int8_t adjusted = (int8_t)raw_level + sensitivity_offset / 2;
    
    if (adjusted < 0) adjusted = 0;
    if (adjusted > RAIN_LEVEL_STORM) adjusted = RAIN_LEVEL_STORM;
    
    return (RainLevel_t)adjusted;
}

/**
 * 根据车速调整间歇时间
 */
uint32_t adjust_interval_by_speed(uint32_t base_interval, float vehicle_speed_kmh)
{
    if (!auto_wiper_config.speed_adaptive) {
        return base_interval;
    }
    
    // 车速越高,间歇时间越短
    // 因为高速时雨滴撞击更频繁
    float factor = 1.0f - auto_wiper_config.vehicle_speed_factor * 
                   (vehicle_speed_kmh / 100.0f);
    
    if (factor < 0.3f) factor = 0.3f;
    if (factor > 1.0f) factor = 1.0f;
    
    return (uint32_t)(base_interval * factor);
}

/**
 * 自动雨刷主控制函数
 */
void auto_wiper_control(float vehicle_speed_kmh)
{
    if (!auto_wiper_state.enabled) {
        return;
    }
    
    uint32_t now = HAL_GetTick();
    
    // 获取当前雨量等级
    RainLevel_t rain_level = rain_sensor_get_level();
    
    // 灵敏度调整
    rain_level = adjust_rain_level_by_sensitivity(rain_level);
    
    // 首次检测到雨的延迟处理
    if (rain_level > RAIN_LEVEL_NONE && 
        auto_wiper_state.last_rain_level == RAIN_LEVEL_NONE) {
        
        if (!auto_wiper_state.startup_delay_active) {
            auto_wiper_state.first_detect_time = now;
            auto_wiper_state.startup_delay_active = 1;
        }
        
        // 延迟500ms启动,避免瞬时干扰
        if (now - auto_wiper_state.first_detect_time < 500) {
            return;
        }
        
        auto_wiper_state.startup_delay_active = 0;
    }
    
    // 雨停后的延迟处理
    if (rain_level == RAIN_LEVEL_NONE && 
        auto_wiper_state.last_rain_level > RAIN_LEVEL_NONE) {
        
        // 额外刮几下确保刮干净
        static uint8_t extra_wipes = 0;
        if (extra_wipes < 2) {
            rain_level = RAIN_LEVEL_MIST;  // 保持间歇
            extra_wipes++;
        } else {
            extra_wipes = 0;
        }
    }
    
    // 获取对应的雨刷设置
    WiperSpeed_t target_speed = auto_wiper_config.level_config[rain_level].speed;
    uint32_t target_interval = auto_wiper_config.level_config[rain_level].interval_ms;
    
    // 车速调整
    if (target_speed == WIPER_SPEED_INT) {
        target_interval = adjust_interval_by_speed(target_interval, vehicle_speed_kmh);
    }
    
    // 应用设置
    if (target_speed != auto_wiper_state.commanded_speed ||
        target_interval != auto_wiper_state.commanded_interval) {
        
        wiper_set_speed(target_speed);
        wiper_set_interval(target_interval);
        
        auto_wiper_state.commanded_speed = target_speed;
        auto_wiper_state.commanded_interval = target_interval;
    }
    
    auto_wiper_state.last_rain_level = rain_level;
}

/**
 * 使能/禁用自动雨刷
 */
void auto_wiper_enable(uint8_t enable)
{
    auto_wiper_state.enabled = enable;
    
    if (!enable) {
        // 禁用时停止雨刷
        wiper_set_speed(WIPER_SPEED_OFF);
    }
}

/**
 * 设置灵敏度
 */
void auto_wiper_set_sensitivity(uint8_t sensitivity)
{
    if (sensitivity > 10) sensitivity = 10;
    auto_wiper_config.sensitivity = sensitivity;
}

智能间歇算法

c 复制代码
/**
 * 智能间歇算法
 * 
 * 根据实际雨量动态调整间歇时间
 * 而不是固定的几个档位
 */

typedef struct {
    // 自适应间歇参数
    float rain_accumulator;         // 雨量累积
    float wipe_threshold;           // 刮动阈值
    uint32_t last_wipe_time;        // 上次刮动时间
    
    // 学习参数
    float avg_rain_rate;            // 平均雨量率
    uint32_t sample_count;
    
    // 间歇时间范围
    uint32_t min_interval_ms;
    uint32_t max_interval_ms;
} AdaptiveIntervalState_t;

static AdaptiveIntervalState_t adaptive_state = {
    .wipe_threshold = 100.0f,
    .min_interval_ms = 500,
    .max_interval_ms = 10000
};

/**
 * 自适应间歇计算
 * 
 * 原理:累积雨量,超过阈值时触发一次刮动
 */
void adaptive_interval_update(float current_rain_rate)
{
    uint32_t now = HAL_GetTick();
    static uint32_t last_update = 0;
    
    if (last_update == 0) {
        last_update = now;
        return;
    }
    
    float dt = (now - last_update) / 1000.0f;  // 秒
    last_update = now;
    
    // 累积雨量
    adaptive_state.rain_accumulator += current_rain_rate * dt;
    
    // 更新平均雨量率(指数滑动平均)
    float alpha = 0.1f;
    adaptive_state.avg_rain_rate = adaptive_state.avg_rain_rate * (1 - alpha) + 
                                   current_rain_rate * alpha;
    
    // 判断是否需要刮动
    if (adaptive_state.rain_accumulator >= adaptive_state.wipe_threshold) {
        // 触发刮动
        adaptive_state.rain_accumulator = 0;
        adaptive_state.last_wipe_time = now;
    }
}

/**
 * 计算建议的间歇时间
 */
uint32_t calc_adaptive_interval(void)
{
    if (adaptive_state.avg_rain_rate < 0.01f) {
        return adaptive_state.max_interval_ms;
    }
    
    // 间歇时间 = 阈值 / 雨量率
    float interval = adaptive_state.wipe_threshold / adaptive_state.avg_rain_rate;
    
    uint32_t interval_ms = (uint32_t)(interval * 1000);
    
    // 限制范围
    if (interval_ms < adaptive_state.min_interval_ms) {
        interval_ms = adaptive_state.min_interval_ms;
    }
    if (interval_ms > adaptive_state.max_interval_ms) {
        interval_ms = adaptive_state.max_interval_ms;
    }
    
    return interval_ms;
}

/**
 * 检查是否应该刮动
 */
uint8_t should_wipe_now(void)
{
    return (adaptive_state.rain_accumulator >= adaptive_state.wipe_threshold);
}

/**
 * 刮动后清零累积
 */
void wipe_completed(void)
{
    adaptive_state.rain_accumulator = 0;
    adaptive_state.last_wipe_time = HAL_GetTick();
}

系统联动控制

自动大灯联动

c 复制代码
/**
 * 雨天自动开灯
 * 
 * 下雨时能见度降低,自动开启近光灯
 */

typedef struct {
    uint8_t auto_light_enabled;     // 联动使能
    RainLevel_t light_threshold;    // 开灯阈值
    uint32_t on_delay_ms;           // 开灯延迟
    uint32_t off_delay_ms;          // 关灯延迟
} RainLightConfig_t;

typedef struct {
    uint8_t light_requested;
    uint32_t request_start_time;
    uint8_t light_state;
} RainLightState_t;

static RainLightConfig_t light_config = {
    .auto_light_enabled = 1,
    .light_threshold = RAIN_LEVEL_LIGHT,
    .on_delay_ms = 3000,        // 3秒后开灯
    .off_delay_ms = 60000       // 1分钟后关灯
};

static RainLightState_t light_state;

/**
 * 雨天大灯控制
 */
void rain_light_control(RainLevel_t rain_level)
{
    if (!light_config.auto_light_enabled) {
        return;
    }
    
    uint32_t now = HAL_GetTick();
    
    if (rain_level >= light_config.light_threshold) {
        // 需要开灯
        if (!light_state.light_requested) {
            light_state.light_requested = 1;
            light_state.request_start_time = now;
        }
        
        // 延迟开灯
        if (light_state.light_requested && !light_state.light_state &&
            now - light_state.request_start_time > light_config.on_delay_ms) {
            // 开启近光灯
            set_headlight(1);
            light_state.light_state = 1;
        }
    } else {
        // 雨停,延迟关灯
        if (light_state.light_state) {
            if (!light_state.light_requested) {
                // 开始关灯计时
                light_state.request_start_time = now;
            }
            light_state.light_requested = 0;
            
            if (now - light_state.request_start_time > light_config.off_delay_ms) {
                set_headlight(0);
                light_state.light_state = 0;
            }
        } else {
            light_state.light_requested = 0;
        }
    }
}

自动关窗联动

c 复制代码
/**
 * 下雨自动关窗
 */

typedef struct {
    uint8_t auto_close_enabled;
    RainLevel_t close_threshold;
    uint8_t windows_closed[4];      // 四个车窗状态
    uint8_t sunroof_closed;         // 天窗状态
} RainWindowConfig_t;

static RainWindowConfig_t window_config = {
    .auto_close_enabled = 1,
    .close_threshold = RAIN_LEVEL_LIGHT
};

/**
 * 检测到下雨时关闭车窗
 */
void rain_window_control(RainLevel_t rain_level)
{
    if (!window_config.auto_close_enabled) {
        return;
    }
    
    if (rain_level >= window_config.close_threshold) {
        // 关闭所有打开的车窗
        for (int i = 0; i < 4; i++) {
            if (!window_config.windows_closed[i]) {
                close_window(i);
            }
        }
        
        // 关闭天窗
        if (!window_config.sunroof_closed) {
            close_sunroof();
        }
    }
}

后视镜加热联动

c 复制代码
/**
 * 雨天后视镜加热除水
 */

typedef struct {
    uint8_t auto_heat_enabled;
    RainLevel_t heat_threshold;
    uint32_t heat_duration_ms;      // 加热时长
    float ambient_temp_max;         // 高于此温度不加热
} MirrorHeatConfig_t;

typedef struct {
    uint8_t heating;
    uint32_t heat_start_time;
} MirrorHeatState_t;

static MirrorHeatConfig_t mirror_config = {
    .auto_heat_enabled = 1,
    .heat_threshold = RAIN_LEVEL_MODERATE,
    .heat_duration_ms = 5 * 60 * 1000,  // 5分钟
    .ambient_temp_max = 20.0f           // 20度以上不加热
};

static MirrorHeatState_t mirror_state;

void rain_mirror_heat_control(RainLevel_t rain_level, float ambient_temp)
{
    if (!mirror_config.auto_heat_enabled) {
        return;
    }
    
    uint32_t now = HAL_GetTick();
    
    // 温度检查
    if (ambient_temp > mirror_config.ambient_temp_max) {
        if (mirror_state.heating) {
            set_mirror_heat(0);
            mirror_state.heating = 0;
        }
        return;
    }
    
    if (rain_level >= mirror_config.heat_threshold) {
        if (!mirror_state.heating) {
            // 开始加热
            set_mirror_heat(1);
            mirror_state.heating = 1;
            mirror_state.heat_start_time = now;
        }
    }
    
    // 超时自动关闭
    if (mirror_state.heating &&
        now - mirror_state.heat_start_time > mirror_config.heat_duration_ms) {
        set_mirror_heat(0);
        mirror_state.heating = 0;
    }
}

CAN/LIN通信

LIN总线通信(雨量传感器常用)

c 复制代码
/**
 * LIN总线通信
 * 
 * 雨量传感器通常作为LIN从节点
 * 主节点(BCM)定期查询雨量数据
 */

// LIN帧ID定义
#define LIN_FRAME_RAIN_SENSOR   0x20    // 雨量数据帧
#define LIN_FRAME_WIPER_CMD     0x21    // 雨刷命令帧

// 雨量数据帧结构
typedef struct __attribute__((packed)) {
    uint8_t rain_level : 3;         // 雨量等级 0-5
    uint8_t sensor_status : 2;      // 传感器状态
    uint8_t calibration_ok : 1;     // 校准状态
    uint8_t reserved : 2;
    
    uint8_t attenuation;            // 衰减率 0-100%
    uint8_t active_channels;        // 激活通道数
    
    int8_t trend;                   // 变化趋势 -100~100
    
    uint8_t checksum;               // 校验和
} RainSensorLINFrame_t;

// 雨刷命令帧结构
typedef struct __attribute__((packed)) {
    uint8_t auto_mode : 1;          // 自动模式
    uint8_t speed : 2;              // 速度档位
    uint8_t reserved : 5;
    
    uint8_t sensitivity;            // 灵敏度 0-10
    uint16_t interval_ms;           // 间歇时间
    
    uint8_t checksum;
} WiperCmdLINFrame_t;

/**
 * 发送雨量数据(从节点响应)
 */
void lin_send_rain_data(void)
{
    RainSensorLINFrame_t frame;
    
    frame.rain_level = rain_state.current_level;
    frame.sensor_status = 0;  // 正常
    frame.calibration_ok = cal_data.calibration_valid;
    frame.attenuation = (uint8_t)rain_state.attenuation_percent;
    frame.active_channels = rain_state.active_channels;
    frame.trend = (int8_t)(rain_state.attenuation_trend * 10);
    
    // 计算校验和
    uint8_t *data = (uint8_t*)&frame;
    frame.checksum = 0;
    for (int i = 0; i < sizeof(frame) - 1; i++) {
        frame.checksum += data[i];
    }
    frame.checksum = ~frame.checksum;
    
    // 发送
    lin_slave_send_response(LIN_FRAME_RAIN_SENSOR, &frame, sizeof(frame));
}

/**
 * 接收雨刷命令(从节点接收)
 */
void lin_receive_wiper_cmd(uint8_t *data, uint8_t len)
{
    if (len < sizeof(WiperCmdLINFrame_t)) {
        return;
    }
    
    WiperCmdLINFrame_t *cmd = (WiperCmdLINFrame_t*)data;
    
    // 验证校验和
    uint8_t checksum = 0;
    for (int i = 0; i < sizeof(WiperCmdLINFrame_t) - 1; i++) {
        checksum += data[i];
    }
    if ((uint8_t)~checksum != cmd->checksum) {
        return;  // 校验失败
    }
    
    // 应用设置
    auto_wiper_enable(cmd->auto_mode);
    auto_wiper_set_sensitivity(cmd->sensitivity);
    
    if (!cmd->auto_mode) {
        // 手动模式
        wiper_set_speed(cmd->speed);
        wiper_set_interval(cmd->interval_ms);
    }
}

CAN总线通信

c 复制代码
/**
 * CAN总线通信
 * 
 * 用于与BCM、仪表等通信
 */

// CAN消息ID
#define CAN_ID_RAIN_STATUS      0x320   // 雨量状态
#define CAN_ID_WIPER_STATUS     0x321   // 雨刷状态
#define CAN_ID_WIPER_CONTROL    0x322   // 雨刷控制

/**
 * 发送雨量状态
 */
void can_send_rain_status(void)
{
    CAN_TxHeaderTypeDef header;
    uint8_t data[8];
    uint32_t mailbox;
    
    header.StdId = CAN_ID_RAIN_STATUS;
    header.IDE = CAN_ID_STD;
    header.RTR = CAN_RTR_DATA;
    header.DLC = 8;
    
    data[0] = rain_state.current_level;
    data[1] = (uint8_t)rain_state.attenuation_percent;
    data[2] = rain_state.active_channels;
    data[3] = (int8_t)(rain_state.attenuation_trend * 10);
    data[4] = cal_data.calibration_valid;
    data[5] = 0;  // 保留
    data[6] = 0;
    data[7] = 0;
    
    HAL_CAN_AddTxMessage(&hcan, &header, data, &mailbox);
}

/**
 * 发送雨刷状态
 */
void can_send_wiper_status(void)
{
    CAN_TxHeaderTypeDef header;
    uint8_t data[8];
    uint32_t mailbox;
    
    header.StdId = CAN_ID_WIPER_STATUS;
    header.IDE = CAN_ID_STD;
    header.RTR = CAN_RTR_DATA;
    header.DLC = 8;
    
    data[0] = wiper_state.state;
    data[1] = wiper_state.current_speed;
    data[2] = auto_wiper_state.enabled;
    data[3] = auto_wiper_config.sensitivity;
    data[4] = (wiper_state.interval_ms >> 8) & 0xFF;
    data[5] = wiper_state.interval_ms & 0xFF;
    data[6] = wiper_state.cycle_count & 0xFF;
    data[7] = 0;
    
    HAL_CAN_AddTxMessage(&hcan, &header, data, &mailbox);
}

/**
 * 接收雨刷控制命令
 */
void can_rx_callback(CAN_RxHeaderTypeDef *header, uint8_t *data)
{
    if (header->StdId == CAN_ID_WIPER_CONTROL) {
        uint8_t cmd_type = data[0];
        
        switch (cmd_type) {
        case 0x01:  // 设置速度
            wiper_set_speed(data[1]);
            break;
            
        case 0x02:  // 设置自动模式
            auto_wiper_enable(data[1]);
            break;
            
        case 0x03:  // 设置灵敏度
            auto_wiper_set_sensitivity(data[1]);
            break;
            
        case 0x04:  // 请求校准
            rain_sensor_start_calibration();
            break;
            
        case 0x05:  // 单次刮动
            wiper_single_wipe();
            break;
        }
    }
}

系统主循环

c 复制代码
/**
 * 自动雨刷系统主程序
 */

// 任务周期定义
#define RAIN_SENSOR_PERIOD_MS   50      // 雨量检测 20Hz
#define WIPER_CONTROL_PERIOD_MS 10      // 雨刷控制 100Hz
#define CAN_TX_PERIOD_MS        100     // CAN发送 10Hz
#define CALIBRATION_CHECK_MS    60000   // 校准检查 1分钟

int main(void)
{
    // 硬件初始化
    HAL_Init();
    SystemClock_Config();
    GPIO_Init();
    ADC_Init();
    TIM_Init();
    CAN_Init();
    
    // 模块初始化
    rain_sensor_init();
    wiper_init();
    
    // 上电自检
    if (!rain_sensor_self_test()) {
        // 传感器故障,进入降级模式
        set_degraded_mode(1);
    }
    
    // 加载校准数据
    load_calibration_from_eeprom();
    
    uint32_t last_rain_sensor_time = 0;
    uint32_t last_wiper_control_time = 0;
    uint32_t last_can_tx_time = 0;
    uint32_t last_calibration_check = 0;
    
    while (1) {
        uint32_t now = HAL_GetTick();
        
        // 雨量传感器处理
        if (now - last_rain_sensor_time >= RAIN_SENSOR_PERIOD_MS) {
            rain_sensor_process();
            last_rain_sensor_time = now;
        }
        
        // 雨刷控制
        if (now - last_wiper_control_time >= WIPER_CONTROL_PERIOD_MS) {
            // 获取车速(假设通过CAN接收)
            float vehicle_speed = get_vehicle_speed();
            
            // 自动雨刷控制
            auto_wiper_control(vehicle_speed);
            
            // 雨刷电机控制
            wiper_control_loop();
            
            // 联动控制
            RainLevel_t level = rain_sensor_get_level();
            float ambient_temp = get_ambient_temperature();
            
            rain_light_control(level);
            rain_window_control(level);
            rain_mirror_heat_control(level, ambient_temp);
            
            last_wiper_control_time = now;
        }
        
        // CAN消息发送
        if (now - last_can_tx_time >= CAN_TX_PERIOD_MS) {
            can_send_rain_status();
            can_send_wiper_status();
            last_can_tx_time = now;
        }
        
        // 自动校准检查
        if (now - last_calibration_check >= CALIBRATION_CHECK_MS) {
            if (should_auto_calibrate()) {
                rain_sensor_start_calibration();
            }
            last_calibration_check = now;
        }
        
        // 校准过程处理
        rain_sensor_calibration_process();
        
        // 处理CAN接收
        process_can_rx();
    }
}

/**
 * 传感器自检
 */
uint8_t rain_sensor_self_test(void)
{
    // 检查各通道响应
    for (int ch = 0; ch < RAIN_CHANNEL_COUNT; ch++) {
        uint16_t value = rain_sensor_read_filtered(ch);
        
        // 值应该在合理范围内
        if (value < 500 || value > 4000) {
            return 0;  // 故障
        }
    }
    
    // 检查LED是否工作
    // 对比开LED和关LED时的信号差
    for (int ch = 0; ch < RAIN_CHANNEL_COUNT; ch++) {
        // LED关
        HAL_GPIO_WritePin(GPIOA, rain_config.channels[ch].led_pin, GPIO_PIN_RESET);
        HAL_Delay(10);
        uint16_t off_value = read_adc(rain_config.channels[ch].adc_channel);
        
        // LED开
        HAL_GPIO_WritePin(GPIOA, rain_config.channels[ch].led_pin, GPIO_PIN_SET);
        HAL_Delay(10);
        uint16_t on_value = read_adc(rain_config.channels[ch].adc_channel);
        
        HAL_GPIO_WritePin(GPIOA, rain_config.channels[ch].led_pin, GPIO_PIN_RESET);
        
        // 差值应该显著
        if (on_value - off_value < 500) {
            return 0;  // LED可能故障
        }
    }
    
    return 1;  // 自检通过
}

总结

自动雨刷系统的核心技术:

模块 关键技术
光学传感器 全内反射原理、多通道检测、同步采样
信号处理 中值滤波、背景光消除、基线校准
雨量判断 衰减率计算、多通道融合、滞环滤波
雨刷控制 双速电机、停止位检测、间歇控制
自动算法 等级映射、自适应间歇、车速补偿
系统联动 自动大灯、关窗、后视镜加热
通信接口 LIN从节点、CAN总线

雨量等级与雨刷对应关系:

雨量等级 衰减率 雨刷模式 间歇时间
无雨 ❤️% 停止 -
雾/毛毛雨 3-8% 间歇 8秒
小雨 8-15% 间歇 4秒
中雨 15-30% 间歇 2秒
大雨 30-50% 低速连续 -
暴雨 >50% 高速连续 -

设计要点:

  1. 快升慢降:雨变大快速响应,雨变小延迟响应
  2. 防误触发:首次检测延迟、多通道确认
  3. 自适应校准:温度补偿、长期漂移修正
  4. 安全保护:堵转检测、过流保护

希望这篇文章对做汽车电子的朋友有帮助,代码可以直接作为参考使用。有问题欢迎评论区交流~


参考资料:

  • 博世雨量传感器技术手册
  • 汽车车身电子系统设计
  • LIN总线协议规范
  • 光学传感器设计原理
相关推荐
檐下翻书1737 小时前
免费工艺流程模板下载_在线编辑建筑/汽车/物流工艺流程图图表
论文阅读·汽车·流程图·论文笔记·pcb工艺
AUTOSAR组织10 小时前
深入解析AUTOSAR框架下的TCP/IP协议栈
网络协议·tcp/ip·汽车·autosar·软件架构·软件·培训
Godspeed Zhao14 小时前
现代智能汽车中的无线技术42——BT与BLE(1)
网络·汽车
Godspeed Zhao17 小时前
现代智能汽车中的无线技术00——智能汽车的无线依赖
网络·汽车
Godspeed Zhao1 天前
现代智能汽车中的无线技术41——BT与BLE(0)
网络·汽车
jhf20201 天前
2026汽车4S店GEO优化高性价比公司选型指南:从效果、成本到适配
python·汽车
王然-HUDDM1 天前
技术领跑:HUDDM-7D系统L4级功能安全预研验证
人工智能·嵌入式硬件·安全·车载系统·汽车
GC_ESD2 天前
汽车IC的ESD防护:电磁兼容性能的隐形关键
汽车·集成电路·芯片设计·汽车电子·esd静电防护
vx_bisheyuange2 天前
【源码免费送】计算机毕设精选项目:基于SpringBoot的汽车租赁系统的设计与实现
spring boot·汽车·毕业设计·需求分析
wechat_Neal2 天前
供应商合作模式中以产品中心取向的转型要点2
人工智能·汽车·devops