二、线控转向系统原理
线控转向,英文叫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分析时,把每个故障模式都走一遍,看看系统到底能不能扛得住。
好了,线控转向的原理就讲到这里。下一章我们聊线控制动,那个更刺激——毕竟刹车出问题,可不是闹着玩的。