二、线控转向系统原理

线控转向,英文叫Steer-by-Wire,简称SBW。说白了,就是方向盘和车轮之间没有那根机械轴了。你打方向,方向盘转它的,车轮转车轮的,中间全靠电信号传递。

我第一次接触SBW是在2018年,当时一个项目要做L4级自动驾驶的底盘。客户要求方向盘必须能收进去,那传统转向柱肯定不行。嗯,从那以后我就开始深入研究这套系统了。

2.1 线控转向(SBW)架构

SBW的架构其实不复杂,我习惯把它分成三块:

  • 方向盘总成:包括方向盘、路感模拟电机、角度传感器
  • 控制器(ECU):处理信号、计算目标转角、监控故障
  • 执行器总成:转向电机、减速机构、齿条位置传感器

你想想看,传统转向系统里,你打方向,力是直接通过转向柱传到齿条的。SBW呢?方向盘转了个角度,传感器检测到,告诉ECU,ECU算一下,再告诉执行器电机去转。中间多了好几步,但好处是——你想怎么调就怎么调。

架构要点:

  • 方向盘与转向器之间无机械连接
  • 采用双路CAN或以太网通信
  • 必须配备失效备份模式

我在项目中遇到过一个问题:通信延迟。当时用的CAN总线,从方向盘转角采集到执行器响应,延迟大概在10ms左右。对于低速行驶还好,但高速时这10ms就让人很不舒服。后来我们换成了CAN FD,延迟降到了3ms以内。

2.2 路感模拟

路感模拟,这是SBW里最有意思的部分。传统转向系统,路感是机械反馈给你的——轮胎压到石子,方向盘会抖一下。SBW没有机械连接,那路感从哪来?全靠电机模拟。

说白了,就是用一个电机给你施加一个反力矩,让你感觉好像方向盘有“力”一样。

路感模拟的核心算法,我一般这样写:

// 路感力矩计算(简化版)
float calculate_steering_torque(float vehicle_speed, float steering_angle, float lateral_accel) {
    float base_torque = 0.0;
    
    // 1. 基础阻尼 - 跟车速相关
    base_torque += K_damping * vehicle_speed * steering_angle;
    
    // 2. 回正力矩 - 跟侧向加速度相关
    base_torque += K_return * lateral_accel;
    
    // 3. 摩擦补偿 - 模拟机械摩擦
    base_torque += K_friction * sign(steering_angle);
    
    // 4. 惯性补偿 - 模拟方向盘惯性
    base_torque += K_inertia * steering_acceleration;
    
    return base_torque;
}

这个算法看着简单,但调起来很费劲。我曾经花了两周时间,就为了调一个阻尼系数。车速从0到120km/h,每个速度段的感觉都要不一样。低速要轻,高速要稳,这个“轻”和“稳”之间的过渡曲线,我调了至少50个版本。

我的经验:

路感模拟不要追求“完全真实”。你想想看,传统转向系统也有它的缺陷——比如低速时太重。SBW的优势恰恰是可以做得比传统更好。我建议把路感调成“比传统好20%”的感觉,这样用户既觉得熟悉,又觉得舒服。

2.3 转向执行器控制

执行器控制,就是让车轮转到你想要的角度。这里用的是伺服控制,核心是PID加前馈。

我常用的控制结构是这样的:

// 转向执行器位置控制
void steering_actuator_control(float target_angle, float current_angle) {
    float error = target_angle - current_angle;
    
    // PID控制
    static float integral = 0;
    float derivative = error - prev_error;
    integral += error * dt;
    
    float pid_output = Kp * error + Ki * integral + Kd * derivative;
    
    // 前馈补偿 - 根据目标角度变化率
    float feedforward = Kff * target_angle_rate;
    
    // 最终输出
    float motor_current = pid_output + feedforward;
    
    // 限幅
    if (motor_current > MAX_CURRENT) motor_current = MAX_CURRENT;
    if (motor_current < -MAX_CURRENT) motor_current = -MAX_CURRENT;
    
    set_motor_current(motor_current);
    prev_error = error;
}

这里有个坑,我踩过。PID参数在空载和带载时完全不一样。空载时调好的参数,装上轮胎后就开始抖。后来我加了自适应增益调度——根据车速和负载动态调整Kp、Ki、Kd。

注意:

执行器控制必须考虑齿条末端保护。我曾经见过一个案例,执行器电机一直往一个方向转,结果齿条撞到了机械限位,硬生生把减速齿轮打碎了。所以一定要加软限位和硬限位双重保护。

2.4 安全冗余设计

安全冗余,这是SBW的命门。没有机械连接,一旦电子系统失效,方向盘和车轮就失联了。所以冗余设计必须做到位。

我一般要求至少做到以下三点:

冗余层级 实现方式 我的要求
传感器冗余 双角度传感器(主+辅) 两路信号偏差<2°
控制器冗余 双MCU(主+备份) 切换时间<50ms
执行器冗余 双绕组电机 单绕组可维持50%性能
通信冗余 双路CAN/以太网 一路失效,另一路接管

我曾经在一个项目中,只做了单路传感器。结果路试时传感器突然漂移,方向盘明明回正了,车轮却偏了5度。还好驾驶员及时发现,手动切到了备份模式。从那以后,我再也不敢省传感器了。

安全冗余设计原则:

  • 任何单点故障都不能导致转向功能完全丧失
  • 故障检测时间 < 100ms
  • 故障响应时间 < 200ms
  • 必须支持故障降级模式(如:降速、限制转角)

嗯,这里还要提一下故障诊断。我习惯用状态机来管理转向系统的健康状态:

enum SteeringState {
    NORMAL,         // 正常
    DEGRADED,       // 降级(如传感器失效)
    LIMP_HOME,      // 跛行(如电机半功率)
    SAFE_STOP       // 安全停止
};

void steering_safety_monitor() {
    // 检查传感器一致性
    if (abs(sensor1_angle - sensor2_angle) > ANGLE_THRESHOLD) {
        state = DEGRADED;
        // 切换到备份传感器
    }
    
    // 检查执行器电流
    if (motor_current > OVERCURRENT_THRESHOLD) {
        state = LIMP_HOME;
        // 限制输出功率
    }
    
    // 检查通信
    if (communication_timeout > TIMEOUT_THRESHOLD) {
        state = SAFE_STOP;
        // 启动紧急制动
    }
}

最后说一句,SBW的安全冗余不是堆硬件就完事了。你堆了双传感器、双MCU、双电机,但如果软件逻辑没写好,该失效的时候还是失效。我建议做FMEA分析时,把每个故障模式都走一遍,看看系统到底能不能扛得住。

好了,线控转向的原理就讲到这里。下一章我们聊线控制动,那个更刺激——毕竟刹车出问题,可不是闹着玩的。