软硬件调试从混乱到有序,产品状态逐步确定
调试是一种思维方式,更是一套系统方法。从工程现场的混乱无序,到建立可复现的模型,从“尝试”到因果验证,我们在不断地将不确定因素转化为确定性。本文总结了我在近期项目中的一些调试体会,分享如下。
一、硬件是基础,软件是竞争力
早期样机阶段,硬件可能存在飞线、暂态干扰等问题。我们的目标是将软硬件一起推向“稳态”:
-
飞线要规范、打胶要及时,确保结构稳定; 大小公司由于技术缺陷、人员能力不足、资金不足、管理问题,积累不足吗,技术探索等原因,很容易导致新产品投板后存在飞线的情况。早期调试很可能是在有飞线的情况进行的。 但是飞线本身是需要稳定可靠的。其实除了一些高速走线飞线可能会引入干扰问题或者SI问题。一般来说低速走线,通过飞线是不会有阻抗和干扰的问题。例如串口、I2C本身都有很强的容忍度。 但是,一些硬件工程师经验不足,或者飞线方案不合理。会导致,焊得不好(手艺潮),或者飞线的走势不合理,导致仍然是个不定态。
-
软件不要在“破硬件”上调试,软硬件问题要解耦分析; 软件会抱怨,这个硬件有飞线,不稳定。 但是,其实不是飞线本身造成的问题,而是飞线的操作层面的问题。 硬件交付应具备可插拔、可重复、误操作保护等基础可靠性;
-
利用测试软件验证硬件可靠性,通过后再正式开展软件调试。 软件应该出一些基本功能验证硬件是可用状态。例如我们的机器人应该是,下位机软件出一套可以验证机器人底盘正常的功能性测试软件,下位机正常后,由上位机出一套验证下位机正常工作的软件。
好的软件工程师早期的时候可以出一些版本帮助硬件定位问题,把硬件的问题做实。防止因为硬件的错误导致软件工程师疑神疑鬼,浪费时间。
二、每项操作要确认结果,不能停留在“感觉对了”
操作完成后必须“确认结果”,而不是凭经验判断:
-
飞线、接线后要用万用表测通断,排查短路、开路;
-
USB线、电源线要测压降;
-
I²C干扰等问题要测阻抗、上示波器看波形;
-
数据通信类问题,示波器+逻辑分析仪确认结果。
三、复杂系统,先解耦,再调试
当系统特别复杂、无从下手时,最重要的是解耦思维:
-
时间上解耦:按启动流程、通信链路、控制逻辑分阶段排查;
-
空间上解耦:将上位机、下位机、控制板、电机拆分单独验证;
-
示例:NAV2加载失败,可以先验证底盘基本功能是否正常,再逐层加复杂度;
-
示例:轮毂不转,不要一开始就调导航逻辑,先用串口直接控制电机。
四、现场能力闭环,是调试成功的保障
如果现场工作人员,基本操作能力都不够,基本都验证手段没法快速开展 会影响调试。
很多基础问题出现在现场处理能力不足:
-
接地、EMC、电源、接线问题,其实是需要有经验的硬件工程师在现场处理;
-
没有飞线、换芯片、万用表、示波器的基本使用能力; 现场需要快速验证,快速给结论。有些怀疑的点,应该直接验证关闭。现场如果人员基础素养不够,结果是调试节奏被严重拖慢。所以,调试前必须完成现场技术能力闭环。
五、调试不是瞎试:要有因果预测和实验验证
我们要每做一个试验,我们清楚输入条件,和可能带来的结果。我们要做因果关系的预测,然后用试验来验证我们的逻辑。
有的人调试,是穷举法,调大调小,先试试,看看结果,再试试。如果基础问题没解决,自己基本预测没有,其实越充分的记录,越多的实验结果,只会扰乱心智,浪费精力。
有保守派调试法,会在这个阶段考虑过多风险。导致主线调试进展缓慢。如同打游戏一样,我们要先打主线任务。支线任务可以在主线任务完成后,再进行。这样的好处是,你首先建立一条可行而稳定的路线。
5.1 调试的核心流程:
-
明确试验目的;
-
预测可能结果;
-
实验验证逻辑;
-
得出结论,调整方案。
盲目调试、穷举法、随手记录反而扰乱心智、浪费资源。
5.2 不要“屎上雕花”
我们如果已经明确了某个错误,那么就是坚决的解决错误,确保我们的设备状态是正确的,而不是:我们改正错误之后,发现没有解决问题,再改回去试试。
例如一个同事把i2c两个脚弄反了,他把飞线改对了,但是仍然没通。他就又改回去试试。这是明显的“瞎试”。因为改回去是一定不通,有什么好试的。看似简单的问题,在黔驴技穷之时,迫于压力,很多工程师思路没有平时清晰,会变得思路混乱。
改对后,仍然没有出来,我们应该整理必要条件:驱动管脚配置是否对;万用表看看有没有短路、断路;示波器看看有没有波形;I2C地址是否正确;I2C设备是否能否扫描到;最后还不行,那就上逻辑分析仪。
例如,我们明显看到一个错误的报警,也可以把机器人启动,但是运行时会有偶发故障。那么我们要先尝试清除这个错误后,再做偶发故障的分析。不要“屎上雕花”。
-
错误必须先解决,而不是放着不管、边调边忍;
-
改错后如果仍不成功,应该继续验证其他必要条件;
-
示例:I²C引脚接反,飞线改正后仍不通,不能再改回去“试试看”;
-
要查:驱动配置、I²C地址、波形是否正常、总线扫描是否识别、逻辑分析仪排查是否有 ACK。
六、面对偶发故障:先找“必现条件”
其实在调试过程中,我们其实并不惧怕“必现问题”、“共性问题”;我们往往惧怕"难复现问题(偶发故障)",“个性问题”。
我们在处理问题时,首先要区分问题是“共性问题”还是“个性问题”;要区分是“必现问题”,“高频问题”,“低频偶发问题”。问题特点不同,策略不同。
对于偶发问题,很重要一点是找到“必现条件”。一旦找到“必现条件”,其实问题已经解决90%了。
如何找到“必现条件”是解决问题的关键。
找必现条件的思路:
a. 探索可稳定运行路径,找到最简可行模型;
当系统出现偶发故障时,我们可以尝试简化模型(关闭暂时不必要的电机)、减少功能(机器人复杂任务变成简单路径,看是否可以完成任务)、裁剪模组(只运行机器人的雷达,关闭IMU、关闭深度相机、关闭测距传感器等等)。
b. 梳理规避措施与前提条件,逐一验证
即:我们上述措施哪条落实之后,机器人是一个稳态。这个稳态可能距离最终目标很遥远,但是没管理。我们先确保其在我们期望的范围。
c. 所有操作都标准化,避免人为干扰;
整理出最简稳定模型的必要条件,每次运行时要确保一定规范操作。手动操作的过程,要完整规范。避免复杂手动操作。
如果有条件和能力尽早进行自动脚本,让计算机代替人的操作。如不能,曾形成操作规范,不要因为人未按照操作规范导致不好结果,而做重复问题定位。最好是每个操作,有个结果确认的过程。
比如我们前两天在定位传感器时钟同步问题,得出一个结论是:在没有RTC时钟的时候,启动时需要获取NPT时钟。但是程序员内心可能觉得这个措施可能不是关键因素,所以他不是每次操作都会执行这步。并且他觉得经常软件重启的时候,没有做这步操作,也没有问题,就没有严格执行这个操作。
但是,其实这个故障激发条件是‘下电’。结果在升级下位机的操作时,他没有严格按照解决问题总结出来的结果去操作。导致又在定位“时钟不同步”的问题。
正确的做法应该规范执行已经拟定的措施,更好的做法是尽早合入软件脚本,而不依赖人的记忆和习惯去保障操作规范。
d. 故障注入,做实“必现条件”
我们在找到可稳定运行最小版本后,再做故意的故障注入,看故障是否稳定复现。确认每个我们怀疑的点是否是真的问题点。
成功运行后,尝试故障注入法,确认可控复现路径;确认故障结果确实是由于某个原因造成的。做实“必现条件”。
e.一次只改一个输入变量
调整输入条件要一步一步进行,避免一次性修改多个变量; 比如,我们去做EMC试验,我们想尽快得到一个好的结果,结果落了一堆措施,又是接地,又是加屏蔽,又是加磁珠,又是加电容。结果:结果更差了。你是不是茫然无措?
你只能回退措施,因为你不知道哪个“整改措施”干了坏事。你应该落一件措施,确认一下结果。如果好了就落实,如果没好就回退。做好记录稳扎稳打。
调试的时候,由于急于求成,思维活跃,往往会在一个措施落实结果还没有出来的时候,就开始思考其他问题,导致思路混乱,东一榔头西一棒。
f. 归档最简稳态模型,以便调试中途回退用; 年轻的工程师有个最严重的问题,就是版本记录的问题。往往干了一堆事情,没有做好版本记录。特别是调试复杂系统的时候,一旦一个最简模型形成稳态之后,需要做归档措施。因为你开始叠加功能时,会新增问题,有可能需要回退。此时需要调试人员保证可以回退到最简稳态。
有结论了,记得抓紧归档。
g. 不要疑神疑鬼,试验能验证的假设就尽快验证。
比如你怀疑是环境光影响,你可以快速做试验,拉窗帘,或者换地方,确认环境光是否有影响。有影响就是有影响,立即解决该问题。没影响就是没影响,试验几次,证明没影响。之后就不要疑神疑鬼。
有一种盲目的勤奋,就是我们还没找到主线最简模型的时候,总是在做故障注入 或者考虑复杂场景。这种行为是徒劳。
调试时,忌讳的是在没有掌握主线流程之前,就开始测试边缘条件。这是典型的“盲目勤奋”。
七、调试必须基于事实与数据
调试时不能说“感觉慢”、“不太稳”、“还行”这种模糊语言。需要:
-
明确每次测试的目标、输入、输出;
-
使用量化手段进行验证,明确是“1ms延迟”还是“偶发丢帧”;
-
调试阶段不是为了“测试覆盖率”,而是为了“验证理论链条”。 八、沟通:技术闭环的加速器
当你在局部遇到无法自闭环的问题时,一定要及时沟通:
-
没有硬件人员时,视频远程请教;
-
跟原厂沟通,让FAE先看看问题,不要闷头硬啃;
-
问题点要细拆,不要一句“调不通”;
-
尽量避免“词不达意”: a. 对方是否听得懂? b. 你的表达是否含糊? c. 是否通顺、准确、量化、无歧义?
九、调试思维:聚焦 vs 发散
人的思维需要在发散和聚焦的状态灵活切换。发散时充分发散,聚焦时充分聚焦。不要刚发散,就急着收敛、刚开始收敛又开始发散。
如果不擅长切换,则安排只做某一个状态岗位。比如有些人只适合做测试(保守思维、防御性思维、风控思维),有的人只适合做新品研发(冒进思维、进攻型思维、机会思维)
调试是理性与直觉的结合,需要不断在发散与聚焦之间切换:
-
聚焦:确保最小功能模型稳定运行;
-
发散:系统性考虑可能的异常路径;
添加图片注释,不超过 140 字(可选)
-
不能快速发散收敛思维切换的人,不适合独立调试复杂系统;
-
可以根据个性分工:
-
保守型做测试验证;
-
冒进型做新品开发。
总结:
以上内容,是我今天夜里做梦总结,凌晨三点多醒来,抓紧用手机快速记录梦里总结了2700多字,今天白天整理了一下,送给正在调试的痛并快乐着的工程师们。
调试是一项综合性的工程能力,需要逻辑、工具、方法和沟通协同。在混乱中建立秩序,在复杂中构建清晰,是调试的本质。
参考文献链接
人工智能芯片与自动驾驶

浙公网安备 33010602011771号