1. Tool I/O 到底控制的是什么从法兰上那几根线说起第一次拆开末端法兰盖板的时候我是有点意外的——线没几根一个七八针的航空插头接出去的就是两路数字输入、两路数字输出外加一路模拟输入和一组工具端供电。这就是 Aubo 协作臂的 Tool I/O。别看它规模小凡是机器人要动手的场景几乎都绕不开它夹爪的张开闭合、吸盘的真空阀、焊枪的气阀、气爪的到位检测、末端力传感器的触发信号最后都要落到这几根线的电平上。很多人刚接触 Aubo 的时候会把 Tool I/O 和控制柜背后的 Board I/O 搞混。这两者逻辑上是一套东西——都是数字量输入输出——但物理位置、用途和接线方式完全不同。Board I/O 在控制柜上走的是柜内端子适合接外围设备安全门、光幕、外部启动按钮、输送线信号。Tool I/O 在机械臂末端法兰上是跟着手臂一起动的专门伺候装在末端的执行器。这个区别决定了你在选型时的第一原则跟着末端跑的信号走 Tool I/O固定不动的信号走 Board I/O。为什么这个区分重要因为 Tool I/O 的线要经过手臂的每一个关节走线长度、弯折次数、电磁环境都比柜内恶劣得多。你把一个不需要跟着动的输送线信号接到末端去等于给自己埋了一颗线缆疲劳断裂的雷。我见过一个现场把气缸的电磁阀装在底座、控制线却拉到了末端 Tool I/O 上运行三个月后线在第三轴处断了排查花了大半天。这不是 Tool I/O 的问题是用法的问题。从学习的角度看Tool I/O 是理解协作臂软硬件分层的一个极好的切口。它同时牵涉三件事电气层电平、负载、隔离、通信层SDK 怎么把一条指令送到控制柜、控制层什么时候发这条指令发了之后怎么确认生效。三层里任何一层没想清楚现象都是同一个——我设了输出但夹爪没动。所以这篇东西我不打算只贴几行 API而是把这三层拆开讲顺便把我踩过的坑一次性摆出来。需要先说明的是不同型号、不同固件版本的末端 I/O 配置是有差异的有的型号末端是两进两出有的还带模拟量工具端供电支持 12V/24V 切换的也见过。下面提到的路数、电流、阈值都是常见配置下的典型值具体参数一定以你手上那台机器随附的接口手册为准我这里给的是让你能建立判断框架的量级不是让你照抄的绝对值。2. 接线之前先搞清楚的电气边界PNP/NPN、Tool Power 与负载电流我在教别人的时候有个习惯先不教怎么写代码先让人拿万用表把末端插头的每一根线量一遍。这一步不做后面所有的调试都是在猜。Tool I/O 的坑有八成出在接线而不是出在程序。2.1 输出到底是给高电平还是拉低电平数字输出的核心问题是极性。工业上常见的两种形态源型输出输出高电平俗称 PNP 型和漏型输出输出拉低到地俗称 NPN 型。你接一个中间继电器或者电磁阀如果极性和输出类型不匹配表现就是程序里置 1 了但负载纹丝不动或者更隐蔽的——负载动了但逻辑是反的。判断方法很直接在示教器或者调试工具里把某一路 DO 强制置 1用万用表直流电压档红表笔接 DO 信号线黑表笔接 Tool I/O 的公共端GND。读数接近 24V说明是源型输出读数接近 0V 而负载端到电源正极之间有电压那大概率是漏型。这一步量完你后面选继电器、选电磁阀、甚至选固态继电器的型号心里就有底了。还有一个容易忽略的点工具端的供电Tool Power本身可能是可配置的。有些机器人在软件里能选 12V 或 24V 输出给末端设备用如果你的夹爪控制器标称 24V而工具端电源被配成了 12V那夹爪可能能动但没劲或者干脆不启动。这种情况最容易误判成IO 没通实际上是供电电压不对。所以在怀疑程序之前先把工具端供电的电压和电流能力核实清楚。2.2 感性负载必须加续流二极管这不是可选项我在一个现场吃过这个亏。末端接的是个小型电磁阀程序跑得好好的用了两周之后某一路 DO 突然永久失效——置 1 也没输出。拆开一看输出级的光耦击穿了。原因就是电磁阀线圈断电瞬间产生的反向电动势几十伏甚至上百伏的尖峰反复冲击输出端迟早击穿。所有感性负载——继电器线圈、电磁阀、直流电机——在 Tool I/O 的输出端都必须并联续流二极管方向是反向并联阴极接正、阳极接地让断电瞬间的感应电流有回路泄放。这个二极管成本几毛钱但能救一路输出。我现在的习惯是只要末端接了任何线圈类负载一律先加二极管和 RC 吸收再谈程序。顺便说一句负载电流也要核常见 Tool DO 单路持续电流在几百毫安量级超了要么加中间继电器扩流要么换用外部驱动板不要让末端 I/O 直接驱动大电流负载。2.3 独立供电时必须共地否则电平会飘末端夹爪如果自带电源适配器独立供电那么夹爪的信号地和机器人的 Tool I/O 地必须是同一个参考点。不共地的后果是机器人的高电平在夹爪看来可能只有十几伏甚至因为浮地而随机跳变表现出来就是输入信号时有时无、偶发误触发。这种故障最难查因为它不规律。我的做法是末端设备统一从机器人的 Tool Power 取电在功率允许的前提下省掉共地的麻烦如果必须独立供电一定把两边的 GND 用一根线连起来并且这根线要和信号线分开走别绑在一起。2.4 线缆走线是被严重低估的一环末端线缆跟着手臂运动这是它和控制柜内接线最大的不同。走线要留出各轴的行程余量用扎带或线夹固定在法兰附近避免在关节处形成锐角弯折。屏蔽层建议单端接地一般接控制柜侧不要两端都接否则容易形成地环路引入干扰。有个现场案例值得说客户反映夹爪到位信号偶发丢失只在高速运动时出现。查了三天程序没结果最后发现是末端线缆在第四轴转动时被反复拉扯内部一根信号线处于半断状态静止时通、运动时断。这种问题万用表静态测量是测不出来的得在运动状态下测或者直接换线验证。所以我的经验是只要故障和运动有相关性第一怀疑对象是线不是程序。3. 用代码把第一路输出点亮SDK、脚本与示教器三条路径电气层确认没问题之后才开始碰软件。Aubo 这边控制 Tool I/O 大致有三条路径用途不一样我按使用场景分开讲。3.1 Python SDK做上位机集成时最顺手Python 这条路适合把机械臂接进一个更大的系统比如视觉引导、产线调度、上位机监控。典型的调用链路是建立 RPC 连接 → 登录 → 拿到机器人接口 → 拿到 IO 控制接口 → 读写。核心代码大概长这样import time import pyaubo_sdk ROBOT_IP 192.168.0.100 ROBOT_PORT 30004 client pyaubo_sdk.RpcClient() client.connect(ROBOT_IP, ROBOT_PORT) client.login(aubo, 123456) robot client.getRobotInterface() io robot.getIoControl() # 置位第 0 路工具端数字输出 io.setToolDigitalOutput(0, True) time.sleep(0.05) # 立刻回读确认状态真的变了 print(DO0 , io.getToolDigitalOutput(0)) # 读第 0 路工具端数字输入比如夹爪到位信号 print(DI0 , io.getToolDigitalInput(0))几点实测心得。第一login的默认账号密码在很多出厂配置下就是示例里那组但上线前必须改这是台联网设备不是玩具。第二setToolDigitalOutput的索引从 0 开始不是 1第一次用容易搞错置了 0 号以为在控制 1 号。第三也是最重要的一点设置之后一定要回读。回读能区分两种情况——指令没发出去和指令发出去了但硬件没响应。这个区别决定了你后面往哪个方向查。C SDK 的逻辑一模一样只是接口形态不同适合对实时性要求更高或者要嵌入现有 C 框架的场景auto io robot_interface-getIoControl(); io-setToolDigitalOutput(0, true); bool state io-getToolDigitalOutput(0); bool di io-getToolDigitalInput(0);工具端供电类型如果需要在软件里切换不同版本的接口命名会有差异有的叫setToolPowerType有的放在别的命名空间下这个别照抄网上的代码直接翻你本地 SDK 头文件或者接口文档确认几分钟的事比试错快。3.2 示教器脚本让 IO 动作和轨迹咬在一起如果 IO 是为了配合一段固定的轨迹动作比如移动到位 → 夹紧 → 抬起那放在示教器脚本里比放在上位机更合适。原因是脚本和运动指令在同一个执行上下文里时序天然同步不会出现上位机发了夹紧指令但机械臂还在走的错位。脚本里控制 Tool I/O 的写法通常是这种形式-- 到位后夹紧 set_tool_do(0, 1) sleep(0.1) local closed get_tool_di(0) if closed 1 then -- 确认夹紧后再抬起 movej(pose_above, a, v, 0, 0) else -- 夹爪没到位报错停机 halt() end不同固件版本里函数名可能有细微差别敲之前在脚本编辑器的函数列表里搜一下关键词比凭记忆写靠谱。这段代码里最有价值的不是set_tool_do而是那个if——用输入信号确认执行结果而不是假设它一定成功。夹爪没夹住就抬起来工件掉在半空这种事故我见过不止一次。3.3 示教器的 IO 面板调试阶段的主力工具真正排查问题时示教器上的 IO 状态面板是最快的窗口。它能实时显示每一路 DI/DO 的电平状态也能手动强制输出。我的排查流程一般是先在这块面板上强制某一路 DO看负载动不动。动了说明电气和接线没问题问题在程序不动直接回去查线。这一步能把排查范围砍掉一半比在代码里加一堆打印高效得多。4. 输出设了却没动作一次完整的排查链路复盘我遇到过最典型的一次值得完整复盘。现象是程序里setToolDigitalOutput(0, True)执行了日志也打出来了但夹爪完全没反应。示教器面板上那一路 DO 的指示灯也是亮的。4.1 第一层指令层是否真的生效先别急着拆线。第一步是回读——getToolDigitalOutput(0)返回 True说明控制柜内部的状态寄存器确实置位了。这一步排除了指令没发出去和发到了错误的路这两种可能。如果回读是 False那问题在通信或索引上跟硬件无关。同时要确认一件事这台机器上的 IO 是不是被别的进程或者后台脚本占用了。我碰到过一次示教器里跑着一个循环脚本在不停地把那一路 DO 拉低上位机设了 True几十毫秒后又被拉回 False表现出来就是设了没用。这种冲突不看代码是发现不了的得把所有可能操作 IO 的地方都过一遍。4.2 第二层物理输出端是否有电压回读正常下一步上万用表。量 DO 信号线对公共端的电压。这里有三种结果对应三条完全不同的排查方向万用表读数说明下一步约 24V源型输出级正常负载侧问题查继电器、查线、查负载供电约 0V 但负载端有电压可能是漏型输出极性接反核对负载接线极性完全没有电压输出级损坏、工具电源未开、或处于禁止输出状态查工具供电、换一路 IO 验证我那次是第三种完全没有电压。但示教器面板显示是亮的这就产生了矛盾——面板显示的是软件状态不是物理电平。这一点很多人会混淆软件状态为 1 不等于端子有 24V。4.3 第三层换一路 IO 做交叉验证怀疑某一路输出损坏时最快的验证方法是把负载换到另一路 DO 上程序里改个索引。如果另一路正常基本可以确认原来那一路的输出级有问题。我那次就是这么确认的——换到 1 号 DO夹爪正常工作。回头查原因就是我前面说的感性负载没加续流二极管电磁阀的反向尖峰把 0 号路的输出光耦打穿了。这个教训之后我所有的末端接线方案里续流二极管是强制项写在接线图上的。4.4 第四层容易被忽略的隐性禁止还有一种情况更隐蔽IO 本身没问题但机器人处于某种状态导致输出被禁止。比如急停按下、安全门打开、或者处于某种特殊运行模式。不同型号的处理策略不一样有的会直接切断工具端输出有的保持。这个必须查手册确认不能想当然。我的建议是调试阶段一旦遇到IO 完全不响应先看一眼机器人当前的运动状态和安全状态再看 IO。这个顺序能省很多时间。4.5 第五层输入侧的假信号输出侧排查完了输入侧同样有坑。Tool DI 接的是夹爪的到位信号如果这个信号是 NPN 型拉低有效而机器人端按源型理解那读到的逻辑就是反的——夹爪明明夹紧了程序读到的是 0。这种情况在混用不同品牌末端设备时特别常见。判断方法还是万用表夹爪动作到位时量 DI 端子的电压。如果到位时是 0V、未到位时是 24V那就是低电平有效程序里的判断逻辑要反过来写。别嫌麻烦这一步不做后面所有的闭环判断都是错的。5. 让夹爪动作和运动轨迹咬合时序、回读与闭环等待IO 通了只是开始真正难的是让它和运动配合得刚刚好。我见过太多程序是这么写的发个夹紧指令sleep(0.5)然后直接抬起来。这种写法在现场跑一天可能没事跑一周就会出一次工件掉落。5.1 为什么 sleep 是靠不住的sleep的问题在于它是固定值而实际执行时间是可变的。夹爪的气路压力会波动、密封件会磨损、环境温度会影响动作速度。你按新夹爪调出来的 0.5 秒三个月后可能就不够了。更麻烦的是这种失败是概率性的不出事的时候你根本不知道它有问题。正确的做法是用输入信号做闭环等待发指令之后循环读 DI直到读到已夹紧或者超时。def wait_tool_di(io, index, expect, timeout2.0, period0.01): 等待某一路 Tool DI 达到期望电平超时返回 False t0 time.time() while time.time() - t0 timeout: if bool(io.getToolDigitalInput(index)) expect: return True time.sleep(period) return False # 使用关夹爪等待到位信号 io.setToolDigitalOutput(0, True) if not wait_tool_di(io, 0, True, timeout2.0): raise RuntimeError(夹爪未在超时时间内到位)这段代码的价值在于它把动作完成的定义从过了多少时间改成了信号到了没有。超时机制又保证了不会无限等下去——夹爪真的坏了程序要报错停机而不是挂在那里。period这个参数也别随便给。给太小比如 1msRPC 调用本身的开销会让你白白占用资源给太大比如 200ms响应就迟钝。我一般用 10ms 到 20ms实测下来响应和开销都合适。5.2 顺序上的两个经典错误第一个错误是先动后夹。程序里运动指令和 IO 指令写反了机械臂已经抬起来了夹爪才闭合。这种错误在纯文本代码里很显眼但在图形化编程或者多线程架构里就不那么明顯了。多线程场景下尤其要注意如果 IO 控制在一个线程、运动控制在另一个线程两个指令的先后顺序是没有保证的必须加同步机制。第二个错误是夹了不等。指令发出去了程序继续往下走但夹爪还没到位。这个问题在低速、轻载时看不出一旦节拍提上来就暴露。解决办法就是上面那个闭环等待。5.3 松开的时候同样需要确认很多人只对夹紧做到位检测松开就不管了。但如果下一动作是伸进一个狭窄空间取件夹爪没完全张开就伸进去会撞。所以如果夹爪有完全张开的到位信号同样要做闭环等待。没有这个信号的话那就退而求其次用一个稍保守的固定延时但要清楚这是妥协不是最佳实践。5.4 时序精度能到什么程度有人会问这套东西的响应延迟有多大。实测量级上从 SDK 调用到端子电平变化通常在毫秒到十几毫秒之间取决于控制周期和通信链路。加上夹爪本身的机械动作时间气爪一般几十到几百毫秒整体在百毫秒量级。对于绝大多数抓取场景这个精度是够的。但如果你要做的是高速飞拍、动态跟踪这类应用就不能依赖软件层的 IO 时序了得考虑硬件触发或者更底层的同步机制。这个边界要心里有数别拿通用 IO 去做硬实时的事。6. 两进两出不够用时的扩展思路与工程化封装Tool I/O 的路数天生就少两进两出在很多场景下是不够的一个夹爪就吃掉一出一进再加个真空检测、再加个吹气阀立刻见底。这时候有几条路可以走。6.1 扩展路数的三种方案对比方案适用场景优点代价用控制柜 Board I/O信号不需要跟着末端动路数多、接线方便线要拉到柜子末端设备不方便末端加 IO 扩展模块走总线末端设备多、需要跟着动扩展灵活、可级联增加成本和末端重量末端设备自带通信如夹爪走串口/总线夹爪、力传感器等智能末端省 IO、能读更多状态需要额外的通信集成工作我的选择逻辑是先看信号要不要跟着动。不动的一律走 Board I/O别浪费末端的宝贵路数。要动的再看末端设备是不是智能的——现在很多电动夹爪支持总线控制开合度、夹持力、到位状态全都能读回来比用两路 IO 表达的信息丰富得多这种情况用通信比用 IO 更划算。只有当末端是纯气动或者简单电磁阀时才老老实实用 Tool I/O。6.2 封装一层别让业务代码碰裸接口项目里如果到处散落着setToolDigitalOutput维护起来会很痛苦。我的习惯是封一个薄薄的一层把索引、极性、超时这些细节收进去class ToolIO: def __init__(self, io_control, do_map, di_map): self.io io_control self.do_map do_map # 名称 - 索引 self.di_map di_map def set(self, name, value): idx self.do_map[name] self.io.setToolDigitalOutput(idx, bool(value)) # 回读校验不一致直接抛异常 if bool(self.io.getToolDigitalOutput(idx)) ! bool(value): raise IOError(fTool DO[{name}] 设置后回读不一致) def get(self, name): return bool(self.io.getToolDigitalInput(self.di_map[name])) def wait(self, name, expect, timeout2.0): ... # 同前面的闭环等待这层封装带来三个好处。一是业务代码里出现的是gripper.close()而不是setToolDigitalOutput(0, True)可读性天差地别。二是索引变更时只改一处。三是把设置后回读校验这个动作固化了任何人调用都不会忘记验证。第三条是最有价值的——把经验固化成代码约束比写在文档里靠人记住靠谱得多。6.3 上下电和异常恢复的顺序还有一个容易被忽略的工程细节上电初始化的顺序。我的做法是机器人上电、连接建立之后先把所有 Tool DO 显式置为安全状态一般是全断再开始业务逻辑。原因是控制柜重启后 IO 的初始状态不一定是你期望的如果上一次异常掉电时某一路是导通的重启后可能还是导通的这时候如果末端接着气缸可能会突然动作。异常恢复同理。程序捕获到异常、准备停机之前应该主动把执行器置于安全状态——夹爪松开或者保持看工艺要求气阀关闭。这个动作要写在异常处理里不能指望反正停电了都会断。6.4 日志要记到什么粒度调试期和量产期的日志需求不一样。调试期我会把每一次 IO 操作和回读结果都打出来包括时间戳这样复盘时序问题时有据可查。量产期则收敛到只记录状态变化和异常否则日志量太大。但有一条我会一直保留每次闭环等待的超时事件必须记录哪怕最后成功了。因为超时次数是设备劣化的早期信号——夹爪密封件老化、气路压力下降最先表现出来的就是偶尔要等更久才到位。盯着这个指标能在故障发生前做预防性维护。这个思路是我从一次连续三天的偶发故障里总结出来的。当时工件偶尔掉落查不出原因最后翻历史日志发现有几次夹紧等待接近超时但没超时说明夹爪已经在劣化边缘。换了密封件之后问题消失。如果当初没记这些数据可能还要再查一周。6.5 一点个人体会Tool I/O 这东西API 就那几个看文档十分钟就能写出来。真正花时间的是那些文档里不会写的部分二极管要不要加、线怎么走、等待用信号还是用延时、索引改了哪里要同步改。这些东西没有捷径都是一次次现场趟出来的。我现在拿到一台新机器第一件事不是写程序是拿万用表把末端每一根线量一遍把极性、电压、有效电平记在本子上。这个习惯让我少走了很多弯路也建议你这么干。
阅读完成 · 觉得有帮助?