前言
前阵子做一个汽车雨刷控制模块的项目,从雨量传感器选型到控制算法都过了一遍。自动雨刷看起来简单,但要做到"智能"------根据雨量大小自动调节频率、避免误触发、响应迅速又不抖动------还是有不少技术细节的。
今天把雨量感应和自动雨刷的技术整理出来,从传感器原理到控制代码,希望对做汽车电子的朋友有帮助。
系统整体架构
┌─────────────────────────────────────────────────────────────────────────────┐
│ 自动雨刷系统架构 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 雨量传感器模块 │ │
│ │ (贴装于前挡风玻璃内侧) │ │
│ │ │ │
│ │ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │ │
│ │ │ 红外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% | 高速连续 | - |
设计要点:
- 快升慢降:雨变大快速响应,雨变小延迟响应
- 防误触发:首次检测延迟、多通道确认
- 自适应校准:温度补偿、长期漂移修正
- 安全保护:堵转检测、过流保护
希望这篇文章对做汽车电子的朋友有帮助,代码可以直接作为参考使用。有问题欢迎评论区交流~
参考资料:
- 博世雨量传感器技术手册
- 汽车车身电子系统设计
- LIN总线协议规范
- 光学传感器设计原理