对WireShark 中的EtherCAT抓包数据进行解析

对WireShark 中的EtherCAT抓包数据进行解析

EtherCAT数据包结构

EtherCAT数据帧结构如下:

在这里插入图片描述

采用 Python 实现对 EtherCAT 数据包进行解析


import numpy as np
import matplotlib.pyplot as plt
from IPython import embed
from collections import Counter
import  pyshark
import pcapng
from datetime import datetime
import dpkt
import socket
from dpkt.utils import mac_to_str, inet_to_str


# https://zhuanlan.zhihu.com/p/582336672

#打开抓包文件


# 位置寻址
#    - APRD(1): Auto Increment Read
#    - APWR(2): Auto Increment Write
#    - APRW(3): Auto Increment Read Write
# # 节点寻址
#    - FPRD(1): Configuration address Read
#    - FPWR(2): Configuration address Write
#    - FPRW(3): Configuration address Read Write
# # 广播寻址
#    - BRD(1): Broadcast Read
#    - BWR(2): Broadcast Write
#    - BRW(3): Broadcast Read Write
# # 逻辑寻址
#    - LRD(1): Logic Memory Read
#    - LWR(2): Logic Memory Write
#    - LRW(3): Logic Memory Read Write
# # 位置寻址
#    - APMW(13): Auto Increment Read Multiple Write

cnt =  2
old_timestamp = 0
file_path = "./TestJoint.pcapng"

time_list_pc_to_control = []
time_list_control_to_pc = []
data_list = []

joint_cmd = []
joint_fd = []
with open(file_path,"rb") as fp:
    pcapng_data = dpkt.pcapng.Reader(fp)
    for timestamp, buf  in pcapng_data:
        eth = dpkt.ethernet.Ethernet(buf)
        cnt += 1
        ## Ethernet_II 帧格式
        # ## 1、目标 Mac 地址
        # eth.dst
        # ## 2、源 Mac 地址
        # eth.src

        ## 3、得到Ethernet II 数据帧的类型。类型字段(Type )用于标识数据字段中包含的高层协议。类型字段取值为0x0800的帧代表IP协议帧;类型字段取值为0x0806的帧代表ARP协议帧。
        ## 0x0800: IP IP协议
        ## IPv4:     0x0800
        ## ARP:      0x0806
        ## IPV6:     0x86DD
        ## EtherCAT: 0x88A4
        # print(hex(eth.type))

        # 如果是EtherCAT 的数据帧
        if(eth.type == 0x88a4):
            ethercat_data = eth.data
            ## 解析EtherCAT 头,数据帧的前两个字节
            ethercat_data_head = int.from_bytes(ethercat_data[:2], byteorder='little')
            ### 得到数据的长度  11 bit, 后面有一个bit的保留位
            ethercat_data_length = (ethercat_data_head & 0x0fff)
            ### 得到EtherCAT 的类型 4bit
            ethercat_data_cmd = (ethercat_data_head & 0xf000) >> 12

            ## 解析一个子报文
            ## 解析子报文的头
            ethercat_subdata_head = int.from_bytes(ethercat_data[2:12], byteorder='little')
            ## 命令 8 bit
            ## LRW = 12
            ethercat_subdata_head_cmd = ethercat_data[2]

            if ethercat_subdata_head_cmd == 12:
                ## 索引 8 bit
                ethercat_subdata_head_index = ethercat_data[3]
                ## 地址区 32 bit
                ethercat_subdata_head_address = int.from_bytes(ethercat_data[4:8], byteorder='little')
                ## 长度 11 bit  216 个字节
                ethercat_subdata_head_length = int.from_bytes(ethercat_data[8:10], byteorder='little') & 0x0eff

                ## R 3 bit
                ethercat_subdata_head_R = (int.from_bytes(ethercat_data[8:10], byteorder='little') & 0x3000) >> 13
                ## C 1 bit
                ethercat_subdata_head_C = (int.from_bytes(ethercat_data[8:10], byteorder='little') & 0x4000) >> 14
                ## M 1 bit
                ## 0: 表示只有 1 包数据
                ## 1:表示后面还有数据包
                ethercat_subdata_head_M = (int.from_bytes(ethercat_data[8:10], byteorder='little') & 0x8000) >> 15
                ## 状态位 16 bit
                ethercat_subdata_head_status = int.from_bytes(ethercat_data[10:12], byteorder='little')

                ## 1:表示后面还有数据包
                if(ethercat_subdata_head_M == 1):
                    ethercat_subdata_data = ethercat_data[12:12 + ethercat_subdata_head_length ]

                    j1_cmd = int.from_bytes(ethercat_subdata_data[4:8], byteorder='little', signed = True)
                    j2_cmd = int.from_bytes(ethercat_subdata_data[16:20], byteorder='little', signed = True)
                    j3_cmd = int.from_bytes(ethercat_subdata_data[28:32], byteorder='little', signed = True)
                    j4_cmd = int.from_bytes(ethercat_subdata_data[40:44], byteorder='little', signed = True) 
                    j5_cmd = int.from_bytes(ethercat_subdata_data[52:56], byteorder='little', signed = True)
                    j6_cmd = int.from_bytes(ethercat_subdata_data[64:68], byteorder='little', signed = True) 


                    j1_fd = int.from_bytes(ethercat_subdata_data[76:80], byteorder='little', signed = True) 
                    j2_fd = int.from_bytes(ethercat_subdata_data[100:104], byteorder='little', signed = True) 
                    j3_fd = int.from_bytes(ethercat_subdata_data[124:128], byteorder='little', signed = True) 
                    j4_fd = int.from_bytes(ethercat_subdata_data[148:152], byteorder='little', signed = True)
                    j5_fd = int.from_bytes(ethercat_subdata_data[172:176], byteorder='little', signed = True)
                    j6_fd = int.from_bytes(ethercat_subdata_data[196:200], byteorder='little', signed = True) 

                    joint_cmd.append([j1_cmd, j2_cmd, j3_cmd, j4_cmd, j5_cmd, j6_cmd])
                    joint_fd.append([j1_fd, j2_fd, j3_fd, j4_fd, j5_fd, j6_fd])
                    
joint_cmd_1 = np.mat(joint_cmd)
joint_fd_1 = np.mat(joint_fd)

for i in range(6):
    plt.plot(joint_cmd_1[:,i],label = 'cmd')
    plt.plot(joint_fd_1[:,i],label = 'fd')
    plt.xlabel("time[ms]")
    plt.ylabel("pos[cnt]")
    plt.legend()
    plt.show()

下面是从数据包解析得到的关节1 和 关节 5 的关节脉冲指令值以及反馈值。
在开始阶段需要将当前的脉冲指令值和反馈值进行同步一下。

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

独坐寒江边

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值