python-can 的实时波形

Live waveform with python-can

我正在尝试使用 python-can 和 matplotlib 库绘制 can-data。我有一个关于如何使用 matplotlib 绘制实时数据的基本示例:

import numpy as np
import matplotlib.pyplot as plt

plt.axis([0, 10, 0, 1])


for i in range(10):
    y = np.random.random()
    plt.scatter(i, y)
    # plt.pause(0.05)
    plt.draw()

plt.show()

我使用了一个基本的 python-can 示例并添加了 matplotlib:

import sys
import argparse
import socket
from datetime import datetime

import can
from can import Bus, BusState, Logger
import numpy as np
import matplotlib.pyplot as plt



def main():

    plt.axis([0, 10, 0, 1])

    bus = Bus(bustype ='pcan')
    i = 0

    print(f"Connected to {bus.__class__.__name__}: {bus.channel_info}")
    print(f"Can Logger (Started on {datetime.now()})")

    plt.show()

    try:
        while True:
            msg = bus.recv(1)
            if msg is not None:
                y = np.random.random()
                plt.scatter(i, y)
                plt.draw()
                i += 1
                print('Message id {id}'.format(id=msg.arbitration_id))

    except KeyboardInterrupt:
        pass
    finally:
        plt.show()
        bus.shutdown()


if __name__ == "__main__":
    main()

然而,一旦我添加了 plt 命令,脚本就会停止工作,它不再输出打印语句。当我对其进行调试并手动执行时,它会起作用。我做错了什么吗?有没有更好的方法来解决这个问题?我没有设置 matplotlib,只是绘制某些内容的最快方法 :)

我找到了一个使用 blit 函数的有效解决方案,它还不完美,但它是一个很好的起点:

from datetime import datetime
import can
from can import Bus, BusState, Logger
import numpy as np
import matplotlib.pyplot as plt
import struct



def main():
    bus = Bus(bustype ='pcan')
    i = 0

    print(f"Connected to {bus.__class__.__name__}: {bus.channel_info}")
    print(f"Can Logger (Started on {datetime.now()})")

    x = np.linspace(0, 1000, num=1000)
    y = np.zeros(1000)

    fig = plt.figure()
    ax1 = fig.add_subplot(1, 1, 1)
    line, = ax1.plot([], lw=3)
    text = ax1.text(0.8, 0.5, "")

    ax1.set_xlim(x.min(), x.max())
    ax1.set_ylim([-10, 10])

    fig.canvas.draw()  # note that the first draw comes before setting data

    ax2background = fig.canvas.copy_from_bbox(ax1.bbox)

    plt.show(block=False)
    k = 0


    try:
        while True:
            msg = bus.recv(1)
            if msg is not None:
                y = np.roll(y, 1)
                value = struct.unpack('f', msg.data)
                y[0] = np.int8(value)
                line.set_data(x, y)
                fig.canvas.restore_region(ax2background)
                ax1.draw_artist(line)
                ax1.draw_artist(text)
                fig.canvas.blit(ax1.bbox)
                fig.canvas.flush_events()
                # print('Message data {data}, value {value}, counter {counter}'.format(data=msg.data, value=value, counter=k))
                k += 1
                if k > 100:
                    k = 0

    except KeyboardInterrupt:
        pass
    finally:
        plt.show()
        bus.shutdown()


if __name__ == "__main__":
    main()

该脚本假定 can 消息在前四个 uint8 上携带一个浮点数并仅绘制它。