您的位置:首页 > 其它

使用边缘计算网关分析CAN报文

2021-01-15 15:55 435 查看

使用边缘计算网关分析CAN报文


介绍一个使用边缘网关分析CAN报文,并将其进行数据可视化的应用案例。

硬件介绍

在此应用案例中,使用的传感器是一个加速度传感器,可以输出x、y、z轴三周的加速度。 传感器的通信协议是CAN Open。
使用的网关是虹科Dynagate 10-12

传感器信息收集

首先,使用网关Dynagate 10-12 收集CAN报文。在此之前,需要设置好网关的CAN接口。这里开放我们的can0接口,并且设置好波特率,与我们的传感器匹配。本次案例的传感器波特率是 1000Mpbs

ip link set can0 down
ip link set can0 type can bitrate 1000000
ip link set can0 up

设置好之后,使用命令获取can报文

candump can0

就会得到原始的 raw_data

首先是CAN id, 其次是dlc, 最后是CAN报文内容。

使用python处理CAN 报文

有了 raw data, 还需要有DBC文件对CAN报文进行解析。我们这里使用python 导入dbc文件,并且进行解析

import datetime
#  导入两个python处理can总线的包
import can
import cantools

#  dbc文件路径
DBC_DIR = "/home/hkaco/demo.dbc"

#  加载dbc文件 并创建can总线实例
db = cantools.database.load_file(DBC_DIR)
can_bus = can.interface.Bus('can0', bustype = 'socketcan')

def main():
while (1):
#  循环获取can总线的数据
msg = can_bus.recv()
#  获取消息并解码
recv = db.decode_message(msg.arbitration_id, msg.data)
timestamp = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
print(timestamp)
print(recv)

if __name__ == "__main__":
main()

通过我们的解析,得到的结果如下图所示:

可以看到,我们成功的使用dbc文件把获取到的raw data解析成了我们能够理解的CAN报文。

将获取到的CAN数据通过UDP协议发送到PC端实现数据可视化

由于边缘网关通常是不带显示设备的,所以我们如果想要直观的看到这个数据产生的结果,可以通过udp协议将网关解析的结果发送到pc端,然后pc端使用matplotlib等数据处理、数据可视化库即可完成。

那么首先是在网关中写好发送的脚本,我们只需要在刚刚的脚本中,添加udp发送的相关代码即可。

import socket
import json
import time
#  导入两个python处理can总线的包
import can
import cantools

#  dbc文件路径
DBC_DIR = "/home/hkaco/demo.dbc"

#  目标ip地址和目标端口,ip地址
DEST_IP = "192.168.189.201"
DEST_PORT = 6789

#  定义一个通过udp协议发送函数
def send_msg(udp_socket, message):
udp_socket.sendto(message, (DEST_IP, DEST_PORT))

#  加载dbc文件 并创建can总线实例
db = cantools.database.load_file(DBC_DIR)
can_bus = can.interface.Bus('can0', bustype = 'socketcan')

def main():

udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while (1):
#  循环获取can总线的数据
msg = can_bus.recv()
#  获取消息并解码
recv = db.decode_message(msg.arbitration_id, msg.data)
#  专为字典格式
recv = json.dumps(recv)
send_msg(udp_socket, bytes(recv, encoding="utf-8"))
time.sleep(0.5)

udp_socket.close()

if __name__ == "__main__":
main()

发送端写好了之后,我们在PC端写好还要写好接收端代码,并完善数据可视化代码

import socket
import matplotlib.pyplot as plt
import time
import datetime
import json
from datetime import datetime

def recv_msg(udp_socket):
msg = udp_socket.recvfrom(1024)
# 解码
recv_ip = msg[1]
recv_message = msg[0].decode('utf-8')
recv_dict = json.loads(recv_message)

#  recv_dict是字典,可以使用键取值

x = recv_dict['Acc_X']
y = recv_dict['Acc_Y']
z = recv_dict['Acc_Z']
t = recv_dict['T']
return x, y, z, t

def main():
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

udp_socket.bind(('', 6789))

font1 = {'family' : 'Times New Roman',
'weight' : 'normal',
'size'   : 9,
}
plt.rcParams['font.sans-serif']=['SimHei']

plt.rcParams['axes.unicode_minus']=False

plt.ion()

timel = []
xl = []
yl = []
zl = []
tl = []

while True:
nowtime = datetime.utcnow().strftime("%H:%M:%S")
x, y, z, t = recv_msg(udp_socket)
xl.append(x)
yl.append(y)
zl.append(z)
tl.append(t)
timel.append(nowtime)

plt.clf()
plt.subplots_adjust(hspace=0.5)

ax1 = plt.subplot(211)
ax1.plot(timel, xl, c="b", label='x')
ax1.plot(timel, yl, c="r", label='y')
ax1.plot(timel, zl, c= "y", label='z')
plt.legend(loc='upper right', prop=font1, frameon=False)
plt.xticks(rotation = 270)
plt.xlabel('时间戳')
plt.ylabel('加速度值')

ax2 = plt.subplot(212, sharex = ax1)
ax2.plot(timel, tl, c="c", label='T')
plt.xticks(rotation = 270)
plt.xlabel('时间戳')
plt.ylabel('T')
plt.legend(loc='upper right', prop=font1, frameon=False)

plt.pause(0.001)
plt.ioff()

socket.close()

if __name__ == "__main__":
main()

最终结果

首先运行接收端,然后在我们的边缘网关Dynagate 10-12中运行发送端。结果如图所示:


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: