ARTICLE DETAIL

资讯详情

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

智能车竞赛独轮组控制与调参全解析:从硬件搭建到开源实战

智能车竞赛独轮组控制与调参全解析:从硬件搭建到开源实战 简介《十八届智能车竞赛独轮组——总结开源篇》是一份面向智能车竞赛独轮组选手与指导教师的系统备赛资料尤其适合准备蓝桥杯智能汽车比赛或同类竞速赛的读者。PDF共1个文件整包约975KB内容精炼便于按章节快速查阅。文档从竞赛规则圈重点入手涵盖路口转向、断路区进出、LED灯光秀等规则细节随后详解车模安装注意事项包括编码器齿轮咬合松紧、皮带调节、飞轮调平、电池固定等常见坑点再结合平衡受力分析说明动量轮原理程序部分重点解析并级PID与串级PID的整体框架、中断周期设置及内外环调参顺序并给出限幅与参数选择经验。目前已有893人浏览学习对于准备十八届智能车竞赛独轮组的同学来说是一份能帮助少走弯路、快速上手的开源总结。1. 独轮组不是比谁快而是比谁先不摔第18届全国大学生智能车竞赛独轮组是近年所有组别里“入门门槛”和“翻车概率”都排在前列的一组。赛道上常出现的画面是队员把车体扶正、松手车在原地前后抖几秒然后要么稳住要么在裁判注视下抽搐着倒地。独轮组真正难的是让只有单个轮子接触地面的倒立摆先“站住”。赛后开源总结通常会把机械装配、传感器选型、控制代码、调参记录打包在一起供后面几届参赛队直接复现。它适合正在准备智能车竞赛的队员、做自平衡机器人的嵌入式开发者以及想从工程角度理解姿态解算和控制闭环关系的读者。2. 独轮组硬件配置与最小系统搭建2.1 独轮车模的机械结构重心决定控制难度独轮组车模可以概括为“一个轮子撑一辆车”。车轮正上方是车身车身里装主控板、电池、驱动板顶部留出摄像头支架位。车体前后方向的倾覆力矩靠轮子加速产生因此机械上最重要的参数不是轴距而是轮轴到车体重心的垂直距离。重心越高同样的角度偏差产生的重力矩越大直立环就必须提供更高带宽的力矩修正重心太低转向响应又会变迟钝。开源总结里比较有价值的部分都会给出实际测得的重心高度并说明电池和传感器安装位置变化后如何重新找重心。很多人照抄代码时容易跳过这部分结果同一套控制参数在两台车上表现完全不同。区别往往不在代码质量而在重心高度差了一两厘米。给车体更换大容量电池或加高摄像头支架后直立环的Kp和Kd都需要重新标定这就是机械结构直接影响控制参数的最直接证据。注意重心高度每上升1cm直立环Kp通常要提高10%到15%。如果换电池后车身明显变“软”先量重心而不是盲目加Kp。2.2 元器件清单与选型原则下表是第18届独轮组参赛队里比较常见的一套硬件配置。竞赛对主控型号有具体限定但独轮组普遍选择的方案思路一致MCU要有硬件浮点运算单元IO资源要能同时驱动PWM和编码器接口IMU必须是六轴并支持高速SPI读取。模块常见选型选择要点主控MCUTC264、TC364、STM32F405硬件FPU至少3组定时器用于PWM和编码器输入姿态传感器ICM-20602、MPU6050六轴SPI优先陀螺仪量程选±2000dps轮速编码器512线AB相增量编码器每圈脉冲数不低于256线否则速度环分辨率不足电机驱动DRV8301、BTS7960或分立半桥重点看刹车模式的反向电流能力不是只看峰值电流视觉模块灰度摄像头、单线激光用于方向环外环给定可不装但会影响过弯成绩选型时最容易被低估的是编码器和电机驱动的组合。独轮组从静止到正常行驶需要很快建立速度驱动板如果刹车余量不足直立环输出反向时母线电压会被瞬间顶高导致单片机复位。比赛现场很多“跑着跑着车上电重启”的问题最后查到的是电源侧储能电容容量不够而不是代码逻辑错误。2.3 1kHz控制任务的数据流怎么搭直立环需要尽量高的控制频率才能压住高频抖动实际项目里建议跑到1kHz。速度环200Hz、方向环100Hz足够三个任务共用全局变量关键变量加volatile或用临界区保护。下面是一段典型的主循环框架int main(void) { // 初始化时钟、PWM、编码器、SPI、IMU board_init(); imu_init(icm20602, SPI1, ICM20602_4K); encoder_init(enc_left, ENC_TIM2); // AB相输入捕获 pwm_init(pwm_left, PWM_TIM1, 10000); // 20kHz PWM while (1) { // 1kHz 直立环用硬件定时器置位标志更精确 if (flag_1ms) { flag_1ms 0; imu_read(raw_gyro, raw_accel); attitude_update(angle, gyro_y, raw_gyro, raw_accel, 0.001f); float base_pwm balance_pd(angle, gyro_y) speed_out; set_duty(pwm_left, base_pwm steer_out); set_duty(pwm_right, base_pwm - steer_out); } // 200Hz 速度环 if (flag_5ms) { flag_5ms 0; speed_update(0.005f); } // 100Hz 方向环 if (flag_10ms) { flag_10ms 0; steer_update(0.01f); } } }这里的关键是1ms标志位由硬件定时器置位而不是用软件延时。直立环和速度环分开时序后车身抖动和噪声更容易定位来源。注意左右电机的PWM必须在同一个控制周期内更新如果左右两次set_duty之间差了一个周期会引入固定差速直观表现就是直道上跑着跑着往一侧偏。3. 直立环、速度环、方向环控制程序的层次3.1 直立环为什么是PD而不是PID搜索智能车比赛怎么准备时看到最多的代码就是平衡车的直立环。独轮组的直立环在形式上与普通两轮平衡车几乎一样都是对角度误差做PD控制。它不需要积分项因为积分项会持续累积重力方向的直流误差最终表现为车身低频摆动。真正的稳态偏差由速度环来收敛直立环只负责对抗重力。/* 角度单位度角速度单位度/秒PWM满量程±10000 */ #define TARGET_PITCH 0.8f /* 机械中值车体静止时的自然前倾角 */ #define BALANCE_KP 900.0f #define BALANCE_KD 30.0f float balance_pd(float pitch, float gyro_y) { float err TARGET_PITCH - pitch; float out BALANCE_KP * err - BALANCE_KD * gyro_y; /* 输出限幅防止电机满幅造成机械冲击 */ if (out 9000.0f) out 9000.0f; if (out -9000.0f) out -9000.0f; return out; }两个参数需要仔细理解。Kp是角度误差到占空比的增益Kp越大车身对小角度偏移的反应越剧烈但同时会把传感器噪声放大Kd是阻尼项权重陀螺仪y轴角速度用来抑制振荡。第一次调参时如果车身高频抖动优先减小Kd而不是Kp因为抖动多数来自阻尼过大造成的相位滞后。陀螺仪方向必须与电机方向匹配否则直立环变成正反馈这是车一上电就猛倒的最常见原因。注意电机转向、编码器相序、陀螺仪正方向三者只要错一项直立环就会变成正反馈。上电前先打印原始数据确认方向一致。3.2 姿态解算互补滤波和四元数怎么取舍智能车摄像头负责外部感知而车身姿态必须完全依赖IMU。初学者往往一上来就选卡尔曼滤波但独轮组对姿态实时性的要求高于绝对精度普遍做法是先用互补滤波把陀螺仪积分和加速度计修正结合。下面是一段最小实现/* 互补滤波dt为解算周期单位秒 */ #define GYRO_WEIGHT 0.98f float attitude_fuse(float angle, float gyro_rate, float accel_angle, float dt) { // 陀螺仪积分提供高频姿态加速度计修正积分漂移 angle gyro_rate * dt; angle angle * GYRO_WEIGHT accel_angle * (1.0f - GYRO_WEIGHT); return angle; }核心参数是GYRO_WEIGHT。取0.98时陀螺仪占主导动态响应好但低频漂移会缓慢显现取0.90时加速度计修正更强但车身振动噪声会直接串进角度估计。独轮组的起步、过坡道等场景都有强烈冲击如果发现启动瞬间车身“点头”通常是加速度计权重太大而不是Kp不够。四元数Mahony算法适合需要同时求解roll、pitch、yaw的场景但独轮组只关心pitch和roll两个轴互补滤波在计算量、代码可读性和开源传承上都更合适。3.3 速度环和方向环如何叠加到直立环直立环输出的是电机PWM但一辆能跑的独轮车还需要两个外部给定目标速度和目标方向。常见做法是速度环输出角度修正方向环输出差速修正三者的计算顺序有明确要求。控制环频率输出变量作用对象直立环1kHz基础PWM直接控制电机速度环200Hz目标角度修正量修改直立环目标角方向环100Hz差速PWM左右电机输出加减void speed_update(float dt) { int16_t speed encoder_get_speed(); float err target_speed - speed; speed_integral SPEED_KI * err * dt; if (speed_integral 80.0f) speed_integral 80.0f; if (speed_integral -80.0f) speed_integral -80.0f; target_pitch SPEED_KP * err speed_integral; }当实际速度低于目标速度时target_pitch变为正数直立环会以为车体应该前倾从而输出更大的前进力矩。方向环与此类似靠左右轮差速转向但输入通常来自摄像头识别出的赛道偏差而不是车身自身转角。速度环积分限幅要小于直立环输出上限的十分之一否则它在起跑时会推动车身前倾过快速度还没起来积分器继续增大反而让电机先饱和。程序跑起来感觉“一冲一停”时先查积分限幅通常能立刻定位问题。4. 独轮组调参顺序与异常现象判读4.1 调参为什么必须是“直立环→速度环→方向环”智能车竞赛的准备过程中最常被问的问题就是“参数怎么调”。独轮组因为没有轮距可依靠参数调错的后果比两轮车严重得多所以顺序必须严格固定。第一步只调直立环让车能原地站立且轻推不倒第二步调速度环让车能前进后退并回到静止第三步才调方向环。前一步不稳定时后一步的所有现象都是假象只会浪费调试时间。调直立环时要把速度环和方向环整体屏蔽将target_pitch固定为静态值否则速度环的积分会不断改变目标角度让直立环的收敛过程很难观察。这一步看似麻烦但能省掉大量“今天能站、明天不能站”的排查时间。在开源总结里调参顺序通常用一张表记录参数名、物理意义和当前值自己建项目时也要同步建表否则隔几天再调很难回忆出“上电前后抖”到底是改Kd还是改滤波系数。4.2 三个典型异常抖动、推倒、点头现象描述优先排查项常见修正上电后车身高频抖动声音发脆Kd是否过大陀螺仪原始噪声是否偏高降低Kd或先降Kp再复调Kd静止能站住轻推一下立刻倒地速度环没有介入Kp余量不足检查速度环任务是否屏蔽加快速度积分跑动中有节奏地“点头”速度环积分时间常数偏小降低Ki或增大积分限幅上限这三类现象在独轮组里出现的概率远高于方向问题。高频抖动还有一个隐蔽来源PWM频率设置太低。普通有刷电机建议PWM高于15kHz低于10kHz时会听到明显的“吱吱”声等效输出力矩波动也会变大。如果Kp已经很低仍然抖先查PWM频率而不是继续改参数。4.3 用上位机曲线给调参装上“眼睛”只用眼睛看车体现象很难判断问题出在角度估计还是控制参数。把角度、角速度、电机输出通过串口发到上位机是智能车调参的标准做法。下面脚本用于接收一帧18字节、三个float数据import serial import struct ser serial.Serial(COM5, 115200, timeout0.1) while True: data ser.read(18) if len(data) 18: pitch, gyro_y, motor_out struct.unpack(3f, data) print(fpitch{pitch:7.2f}deg gyro{gyro_y:8.2f}dps motor{motor_out:7.1f})单片机端按相同字节序发送即可上位机软件用VOFA这类支持JustFloat协议的方案就能直接出曲线。曲线数据的价值在于分辨“车体在颤抖”和“输出在颤抖”的区别如果pitch和gyro曲线平滑但motor抖动大问题在控制环或机械结构如果pitch本身就在快速跳变问题在姿态解算或传感器安装。这两个判断方向不同改的参数也完全不同。4.4 记录参数修改与现象对应关系开源项目的可复现性很大程度上取决于调参记录是否能回答“为什么是这个值”。建议每半天导出一份参数表记录当时的机械状态、电池电压、参数值和现象。电池电压对独轮组影响极大满电和半电状态下的直立环效果可能相差30%以上不记录电压的调参表基本没有复用价值。这一条在赛后写总结时尤其重要因为后面几届队员复现项目时参照的正是这些看似琐碎的环境变量。5. 开源总结类项目怎么放代码、图和记录5.1 仓库目录结构决定复现成本“十八届智能车竞赛独轮组——总结开源篇”这类文档最后落到开源仓库里时常见问题是代码、机械图、说明文档混在一起。工程类开源项目应该有明确结构区分固件源码、调试工具、机械文件和正式文档。. ├── README.md ├── docs/ │ ├── mechanical.md │ ├── electrical.md │ ├── control_loop.md │ └── tuning_records.md ├── hardware/ │ ├── pcb/ │ │ ├── board_sch.pdf │ │ └── board_gerber.zip │ └── mechanical/ │ ├── chassis.step │ └── assembly_note.md ├── firmware/ │ ├── core/ │ ├── modules/ │ └── project/ └── tools/ └── vofa_justfloat.py根目录的README应开门见山说明三件事硬件型号清单、需要哪些软件工具链、用什么方式下载固件。独轮组项目的电机驱动方向、编码器接口定义、IMU安装方向这三个信息不写清楚后面接手的同学大概率一周内弃坑。5.2 接口约定比代码本身重要平衡车代码框架大同小异真正不同的是“车体怎么接到板子上”。编码器A相接哪个定时器通道、IMU的SPI占用哪些引脚、左右电机PWM极性相反的系统如何统一配置这些固化为头文件宏定义比任何长篇注释都有效。/* 硬件接口映射不同代际板子的唯一修改点 */ #define IMU_SPI SPI1 #define IMU_CS_PORT GPIOA #define IMU_CS_PIN GPIO_PIN_4 #define ENC_LEFT_TIM TIM2 #define ENC_RIGHT_TIM TIM3 #define MOTOR_PWM_FREQ 20000u #define PWM_ARR_VALUE 10000u开源文档贡献经验点接口宏集中放在board_config.h避免散落在各控制文件里。这个头文件一经评审就不再改动所有代码模块都通过它访问硬件。独轮组调试后期最大的成本是重新验证极性符号接口层的稳定性直接决定整体效率。5.3 调参表是最有传承价值的开源内容代码仓库不会告诉后来者“这个Kd为什么从28改成22”。调参表可以。下面是一份可复现性足够强的记录示例日期电池电压直立Kp/Kd速度Kp/Ki现象和结论08-0212.2V850/260.62/6静止稳定轻推前倒需要增大Kp08-0312.1V950/280.62/6直行仍有低频点头Ki减小到408-0412.0V950/280.58/4起跑平滑过弯轻微侧滑同一行记录里写清电池电压和当时任务才是别人能按图索骥的关键。之后再遇到“起步就抖”的反馈可以顺着调参表定位到电压变化这条规律而不是重新从头调一遍。6. 拿到开源总结后用这三个空转检查验证自己的能力即使文档再完整下载代码后直接装车就跑大概率还是会翻车。从开源总结到自己的车能站住中间要过三个空转检查建议按顺序执行。6.1 开环给电确认电机方向和编码器的一致性先在代码里屏蔽所有闭环直接给定固定占空比比如左右电机各输出1500/10000。用手轻轻握住轮子感受力矩方向是否与代码注释一致再看编码器读数方向是否与轮子方向相同。不一致时调整接线或程序里的符号这个检查不能省因为直立环合上后只有一个矛盾点会被放大成剧烈反弹。void openloop_check(void) { /* 开环测试左轮正转右轮反转预期编码器符号相反 */ set_duty(pwm_left, 1500); set_duty(pwm_right, -1500); /* 打印编码器读数确认通道方向与PWM一致 */ printf(%d %d\r\n, encoder_read_left(), encoder_read_right()); }6.2 手持车体验证姿态解算的角度趋势把电机电源断开或电流限制调低用手托住车身前后俯仰同时通过串口打印解算后的角度值。角度应该平滑跟随实际倾斜方向不能出现跳变或缓慢漂移。如果角度响应快且准确说明互补滤波参数和传感器安装方向都正确如果手不动角度几秒内漂移好几度说明加速度计修正权重太低需要调大加速度计的系数。这一步在开源总结里往往只给结果但对第一次复现的人来说是避免后续调直立环时方向混乱的关键前提。6.3 闭环但轮子悬空确认输出不饱和最后把车身架起来让轮子悬空开启所有控制环但不给速度指令。轻轻晃动车体观察电机输出是否跟随晃动方向反向修正以及输出值是否会长时间贴在限幅值上。悬空时轮子没有负载输出饱和会立即表现为占空比顶到上下界比装车后更好观察。如果悬空状态下出现周期性饱和说明某个控制环增益过高需要回到调参表往下退参数。三个空转检查全部通过后再真正把车放地上验证上电起跑的稳定性会高很多基本不会出现刚松手就翻车的情况。本文还有配套的精品资源点击获取
返回列表