1. 项目概述:从赛题到一辆能跑的小车
看到“智能送药小车”这个题目,很多参加过电赛或者正在备赛的同学应该都不陌生。这不仅仅是2021年电赛F题的原型,更是一个集机械、电子、控制、算法于一体的经典综合实践项目。它远不止是让一个小车底盘在地上跑起来那么简单,其核心是模拟一个真实的院内物流场景:小车需要自主识别路径(循迹),准确抵达指定的病房(房间号识别),完成模拟的药品投放(执行机构动作),最后还要能自己返回起点。整个过程要求全自动,这对系统的稳定性和算法的鲁棒性提出了很高的要求。
我当年带队做这个题目时,最大的感触是:它完美地区分了“玩具小车”和“竞赛级智能车”。你可能用51单片机加几个红外传感器就能做一个简单的循迹小车,但智能送药小车要求你在有限的资源(通常是8位或32位单片机)内,集成路径识别、位置判断、决策控制、人机交互等多个模块,并让它们协同工作,稳定运行数分钟甚至更久。这其中的每一个环节,从传感器数据的滤波处理,到电机控制的PID调节,再到状态机的逻辑设计,都是对开发者综合能力的考验。
为什么直到今天,这个题目以及“循迹小车”依然是电赛、课程设计的热门选题?因为它是一个绝佳的“最小可行产品”实践。它涵盖了嵌入式开发从底层驱动到上层应用的大部分关键知识点:GPIO控制、定时器/PWM、ADC采样、外部中断、串口通信,以及更上层的传感器融合、控制算法和系统调度。无论你是初学者想入门,还是有一定基础的同学想深化理解,把这个项目吃透,都能让你对电子系统的设计有一个质的飞跃。接下来,我就结合当年的实战经验,把这辆小车的“五脏六腑”拆开,从设计思路到代码调试,毫无保留地分享给大家。
2. 核心需求解析与系统方案设计
拿到一个赛题或项目需求,第一步不是急着画电路图或写代码,而是要把任务书“嚼碎”,提炼出明确、可量化的技术指标,并据此规划系统架构。2021年F题的“智能送药小车”任务书通常包含几个核心任务点,我们将其转化为工程需求:
2.1 功能性需求分解
- 自主循迹与路径跟踪:小车需在铺有黑色引导线的白色赛道上稳定行驶。这是所有功能的基础,要求小车能识别直线、弯道(尤其是急弯)、十字路口、丁字路口等路径元素,并做出正确的转向决策。
- 房间识别与定位:赛道旁会设置代表病房的标识,可能是二维码、AprilTag、特定颜色的色块或数字编号。小车需要在行驶过程中识别出目标房间号,并判断是否到达指定送药点。
- 精准停车与动作执行:到达目标房间后,小车需在指定区域内精准停车(通常要求车身完全进入停车区)。随后,触发执行机构,完成“送药”动作,例如通过舵机控制的机械臂投放一个小球,或者点亮一个LED作为送达指示。
- 任务管理与状态控制:小车需要根据预设的送药清单(如“去3号房,然后去5号房”),有序地执行多个任务。这涉及到任务队列管理、行驶状态(寻线、识别、停车、转弯)之间的切换,是一个典型的状态机设计问题。
- 人机交互与调试:需要提供基础的人机界面,如按键启动/停止、LCD显示当前状态和目标房间、蜂鸣器提示等。同时,必须预留调试接口(如串口打印),这是后期排查问题的生命线。
2.2 非功能性需求(性能指标)
- 实时性:传感器数据采集、电机控制指令输出必须在毫秒级完成,否则会导致小车响应迟钝,冲出赛道。
- 稳定性:系统需能抵抗环境光变化、赛道轻微污渍、电池电压波动等干扰,连续运行多次而不出错。
- 准确性:房间识别不能误判或漏判;停车位置误差需控制在厘米级。
- 可维护性:代码结构清晰,模块化程度高,便于调试和功能增减。
2.3 主流系统方案对比与选型
基于以上需求,核心控制器(MCU)的选型是首要决策点。热搜词里提到了“51单片机”,这确实是入门首选,但在应对复杂任务时有其局限性。
| 方案 | 核心MCU | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 经典51方案 | STC89C52/STC12C5A60S2 | 资源需求极低,成本低廉,学习资料海量,易于理解底层原理。 | 主频低(通常12MHz),计算能力弱;片上资源(RAM、Flash)紧张;缺乏硬件乘除法器、高级定时器,实现复杂算法(如浮点PID)吃力。 | 功能极度精简的循迹小车,仅要求基础循迹,不涉及复杂识别与多任务。 |
| 增强型51/STC15方案 | STC15W4K系列 | 1T架构,速度比传统8051快8-12倍;资源更丰富(更大Flash、RAM),集成ADC、PWM、高精度定时器。 | 生态仍以8051为核心,开发效率低于32位机;在同时处理多路传感器数据、图像识别和复杂控制时可能捉襟见肘。 | 中等复杂度的智能小车,可以胜任循迹+简单颜色或数字识别。 |
| ARM Cortex-M方案 | STM32F1/F4系列、GD32系列 | 性能强劲,主频可达72MHz甚至更高;外设丰富(多路高级定时器、DMA、硬件浮点单元);开发环境(Keil MDK)成熟,社区支持好。 | 成本稍高,学习曲线比51陡峭,需要对ARM架构和库函数有一定了解。 | 强烈推荐用于电赛等竞赛项目。能轻松应对多传感器数据融合、浮点运算PID、图像处理(配合摄像头)等复杂任务,系统稳定性和开发效率高。 |
选型心得:对于“智能送药小车”这种综合性强、有一定性能要求的项目,我强烈建议使用Cortex-M内核的32位单片机,如STM32F103C8T6(蓝色药丸板)。它的性价比极高,资源完全够用,能让你把精力集中在算法和系统设计上,而不是绞尽脑汁地优化代码节省那几百字节的内存。如果学校课程或基础限制必须用51,那么请选择STC15系列增强型51,并做好在代码优化上投入更多时间的准备。
确定了“大脑”,我们再来规划“感官”和“四肢”。
- 循迹传感器:这是小车的“眼睛”。常见的有红外对管式(五路、八路灰度传感器)和摄像头式。
- 红外对管/灰度传感器:原理简单,价格便宜,输出数字量或模拟量。五路、八路循迹模块通过多路传感器感知黑线在车底下的相对位置,误差信号直观(如:01000表示线在右边)。优点是响应快,处理简单;缺点是前瞻距离短,对路径曲率变化大的弯道适应性较差,且受环境光影响。
- 摄像头(如OV7670):获取全局图像信息,通过图像算法提取中线,可以实现更远的“预见性”,过弯更平滑。但需要较强的图像处理能力和MCU资源,调试复杂。对于初次参赛或时间紧迫的队伍,建议从多路灰度传感器起步,先保证基础循迹的稳定。
- 房间识别传感器:这是小车的“目标识别系统”。
- 方案一:颜色传感器(如TCS3200):识别赛道旁边特定颜色的色块。简单直接,但受光照影响大,需精心校准。
- 方案二:二维码/AprilTag识别:配合摄像头使用,识别率高,信息容量大。是更高级、更可靠的方案,但同样有图像处理的负担。
- 方案三:数字识别:对于显示数字的房间号,可以使用灰度传感器阵列“扫描”数字图案,或者使用小型OLED屏显示数字,再由摄像头识别。复杂度较高。
- 折中方案:在电赛中,有时为了降低难度,房间标识可能就是一张打印了数字的纸。这时,一个布置在车头侧方的单独的红外对管或灰度传感器,当检测到与赛道地面不同的灰度值(即标识纸)时,结合编码器记录的行进距离,也可以实现简单的“到达检测”,虽然无法识别具体房号,但可以配合预设的路径地图使用。
- 电机与驱动:这是小车的“腿”。
- 电机:常用N20减速电机或TT马达,需搭配编码器(用于测速和里程计算)。
- 驱动芯片:TB6612FNG或DRV8833是比传统L298N更好的选择,它们效率更高,发热小,支持PWM调速和正反转控制。
- 电源管理:这是常被忽视但至关重要的“心脏”。电机启动瞬间电流很大,会造成电压跌落,导致单片机复位。必须为单片机和数字电路(传感器、驱动芯片逻辑电源)与电机驱动电源进行隔离或使用独立的LDO/DC-DC稳压。例如,用一块7.4V锂电池供电,一路通过大电流降压模块给电机驱动供电,另一路通过低压差线性稳压器(如AMS1117-5.0/3.3)得到稳定的5V或3.3V给单片机和传感器。
3. 硬件系统搭建与核心电路详解
硬件是算法运行的舞台,一个稳定可靠的硬件平台能省去后期无数调试的烦恼。我们按照信号流向来梳理硬件搭建要点。
3.1 控制器最小系统与电源树
无论你选用51还是STM32,一个稳定的最小系统是基石。
- STM32最小系统:包含MCU、复位电路(10k上拉电阻+0.1uF电容到地)、 boot模式选择电路(通常boot0下拉,boot1任意)、外部高速晶振(8MHz,并匹配两个22pF负载电容)以及电源滤波网络。每个电源引脚(VDD/VSS)附近都必须放置一个0.1uF的退耦电容,且尽量靠近引脚。这是抑制高频噪声、保证芯片稳定工作的关键,绝不能省略。
- 电源树设计:
- 输入:7.4V 2S锂电池。
- 电机驱动级:7.4V直接接入TB6612FNG的VM引脚。TB6612的VCC引脚(逻辑供电)需要接5V。
- 核心控制级:7.4V经过一个二极管防反接后,输入至开关降压稳压模块(如MP1584EN),输出稳定的5V。这路5V主要给TB6612的VCC、部分5V传感器供电。
- 单片机与数字传感器级:上述5V再经过AMS1117-3.3稳压芯片,得到3.3V,给STM32、OLED屏、3.3V传感器供电。
- 关键点:电机的地线和单片机系统的地线,最终应在电池负极处单点汇合,避免电机大电流噪声通过地线干扰敏感的信号地。
3.2 传感器接口电路与布局
- 五路/八路灰度传感器:这类模块通常输出模拟电压(0-3.3V或0-5V),对应不同的反射强度。需要连接到MCU的ADC采集引脚。如果模块输出已经是数字量(阈值比较后的高低电平),则接普通GPIO即可。
- 布局黄金法则:传感器的安装位置直接决定循迹性能。对于前瞻性要求,可以将中间几个传感器安装在车头前伸的“探杆”上。传感器间距需要根据赛道黑线宽度(通常是2.5cm)调整,理想状态是当小车压线行驶时,黑线能覆盖中间1-2个传感器。安装高度也需要反复调试(通常距地面1-2cm),以获取信噪比最好的信号。
- 编码器接口:电机编码器输出两路相位差90度的方波(A相、B相)。需要连接到MCU的定时器编码器接口(如STM32的TIMx_CH1, CH2),或者配置为外部中断输入。利用硬件编码器模式可以极大减轻CPU负担,精准计算轮子转速和累计脉冲数(用于里程计算)。
- 按键与显示:按键接GPIO,注意软件消抖。OLED屏(I2C或SPI接口)用于显示状态、调试信息,是必备的调试利器。
3.3 电机驱动电路与布线
- TB6612FNG电路:接线务必准确。
AIN1/AIN2、BIN1/BIN2:接MCU的GPIO,控制电机方向。PWMA/PWMB:接MCU的定时器PWM输出通道,控制电机速度。STBY:使能引脚,接高电平(如3.3V)使能芯片。VM:接电池电源(7.4V)。VCC:接逻辑电源(5V)。AO1/AO2, BO1/BO2:接电机两极。
- 布线避坑指南:
- 大电流路径最短最粗:从电池到驱动芯片VM,再到电机的导线,应尽可能短并使用粗线(如AWG18),以减少压降和发热。
- 信号线与功率线分离:PWM和方向控制线不要与电机电源线捆扎在一起,平行走线,避免电磁干扰。
- 地线环路:注意避免形成大的地线环路,所有地最终星型汇聚到电池负极。
4. 软件架构设计与核心算法实现
硬件搭好只是有了躯体,软件才是赋予其灵魂的关键。一个清晰的软件架构能让开发、调试事半功倍。
4.1 基于时间片轮询的软件框架
对于资源有限的单片机,不建议上实时操作系统(RTOS),一个轻量级的时间片轮询框架就非常高效。其核心思想是利用一个1ms的定时器中断作为系统时钟基准,在主循环中查询各个任务是否到达其执行周期。
// 伪代码示例 volatile uint32_t sys_tick = 0; // 1ms递增,在定时器中断中更新 void TIMx_IRQHandler(void) { // 1ms定时器中断 if(TIM_GetITStatus(TIMx, TIM_IT_Update) != RESET) { sys_tick++; TIM_ClearITPendingBit(TIMx, TIM_IT_Update); } } // 任务结构体 typedef struct { uint32_t interval; // 执行间隔 (ms) uint32_t last_run; // 上次运行时间 void (*task_func)(void); // 任务函数指针 } Task_t; Task_t task_list[] = { { 2, 0, Sensor_Data_Update }, // 2ms: 传感器数据采集 { 5, 0, Speed_Control }, // 5ms: 速度PID控制 {10, 0, Trace_Algorithm }, // 10ms: 循迹算法 {20, 0, State_Machine_Update }, // 20ms: 状态机更新 {100, 0, OLED_Display_Update }, // 100ms: 显示更新 // ... 更多任务 }; int main(void) { Hardware_Init(); // 初始化所有硬件 while(1) { uint32_t now = sys_tick; for(int i=0; i<TASK_COUNT; i++) { if(now - task_list[i].last_run >= task_list[i].interval) { task_list[i].task_func(); task_list[i].last_run = now; } } // 可以在这里处理一些非实时性任务 } }这个框架保证了关键任务(如传感器采集、电机控制)的定时执行,又避免了中断嵌套过深的问题,结构清晰,易于扩展。
4.2 循迹算法:从简单逻辑到PID控制
循迹算法的目标是根据传感器阵列的数据,计算出一个“偏差”error,然后通过控制左右轮速差来修正这个偏差,使小车保持在黑线上。
基础逻辑法(适用于数字传感器): 如果传感器是数字输出(1为白,0为黑),可以定义一个简单的规则表。例如,五路传感器
S1 S2 S3 S4 S5(S3为中):00100:线在正中,直行。00010或00011:线微微偏右,轻微左转。11000:线在很左边,急右转。00000:全部见白,可能脱线,根据上次偏差记忆或减速停车。11111:全部见黑,可能到十字路口或停车区,触发特殊逻辑。 这种方法简单粗暴,但转弯生硬,速度稍快就容易震荡或冲出赛道。
位置式PID控制(适用于模拟传感器): 这是提升循迹平滑度和速度的关键。我们将多路模拟传感器的AD值进行加权处理,计算出一个连续的偏差量。
- 偏差计算:假设五路传感器AD值分别为
V1到V5(值越小表示越黑)。可以定义一个位置权重,例如W = [-2, -1, 0, 1, 2]。error = (V1*W1 + V2*W2 + V3*W3 + V4*W4 + V5*W5) / (V1+V2+V3+V4+V5)。 这个error是一个连续值,正负代表偏离中心的方向,大小代表偏离程度。 - PID控制器:
output = Kp * error + Ki * integral + Kd * derivative。Kp(比例):决定了对当前偏差的反应强度。Kp太大易震荡,太小则响应慢。Ki(积分):累积历史偏差,消除静态误差(如小车始终偏向一侧)。但Ki太大会引起积分饱和,导致控制滞后。Kd(微分):预测偏差变化趋势,抑制超调,增加稳定性。对噪声敏感,需要配合滤波。
- 输出融合:
output作为转向控制量。设定一个基础速度BaseSpeed。LeftMotorSpeed = BaseSpeed + output;RightMotorSpeed = BaseSpeed - output;这样就实现了差速转向。
- 偏差计算:假设五路传感器AD值分别为
PID调参心得:“先P后I再D”。先将
Ki和Kd设为0,逐渐增大Kp,直到小车在直道上出现轻微、稳定的振荡。此时Kp约为临界值的0.6倍。然后加入较小的Kd,用于抑制振荡。最后,如果小车在长期运行后存在固定的偏向,再加入很小的Ki。调试时,一定要通过串口或OLED实时打印出error和output的波形,这是最直观的调试手段。
4.3 房间识别与状态机设计
房间识别逻辑与传感器选型强相关。假设我们使用侧向的单个灰度传感器检测数字标牌(标牌区域灰度值与赛道不同)。
// 状态机示例 typedef enum { STATE_IDLE, // 空闲 STATE_TRACING, // 循迹中 STATE_DETECTING, // 检测到标识(可能为房间) STATE_ARRIVED, // 确认到达目标房间 STATE_STOPPING, // 停车中 STATE_DELIVERING, // 执行送药动作 STATE_TURNING, // 转弯(如路口转向) STATE_RETURNING // 返回中 } CarState_t; volatile CarState_t current_state = STATE_IDLE; uint8_t target_room = 3; // 目标房间号 uint8_t detected_room_counter = 0; // 房间计数器 uint32_t entry_detect_time = 0; // 进入检测状态的时间 void State_Machine_Update(void) { switch(current_state) { case STATE_TRACING: // 正常PID循迹 if(Side_Sensor_Detected_Marker()) { // 侧边传感器触发 current_state = STATE_DETECTING; entry_detect_time = sys_tick; detected_room_counter++; // 可以根据编码器里程判断这是第几个房间,与target_room比较 if(detected_room_counter == target_room) { // 准备停车 } } if(Crossroad_Detected()) { // 五路传感器同时见黑,检测到十字路口 current_state = STATE_TURNING; // 根据路径规划,执行左转/右转/直行逻辑 } break; case STATE_DETECTING: // 持续检测一段时间,防抖 if(sys_tick - entry_detect_time > 50) { // 持续检测50ms if(Side_Sensor_Detected_Marker()) { // 确认检测到房间标识 if(detected_room_counter == target_room) { current_state = STATE_ARRIVED; } else { current_state = STATE_TRACING; // 不是目标,继续走 } } else { // 可能是误触发,回到循迹 current_state = STATE_TRACING; } } break; case STATE_ARRIVED: // 触发精准停车程序(例如使用编码器定距离前进进入停车区) Start_Precise_Stop(); current_state = STATE_STOPPING; break; case STATE_STOPPING: if(Is_Stopped_In_Zone()) { // 判断是否停稳在区域内 current_state = STATE_DELIVERING; } break; case STATE_DELIVERING: Servo_Drop_Medicine(); // 控制舵机投药 delay_ms(1000); // 送药完毕,规划下一步(去下一个房间或返回) current_state = STATE_TRACING; break; // ... 其他状态处理 } }这个状态机清晰地划分了小车的不同行为阶段,逻辑严密,避免了功能之间的相互干扰。
4.4 速度闭环控制与里程计
开环控制电机(只给PWM不管实际转速)受电池电量、负载影响大。加入速度闭环能让小车运行更稳定。
- 速度获取:通过定时器编码器模式读取电机在一定时间间隔(如10ms)内的脉冲数,根据轮子周长和编码器线数换算成实际速度。
- 速度PID:设定目标速度
TargetSpeed,测量实际速度ActualSpeed,计算速度误差SpeedError,通过另一个PID控制器计算出PWM占空比。这个PID的参数通常比循迹PID更柔和。 - 里程计:累计编码器的总脉冲数,可以估算行驶距离,用于精准停车(例如,检测到房间标识后,再前进20cm停车)和路径规划。
5. 系统调试与性能优化实录
调试是项目开发中耗时最长、也最能积累经验的环节。以下是一些实战中总结的“血泪”经验。
5.1 分模块调试法
绝对不要把所有代码写完后一次性调试。务必遵循“硬件测试 -> 底层驱动 -> 功能模块 -> 算法联调 -> 系统集成”的顺序。
- 硬件裸测:上电前,万用表检查电源和地是否短路。上电后,测量各点电压(电池电压、5V、3.3V)是否正常。手动触碰传感器,观察其输出信号(用万用表或示波器)是否变化。
- 驱动测试:单独写一个测试程序,让电机正转、反转、调速,看是否受控。单独测试每个传感器,通过串口打印其原始AD值,用手在传感器下移动,观察数值变化是否灵敏、范围是否合理。
- 功能模块测试:
- 循迹模块:将小车放在赛道上,打印五路传感器的AD值或二值化状态,观察是否能正确反映黑线位置。
- 速度闭环:让小车空载运行,设定一个目标速度,打印实际速度,看是否能稳定跟随。调整速度PID参数。
- 状态机:通过按键模拟各种触发条件(如检测到房间、到达路口),观察状态切换和对应的执行动作(如停车、转弯)是否正确。
- 联调与优化:所有模块工作正常后,进行整体联调。重点关注模块间耦合带来的问题,例如电机PWM噪声对ADC采样的干扰。
5.2 传感器数据处理与滤波
传感器原始数据通常带有噪声,直接使用会导致控制抖动。
- 软件滤波:
- 均值滤波:连续采样N次取平均。简单有效,但会引入滞后。
- 滑动平均滤波:维护一个长度为N的队列,每次更新队列并计算平均值。实时性更好。
- 限幅滤波:若本次采样值与上次有效值差值超过一个阈值,则视为干扰,保留上次值。
- 复合滤波:实践中常结合使用,例如“限幅+滑动平均”。
#define FILTER_LEN 5 uint16_t adc_buf[FILTER_LEN] = {0}; uint8_t buf_index = 0; uint16_t ADC_Filter(uint16_t new_val) { static uint16_t last_valid = 0; // 1. 限幅滤波 if(abs(new_val - last_valid) > 50) { // 阈值根据实际情况调整 new_val = last_valid; } // 2. 滑动平均 adc_buf[buf_index] = new_val; buf_index = (buf_index + 1) % FILTER_LEN; uint32_t sum = 0; for(int i=0; i<FILTER_LEN; i++) { sum += adc_buf[i]; } last_valid = sum / FILTER_LEN; return last_valid; }
5.3 抗干扰与稳定性提升
- 电源噪声:电机PWM频率建议选择在20kHz以上(人耳听不到),避免低频噪声。在电机两端并联一个104(0.1uF)陶瓷电容和一个电解电容(如100uF),可以有效吸收高频和低频干扰。
- 信号干扰:传感器信号线使用双绞线或屏蔽线。在MCU的ADC输入引脚对地加一个几十皮法的小电容,可以滤除高频毛刺。
- 软件看门狗:开启独立看门狗(IWDG),在主循环中定期喂狗。防止程序跑飞导致小车失控。
- 参数存储:将调试好的PID参数、传感器阈值等存储在单片机的Flash或EEPROM中,避免每次上电重新校准。
5.4 经典问题排查速查表
| 现象 | 可能原因 | 排查思路 |
|---|---|---|
| 上电单片机不工作 | 1. 电源电压不对或电流不足 2. 复位电路问题 3. 晶振未起振 | 1. 测量VCC、GND电压 2. 检查复位引脚电平,手动复位试试 3. 示波器看晶振引脚波形,检查负载电容 |
| 电机不转或单向转 | 1. 驱动芯片使能脚未拉高 2. PWM输出配置错误 3. 电机线虚焊或断开 | 1. 检查STBY引脚电平 2. 用示波器测量PWM引脚是否有波形,频率/占空比是否正确 3. 万用表测量电机接线 |
| 循迹小车左右摇摆(震荡) | 1. 循迹PID的Kp太大 2. 传感器安装过高或过低 3. 传感器采样周期太慢 | 1. 减小Kp,适当增加Kd 2. 调整传感器高度,优化安装位置 3. 提高ADC采样和算法执行频率 |
| 小车在弯道冲出赛道 | 1. 前瞻不足,反应太慢 2. 转弯时内外轮速差不够 3. 传感器间距不适合弯道曲率 | 1. 增加传感器前瞻距离 2. 增大转弯时的output输出限幅 3. 尝试调整传感器间距,或使用曲率预测算法 |
| 房间识别误触发或漏触发 | 1. 传感器阈值设置不当 2. 环境光干扰 3. 检测逻辑无防抖 | 1. 动态阈值或根据环境自适应校准 2. 为传感器增加遮光罩 3. 加入持续检测时间的判断(如上述状态机中的50ms) |
| 停车位置不准 | 1. 编码器精度或安装问题 2. 停车阶段速度过高,惯性大 3. 地面打滑 | 1. 检查编码器计数是否准确,轮胎周长参数是否正确 2. 停车前先减速,采用多段式停车(快-慢-停) 3. 使用摩擦力更大的轮胎,或加入基于地面传感器的最终位置校正 |
调试的过程就是不断假设、验证、修正的过程。养成用数据说话的习惯,善用串口打印、OLED显示、甚至蓝牙透传数据到电脑上位机绘图分析,能让你快速定位问题根源。
从读懂题目到小车稳稳地停在目标房间前完成动作,这个过程是对知识综合运用能力的一次淬炼。它没有唯一的正确答案,只有更优的解决方案。我强烈建议你在实现基础功能后,尝试挑战更优的算法,比如将循迹PID升级为模糊PID,或者尝试用摄像头和OpenMV进行图像识别,甚至尝试简单的路径规划算法。这些探索不仅能让你在比赛中脱颖而出,更是你工程能力成长的坚实阶梯。最后,别忘了整理一份清晰的报告,记录你的设计思路、硬件选型、算法原理和调试过程,这既是比赛的必需,也是对自己工作的最好总结。