ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

ABB机器人RAPID Socket通讯实战:客户端服务端与排错指南

ABB机器人RAPID Socket通讯实战:客户端服务端与排错指南 做ABB机器人调试的最躲不开的一件事就是跟外部系统“对话”。视觉系统告诉你工件坐标MES要拿走产量数据上位机要远程控制机器人启动产线还要实时上报状态——这种场景太多了。信号量太粗糙走总线又要配一堆硬件加扫描配置这时候socket通讯几乎是最省事的方案一根网线两端各写几行代码数据就通了。这篇文章把ABB机器人RAPID里的socket客户端和服务端写法、上位机怎么配合、以及我调了无数个项目后攒下来的排查经验一次讲清楚。不管你是刚接触机器人通讯的电气工程师还是想先在RobotStudio里把流程验证一把的集成商照着走基本都能跑起来。1.1 现场通讯方案怎么选才不折腾先说说为什么我偏爱socket。现场做设备互联常见的有三条路。第一条是硬接线IO简单直接但要传的东西稍微多一点就完蛋。几十个点位拉线拉到怀疑人生而且只能传开关量你说要把一个工件的X、Y、Z坐标传过去用IO怎么传要么拆成N位二进制慢慢抖要么加模拟量模块折腾一圈下来精度还不一定够。第二条是走现场总线Profinet、EtherNet/IP这些。这类方案非常稳适合PLC和机器人之间做实时控制但配置成本高。机器人要装对应选件、PLC要组态GSD文件、博途里面一顿操作两边工程师凑到一起对半天才能把IO映射对上。如果是异种设备之间高速交互比如机器人和工控机、机器人和MES走总线反而痛苦。第三条就是socket通讯。TCP/IP是通用协议任何语言都有socket库C#、Python、Java、C随便挑。两端约定好报文格式建立连接之后就是收发字符串或者字节流。它解决的最大问题是“跨平台、跨厂商的系统之间用一套大家都认的协议去传数据”。不挑硬件不挑操作系统一条网线就完事。从ABB机器人角度来看RAPID语言本身就内置了完整的socket指令不需要额外购买什么昂贵选件标准系统就能用。这就是它在我这里成为首选的根本原因零成本、开箱即用、灵活度高。1.2 Socket适合干什么不适合干什么用socket之前要先清楚它的边界。它适合做非实时、响应时间在几十毫秒到秒级的数据交换比如视觉系统给机器人发工件坐标机器人走位完成后回传OK机器人向上位机上报当前状态、报警、产量上位机下发配方、任务、切换程序的命令MES采集设备数据机器人周期性地把节拍、故障代码推上去但如果你的需求是真正意义上的实时同步运动控制比如多轴联动、插补、伺服同步那socket不适合那得走EtherCAT或者专用总线。TCP本身有延迟、有重传、有粘包它保证的是“最终送达”不保证“准时送达”。拿它来做实时控制方向就错了。还有一个容易忽略的点socket通讯在项目里通常只担当数据管道不在上面做复杂的业务逻辑。复杂逻辑放上位机或者后台任务里处理机器人端越简单越稳。2. 开工前的准备网络规划和软件坑2.1 网口、IP和网段怎么搭很多人第一步就挂在网络配置上。ABB机器人控制柜上面有好几个网口用途不一样。Service口一般是用来连RobotStudio做在线编程的部分型号默认IP是192.168.125.1这个网段LAN口或者WAN口才是用来做外部通讯的。不同型号、不同系统版本不太一样最靠谱的做法是拿到控制柜之后在示教器里进控制面板找到IP设置看清楚每个网口实际地址。做socket通讯我的习惯是给机器人单独规划一个固定的调试网段不跟办公网混在一起。举个例子机器人LAN口设成192.168.1.10上位机设成192.168.1.20掩码都是255.255.255.0。不要用DHCP不要用自动获取。工业现场一旦上位机重启之后IP漂了那你通讯就废了。接线方面点对点调试用一根网线直连最省事机器人和PC网卡都是千兆口直连完全没问题。如果现场设备多就加一个工业交换机把机器人、上位机、视觉相机、PLC全部拉进同一个网段。注意别跟车间大网冲突尤其是那种整个厂房一个网段的极易撞IP。真撞了你ping网关都是通的但就是连不上机器人排查半天才发现是地址被人占用了。最后补一句调试前先在PC上ping一下机器人IP通了再接下一步。ping不通的情况下搞socket纯属浪费时间。2.2 RobotStudio仿真与安装常见问题没有真实机器人的时候先用RobotStudio仿真验证socket逻辑这个习惯非常推荐。虚拟控制器和真实控制器的RAPID行为基本一致上位机程序也几乎不用改省了现场大量调试时间。如果是PC和RobotStudio在同一台电脑上机器人客户端可以直接连127.0.0.1访问本机的上位机服务端实测是通的。但要注意RobotStudio本身也有网络设置稳妥一点的做法是给虚拟控制器配上固定IP然后上位机和机器人互ping验证一下确认通了再跑程序。顺带说一个很多人问的问题RobotStudio 6.08安装刚开始就结束怎么办。我遇到过好几次共性原因基本是这几个安装包或者电脑缺.NET运行库、杀毒软件把安装进程拦了、之前装过旧版本残留注册表导致冲突、还有用户权限不够。通用解法是右键管理员身份运行安装程序安装前退出杀毒软件和防火墙用控制面板卸载干净旧版本再用清理工具把注册表残留清一遍最后重新装。装的时候全程别切窗口安装路径别带中文。这套流程下来99%都能解决。2.3 RAPID Socket指令族一览写代码之前先熟悉几条核心指令。RAPID的socket通讯指令不算多我整理了一张表对照着看思路会很清楚。功能指令客户端服务器端创建socketSocketCreate用用绑定端口SocketBind不用用监听端口SocketListen不用用等待并接受连接SocketAccept不用用连接远端SocketConnect用不用发送数据SocketSend用用接收数据SocketReceive用用关闭连接SocketClose用用客户端和服务器端的角色差异很好理解。客户端主动去connect别人的IP和端口服务器端先在本地绑定一个端口然后listen监听再调用accept等别人连进来。ABB机器人两个角色都能当具体用哪种取决于你的应用架构。比如视觉引导通常是上位机或者视觉软件做服务器机器人做客户端主动上报坐标请求反过来如果上位机要随时查询机器人状态那更自然的是机器人做服务器上位机往这个端口发查询命令。两种我都做过代码结构上差别不大核心就是上面这8个指令来回组合。3. 机器人做客户端主动上报给上位机3.1 上位机先开一个TCP服务器我举一个最典型的场景机器人每次完成抓取把当前坐标发给上位机上位机收到后回一个“OK”。先写上位机。这里给两个版本一个是C#一个是Python看你自己的环境选。C#用TcpListener代码非常清晰using System; using System.Net; using System.Net.Sockets; using System.Text; class Program { static void Main() { TcpListener server new TcpListener(IPAddress.Any, 5000); server.Start(); Console.WriteLine(服务器监听中端口5000 ...); while (true) { TcpClient client server.AcceptTcpClient(); Console.WriteLine(机器人已连接); NetworkStream stream client.GetStream(); byte[] buffer new byte[1024]; string msg ; while ((bytesRead stream.Read(buffer, 0, buffer.Length)) 0) { msg Encoding.ASCII.GetString(buffer, 0, bytesRead); if (msg.EndsWith(\n)) break; // 遇到换行符认为一条完整指令 } Console.WriteLine(收到: msg); byte[] reply Encoding.ASCII.GetBytes(OK\n); stream.Write(reply, 0, reply.Length); client.Close(); } } }Python版更短import socket server socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((0.0.0.0, 5000)) server.listen(1) print(等待ABB机器人连接...) conn, addr server.accept() print(连接来自:, addr) while True: data conn.recv(1024) if not data: break if data.endswith(b\n): print(收到:, data) conn.sendall(bOK\n) conn.close() server.close()两个版本的共同点是收到一条以换行符结尾的数据后才认为是一条完整报文。这个习惯非常关键具体原因看3.3节ABB侧对换行符有硬性依赖。3.2 RAPID端连接、发送、接收机器人这一侧RAPID代码结构大概是这样的VAR socketdev client_socket; VAR string received_data; PROC Sock_Client() ! 1. 创建套接字 SocketCreate client_socket; ! 2. 连接上位机 SocketConnect client_socket, 192.168.1.20, 5000; ! 3. 发送请求注意字符串结尾加了换行符\n SocketSend client_socket \Str:REQ_POSE\n; ! 4. 接收上位机回包加2秒超时 SocketReceive client_socket \Str:received_data \Time:2000; TPWrite 收到回复: received_data; ! 5. 关闭连接 SocketClose client_socket; ERROR IF ERRNO ERR_SOCK_TIMEOUT THEN TPWrite 通讯超时; ELSEIF ERRNO ERR_SOCK_CONN_CLOSED THEN TPWrite 连接被对端关闭; ELSE TPWrite Socket错误错误号: ValToStr(ERRNO); ENDIF SocketClose client_socket; END这段代码的逻辑很直白创建socket连接发送接收关闭。关键词都在不需要额外解释。需要注意几点。第一SocketConnect是阻塞的。如果IP不通或者端口不对它不会像上位机那样立刻抛异常而是会卡在那里一段时间。所以调试时一定先确认网络通否则你会看到机器人程序一直卡在连接语句那一行。第二SocketSend \Str:发送的是普通的ASCII字符串。上位机收到的就是这一串字节。RAPID里字符串拼接用加号REQ_POSE \n这样也行但我习惯直接写在一个字符串里。第三SocketReceive的\Time是超时时间单位是毫秒。我强烈建议给所有接收指令都加上超时否则一旦对端不回复机器人就会一直傻等现场生产就卡住了。3.3 换行符、超时、STRING长度三个绕不开的坑这一节是重点全是实战踩出来的。第一个坑SocketReceive \Str:这个形式收到换行符才算接收完成。ABB官方文档里的讲法是当收到\n字符或者超时到达时接收指令才会返回。也就是说如果你上位机发送的数据末尾没有加换行符机器人那边就会一直等等到你设置的超时时间到然后报超时错误。我见过太多新人在这一步卡一整天。上位机明明把数据发出去了机器人就是收不到最后发现是没加\n。所以无论哪端发给机器人只要是字符串报文末尾一定要带上换行符。第二个坑RAPID的STRING类型有长度限制。常规情况下STRING最大长度80字符超了直接报错。所以做通讯协议时不要设计那种动辄几百个字节的文本报文。要么把长数据拆成多条短消息要么干脆用rawbytes字节流来收发二进制数据。对于现场大多数应用先按短报文设计一条指令控制在80字符以内能省掉大量麻烦。第三个坑TCP是流式协议天然存在粘包和半包。上位机一次send机器人不一定一次receive就能拿到全部数据上位机两次send的数据也可能被合并成一次到达。所以通讯协议里必须要有边界标识。我用得最多的就是换行符做边界简单可靠。如果传二进制一般用固定长度或者“长度头数据体”的结构后面第4.3节会展开讲。4. 机器人做服务器让上位机来读取4.1 Bind、Listen、Accept三步走机器人做服务器最大的好处是上位机可以随时主动来查询不需要机器人一直主动上报。比如产线有个上位机每个工位都可能来查机器人当前状态这时候机器人作为服务端更自然。RAPID端的服务器初始化代码VAR socketdev server_socket; VAR socketdev client_socket; VAR string recv_cmd; PROC Sock_Server_Init() ! 创建服务器socket SocketCreate server_socket; ! 绑定到所有网卡端口5000 SocketBind server_socket, 0.0.0.0, 5000; ! 开始监听 SocketListen server_socket; TPWrite 服务器启动等待上位机连接...; END这里有个细节SocketBind的地址我通常写0.0.0.0表示监听机器人所有的网卡。如果机器人有多个网口这样最省事不会出现上位机连了A网口、数据却从B网口进来的问题。紧接着是等待上位机连接。SocketAccept也是一个阻塞指令会一直等待直到有客户端连进来或者超时时间到。PROC Sock_Server_Loop() WHILE TRUE DO SocketAccept server_socket, client_socket \Time:60000; SocketReceive client_socket \Str:recv_cmd \Time:3000; TPWrite 收到命令: recv_cmd; IF recv_cmd GET_POSE\n THEN SocketSend client_socket \Str:100,200,300\n; ELSE SocketSend client_socket \Str:UNKNOWN_CMD\n; ENDIF SocketClose client_socket; ENDWHILE ERROR IF ERRNO ERR_SOCK_TIMEOUT THEN SocketClose client_socket; RETRY; ENDIF END这段逻辑是服务器端最常见的形态一直接收连接处理完一条命令就关闭连接然后回到循环继续等下一个。每条命令都是一个独立的TCP连接虽然效率不是最高的但胜在逻辑简单、不容易出状态问题。4.2 一个连接处理完再接下一个有一个新手很容易踩的坑RAPID的socketdev变量一次只能维护一个连接。你创建了client_socket接收了上位机连接在没有关闭之前SocketAccept不能再次调用或者说即使调用了也没法同时处理两个客户端。所以服务器端的编程模型必须是一个连接处理完、关闭、再accept下一个。如果上位机那边频繁重连也要确保旧的client_socket被关闭否则连接资源会泄漏最终导致机器人无法再接受新连接。处理上位机异常断开的情况也要小心。对端直接拔网线或者程序崩溃机器人这边的SocketReceive会报连接被关闭的错误。所以每次收发都要有ERROR分支兜底。我上面示例里只要出现超时或者错误就把client_socket关掉然后RETRY回到accept等待状态。这样即使上位机抽风机器人的服务端也不会死。还有一个实际经验给SocketAccept也加超时。如果长时间没有客户端连接accept会一直阻塞后台任务就卡在那里。加上超时之后哪怕没有连接循环也能定期醒来做点状态刷新之类的事情程序整体更健康。4.3 设计一个稳一点的报文协议通讯写多了你会发现代码本身不是难点协议设计才是。一个烂协议会在调试现场反复折磨你。我总结的报文协议三件套边界、校验、超时。边界就是告诉对端“一条完整消息到哪里结束”。文本协议用换行符最简单但只适合短小的指令。二进制协议我推荐固定长度比如每条消息固定16字节不够补零简单粗暴好解析。再进阶一点用4字节长度头加数据体上位机先读长度再读数据体这样能兼容任意长度。校验是防止数据在传输过程中被干扰。工业现场电磁环境复杂偶尔会出现一个字节被改掉的情况。简单的做法是加一个累加和校验Checksum复杂一点上CRC16。对大多数非安全级应用来说累加和已经够用。超时前面反复强调了接收时一定要设超时。协议层面最好还能约定如果对端在N秒内没有回应发起方就认为这次通讯失败进入错误处理。举个例子我常用的文本指令协议大概是这样的GET_POSE\n SET_SPEED,100\n MOVE,100,200,300,10\n每条命令都是“命令字参数逗号分隔换行符”。机器人收到后按逗号拆字段命令字做逻辑分支参数转成数值非常容易解析。注意RAPID里字符串拆分需要自己写循环没有现成的Split函数所以字符串指令的字段别搞太多简化解析逻辑。5. 实战中高频问题的排查清单5.1 连不上先按这个顺序查通讯出了问题千万不要瞎改代码。按顺序排查绝大多数问题几分钟就能定位。第一先ping。PC上ping机器人IP机器人侧的服务器地址也ping一下上位机。ping不通说明物理链路、IP配置有问题后面全白搭。检查网线是否插对口、IP是否同网段、交换机哪个灯亮了。第二确认端口通不通。用Windows自带的telnet或者用Test-NetConnection -Port 5000来测试。如果端口不通可能服务端没启动、端口被防火墙拦住、或者机器人程序根本没跑到listen那一行。第三确认Windows防火墙是否放行了端口。这个问题在开发机上尤其常见服务端程序明明启动了但本机防火墙默认禁止外部连接导致机器人连不过来。解决方法是进防火墙高级设置添加入站规则放行TCP 5000端口。开发调试时图省事可以先关防火墙但现场部署一定按规则放行别把安全关了。第四看机器人示教器上的程序走到哪一行了。如果在SocketConnect上停着说明连接阶段就失败了如果在SocketReceive上停着多半是数据发了但没带换行符或者对端没回。示教器上的光标位置和TPWrite日志比任何工具都直观。5.2 数据乱、粘包、半包怎么处理数据收到了但是内容不对一般就三类。第一种是编码问题。RAPID的字符串本质上是字节上位机如果按UTF-8解析机器人按ASCII发送的中文就会变成乱码。我的建议是现场通讯报文统一用ASCII字符集能不用中文就不用中文。像“OK”“ERROR”“100,200,300”这种纯ASCII内容永远不会出编码问题。如果一定要传中文就用字节数组配合UTF-8编码收发上位机那端用Encoding.UTF8机器人端用rawbytes两边约定好编码费点事但能通。第二种是粘包。上位机连续发两条指令比如“SET_SPEED,100\nMOVE,1,2,3\n”机器人一次接收可能拿到的是一整串“SET_SPEED,100\nMOVE,1,2,3\n”。这时按行解析把\n作为分隔符拆开逐条处理。注意处理完一条命令后剩余的数据要保留到下一次接收拼接不能丢掉。第三种是半包。一条完整指令被拆成了两截到达。解决办法是上位机或者机器人收到数据后先缓存直到缓冲区里出现了换行符才认为是一条完整的消息。这就是为什么我前面反复强调边界符——没有边界符粘包半包问题几乎无解。5.3 机器人卡死、超时怎么兜底机器人程序卡在socket指令上是现场最闹心的问题。生产节拍停在那里设备一动不动后面工位全堵住。所以要提前做防护。我的习惯是所有阻塞型的socket操作全部加超时。SocketReceive加\TimeSocketAccept加\Time这是底线。SocketConnect本身没有直接的超时参数但连接失败会报错误同时RAPID的ERROR块可以捕获并处理不会无限阻塞在系统层。另外程序里要防“死循环重试”。有些人图省事出错就RETRY结果网络一直不通机器人就在错误处理和重试之间反复横跳程序还是卡着。更好的做法是设置一个重试次数上限比如连续重试3次还失败就退出socket流程把故障状态抛给主程序让产线逻辑决定是停机报警还是继续尝试。真正重要的经验是不要在机器人主程序里做长时间的socket阻塞等待。如果通讯数据量比较大或者对端响应慢把socket通讯放到后台任务里主任务只负责读取共享变量。后面专门讲这个。5.4 后台任务与主任务协同ABB机器人支持多任务只要系统选项里启用了Multitasking就可以新建一个后台任务专门跑socket通讯。后台任务和主任务通过PERS变量共享数据互不阻塞。我的常用结构是这样后台任务里跑一个socket服务器循环一直等上位机连接、接收命令、解析命令把结果写入一个PERS变量。主任务在运动程序里周期性读取这个PERS变量发现有新命令就响应。PERS string recv_buffer; PERS bool new_cmd_flag; PROC Sock_Background() WHILE TRUE DO ! 接收数据写入recv_buffer SocketReceive client_socket \Str:recv_buffer \Time:100; IF recv_buffer THEN new_cmd_flag : TRUE; ENDIF ENDWHILE END主任务那边IF new_cmd_flag THEN new_cmd_flag : FALSE; ! 解析recv_buffer并执行 ENDIF这里要特别注意数据一致性问题。主任务和后台任务同时访问同一个PERS变量理论上会有读写竞争。我的处理方式是用一个简单的布尔标志做互斥写数据前先清标志写完再置位读数据前等标志位稳定。对于这个应用场景已经完全够用。这个架构带来的最大好处是通讯不会拖累机器人运动。就算上位机长时间不回复后台任务卡住了主任务照样可以走轨迹、做逻辑生产不会因为通讯问题停下来。这个设计在真实产线上价值极大。最后说点个人习惯。我每写一个socket通讯程序不管多简单都会做三件事第一把报文格式先写在程序注释里包含命令字、分隔符、结束符、超时时间这样换人维护也看得懂第二所有接收指令都加超时绝不让机器人无限等第三通讯程序的错误分支要单独测试一次把网线拔了、把上位机关了、把端口占了看程序会不会报错僵住。这三次破坏性测试帮我少熬了很多夜。如果你现在正卡在“上位机收不到数据”或者“机器人一直等”这两个问题上先去检查发送方有没有在报文末尾加换行符。这是ABB socket通讯里出现频率最高、也最容易忽视的坑。
返回列表