ABB机器人socket通讯的3种方式及解析详解 

一、前言

在工业自动化中,最常用的其实是profinet,工业设备通过配置,一根网线便可以实现数据可靠的实时发送或接受(1ms或者更短),profinet类似于profibus+ethernet。但对于普通计算机,则不能与ABB机器人实现profinet通讯,只能用socket通信。

那么,tcp/ip与socket怎么理解呢?

在TCP和UDP同属于传输层,共同架设在IP层(网络层)之上。IP层主要负责的是在节点,或者叫网络设备,或者叫电脑之间(End to End)的数据包传送,不区分应用。所以TCP和UDP协议在其基础上加入了端口,端口标识的是一个节点上的一个应用程序。

UPD协议除了增加端口信息,基本就没有对IP层的数据进行任何的处理了。而TCP协议还加入了更加复杂的传输控制,比如滑动的数据发送窗口(Slice Window),以及接收确认和重发机制,以达到数据的可靠传送。

socket跟TCP/IP并没有必然的联系。socket编程接口在设计的时候,就希望也能适应其他的网络协议。所以,socket的出现只是可以更方便的使用TCP/IP协议栈,其对TCP/IP进行了抽象,形成了几个最基本的函数接口,例如socketcreate,socketlisten,socketaccept等等。

如果一个程序创建了一个socket,并监听4002端口,其实是向TCP/IP协议栈声明了其对4002端口的占有,之后,所有目标是4002端口的TCP数据包都会转发至socket层传至该程序。

另外,TCP/IP协议不仅仅指的是TCP 和IP两个协议,而是指一个由FTP、SMTP、TCP、UDP、IP等协议构成的协议簇, 只是因为在TCP/IP协议中TCP协议和IP协议最具代表性,所以被称为TCP/IP协议。

二、原理图

理解了基本的通讯知识,再看ABB机器人socket。

图片[1]-ABB机器人socket通讯

通过上面这张图可以看到socket的基本用法,socket的声明、服务端与客户端的建立等等,使用SocketGetStatus(server_socket)还可以查看socket的状态。

然后重点讲一下socket发送接收的三种数据类型:Str、Data、RawData。

三、字符串类型

字符串类型的发送接收是简单的,不过有80个字符的限制

声明变量

VAR socketdev sockte1;
VAR string sendStr;
VAR string receiveStr;
VAR num receiveStrNum;
VAR string stringPart;
VAR string strVar;
VAR string Data{20}:=["","","","","","","","","","","","","","","","","","","",""];
VAR bool OK;
PERS num putX;
PERS num putY;
PERS num putZ;

接收指令

SocketReceive sockte1 \str:=receiveStr\NoRecBytes:=receiveStrNum;

解析程序

        j:=1;
        strVar:="";
        FOR i FROM 1 TO receiveStrNum DO
            stringPart:= strPart (receiveStr,i,1);
            IF stringPart<>";" THEN
                strVar:=strVar+stringPart;
                stringPart:="";
            ELSEIF stringPart=";" THEN
                Data{j}:=strVar;
                strVar:="";
                stringPart:="";
                j:=j+1;
            ENDIF
        ENDFOR
        OK:=StrToVal(Data{1},pickX);
        OK:=StrToVal(Data{2},pickY);
        OK:=StrToVal(Data{3},pickZ);

发送指令

sendStr:="1";
SocketSend sockte1\str:=sendStr;

四、字节类型

字节类型的发送接受,与字符串类似,只不过是建了一个byte类型的数组,用于存放数据。因最多发送接收为1024个byte,那就声明一个byte类型的1024长度的一维数组。
声明变量

    VAR socketdev sockte2;
    VAR byte receiveByte{1024};
    VAR string sendStr;
    VAR num receiveByteNum;
    VAR string strPart{1024};
    VAR string strVar:="";
    VAR string Data{512};
    VAR bool OK;

接收指令

SocketReceive sockte2\Data:=receiveByte\NoRecBytes:=receiveByteNum;

解析程序

    j:=1;
    strVar := "";
    FOR strP FROM 1 TO 1024 DO
        strPart{strP} := "";
    ENDFOR
    FOR i FROM 1 TO receiveByteNum DO
        strPart{i}:=ByteToStr(receiveByte{i}\Char);
        IF strPart{i}<>";" THEN
            strVar:=strVar+strPart{i};
        ELSEIF strPart{i}=";" THEN
            Data{j}:=strVar;
            strVar:="";
            j:=j+1;
        ENDIF
    ENDFOR

发送指令

sendStr:="1";
SocketSend sockte1\str:=sendStr;

五、二进制字节类型

二进制字节,ABB提供了丰富的解析指令,UnpackRawBytes解二进制字节、CopyRawBytes复制二进制字节、PackRawBytes把变量转为二进制字节等等。

但有个非常要注意点,ABB为了数据能可靠的得到接收内容,有一个“分包”发送机制:先发4个字节,再发剩余字节。

此处在ABB机器人端表现为2个receive指令。我们在开发上位机程序时,肯定想方设法满足这个“分包”,那就掉到“坑”里了,其实在实际测试中发现,上位机1包发所有的也可以,只要有4个字节的包头就行。

声明变量

VAR socketdev sockte3;
VAR rawbytes receiveRawData;
VAR rawbytes sendRawData;
VAR num bytes_rcvd;
VAR num msg_length;
VAR num pickX;
VAR return_value

接收指令

SocketReceive sockte3, \RawData:=receiveRawData, \ReadNoOfBytes:=4;
UnpackRawBytes receiveRawData,1,msg_length,\IntX:=UDINT;
SocketReceive sockte3,\RawData:receiveRawData,\ReadNoOfBytes:=msg_length,\NoRecBytes:=bytes_rcvd;
IF (bytes_rcvd<>msg_length) THEN
    ErrWrite\W,"ROS Socket Recv Failed","Did not receive expected # of bytes.",
                     \RL2:="Expected: "+ValToStr(msg_length),
                     \RL3:="Received: "+ValToStr(bytes_rcvd);
    RETURN ;
ENDIF
UnpackRawBytes receiveRawData,1,pickX,\IntX:=DINT;

发送指令

PackRawBytes return_value,sendRawData,1,\IntX:=DINT;
SocketSend sockte3,\RawData:=sendRawData;
THE END
喜欢就支持一下吧
点赞10 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容