Python基于周立功盒子接收特定报文信号并实时绘制折线图(一)
一、背景
为了节省成本,最大限度利用资源,放弃了用Vector的盒子,采用周立功盒子来做二次开发,以方便来进行压力测试
二、需求
- 需要实时取六个信号值;
- 六个信号在同一个CANFD报文中;
- 实时对六个信号值进行画图以便于观察走势;
- 同时记录下来采集的数据文件
三、实现难点
- 报文的解析,如何拿到CAN信号值;
- 如何实时画图;
- 长时间边取数据边做图会不会影响接受数据
四、实现
结构跟上篇提到的Python基于周立功盒子的二次开发的封装和调用是一样的,我们只是新改了业务代码zlg_test.py文件,以下是zlg_test.py文件的实现
import time
from zlgcan import *
import threading
import matplotlib.pyplot as plt
import csv
# USBCANFD-MINI Demo
def com_extract_signal(endian, bit_pos, bit_size, src_buf, factor, offset):
byte_no = bit_pos // 8
if (((byte_no * 8) + 8) - bit_pos) <= bit_size:
total_bits_copied = ((byte_no * 8) + 8) - bit_pos
a_data = src_buf[byte_no] >> (bit_pos - (byte_no * 8))
else:
a_data = src_buf[byte_no] >> (bit_pos - (byte_no * 8))
a_data = a_data & (~(0xFF << bit_size))
total_bits_copied = bit_size
while total_bits_copied < bit_size:
bits_left = bit_size - total_bits_copied
if endian != 1: # big_endian == 1
byte_no += 1
else:
byte_no -= 1
if bits_left >= 8:
a_data = (src_buf[byte_no] << total_bits_copied) | a_data
total_bits_copied = total_bits_copied + 8
else:
a_data = ((src_buf[byte_no] & (0xFF >> (8 - bits_left))) << total_bits_copied) | a_data
total_bits_copied = total_bits_copied + bits_left
return a_data * factor + offset
if __name__ == "__main__":
time_flag = 0
x = []
y1 = []
y2 = []
y3 = []
y4 = []
y5 = []
y6 = []
zcanlib = ZCAN()
testcantype = 1 # 0:CAN; 1:canfd
handle = zcanlib.OpenDevice(ZCAN_USBCANFD_MINI, 0, 0)
if handle == INVALID_DEVICE_HANDLE:
print("Open CANFD Device failed!")
exit(0)
print("device handle:%d." % (handle))
info = zcanlib.GetDeviceInf(handle)
print("Device Information:\n%s" % (info))
# set auto send obj
AutoCAN_A = ZCAN_AUTO_TRANSMIT_OBJ()
AutoCAN_B = ZCAN_AUTO_TRANSMIT_OBJ()
AutoCAN_A.enable = 1 # enable
AutoCAN_A.index = 0
AutoCAN_A.interval = 200 # ms
AutoCAN_A.obj.frame.can_id = 0x100
AutoCAN_A.obj.transmit_type = 0
AutoCAN_A.obj.frame.eff = 0
AutoCAN_A.obj.frame.rtr = 0
AutoCAN_A.obj.frame.can_dlc = 8
for j in range(AutoCAN_A.obj.frame.can_dlc):
AutoCAN_A.obj.frame.data[j] = j
AutoCAN_B.enable = 1 # enable
AutoCAN_B.index = 1
AutoCAN_B.interval = 200 # ms
AutoCAN_B.obj.frame.can_id = 0x300
AutoCAN_B.obj.transmit_type = 0
AutoCAN_B.obj.frame.eff = 0
AutoCAN_B.obj.frame.rtr = 0
AutoCAN_B.obj.frame.can_dlc = 8
for j in range(AutoCAN_B.obj.frame.can_dlc):
AutoCAN_B.obj.frame.data[j] = j
AutoCAN_B_delay = ZCANFD_AUTO_TRANSMIT_OBJ_PARAM()
AutoCAN_B_delay.index = AutoCAN_B.index
AutoCAN_B_delay.type = 1
AutoCAN_B_delay.value = 100
# Start CAN
chn_handle = canfd_start(zcanlib, handle, 0, AutoCAN_A, AutoCAN_B, AutoCAN_B_delay)
print("channel handle:%d." % (chn_handle))
rec_msg_thread = threading.Thread(target=input_thread)
rec_msg_thread.start()
fig = plt.figure('CPU Load Monitor', figsize=(16, 9))
fig.suptitle(' J6VL3 ADU CPU Load Monitor ', fontsize='x-large')
ax = fig.add_subplot(6, 1, 1)
ax.plot([], [], 'bo-', markersize=1, linewidth=0.5, label='Core0 Cpuload')
ax.legend()
bx = fig.add_subplot(6, 1, 2)
bx.plot([], [], 'ro-', markersize=1, linewidth=0.5, label='Core1 Cpuload')
bx.legend()
cx = fig.add_subplot(6, 1, 3)
cx.plot([], [], 'go-', markersize=1, linewidth=0.5, label='Core2 Cpuload')
cx.legend()
dx = fig.add_subplot(6, 1, 4)
dx.plot([], [], 'co-', markersize=1, linewidth=0.5, label='Core3 Cpuload')
dx.legend()
ex = fig.add_subplot(6, 1, 5)
ex.plot([], [], 'mo-', markersize=1, linewidth=0.5, label='Core4 Cpuload')
ex.legend()
fx = fig.add_subplot(6, 1, 6)
fx.plot([], [], 'yo-', markersize=1, linewidth=0.5, label='Core5 Cpuload')
fx.legend()
fx.set_xlabel("Sampling: 1Hz")
time_count = 3600
while time_count:
# Receive Messages
while True:
sys_time = '{}_{}_{}_{}_{}_{}'.format(time.localtime().tm_year, time.localtime().tm_mon,
time.localtime().tm_mday, time.localtime().tm_hour,
time.localtime().tm_min, time.localtime().tm_sec)
fp = open(sys_time + '.csv', 'w')
csv_writer = csv.writer(fp)
csv_writer.writerow(['Time', 'Core0 Cpuload', 'Core1 Cpuload', 'Core2 Cpuload',
'Core3 Cpuload', 'Core4 Cpuload', 'Core5 Cpuload'])
rcv_canfd_num = zcanlib.GetReceiveNum(chn_handle, ZCAN_TYPE_CANFD)
if rcv_canfd_num:
# print("Receive CANFD message number:%d" % rcv_canfd_num)
rcv_canfd_msgs, rcv_canfd_num = zcanlib.ReceiveFD(chn_handle, rcv_canfd_num, 1000)
for i in range(rcv_canfd_num):
if rcv_canfd_msgs[i].frame.can_id == 0x101:
time_str = str(rcv_canfd_msgs[i].timestamp)
time_flag += 1
time_count -= 1
x.append(time_flag)
core0_cpuload = com_extract_signal(0, 88, 16, rcv_canfd_msgs[i].frame.data, 0.1, 0)
core1_cpuload = com_extract_signal(0, 104, 16, rcv_canfd_msgs[i].frame.data, 0.1, 0)
core2_cpuload = com_extract_signal(0, 120, 16, rcv_canfd_msgs[i].frame.data, 0.1, 0)
core3_cpuload = com_extract_signal(0, 136, 16, rcv_canfd_msgs[i].frame.data, 0.1, 0)
core4_cpuload = com_extract_signal(0, 152, 16, rcv_canfd_msgs[i].frame.data, 0.1, 0)
core5_cpuload = com_extract_signal(0, 168, 16, rcv_canfd_msgs[i].frame.data, 0.1, 0)
y1.append(core0_cpuload)
y2.append(core1_cpuload)
y3.append(core2_cpuload)
y4.append(core3_cpuload)
y5.append(core4_cpuload)
y6.append(core5_cpuload)
csv_writer.writerow([time_str, str(core0_cpuload), str(core1_cpuload), str(core2_cpuload),
str(core3_cpuload), str(core4_cpuload), str(core5_cpuload)])
print(rcv_canfd_msgs[i].timestamp, com_extract_signal(0, 88, 16, rcv_canfd_msgs[i].frame.data, 0.1, 0))
ax.plot(x, y1, 'bo-', markersize=1, linewidth=0.5)
bx.plot(x, y2, 'ro-', markersize=1, linewidth=0.5)
cx.plot(x, y3, 'go-', markersize=1, linewidth=0.5)
dx.plot(x, y4, 'co-', markersize=1, linewidth=0.5)
ex.plot(x, y5, 'mo-', markersize=1, linewidth=0.5)
fx.plot(x, y6, 'yo-', markersize=1, linewidth=0.5)
plt.pause(1) # 暂停十秒以更新图像
plt.ioff()
else:
if not rec_msg_thread.is_alive():
break
plt.savefig('./PDF/pic-{}.pdf'.format(sys_time))
# Close CAN
ret = zcanlib.ResetCAN(chn_handle)
if ret == 1:
print("ResetCAN success! ")
# Close Device
ret = zcanlib.CloseDevice(handle)
if ret == 1:
print("CloseDevice success! ")
fp.close()