ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

电赛双车跟随系统全攻略:从硬件选型到PID算法调试

电赛双车跟随系统全攻略:从硬件选型到PID算法调试 在实际电子设计竞赛电赛中双车跟随是一个经典的控制类题目它综合考察了嵌入式系统、传感器融合、运动控制和通信协同等多方面的能力。2022年电赛B题“双车跟随”要求两辆智能车在特定赛道上实现一主一从的跟随行驶对路径识别、速度匹配、距离保持和抗干扰能力提出了很高要求。很多队伍在实现基础功能后往往在稳定性、精度和应对复杂场景上失分。本文将围绕如何构建一个稳定、高分的双车跟随系统展开从系统架构设计、核心算法实现到现场调试技巧提供一个完整的工程实践指南。无论你是初次接触电赛的新手还是希望优化现有方案的参赛者都能从中获得从理论到落地的具体方法。我们将重点讲解如何让主车领航车精准识别路径以及从车跟随车如何根据主车状态实现平滑、稳定的跟随最终达到“满分套餐”级别的性能。1. 系统总体设计与核心模块选型双车跟随系统的核心在于信息的可靠获取与精准控制。一个稳健的系统设计需要明确各模块的职责和交互方式。1.1 系统架构与通信链路典型的双车系统采用主从分布式架构。主车负责环境感知主要是路径识别和自身运动控制同时将关键状态信息发送给从车。从车接收主车信息结合自身的传感器数据计算出合适的运动指令实现跟随。通信方案选型无线通信的稳定性和实时性是关键。常见方案对比如下通信方式优点缺点适用场景蓝牙 (HC-05/06)成本低集成简单功耗较低。传输距离短通常10米易受干扰带宽和实时性一般。室内、短距离、低速跟随的验证性项目。2.4GHz 无线模块 (NRF24L01)成本低传输速率较高可组网实时性好。需要编写通信协议穿透性一般配置稍复杂。电赛主流选择距离和实时性平衡较好。Wi-Fi (ESP8266/32)带宽高可传输图像等大数据距离较远。功耗高网络延迟不稳定协议栈复杂。需要传输摄像头图像或进行复杂计算的场景。ZigBee组网能力强功耗低。传输速率低开发复杂度高实时性一般。多节点传感器网络对实时性要求不高的场景。对于电赛场景NRF24L01通常是性价比和可靠性的最佳选择。它需要一套简单的应用层协议来封装数据。数据包设计示例 主车周期性如50ms发送一个数据包包含包头固定值如 0xAA, 0xBB主车速度左轮、右轮速度或合成线速度、角速度主车航向角来自陀螺仪主-从车相对距离可选如果从车能测量校验和如累加和或CRC81.2 主车核心模块路径识别方案路径识别是主车的“眼睛”其精度和鲁棒性直接决定整个系统的上限。方案一摄像头OpenMV/MT9V034这是目前的主流和高分方案。通过图像处理可以获取丰富的路径信息中心线、拐弯类型、十字路口等。优点信息量大前瞻距离远可识别复杂元素环岛、坡道。难点算法复杂度高受光照影响大处理速度要求高。核心处理流程图像采集与预处理灰度化、二值化动态阈值或固定阈值。ROI感兴趣区域划定只处理图像下方一定区域减少计算量。边缘检测与中线提取常用“扫线法”从ROI底部向上逐行扫描找到左右边线计算中心点。偏差计算将图像中心与提取到的路径中心线的横向偏移量作为控制偏差。方案二红外对管/激光传感器阵列使用多路如8-16路红外收发管或激光管横向排布检测赛道黑线的位置。优点响应速度快算法简单不受光照影响。缺点前瞻近信息量少对赛道宽度和颜色对比度敏感。关键点传感器布局密度和高度决定了分辨率。常用“加权平均法”计算偏差偏差 Σ(传感器位置 * 权重) / Σ(权重)其中权重为传感器检测到黑线时的值。对于追求高分的队伍摄像头方案是必选项。它不仅用于循迹还能为从车的跟随策略提供更丰富的预测信息。1.3 从车核心模块状态感知与跟随策略从车需要知道“主车在哪”和“自己在哪”才能决定“该怎么走”。状态感知来源主车无线数据获取主车的速度、航向角。这是跟随的基准。自身编码器测量自身的实际速度用于速度闭环控制。相对测距传感器可选但强烈推荐用于测量与主车的实时距离。超声波模块 (HC-SR04)成本低但波束角大在动态场景中易受干扰刷新率低。激光测距模块 (TOF)如VL53L0X精度高波束角小响应快是更优选择。跟随策略核心从车的目标不是复现主车的轨迹而是保持一个稳定的相对状态距离和角度。控制模型可以简化为一个串级控制系统外环位置环。输入是目标相对距离和当前测量距离输出是目标速度。内环速度环。输入是外环给出的目标速度通过编码器反馈进行PID控制输出电机PWM。2. 硬件平台搭建与软件环境准备一套稳定可靠的硬件平台是算法得以发挥的基础。2.1 硬件清单与连接以下清单基于常见的STM32F4或K210主控方案模块型号推荐数量主要作用连接说明主控制器STM32F407/F103, K2102核心运算与控制主、从车各一电机驱动TB6612FNG, DRV88332驱动直流减速电机使用PWM和方向控制引脚路径识别MT9V034全局快门摄像头1主车采集赛道图像I2C配置DMA传输图像数据无线通信NRF24L01 (带PALNA)2主从车数据交互SPI接口注意电源滤波姿态传感器MPU6050 (六轴)2测量航向角融合后I2C接口编码器光电/霍尔编码器4测量车轮转速接单片机定时器编码器模式测距模块VL53L0X1从车测量与主车距离I2C接口电源管理降压模块 (如LM2596)若干提供稳定5V/3.3V注意电机与逻辑电源隔离关键接线提示电机驱动电源务必与单片机逻辑电源隔离使用独立的电池或稳压模块并在电源入口处加装大电容如470uF滤除电机干扰。NRF24L01VCC引脚必须连接稳定的3.3V且最好并联一个10uF和0.1uF的电容。SPI的MISO、MOSI、SCK、CSN、CE引脚连接正确。编码器推荐使用单片机硬件编码器接口如TIMx的Encoder模式软件计数在高速下可能丢失脉冲。2.2 软件开发环境与关键库IDEKeil MDK (STM32) 或 PlatformIO (VSCode)。固件库使用HAL库或标准库确保定时器、PWM、编码器、I2C、SPI、DMA等外设配置正确。图像处理如果使用K210可使用MaixPy或自写算法如果使用STM32OV7725/MT9V034通常需要将图像数据通过DMA传至内存自己编写二值化、寻线算法。PID控制库需要实现位置式或增量式PID控制器。建议封装成结构体便于管理多组PID参数。// PID控制器结构体示例 typedef struct { float Kp, Ki, Kd; // PID参数 float integral; // 积分项 float prev_error; // 上次误差 float output_max; // 输出限幅 float output_min; } PID_Controller; float PID_Calculate(PID_Controller *pid, float error, float dt) { // 比例项 float proportional pid-Kp * error; // 积分项抗饱和处理 pid-integral error * dt; if (pid-integral pid-output_max) pid-integral pid-output_max; if (pid-integral pid-output_min) pid-integral pid-output_min; float integral pid-Ki * pid-integral; // 微分项可选对误差微分或对测量值微分 float derivative pid-Kd * (error - pid-prev_error) / dt; pid-prev_error error; // 计算并限幅输出 float output proportional integral derivative; if (output pid-output_max) output pid-output_max; if (output pid-output_min) output pid-output_min; return output; }3. 核心算法实现与代码详解算法是系统的灵魂这里将分解主车的路径识别与从车的跟随控制。3.1 主车基于摄像头的路径识别与运动控制主车的任务是稳定、快速地沿赛道中心行驶。其控制流程为图像采集 - 图像处理 - 偏差计算 - PID控制 - 电机输出。图像处理与中线提取简化扫线法 假设图像宽度为IMG_WIDTH高度为IMG_HEIGHTROI从第START_ROW行开始。#define IMG_WIDTH 160 #define IMG_HEIGHT 120 #define START_ROW 80 #define BLACK_THRESHOLD 50 // 二值化阈值 uint8_t image[IMG_HEIGHT][IMG_WIDTH]; // 假设已是灰度图 int left_line[IMG_HEIGHT - START_ROW]; int right_line[IMG_HEIGHT - START_ROW]; int center_line[IMG_HEIGHT - START_ROW]; void find_center_line() { for (int row START_ROW; row IMG_HEIGHT; row) { int left 0, right IMG_WIDTH - 1; // 从左向右找左边缘 for (int col 0; col IMG_WIDTH; col) { if (image[row][col] BLACK_THRESHOLD) { left col; break; } } // 从右向左找右边缘 for (int col IMG_WIDTH - 1; col 0; col--) { if (image[row][col] BLACK_THRESHOLD) { right col; break; } } left_line[row - START_ROW] left; right_line[row - START_ROW] right; // 计算该行中心点 if (right left) { // 找到有效线 center_line[row - START_ROW] (left right) / 2; } else { // 丢线处理可沿用上一行中心或设定默认值 center_line[row - START_ROW] IMG_WIDTH / 2; } } }偏差计算与控制 通常选取ROI中靠近车体的某一行或几行的加权平均的中心点与图像中心点的差值作为横向偏差。#define TARGET_ROW_OFFSET 20 // 选取ROI中从上往下第20行靠近车体 int calculate_error() { int row_index TARGET_ROW_OFFSET; int center_at_row center_line[row_index]; int image_center IMG_WIDTH / 2; return center_at_row - image_center; // 偏差值正数表示路径中心偏右 }运动控制差速转向 使用一个PID控制器处理横向偏差输出为角速度或直接为左右轮速差。PID_Controller steering_pid {2.0, 0.01, 0.5, 100, -100}; // 示例参数 float base_speed 800; // 基础PWM值 float dt 0.02; // 控制周期50ms void motor_control(int error) { float adjust PID_Calculate(steering_pid, (float)error, dt); int left_pwm (int)(base_speed adjust); int right_pwm (int)(base_speed - adjust); // PWM限幅 left_pwm constrain(left_pwm, 0, 1000); right_pwm constrain(right_pwm, 0, 1000); set_motor_pwm(MOTOR_LEFT, left_pwm); set_motor_pwm(MOTOR_RIGHT, right_pwm); }3.2 从车基于状态反馈的跟随控制从车的控制核心是维持与主车的期望距离。我们采用“速度-距离”串级PID控制。数据接收与解析 在从车主循环或中断中接收并解析主车发来的数据包。typedef struct { float leader_speed; // 主车线速度 float leader_yaw; // 主车航向角 // ... 其他数据 } LeaderData; LeaderData g_leader_data; void parse_rf_data(uint8_t *buf) { // 假设数据包格式已定义这里简单解析 if (buf[0]0xAA buf[1]0xBB) { memcpy(g_leader_data.leader_speed, buf[2], sizeof(float)); memcpy(g_leader_data.leader_yaw, buf[6], sizeof(float)); // 校验和检查... } }串级PID控制器实现 外环PID根据距离偏差计算目标速度内环PID根据速度偏差计算电机PWM。PID_Controller distance_pid {1.5, 0.05, 0.2, 200, -200}; // 距离环PID PID_Controller speed_pid {10.0, 0.1, 0.0, 1000, -1000}; // 速度环PID float target_distance 30.0; // 目标跟随距离单位厘米 float dt 0.05; // 控制周期100ms void follower_control() { // 1. 读取当前距离例如从VL53L0X读取 float current_distance get_current_distance(); // 2. 外环距离偏差 - 目标速度 float distance_error current_distance - target_distance; float target_speed g_leader_data.leader_speed PID_Calculate(distance_pid, distance_error, dt); // 将主车速度作为前馈加快响应 // 3. 读取自身编码器速度 float current_speed (get_left_speed() get_right_speed()) / 2.0; // 4. 内环速度偏差 - PWM输出 float speed_error target_speed - current_speed; float pwm_adjust PID_Calculate(speed_pid, speed_error, dt); float base_pwm target_speed * SPEED_TO_PWM_RATIO; // 速度到PWM的换算系数 int left_pwm (int)(base_pwm pwm_adjust); int right_pwm (int)(base_pwm - pwm_adjust); // 限幅并输出 left_pwm constrain(left_pwm, 0, 1000); right_pwm constrain(right_pwm, 0, 1000); set_motor_pwm(MOTOR_LEFT, left_pwm); set_motor_pwm(MOTOR_RIGHT, right_pwm); }航向角同步进阶 如果要求两车保持同向可以在从车控制中加入航向角偏差控制。使用MPU6050获取从车航向角与主车航向角比较其偏差通过另一个PID控制器影响左右轮差速实现转向同步。4. 系统联调、参数整定与性能优化代码编写完成后调试和参数整定是决定最终性能的关键步骤。切忌盲目调参必须有方法、有顺序。4.1 分模块独立调试在集成前务必确保每个模块单独工作正常。主车循迹调试断开无线模块让主车单独跑。先确保摄像头能稳定输出二值化图像并在屏幕上显示识别出的中线。PID参数整定顺序先调Kp让车能大致跟着线走但左右摆动再加入Kd抑制摆动使运行平滑最后加入很小的Ki消除静态误差。调试时逐步提高基础速度base_speed。通信调试将主从车靠近编写简单的测试程序让主车发送一个递增的数字从车接收并打印。确保数据能连续、无误地传输。测试最远通信距离和抗干扰能力用手遮挡、在其他2.4G设备旁测试。从车测距与速度闭环调试固定主车手动移动从车检查测距传感器读数是否准确、稳定。让从车空载车轮悬空给定一个目标PWM观察编码器反馈的速度值是否线性、准确。整定速度环PID使电机能快速、无超调地达到设定速度。4.2 联合调试与参数微调当各模块独立工作后进行联合调试。静态跟随测试主车静止从车启动。观察从车是否能平滑加速并稳定停在目标距离处。主要调整距离环PID。低速匀速跟随测试主车低速直线行驶。观察从车距离是否稳定速度是否同步。此时可能需微调距离环和速度环。弯道跟随测试这是难点。主车过弯时速度会变化从车容易因响应滞后而导致距离突变或撞车。策略主车在发送数据时除了当前速度还可以发送一个“预期速度变化”或“弯道标志”。从车收到后可以提前微调距离环的目标值或PID参数。参数自适应可以根据距离误差的大小动态调整PID参数。例如当距离误差很大时使用一组更激进的参数快速接近误差很小时使用一组更温和的参数保持稳定。4.3 现场适应性优化比赛现场环境与实验室不同必须准备优化方案。光照适应性摄像头的二值化阈值不能写死。可以采用动态阈值法如统计图像某块区域的灰度均值作为阈值。int calculate_dynamic_threshold(uint8_t *img, int width, int height) { long sum 0; for (int i 0; i width * height; i) { sum img[i]; } int mean sum / (width * height); return mean - 20; // 根据赛道颜色调整偏移量 }抗通信干扰使用NRF24L01的自动重发和自动应答功能。在数据包中加入包序号和校验和从车发现丢包或错包时可采取保持上一帧数据或减速等安全策略。为NRF模块加装屏蔽罩并使用独立的3.3V LDO供电。异常处理与鲁棒性主车丢线处理当摄像头连续多帧找不到有效边线时应进入“搜索模式”例如按照上一帧的角速度原地缓慢旋转直到重新寻线。从车通信超时处理如果超过一定时间如200ms未收到主车数据从车应逐渐刹车停止并报警。传感器失效处理如果测距传感器连续返回异常值应切换为纯速度跟随模式并降低跟随速度。5. 常见问题排查与实战技巧在调试和比赛过程中会遇到各种问题。下表列出典型问题及排查思路问题现象可能原因排查步骤解决方案主车跑偏或冲出赛道1. 摄像头图像二值化效果差。2. 中线提取算法有误。3. PID参数不合适。1. 通过串口或屏幕查看二值化图像检查黑白是否分明。2. 打印出提取到的左右边线和中心点坐标看是否合理。3. 观察偏差曲线是震荡还是静差大。1. 优化光照或改用动态阈值。2. 调试扫线逻辑处理丢线情况。3. 按Kp-Kd-Ki顺序重新整定PID。从车跟随距离波动大1. 测距传感器数据跳动。2. 距离环PID参数过激。3. 主车速度波动大。1. 静止状态下测试测距传感器观察数据稳定性。2. 观察距离误差曲线看是否超调或震荡。3. 查看主车速度输出是否平滑。1. 对测距数据进行软件滤波如均值滤波、卡尔曼滤波。2. 降低距离环Kp和Kd。3. 优化主车速度控制或从车对主车速度进行滤波。无线通信时断时续1. 电源不稳。2. 模块天线损坏或朝向不对。3. 同频段干扰。4. 软件配置错误。1. 用示波器测量NRF模块VCC引脚电压。2. 检查天线是否焊接牢固。3. 更换通信频道。4. 检查SPI时序、CE/CSN引脚控制。1. 增加滤波电容使用独立LDO供电。2. 确保天线竖直向上避免被金属遮挡。3. 选择干扰少的频道并启用自动重发。4. 对照数据手册检查初始化代码。弯道时从车撞上主车1. 从车响应滞后。2. 主车过弯减速信息未及时传递。1. 分析通信延迟和控制周期。2. 检查主车在弯道时发送的速度值是否准确反映了减速。1. 缩短控制周期优化代码效率。2. 主车可增加“弯道预测”提前发送减速指令或标志位。从车收到后提前增大目标距离。系统上电后电机乱转1. 电机驱动使能逻辑错误。2. PWM初始化输出非零占空比。3. 电源干扰导致单片机复位异常。1. 检查电机驱动芯片的使能引脚电平。2. 检查PWM初始化函数确保初始输出为0。3. 监测单片机复位引脚。1. 在程序初始化阶段先将所有电机控制引脚设为安全状态如驱动芯片待机。2. 确保先配置PWM为0再启动定时器。3. 加强电源滤波电机电源与逻辑电源完全隔离。现场实战技巧备件策略核心模块如主控、摄像头、NRF模块、电机驱动必须准备双份。参数固化与快速切换将调试好的PID参数、阈值等存储在单片机的Flash中。准备多套参数如针对强光、弱光、不同赛道摩擦系数通过按键快速切换。调试接口务必保留串口打印调试信息的功能。可以输出关键变量如偏差、速度、距离到上位机绘图便于分析。电源监控在代码中加入电池电压检测当电压低于阈值时让小车减速或停车防止因电量不足导致控制异常。6. 从学习到生产的进阶考量将实验室作品升级为稳定可靠的竞赛系统还需要考虑以下工程化问题。系统稳定性保障看门狗启用硬件看门狗防止程序跑飞。软件架构使用实时操作系统如FreeRTOS或基于时间片轮询的调度器确保关键任务图像采集、控制计算、通信的定时执行。状态机设计将小车行为划分为不同状态如初始化、寻线、弯道处理、停车使逻辑清晰易于调试和维护。性能优化图像处理加速将二值化、寻线等算法中用到的查找表、阈值计算等提前完成。利用单片机的DMA、硬件乘法器、DSP指令。控制频率确保核心控制循环频率不低于50Hz周期20ms通信频率不低于20Hz。数据滤波对传感器数据编码器速度、陀螺仪、测距进行滤波。简单的移动平均滤波或一阶低通滤波能有效抑制噪声。测试与验证单元测试单独测试每个传感器和执行器。集成测试在直道、弯道、十字路口等不同赛道上测试跟随效果。压力测试长时间运行测试系统发热、电源稳定性。异常注入测试模拟通信中断、传感器失效等情况检查系统的安全策略是否生效。实现一个满分级别的双车跟随系统是对团队硬件设计、软件编程和现场调试能力的综合考验。核心在于理解“感知-决策-控制”这一闭环并在每个环节做到足够鲁棒。从精准的图像识别到稳定的无线通信再到快速且平滑的闭环控制每一步都需要精心设计和反复调试。建议先让主车能稳定高速循迹再单独调试从车的测距与速度闭环最后进行联合调试。在算法上不必追求过于复杂一个调校良好的串级PID往往比未经充分验证的先进算法更可靠。最后永远为现场变化做好准备灵活的参数调整机制和完备的异常处理是获得高分的最后一块拼图。
返回列表