共计 1943 个字符,预计需要花费 5 分钟才能阅读完成。
背景痛点
电子设计竞赛中的交叉行驶场景对自动驾驶小车提出了较高要求,尤其是直角转弯和会车避让时,需要精确的航向角控制。对于新手而言,使用陀螺仪时常见以下问题:

- 零漂累积:陀螺仪在长时间运行后会产生偏差,导致角度计算不准确。
- 加速度计干扰:小车加速或减速时,加速度计数据会受到重力分量影响,导致姿态解算错误。
- 数据抖动:由于传感器噪声或电机振动,原始数据波动较大,影响控制稳定性。
技术选型
常见的陀螺仪传感器有 MPU6050 和 BNO055,它们的优劣对比如下:
- MPU6050:成本低,集成加速度计和陀螺仪,但需要自行实现数据融合算法,温漂较明显。
- BNO055:内置传感器融合算法,直接输出姿态角,温漂较小,但价格较高。
对于竞赛场景,推荐使用 MPU6050,因其成本低且灵活性高,适合学习与调试。关键参数选择依据:
- 采样率:至少 100Hz,以满足实时控制需求。
- 温漂参数:选择温漂系数较小的型号,减少长时间运行的误差累积。
核心实现
1. 陀螺仪原始数据采集与 IIR 滤波
首先,通过 STM32 HAL 库读取 MPU6050 的原始数据。以下是一个简单的代码片段:
// 初始化 I2C 接口
HAL_I2C_Init(&hi2c1);
// 读取陀螺仪数据
uint8_t data[6];
HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR, GYRO_XOUT_H, 1, data, 6, 100);
int16_t gx = (data[0] << 8) | data[1];
int16_t gy = (data[2] << 8) | data[3];
int16_t gz = (data[4] << 8) | data[5];
为了减少噪声,可以使用 IIR 滤波算法:
float filtered_gx = 0.9 * filtered_gx + 0.1 * gx;
2. 互补滤波算法实现姿态解算
互补滤波结合了陀螺仪的高频响应和加速度计的低频稳定性,公式如下:
angle = 0.98 * (angle + gyro * dt) + 0.02 * accel_angle
代码实现:
float angle = 0;
float dt = 0.01; // 采样周期 10ms
void update_angle(float gyro, float accel_angle) {angle = 0.98 * (angle + gyro * dt) + 0.02 * accel_angle;
}
3. 基于航向角的 PID 控制逻辑
PID 控制器根据航向角误差调整小车的转向:
float pid_control(float target_angle, float current_angle) {
float error = target_angle - current_angle;
static float integral = 0;
static float last_error = 0;
integral += error * dt;
float derivative = (error - last_error) / dt;
last_error = error;
return KP * error + KI * integral + KD * derivative;
}
避坑指南
1. 磁力计受电机干扰的解决方案
电机运行时会产生磁场干扰,导致磁力计数据不准确。解决方法:
- 将磁力计远离电机安装。
- 使用软件校准,记录干扰磁场并补偿。
2. 卡尔曼滤波参数调优技巧
卡尔曼滤波的参数(过程噪声和测量噪声)需要根据实际场景调整:
- 过程噪声(Q)较大时,滤波结果更依赖测量值。
- 测量噪声(R)较大时,滤波结果更依赖预测值。
3. 紧急制动时的传感器数据异常处理
紧急制动时,加速度计数据会剧烈变化,可能导致姿态解算错误。解决方法:
- 检测加速度变化率,超过阈值时暂停姿态更新。
- 使用陀螺仪数据单独估算角度。
验证测试
1. 不同路面材质下的角度误差测试数据
在木板和亚克力路面上测试航向角误差:
| 路面材质 | 平均误差(度) |
|---|---|
| 木板 | 1.2 |
| 亚克力 | 2.5 |
2. 连续运行 2 小时的零漂变化曲线
长时间运行后,零漂逐渐累积,但通过定期校准可以控制在合理范围内:
时间(分钟)| 零漂(度 / 秒)0 | 0.01
30 | 0.05
60 | 0.12
120 | 0.25
实战挑战
扩展功能:如何增加激光雷达避障?
- 选择一个合适的激光雷达(如 RPLIDAR A1)。
- 通过串口读取雷达数据,解析障碍物距离和角度。
- 在路径规划算法中避开障碍物。
示例代码:
// 初始化串口
HAL_UART_Init(&huart2);
// 读取雷达数据
uint8_t buffer[128];
HAL_UART_Receive(&huart2, buffer, 128, 100);
// 解析数据
// ...
结尾体验
通过本次实践,我们实现了自动驾驶小车的交叉行驶功能,从传感器选型到算法实现,每一步都充满了挑战与收获。希望这篇指南能帮助你在竞赛中快速搭建稳定可靠的自动导航系统。如果有任何问题,欢迎在评论区交流!
正文完
发表至: 未分类
近两天内
