☰
MicroPython在RT1021智能车极速光电组的实战方案
2026/10/2 7:42:22 网站建设 项目流程

第二十届全国大学生智能汽车竞赛极速光电组,赛道依旧是白底黑线,赛车依旧是那辆靠转向和速度刷圈的小车。但这几年我注意到一个变化:越来越多的队伍开始把 MicroPython 跑在恩智浦 RT1021 上做硬件编程,这在整天和寄存器、编译链打交道的嵌入式圈子里,是个值得认真聊的话题。这篇文章就是我带队备战这个组别时,从固件烧录、底层驱动到巡线算法、双环控制一路踩坑总结出来的实战方案,适合想快速起步的参赛队,也适合想给 RT1021 换一种开发方式的工程师参考。

先说结论:用 MicroPython 跑智能车竞赛,不是要用脚本语言取代 C,而是把 Python 的迭代效率用到调车全流程里。极速光电组对算力要求不像摄像头组那么高,但又是纯竞速组别,代码改动极其频繁。传统 C 工程每次改个参数都要编译、烧录、复位,一套下来少说十几秒;MicroPython 下直接改脚本重启,配合串口 REPL 改参数,那体验真是用过就回不去。当然,这种便利是有代价的,性能、内存、实时性都得花心思去平衡。这篇文章就围绕这些平衡点展开。

1. 赛道认知与方案选型:极速光电组为什么需要 MicroPython

1.1 极速光电组的比赛逻辑

极速光电组是智能车竞赛里一个传统的竞速组别。比赛场地通常铺设白色底板,赛道中央有一条黑色引导线,车辆从起点出发,在完全自主的情况下沿黑线高速行驶,最终以完赛时间和稳定性决定名次。这个组别多年前叫“光电组”,大家用光电传感器排成一排检测黑线,后来逐渐演变成以摄像头为主要感知方式,比赛规则也在不断调整,比如引入障碍、坡道、环岛等元素。

和完全依靠视觉识别大幅图像的摄像头组相比,极速光电组的“视觉任务”相对可控:只需要区分黑和白,找到黑线的横向位置,不需要识别数字、锥桶、交通标志这类复杂目标。所以它对处理器的算力要求是“够用但不高”,但对系统的实时性、稳定性和调参效率要求非常高。比赛现场留给每支队伍的准备时间有限,遇到图像歪了、丢线频繁、转向过晚这类问题,能否快速定位和修正,直接决定最终圈速。

1.2 为什么 RT1021 配 MicroPython 是可行路线

先看硬件。恩智浦 RT1021 属于 i.MX RT 跨界处理器系列,核心是主频最高能到 500MHz 的 Cortex-M7,片上自带 288KB SRAM,封装最小的做到 LQFP100 甚至更小,非常适合智能车这种对体积和重量敏感的场景。它在恩智浦的芯片路线图里定位低于 RT1062、RT1064,但跑 MicroPython 完全绰绰有余。RT1021 的外设也很齐全,FlexIO 可以模拟摄像头并行接口时序,SAI、PWM、编码器接口、CAN、USB 都有,做一辆小车不需要外挂太多芯片。

再看软件生态。恩智浦官方维护了一个 MicroPython 分支仓库(NXPmicro/micropython),专门支持 i.MX RT 系列,RT1020、RT1050、RT1060 都在支持列表里。这个分支和 OpenMV 使用的 MicroPython 同源,所以如果你用过 OpenMV,上手会非常快。更重要的是,RT1021 的 MicroPython 固件里已经带了 machine 模块,可以操作 Pin、PWM、UART、I2C、SPI 等基本外设,直接拿来写控制逻辑足够了。

这套组合的吸引力在哪?我用一句话概括:底层的苦活累活交给固件和 C 扩展,上层的算法和策略交给 Python。摄像头采集一帧图像、DMA 搬运数据、图像二值化、角点扫描、提取中线,这些高频重复操作在 C 层实现;而 PID 参数调整、速度规划、特殊赛道元素处理、启动逻辑这些需要频繁改动的部分,全部放在 Python 层。这样既保证了实时性,又保住了开发效率。

1.3 MicroPython 方案的边界与代价

必须诚实地说,MicroPython 不是万能的。Python 是解释执行,一条简单的循环可能比 C 慢几十倍;垃圾回收(GC)偶发的工作会造成时间抖动,极端情况下可能让控制周期从 1ms 突然变成 10ms;如果图像分辨率开到 640x480,再把每一帧都拿到 Python 层逐像素处理,直接卡成幻灯片。这些问题我都踩过,后面会详细讲对策。

还有一个容易被忽视的点:MicroPython 不是所有 RT1021 的引脚都默认开放,不同核心板的引脚布局、时钟配置、外部 Flash 型号不一样,直接烧官方固件可能出现串口识别不到、PWM 输出无波形这类问题。所以别拿到板子就把固件烧进去,一定先确认你的板子原理图和官方 EVK 的差异,再做引脚适配。这个细节能帮你省掉后面大量排查时间。

2. 先用 15 分钟把 MicroPython 跑起来:RT1021 环境搭建与最小系统验证

2.1 硬件准备

动手之前,先把东西备齐。我的建议清单如下:

  • 一块基于 RT1021 的核心板或者主板,优先选择已经适配过 MicroPython 的型号。如果是自制板,务必确认外部 NOR Flash 型号、晶振频率、调试下载接口定义。
  • 一个 USB 转 TTL 串口模块,推荐带 DTR/RTS 的型号,便于后面用串口工具自动复位进入下载模式。
  • 一根能连电脑的 USB 线,用于给核心板供电和调试。建议用带屏蔽层的短线,工业现场和比赛场地附近电磁干扰大,劣质 USB 线容易导致掉盘、复位。
  • 可选:一个 J-Link 或者 DAP-Link 调试器。虽然 MicroPython 开发流程不依赖调试器,但烧录引导程序和排查固件问题时会非常有用。

这些硬件加起来成本不高,核心板一两百元,串口模块几十元,比买一套完整开发套件便宜得多,也贴合智能车竞赛“低成本、可快速复制”的调车需求。

2.2 烧录固件到 RT1021

把 MicroPython 固件烧进 RT1021,有两条常用路径,两条我都试过,各有适用场景。

第一条路径是使用恩智浦的 MCUXpresso IDE。在 IDE 里新建一个工程,选择 RT1021 对应型号,然后导入官方 MicroPython 仓库中编译好的固件工程。编译完成后直接点下载按钮,IDE 会通过 J-Link 或板载 DAP-Link 把固件写到外部 Flash。这条路径最稳妥,适合第一次上手,因为 IDE 会帮你处理好链接脚本和 Flash 下载算法,不会出现“固件烧了但跑不起来”这类玄学问题。缺点是 IDE 体积大、启动慢,如果你只改 Python 脚本,完全不需要每次打开它。

第二条路径是使用恩智浦的 Flashloader 工具。RT1021 支持通过串口或 USB 进入 ISP 下载模式,你可以在上电时把 BOOT 引脚拨到相应电平,然后使用 Flashloader 命令行工具把固件 bin 文件下载到外部 Flash。这条路径的优点是不需要额外的调试器,只要有一根串口线就能干活,非常适合在比赛现场快速恢复一台“变砖”的车。缺点是需要手动设置 BOOT 引脚和拨码开关,对新手稍微有点门槛。

无论走哪条路,都建议在烧录前先把原厂 EVK 的示例固件备份一份。别问我为什么,我遇到过不止一次固件刷坏导致板子黑屏,最后靠备份固件救回来的情况。

2.3 第一个 MicroPython 测试代码

固件烧好后,串口连接电脑,打开你习惯的串口工具(我用的是串口调试助手或者 minicom),波特率通常设置为 115200,复位开发板后能看到 MicroPython 的交互提示符。这时你就可以在 REPL 里敲代码了。

先做个最基础的验证,点亮板载 LED 或者控制一个空闲引脚翻转:

from machine import Pin import time led = Pin(0, Pin.OUT) while True: led.toggle() time.sleep_ms(200)

这段代码的含义很简单:把第 0 号引脚配置为输出,然后每 200ms 翻转一次电平。如果 LED 按预期闪烁,说明固件、串口、时钟三个环节都基本正常,可以继续往下走了。这里有个小经验:首次测试尽量用板载 LED,不要用杜邦线外接 LED,因为板载 LED 的引脚映射已经写在固件里,成功率最高。等你确认环境没问题,再外接自己的传感器和执行器。

2.4 引脚和外设资源规划

正式写智能车代码前,先做一张引脚分配表。我一般先把 RT1021 的关键外设和对应引脚列清楚:

外设功能建议使用的外设说明
图像采集FlexIO / GPIO 模拟DVP 并口摄像头,优先用 FlexIO 接 PCLK、VSYNC、HSYNC
舵机控制PWM 定时器50Hz 左右信号,脉宽 1ms 到 2ms
电机驱动PWM 输出 + GPIO一般用两路 PWM 或一路 PWM 加方向脚
编码器测速编码器定时器 / 外部中断需要确认定时器是否支持正交解码
串口调试UART至少留一路给上位机调参
拨码开关 / 按键GPIO 输入用于模式切换和参数选择
指示灯GPIO 输出调试状态显示,强烈建议留至少两个

这张表的价值不在于推荐具体引脚号,而在于提醒你:别把关键外设挤在同一个定时器或者同一组冲突引脚上。RT1021 的引脚复用非常灵活,但也容易踩坑,比如同一个定时器的两个通道被占用了另一个外设,结果 PWM 死活输出不了。所以动手布线之前,先打开芯片手册的引脚复用表,把分配确认好再画板、再接杜邦线,这是老调车人都会做的事。

3. 核心算法落地:图像预处理、巡线与双环控制

3.1 图像采集层的“朴实”设计

智能车主流的感知是摄像头。RT1021 本身没有直接的高清摄像头接口,我看到很多队伍用 FlexIO 去模拟 DVP 并行口时序,接 MT9V034 这类灰度摄像头,也有用 OV7725 的。图像采集这种高频操作,不建议全放到 Python 层做,因为单帧图像像素传输和行场中断处理在解释执行下根本扛不住。我的做法是:在 C 扩展层完成帧同步、行数据 DMA 搬运、简单的二值化,最后只把处理好的灰度数组或二值化数组交给 Python 层。

这样设计有个很大的好处:Python 层不需要关心摄像头时序、像素时钟这些底层细节,拿到的 frame 就是一个普通的二维数组。比如可以这样封装:

import camera # camera 是 C 扩展模块,已经封装好底层采集逻辑 w, h = camera.init(resolution=camera.R160x120) frame = camera.snapshot() # 返回 bytes 或 memoryview,长度为 w * h

底层 C 扩展每采集一帧,把灰度数据放到一块固定的缓冲区,Python 层只是拿到这个缓冲区的引用。这里有一个关键优化点:不要让 Python 层每次重新拷贝数据,而是复用同一个缓冲区,减少内存分配和 GC 压力。下面这段代码就是典型的“反例”:

# 不推荐:每次 snapshot 都新建大对象,内存会被快速吃光 for i in range(1000): frame = camera.snapshot() # 每次都重新分配内存

推荐改成复用内存的方式。比如 Camera 模块内部维护固定缓冲区,snapshot 返回 memoryview,Python 层直接读写同一块内存。这样跑一晚上循环内存占用也稳定。

3.2 二值化与中线提取的代码优化

拿到灰度图后,最简单的巡线方法是把图像二值化:像素灰度低于阈值记为黑色,高于阈值记为白色。然后从下往上扫描每一行,找到左右黑边,计算中线位置。

下面是一段比较实用的中线提取代码:

def extract_center(frame, w, h, threshold): mid = w // 2 sum_x = 0 count = 0 # 每隔 4 行采样一次,降低计算量 for y in range(0, h, 4): row_offset = y * w left = -1 right = -1 # 从左往右找第一个黑点 for x in range(0, w): if frame[row_offset + x] < threshold: left = x break # 从右往左找第一个黑点 for x in range(w - 1, -1, -1): if frame[row_offset + x] < threshold: right = x break if left >= 0 and right >= 0: center = (left + right) // 2 sum_x += center count += 1 if count == 0: return None # 丢线 return sum_x // count - mid # 返回中心偏差,正数表示线在右侧

这段代码有几个细节值得展开:

  • 隔行扫描。逐像素扫全图当然也行,但 RT1021 跑 MicroPython 时纯 Python 循环的开销不小,隔 4 行采样可以显著降低耗时,而扇形区中线信息基本保留。
  • 左、右分向扫描。从左往右找第一个黑点,从右往左找第一个黑点,取中点作为该行中心。这种算法在直线和缓弯上非常稳,比“先整体二值化再找联通域”简单得多。
  • 丢线返回 None。这是一个非常关键的设计。你在赛道上一定会遇到黑线跑出画面、车在环岛里、或者前车压线等场景,这时候如果算法强行返回一个错误中心,转向会瞬间乱跳。正确的做法是让上层做“丢线补偿”,比如沿用上几次偏差外推。

阈值选取上,固定阈值最简单,但不同光照环境下效果差异很大。我的建议是做一个自适应阈值:取图像顶部区域的灰度均值或直方图谷底作为阈值,而不是在所有环境下都用一个数。比赛场地灯光变化频繁,固定阈值在调试时表现不错,一上赛场就翻车的情况我见过太多次了。

3.3 方向环 PD 与速度环 PI 联合调试

巡线偏差计算出来后,控制部分可以拆成两个环:方向环负责转向,速度环负责车速。方向环我习惯用 PD 控制,速度环用 PI 控制。原因很简单:方向环需要快速响应偏差变化,D 项可以抑制超调;速度环要消除稳态误差,I 项是必要的。

方向环代码示例如下:

from machine import PWM, Pin import time servo = PWM(Pin(5), freq=50) # 舵机引脚,50Hz center_servo = 75000 # 对应中位脉宽,单位 ns kp = 1.2 kd = 3.5 last_err = 0 def set_servo_from_error(err): global last_err # 丢线时把误差放大,逼车大幅转向找回黑线 if err is None: if last_err > 0: err = 100 else: err = -100 else: err = max(-80, min(80, err)) # 限幅 duty = center_servo + int(kp * err + kd * (err - last_err)) duty = max(50000, min(100000, duty)) # 舵机脉宽限幅 servo.duty_ns(duty) last_err = err while True: frame = camera.snapshot() err = extract_center(frame, w, h, threshold) set_servo_from_error(err) time.sleep_ms(5) # 控制周期 5ms,约 200Hz

这里提两个容易踩的坑:

第一个坑是单位不统一。MicroPython 的 duty_ns 单位是纳秒,但新手经常拿示波器量出来的毫秒值直接填,结果舵机打死。建议在代码里写清楚单位,并且用min/max限幅,避免异常值把舵机搞到极限位置。

第二个坑是 D 项噪声放大。误差信号来自图像,图像本身有噪点,D 项会对高频跳变非常敏感。如果车在高频抖动,先别急着加 D,先确认图像是不是稳定了;图像稳定后 D 的范围一般在 kp 的 2 到 5 倍之间,具体还得看赛道曲率。

速度环相对简单,增量式 PI 是主流:

speed_p = 0.8 speed_i = 0.15 target_speed = 2500 # 编码器计数值,单位取决于测速周期 integral = 0 def speed_control(current_speed): global integral err = target_speed - current_speed integral += err integral = max(-500, min(500, integral)) output = speed_p * err + speed_i * integral return output

注意积分限幅。速度环的积分如果没有限幅,车刚起步时积分会快速累积,导致电机全力输出,出现“一松手就冲出去”的惊险画面。比赛现场常见的起步飞车,八成就是积分饱和闹的。

3.4 参数存储与标定

MicroPython 开发最大的优势是调参快,但调参快也带来一个新问题:参数散落在脚本各处,每次改完都不知道是哪一版。我的做法是把参数集中放到一个 config.py 文件里,并且用串口做一个简单的标定指令。

比如你可以在 REPL 里直接执行:

import config config.kp = 1.5 config.kd = 4.0 config.save()

这里的 save 函数把当前参数序列化后写到 Flash 文件系统,下次开机自动加载。MicroPython 的 Flash 文件系统是可以读写的,利用它做参数持久化非常方便。这样整个调车过程就变成了:改参数、看效果、再改参数,完全不用重新编译。

另外,我强烈建议在车上保留一个拨码开关,用来切换“竞速参数”和“调试参数”。比赛时用保守参数保证完赛,调试时用激进参数试极限。这个习惯救了我很多次,因为激进参数调车往往会翻车,一翻车电机就可能扫齿,结果连保守跑法的车都没了。

4. 性能优化与可靠性设计:让脚本车也能跑出稳定圈速

4.1 解释执行与 C 扩展的边界

MicroPython 上做控制,最核心的原则是:把高频、固定模式的操作全部下沉到 C,把低频、需要灵活调整的策略留在 Python。图像采集、DMA 搬运、编码器计数、PWM 输出这些都应该是 C 层固件的事情,Python 层只拿结果、做判断、发指令。

我见过有的同学在 Python 层写了一个巨大的 for 循环去翻转 GPIO,模拟 I2C 时序,结果周期长、波形乱,怎么调都不稳定。这种问题不是 MicroPython 不行,而是用错了工具。就好比你非要用一把螺丝刀去钉钉子,钉子没进去,你不能怪螺丝刀不行。在 RT1021 上做硬件编程,先分清哪些是“该用 C 的”,哪些是“可以用 Python 的”,这是最基础的认知。

4.2 内存和垃圾回收避坑

MicroPython 的内存管理有两个关键点:内存池有限和 GC 抖动。RT1021 的 288KB SRAM 本来不小,但固件、C 缓冲区、Python 堆都要瓜分它,留给 Python 对象的内存可能只有几十 KB。图像数组这种大对象千万不能随便建,否则跑几圈内存就满了。

我的三个实用建议:

  • 大缓冲区统一走 C 层分配,Python 层只拿 memoryview 引用,不要反复创建 bytes 对象。
  • 避免在控制循环里使用append、字符串拼接、字典遍历这类容易触发 GC 的操作。把这些操作放到初始化阶段做,循环里只做纯计算。
  • 善用micropython.alloc_emergency_exception_buf和micropython.mem_info()查看内存使用情况,定期检查内存峰值。如果你发现内存占用持续上涨,多半是某处产生了内存泄漏。

GC 抖动在调车时表现得很隐蔽:车子平时跑得好好的,突然某一次转向延迟了 50ms,然后恢复正常。比赛现场大家通常怀疑是舵机问题,其实很可能是 GC 在回收大对象。网上的一个技巧是把可能触发 GC 的代码放在启动时预执行一遍,让内存分配稳定下来,这样运行期的 GC 次数会大幅减少。

4.3 用中断和 DMA 接线,Python 只做控制

RT1021 的硬件资源非常丰富,如果把中断、DMA、定时器全用起来,MicroPython 下也能实现比较强的实时控制。我的推荐架构是:

  • 摄像头帧完成通知走 FlexIO 中断或 DMA 完成中断,中断里只做标记,把帧数据交给 C 缓冲。
  • 编码器计数由硬件定时器完成,不需要占 CPU,Python 层定时读取寄存器的值即可。
  • 舵机控制 PWM 由硬件 PWM 输出,Python 层只需要定时更新比较寄存器。
  • 主控循环保持 200Hz 到 500Hz 的周期,每个周期只做图像处理和控制计算,不做任何阻塞式等待。

这样设计之后,Python 层的负担很小,控制周期也容易保持稳定。我曾经把控制周期压到 2ms(500Hz),这种情况下 MicroPython 依然可以稳定运行,前提是控制循环里不要有 print、sleep 这类阻塞调用。调试时 print 没问题,比赛前记得全部关掉或者用条件编译屏蔽。

4.4 可靠性设计至少要有这几件事

智能车不是玩具,一台调好的车在赛道上可能跑到每秒好几米,一旦失控冲出赛道,轻则丢分,重则撞坏摄像头、扫掉舵机齿轮、烧掉电机驱动。可靠性设计必须有:

看门狗必须有。RT1021 的 MicroPython 固件支持machine.WDT,在主循环里定期喂狗。一旦程序跑飞或者死循环,看门狗自动复位整车,至少保证车子不会带着故障继续冲。我见过没开看门狗的车在赛道上突然失控,直接撞上护栏,电机驱动板冒烟的场面,真的后怕。

电压监控必须有。加一个分压电阻把电池电压采样到 ADC,Python 层每 100ms 读一次,低于阈值就降速或者停车。锂电池过放对电池寿命影响很大,比赛现场如果换电池不及时,很容易把电池搞到无法恢复。

电机堵转保护必须有。当编码器读数为零但 PWM 输出很大时,大概率电机被卡住,此时应立即切断输出并报警。

这些可靠性逻辑用 MicroPython 写非常简单,几十行代码就能搞定。很多队伍只关注速度和算法,忽略这些“看不见”的代码,结果一到现场就出各种幺蛾子。把这些可靠性设计当作一个硬性模块,优先级等同于巡线算法。

5. 常见问题排查与避坑清单

5.1 烧录后串口无响应

这是最基础也最常见的问题。插上 USB 转串口模块后,打开串口工具,完全看不到 MicroPython 的提示符。按我的经验,原因通常有三个:

  • 固件没烧进去,或者烧到了错误地址。用 IDE 烧录时会自动处理地址,但用手动烧录很容易把固件下载偏移搞错。解决办法是先确认 BOOT 模式,再看烧录工具输出是否提示成功。
  • 串口模块的 TX/RX 接反了。这个听起来很傻,但我确实在比赛现场见过好几组人因为杜邦线插反而折腾半天。
  • 波特率不对。MicroPython 默认波特率一般是 115200,但有些改版固件是 921600,建议两个都试一下。

如果以上都确认没问题,再试试上电瞬间按复位键,很可能固件在等待你手动进入下载模式。RT1021 的 BOOT 引脚组合决定了启动来源,仔细看核心板的丝印,一般会有标注。

5.2 图像花屏、条纹、颜色不对

图像花屏,面前一片雪花或者左右错位,大概率出在硬件时序上。很多同学一上来就怀疑代码,其实先要用示波器看三根信号:PCLK 像素时钟、VSYNC 帧同步、HSYNC 行同步。如果 PCLK 电平不对,多半是引脚复用或者时钟配置有问题;如果 HSYNC 跟 VSYNC 的极性反了,画面会整体错位。

灰度摄像头还有一个常见问题:阈值设置不合理导致二值化后黑线断裂或者大面积黑斑。建议先在 REPL 里把灰度图数据打印出来,统计一下最大值、最小值、平均值,再确定阈值。我觉得与其反复试阈值,不如直接写一个小函数,采集 10 帧图像,自适应计算阈值,这样应对不同光线环境会更从容。

5.3 车在直道上左右摆头

直道上左右摆头,常见原因有两个:一是 D 项过大,二是图像中线提取不够稳。D 项过大时,车会频繁修正方向,表现为高频小幅抖动;图像中线提取不稳时,误差序列本身就有跳动,D 项会放大这种噪声。

处理办法分两步:先把 D 项降为零,看直道是否还抖;如果还抖,就去检查图像,看每帧中线是不是在轻微左右跳。如果是阈值太敏感导致边缘频繁变化,就适当提高阈值或者做一次中值滤波;如果图像稳定了还抖,再慢慢加 D 项,每次加一点,观察实际效果。调车不需要高深理论,多一点耐心就能调好。

5.4 “VB6.0 能不能编程嵌入式硬件”这类问题给我的启发

最近网上有个讨论还挺有意思:VB6.0 可以编程嵌入式硬件吗?从严格意义上说,VB6.0 不能用来写单片机固件,因为对应的编译器、链接器、芯片支持包都不存在。但如果你把它理解成“用 VB6.0 和单片机通信、做上位机控制”,那完全可以,串口控件、网络控件都能和 RT1021 交互。这个问题的本质是:嵌入式开发是一个工具链生态的集合,不是说一门语言“能不能”搞定一切,而是这套工具链适不适合你的目标硬件。这和 MicroPython 在 RT1021 上的定位很像——它不是万能的,但在合适场景下,它是效率极高的工具。

用 MicroPython 调智能车也是一样的道理。你不需要用它写所有代码,只需要把它放到最能发挥价值的层面——快速迭代算法、灵活调整策略、降低开发门槛。至于底层的高速驱动、严格要求时序的部分,该用 C 还用 C,该用中断还用中断。这样的混合开发模式,才是 MicroPython 在嵌入式硬件上最正确的打开方式。

6. 一点个人体会和后续可以扩展的方向

如果让我重新带一次极速光电组的队伍,我依然会选 MicroPython 加 RT1021 这套组合,但我会在第一天就跟队员说清楚:MicroPython 是我们调车的“油门”,不是我们躲开底层的“避风港”。花一周时间把 C 扩展、DMA、摄像头时序摸透,后面 Python 层的所有算法才有底气;反过来,如果只会 C 不接触脚本,调车效率又会被编译周期拖垮。两者配合,才是一个真正能打胜仗的车队该有的技术栈。

在赛场上,真正让我觉得这套方案值得推广的场景是:中午刚调整完赛道元素策略,下午就要上场比赛,别的队伍还在等编译器烧程序,我们已经用串口改了 20 次参数,把环岛处理逻辑从“进环岛减速”改成“进环岛后加速出环”,整个过程不超过 10 分钟。这种开发效率,正是智能车竞赛这种“时间紧迫、环境多变”的场景最需要的。

后续如果想继续玩深一点,可以从这几个方向扩展:把 RT1021 的 MicroPython 工程升级到支持双核协作,把图像识别部分放到第二个核上跑;或者把上位机调参系统升级成 Web Dashboard,手机直接在局域网里改 PID、看实时曲线;再往后,RT1170 这类更高性能的跨界处理器也已经有了 MicroPython 支持,留给你的发挥空间真的很大。总而言之,工具只是起点,怎么把工具用到极致,才是技术能力的分水岭。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询