第一次参加电子设计竞赛时,面对MSP432P401R主控板和一堆零配件确实有点懵。经过多次调试,我总结出这套硬件组合方案:核心采用TI的MSP432P401R LaunchPad开发板,这款Cortex-M4F内核的控制器性价比超高,主频48MHz完全能满足实时控制需求。电机驱动选用经典的TB6612模块,比L298N发热量小很多,配合7.3V航模电池能稳定驱动两个霍尔编码电机。
视觉部分我放弃了传统的红外对管方案,改用OpenMV H7 Plus摄像头模块。实测发现对于电赛常见的黑白虚线,红外传感器在强光环境下误判率高达30%,而OpenMV在相同场景下能达到95%以上的识别准确率。为了减轻主控负担,我将图像处理完全放在OpenMV端完成,通过串口只传输处理后的坐标数据。
转向机构是很多人容易忽视的关键点。我最初用SG90塑料齿轮舵机,在连续工作2小时后就会出现齿轮滑牙。后来换成MG996R金属齿轮舵机,虽然贵了3倍价格,但比赛全程零故障。这里有个小技巧:舵机安装时要使用3D打印的转向连杆机构,比直接用胶水固定稳定得多。我们用SketchUp设计了可调角度的云台支架,通过Cura切片后打印,完美适配不同赛道曲率。
在OpenMV IDE里写巡线代码时,我发现几个影响性能的关键参数。首先是ROI(感兴趣区域)设置,经过反复测试,(0,90,320,60)这个矩形区域最合理——既避开了远处干扰物,又保留了足够的预判距离。色块识别时一定要设置x_stride和y_stride参数,我们设为(10,5)可以在保证识别精度的前提下,将处理耗时从15ms降到8ms。
色块阈值设定有个实用技巧:不要在IDE里手动调,而是用OpenMV的阈值助手工具。具体操作是:按住Alt键点击阈值选择器,拖动选取赛道黑线的明暗范围,系统会自动生成thresholds元组。我们最终采用的阈值是[(25, 0, -20, 50, -20, 20)],这个LAB色彩空间参数对光照变化最不敏感。
数据处理我对比了两种方案:PID连续控制和区域离散控制。PID方法需要精心调参,但响应更平滑。核心代码如下:
python复制# PID控制示例
Kp = 0.8; Ki = 0.1; Kd = 0.05
err = blob.cx() - 160 # 中心偏移量
integral += err
derivative = err - last_err
output = Kp*err + Ki*integral + Kd*derivative
uart.write("%d" % int(output))
区域划分法则更简单可靠,特别适合新手。我们将320像素宽度划分为11个区域,每个区域对应不同的转向指令。实测发现增加(130,150)和(170,190)两个过渡区域后,小车抖动明显减少。具体实现时要注意:区域边界值要留10%重叠区,避免临界点频繁切换。
舵机控制看似简单,实则暗藏玄机。首先要注意PWM信号周期必须严格保持20ms,我们使用TimerA的UP模式,SMCLK经16分频后得到3MHz时钟源,设置CCR0=60000实现精确周期。角度控制有个常见误区:很多人直接用500-2500us的脉宽范围,实际上不同舵机存在个体差异,应该用示波器校准。
我们开发的舵机控制库包含这些关键功能:
c复制void Servo_Init(uint32_t period, uint16_t minPulse, uint16_t maxPulse) {
PWMConfig.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;
PWMConfig.timerPeriod = period;
PWMConfig.compareOutputMode = TIMER_A_OUTPUTMODE_TOGGLE_SET;
}
void Set_Angle(uint8_t angle) {
uint16_t pulse = minPulse + (maxPulse-minPulse)*angle/180;
MAP_Timer_A_setCompareValue(TIMER_A0_BASE,
TIMER_A_CAPTURECOMPARE_REGISTER_3, pulse);
}
转向策略上,我们采用渐进式调整算法。当收到"F"指令时保持90°;收到"1"-"4"左偏指令时,每次增加15°直到达到目标角度;右偏同理。这样比直接跳转到目标角度更平稳,避免了机械冲击。特别提醒:舵机供电一定要单独走线,不能和电机共用电源,否则PWM信号会被干扰。
系统整体架构采用"视觉前端+决策中台+执行后端"的三层设计。OpenMV作为视觉前端,运行在100fps模式下,每10ms通过UART发送一次坐标数据。MSP432作为决策中台,采用中断驱动架构:UART接收中断立即处理新坐标,TimerA定时中断负责电机PID计算。
关键的时间序列如下:
实测表明,从图像采集到舵机响应整个链路延迟控制在15ms内时,小车能以0.5m/s速度稳定巡线。我们使用OLED显示屏实时显示关键数据:当前坐标、舵机角度、电池电压等,调试时非常方便。
爬坡时的重心变化是常见问题。我们在车体后部加装了配重块,使重心始终保持在驱动轮轴心前5cm处。对于30°以下的坡道,只需适当提高电机基础转速即可。更陡的坡道则需要动态调整PID参数,我们开发了基于倾角传感器的自适应算法:
c复制if(angle > 15) {
PID_SetKp(&pid, original_Kp * 1.5);
PID_SetKi(&pid, original_Ki * 0.8);
}
停止线识别采用双保险策略:既检测色块宽度(>80像素判定为停止线),又通过编码器记录行驶距离。当两个条件任一触发时,立即切断电机电源并拉起手刹(我们用一个微型电磁铁实现)。实际比赛中,这种冗余设计帮助我们100%成功识别了停止线。
调试时一定要先分模块测试。我们总结的checklist如下:
功耗优化方面,我们发现几个省电技巧:将MSP432运行频率从48MHz降到24MHz可降低30%功耗;OpenMV关闭JPEG编码器后功耗从280mA降到180mA;给不用的GPIO口设置为输出低电平。最终系统在满负荷运行时整机电流控制在1.2A以内,2000mAh电池可连续工作90分钟。