ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

RoboMaster硬件基础讲义V0.2.1:接口、供电与CAN总线

RoboMaster硬件基础讲义V0.2.1:接口、供电与CAN总线 刚接手硬件组的那年我干得最多的事不是画板子也不是调电机而是把同一套话重复讲给每一批新队员听CAN 线为什么必须双绞、电调 ID 为什么要先拨再上电、电池那个通信口到底该怎么读。讲到第三批人的时候我才意识到问题不在新人笨而在这套东西本身没有一份从零到能跑的入口文档。于是有了这份《Robomaster 硬件基础讲义》改到 V0.2.1 时它已经从一叠零散的截图和笔记变成了一份能直接丢给大一新生、两周后他就能自己点亮底盘的东西。这篇内容我就把这份讲义的骨架、每块内容的取舍理由、以及那些写在页边空白处的踩坑记录摊开讲一遍适合刚进硬件组的新人、负责带队的电控老队员或者想把自己的队伍文档体系重新梳理一遍的人参考。1. 讲义为什么要从接口讲起而不是从模电数电讲起1.1 新队员真正卡住的地方从来不是原理带过几届人之后你会发现一个很反直觉的现象新队员看《模拟电子技术基础》看得下去画个分压电路也画得出来但把它接到实车上就懵了。他不知道 M3508 那根四芯线里哪根是 CAN_H、哪根是 CAN_L不知道电调要接 24V 还是 12V不知道电池上那个多出来的通信口是干什么的。这些内容任何一本教材都不会写因为它们不是电子学知识而是这套特定系统的约定。V0.2.1 最大的改动就是把开篇从电学基础回顾换成了接口速查。第一节只讲三件事供电接口、通信接口、机械安装接口。每件事配一张实物照片加一张标注图标注内容是这根线是什么信号、电压范围多少、接错了会怎样。比如供电这一节会明确告诉你底盘主回路是直接挂 6S 电池的也就是满电 25.2V 往下掉到 19V 左右任何标着5V 输入的模块直接往上接就是当场冒烟中间必须经过 DC-DC。这个顺序调整背后的逻辑很简单新人第一周的目标不是理解而是能复现一套已知能跑的接线。先给他一条走得通的路让他把车跑起来兴趣和信心建立起来之后再去追问为什么接受度会高得多。反过来先灌两周理论再让他接线大概率第三周人就没了。1.2 三张接口图撑起了半支队伍的排障能力讲义里我坚持放了三张全车接口总图分别是电源拓扑图、CAN 总线拓扑图和信号地拓扑图。这三张图看着土但在实战排障里的价值极高。车不动了第一步永远是顺着电源图量电压电机某个 ID 没响应顺着 CAN 图看它挂在哪一段、终端电阻装在哪个节点出现莫名其妙的重启或者传感器乱跳就去查地拓扑图看是不是某个模块的地没共上。提示接口图一定要画成物理连接图而不是原理框图。原理框图省掉了线长、接插件位置和转接板而 90% 的现场故障恰恰发生在这三样东西里。我印象最深的一次是分区赛前夜云台一直随机丢 CAN 帧。按框图查了半天没结果最后顺着物理连接图发现从主控到云台的 CAN 线中间经过了一个自制转接板那个板子上的 120Ω 终端电阻居然被贴了两颗等效 60Ω总线负载直接把信号吃掉了一半。这种事原理图上根本看不出来只有物理连接图能救你。1.3 讲义的版本号里藏着一套内容管理方法V0.2.1 这个号不是随便编的。我们内部约定主版本号变化代表结构重写次版本号变化代表新增章节末位版本号变化代表纠错和补充细节。V0.1 是十页的手写笔记扫描件V0.2 是第一次系统化整理出的六个章节V0.2.1 则修掉了 V0.2 里三处错误——比如把电调的控制值范围和实际电流的对应关系写错了以及漏掉了 DBUS 信号需要反相这个关键点。这套版本约定最大的好处是责任可追溯。讲义末尾有一张修订记录表写着谁在什么时间、因为什么事改了哪一页。新人踩了一个新坑改完讲义就在表上记一笔下一届就不会再踩。几年下来这份东西的实际价值已经远超任何一本买来的教材因为它记录的是你们这支队伍真实遇到过的所有问题。2. 主控与外设骨架为什么新人仍然该从官方开发板起步2.1 自制主控板的诱惑与代价几乎每一届都有新人问为什么不用我们自己画的板子官方开发板又贵又大。这个问题我在 V0.2.1 里专门写了一节来回答因为我见过太多队伍在自制主控上翻车。自制主控板的问题不在于画不出来而在于你同时要面对三件事硬件设计电源、时钟、接口保护、底层驱动时钟树、外设初始化、中断优先级和系统集成和电调、裁判系统、图传的联调。三件事叠在一起任何一件出问题现象都是车不动你根本没有办法二分定位。官方开发板的意义就在于它把前两件事替你做了让你在起步阶段只有一个变量系统集成。注意这不是说自制板不好。等到你队伍里有人能独立调通一套 CAN 通信、独立跑通一套 FreeRTOS 任务调度之后再上自制板成功率会高出好几倍。顺序反了就是拿比赛当学费。2.2 引脚资源分配表该怎么写才不返工讲义里有一张空白的引脚分配表模板要求每个新人自己填。表头是引脚号、外设功能、占用模块、冲突备注、确认人。看起来简单但填这张表的过程本身就是一次系统设计训练。填表时最容易忽略的是复用冲突。比如某两个串口共用了一个时钟源或者某个定时器的四个通道你想同时用来做四路 PWM但其中一路的引脚已经被 CAN 占用了。这些冲突在纸上查手册的时候能发现在代码里编译能过、烧录能过、跑起来才发现某路输出没反应那时候排障成本是十倍。我一般要求新人在填表之前做两件事第一把主控的引脚复用表打印出来用荧光笔把打算用的引脚全部标出第二把所有模块的接口需求列成清单包括数量、类型、电压。然后两边对照着填。这个流程走一遍大概两小时但能省掉后面两天的调试。模块接口类型数量电压需求常见冲突点底盘电调CAN1 路总线24V 供电与云台电调共用总线时的 ID 冲突云台电机CAN1 路总线24V 供电终端电阻位置遥控接收机UARTDBUS1 路5V波特率与校验位配置裁判系统UART1 路5V与图传共用时的收发方向图传模块以太网1 路12V/24V网口差分对走线传感器I2C/SPI视方案3.3V上拉电阻与总线电容2.3 时钟与波特率HAL 配置里最隐蔽的两个坑用图形化工具配置底层驱动确实省事但有两个地方我要求新人必须手工核对不能全信图形界面。第一个是时钟树。图形界面默认给的时钟配置有时候和你的实际需求不匹配尤其是涉及到 USB、以太网这类对时钟精度敏感的模块时。时钟配错的表现往往不是完全不能用而是偶尔丢包跑一会儿就死这种间歇性故障最难查。讲义里的做法是配完时钟后把实际算出来的各总线频率写进注释和手册里的范围对一遍。第二个就是 CAN 波特率。这套系统里电调用的总线速率是固定的 1 Mbps而 1 Mbps 对时钟分频的要求比较苛刻稍微偏一点就会导致误码率上升。新人最常犯的错是照着别的例程抄了一个波特率参数表面看能通信但一上高负载就丢帧。讲义里给了一小段自查代码思路把 CAN 的位时序参数分频、时间段 1、时间段 2、跳变宽度都算出来验证采样点落在 75% 到 87.5% 这个区间内。/* 位时序自查示例验证采样点位置是否合理 */ float tq 1.0f / (can_clk / prescaler); float total (1 bs1 bs2) * tq; float sample_point (1 bs1) * tq / total; /* 建议 sample_point 落在 0.75 ~ 0.875 之间 */3. 供电链条从电池到分电板再到每一级稳压3.1 智能电池那个多出来的通信口到底读什么第一次拿到电池新人最容易疑惑的就是除了两根粗线之外的那个多针接口。那是电池管理系统对外输出的通信口能读到电池的总电压、每一节电芯的电压、放电电流、剩余电量和温度。为什么一定要读因为主回路电压在负载突变时会明显跌落你如果只看总电压来判断电量会严重误判。讲义里把这件事的价值写得很直白知道剩余电量你才能在比赛中决定是继续进攻还是保电知道单节电压差异你才能及早发现某节电芯衰减避免它在大电流放电时先掉到保护阈值导致整车断电。读取这块数据的实现方式通常是主控通过一路串口按固定协议去要数据然后解析成结构体。讲义的示例代码只给了框架因为协议本身会随电池型号变化但结构是通用的typedef struct { float total_voltage; /* 总电压 V */ float cell_voltage[6]; /* 单节电压 V */ float current; /* 放电电流 A充电为负 */ uint8_t soc; /* 剩余电量 % */ uint8_t temperature; /* 温度 ℃ */ } battery_info_t;提示读电池数据一定要做超时和校验处理。串口线在震动环境下偶尔会接触不良没有超时保护的话解析函数会拿着半帧数据算出一堆离谱数值然后你的低电量保护逻辑就会误触发。3.2 分电板与超级电容瞬时大电流下的电压跌落底盘四轮同时急加速的瞬间电流可以轻松冲到几十安培。这时候如果电池和电调之间的线径不够、接头接触电阻偏大主回路电压会瞬间跌好几个伏。电压一跌电调可能直接报欠压保护表现就是一加速就断电松开又恢复。解决办法有两个层面。线径和接头上讲义要求主回路走线尽量短、尽量粗接头优先选接触面积大的类型并且定期检查有没有氧化发黑。另一个层面就是并联储能模块也就是常说的超级电容。它的作用是在大电流冲击的瞬间补上这部分能量把电压跌落压在一个可接受的范围内。但这里有个新人常犯的错装了储能模块就以为万事大吉结果模块本身没做好预充和限流上电瞬间浪涌电流直接把保险丝烧了。讲义里专门写了一节预充流程要求上电前先经过限流电阻给电容充电等电压接近电池电压后再切换到主回路。3.3 防护三件套防反接、瞬态抑制与保险讲义的电源章节最后固定讲三个保护器件我管它叫防护三件套。防反接是最基础的常见做法是用一颗 P 沟道场效应管做理想二极管压降小、发热低。新人容易用错的地方是选型时只看电流不看导通电阻结果正常工作时管子上压降零点几伏几十安培下发热量惊人。瞬态抑制器件用来对付感性负载断电瞬间的反向尖峰。底盘和拨弹机构里全是感性负载没有抑制的话这些尖峰会在整个电源网络上乱窜表现为随机复位、传感器误动作。选型时要关注钳位电压和响应时间别只盯着封装。保险丝的作用不是防短路而是防短路之后把电池也带走。选值我一般建议按峰值工作电流的 1.5 到 2 倍来定太小了会在急加速时误断太大了就失去意义。这一类参数没有绝对标准讲义里给的是思考方法不是固定数值因为不同车重、不同轮径的电流曲线差别很大。4. 执行机构与总线CAN 网络上的那些约定4.1 电机编号、报文与先拨码后上电的铁律这套电驱系统的通信几乎全走 CAN 总线电机和电调的身份靠各自内部的编号区分。翻车最多的地方就是两个电调编号撞了或者编号和代码里写的不一致。现象是明明只给一个电机发指令两个电机一起转或者某个电机怎么发都没反应。讲义的规矩是每次上车前逐个确认编号确认时只接一个电调。更重要的是改编号必须在断电状态下进行改完再上电。带电改码轻则无效重则电调进保护状态需要重新上电复位。CAN 报文的收发结构也要求在讲义里写清楚。控制报文是几路控制量打包成一帧反馈报文是每个电调单独回一帧数据段里依次是机械角度、转速、实际电流和温度。新人第一次看这些数据时会很困惑为什么角度是 0 到 8191因为那是编码器的原始计数值对应一圈的机械角度要做多圈累计得自己写溢出处理。/* 反馈报文解析框架角度为编码器原始值 */ typedef struct { uint16_t ecd; /* 机械角度原始值 0~8191 */ int16_t speed; /* 转速 rpm */ int16_t current; /* 实际转矩电流原始值 */ uint8_t temp; /* 温度 ℃ */ } motor_feedback_t; /* 多圈角度累计处理每圈溢出 */ static void update_total_angle(motor_feedback_t *fb, int32_t *total) { static uint16_t last_ecd 0; int16_t delta (int16_t)(fb-ecd - last_ecd); if (delta -4096) delta 8192; if (delta 4096) delta - 8192; *total delta; last_ecd fb-ecd; }注意角度溢出处理没做的话你的位置环在跨圈瞬间会看到角度从最大值跳回 0PID 会以为电机瞬移了半圈输出一个巨大的修正量表现就是云台突然抽搐一下。这个问题在慢速调试时很难发现一上高速就暴露。4.2 控制量、电流与力矩之间的关系讲义里有一张换算表讲的是下发的控制值、电调实际输出电流和电机输出力矩之间的对应关系。很多新人以为下发的是速度其实下发的是电流环的目标值也就是力矩。速度能到多少取决于负载。这个认知差异导致一个典型问题新人写位置环时直接拿控制值当速度去调参数结果参数怎么调都不对。正确的做法是把整条链路理清楚位置误差经过位置环输出速度期望速度期望经过速度环输出电流期望电流期望再经过限幅转成下发的控制值。三层环各管各的混在一起就永远调不好。层级输入输出主要作用位置环目标角度、实际角度速度期望决定响应快慢与超调速度环速度期望、实际转速电流期望抑制扰动、稳定转速电流环电流期望电调控制值电调内部闭环响应最快摩擦轮这类应用又不太一样。它不需要精确位置反而需要两个轮子转速严格一致否则弹道会偏。这时候位置环直接砍掉速度环的两路反馈拿来互相做差差的绝对值超过阈值就报警或降速。这套做法讲义里写得很细因为它属于典型的文档里不会写、实际必须这么做的经验型内容。4.3 拨弹机构为什么总卡拨弹卡弹是几乎每支队伍都遇到过的问题讲义里单独用一节来讲。原因大致分三类机械装配间隙、控制参数不合理、检测逻辑缺失。机械层面拨盘和弹道之间的间隙如果偏大或偏心弹丸会在入口处被夹住。控制层面如果拨盘电机用的是纯电流控制遇到阻力时它只会硬顶越顶越紧。正确做法是加上堵转检测监测实际转速和实际电流当转速明显低于期望而电流明显高于阈值时立刻反转一小段再尝试。讲义给出的检测逻辑是转速-电流双阈值单独用转速会被误判单独用电流会被负载波动干扰。两个条件同时满足才判定为堵转这样误报率会低很多。这套逻辑在 V0.2.1 里加了一段伪代码说明因为 V0.2 只有文字描述新人照着实现经常把阈值定死换一批弹丸就失效。5. 遥控、裁判系统与接地现场故障高发区5.1 遥控信号解析里那几个必须记住的参数遥控接收机输出的串口信号是最容易配错的一环。它的参数和普通串口不一样常规的 8 位数据、无校验、1 位停止位在这里不成立。讲义里把正确参数用加粗标出来并要求新人第一次调试时打印原始字节流验证。新人的典型错误是串口参数配对了但收到的数据全是乱的或者遥控器不动的时候数据也在跳。前者多半是参数没配对后者往往是信号极性或者解析偏移搞错了。正确的验证方法很简单遥控器摇杆全部回中打印出的一帧数据应该是稳定的一组中位值推动某一个通道只有对应位置的两个字节变化。用这个方法五分钟就能定位问题。提示调试遥控信号时建议先完全不接电机只把解析结果映射成几个点灯 LED。看到 LED 跟着摇杆动再去接执行机构。这样能把信号问题和执行问题彻底分开。5.2 裁判系统的供电与数据流裁判系统是比赛里非常特殊的一环它既提供判罚数据也是很多功能的数据源。讲义里对它的描述集中在两点供电和数据方向。供电上它有独立的电源输出接口不要图省事直接接到主回路上电压对不上。数据方向上它和主控之间的串口是双向的但要区分哪些数据是它发给你的哪些是你发给它的。新人最容易犯的错是把两路串口的收发方向搞反结果数据一条都读不到。还有一点讲义里反复强调裁判系统相关的线束在比赛前要单独固定因为它的接口大多是插拔式的震动环境下很容易松。我在一次区域赛上亲眼见过对手因为裁判系统线松了被判通信异常那是非常可惜的失分。5.3 共地、屏蔽和一次真实的排查全过程接地问题是最玄学的一类故障讲义里用一个完整的排查案例来教方法。现象整车在静止时一切正常一旦底盘大电流启动云台就开始随机抖动同时图传画面出现横条纹。第一步排除电源。用示波器看主控的 5V 和 3.3V 轨发现启动瞬间有约 0.3V 的跌落但仍在器件工作范围内暂时不认为是根因。第二步怀疑 CAN 干扰。把云台从总线上单独断开用独立线缆直连主控抖动依旧。说明不是总线竞争。第三步查信号地。用万用表量主控地和云台地被连接的那根线发现两者之间居然有几十毫伏的电位差而这根地线走的是细线还和电机的相线捆在了一起。至此基本锁定电机相线的高频开关噪声通过线束耦合进了信号地因为地线阻抗高噪声无法快速泄放。解决办法有三步把信号地和功率地分开走线只在电源入口处单点汇合给云台通信线换成带屏蔽的线屏蔽层单端接地在云台电源入口加共模电感。改完之后抖动消失图传横条也没了。这个案例在讲义里的价值不在于给出答案而在于展示怎么一步步缩小范围。所以我要求学生读完这一节后自己复述一遍排查顺序作为考核项。现象优先怀疑快速验证方法静止正常、启动异常接地或耦合干扰分开信号地与功率地后复测单个电机无响应编号或接线断电重新确认编号随机复位电源跌落或瞬态干扰示波器观测供电轨角度跳变编码器溢出未处理检查多圈累计逻辑遥控数据乱跳串口参数或极性回中位打印原始数据6. 讲义 V0.2.1 的迭代方法与新人上手节奏6.1 把踩过的坑变成讲义里的固定章节这份讲义最大的特点是没有一节是凭想象写的。每一节后面都能追溯到某一次真实的故障。我的做法是每次故障解决后填一张故障记录卡内容包括现象、排查过程、最终原因、改进措施、是否写入讲义。填完归档等到版本迭代时统一整理。这样做的好处是讲义永远在生长而且生长方向是正确的——它补的都是真实缺口不是理论盲区。V0.2 到 V0.2.1 的几十处修订里有三分之一是文字表述优化三分之二是实打实的技术纠错。比如有一处把电调控制值与电流的对应关系写错了量程导致新人按错的量程去算限幅电机上电就猛冲一下非常危险。注意技术文档里的数值错误比缺内容更危险。缺失会让人去查手册错误会让人以为自己是错的从而把正确的做法改掉。所以每次修订数值部分我都要求至少两个人交叉核对。6.2 两周上手路线怎么排讲义的最后是一张两周上手路线表这不是给老师看的是给新人自己勾的进度表。时间目标验收标准第 1–2 天认接口、读三张总图能口述全车电源和总线拓扑第 3–4 天点亮主控、跑通串口打印串口能看到自定义输出第 5–6 天单电机 CAN 通信独立控制一个电机的转速和方向第 7–8 天遥控信号解析摇杆动作能映射到 LED 或变量第 9–10 天多电机联调四个底盘电机同时受控第 11–12 天电池数据与保护逻辑低电量时能触发行为变化第 13–14 天整车联调手动遥控整车正常行走这张表的关键设计是每天都有看得见的验收标准。新人最怕的是学了一周不知道自己会了什么有验收标准就不会。而且每天的验收都建立在昨天的成果上中间断了会立刻暴露不会拖到比赛前才发现。我自己带人的时候还会在验收环节故意制造两个小故障让他排查比如把某个电调编号改掉、或者把一根 CAN 线拔松。他在没有提示的情况下能不能定位才是真正判断上手了没有的标准。这个做法后来也写进了 V0.2.1作为带训人的操作建议。6.3 讲义的传播方式别做成只读的 PDF最后说一个容易被忽略的点讲义的形式。V0.1 是 PDF结果是没人愿意改因为改一次要走一遍导出流程麻烦。V0.2.1 换成了可协作编辑的在线文档任何人发现问题当场就能改改完在修订记录里留一笔。这个改动看起来只是工具切换实际上改变了团队的文档习惯。文档从某个人的成果变成了所有人的公共资产新人改起来没有心理负担老人也不用每次亲自维护。为了让改动可控我们在文档里加了一条约定涉及数值和接口定义的修改必须留修改理由并且当天在群里说一声。这份讲义到现在还没有完成版我觉得也不应该有。每年规则在变器件在换新问题层出不穷它能保持更新本身就是它最大的价值。真正让我觉得这份东西值得做下去的是有一次新人自己排查出一个从没遇过的电源问题解决之后主动跑来跟我说我能不能把这个加到讲义里。那一刻我就知道这东西已经不只是我一个人的讲义了。
返回列表