【问题标题】:Receive message on CANbus always returns same value with python-can在 CANbus 上接收消息总是返回与 python-can 相同的值
【发布时间】:2019-07-30 14:58:01
【问题描述】:

我有一个带有多个输入的 CAN 总线 (PCAN)。我尝试在 python 中读取输入并将它们打印在控制台上。 我从总线得到的第一条消息是正确的,但是如果我改变输入的状态,消息中的数据不会改变,并且会不断吐出它得到的第一个数据。 在 PCAN-view 中我可以看到数据的变化,所以这不是硬件故障。

我的代码:

import can
from time import sleep


def main():
bus = can.interface.Bus(bustype='pcan', channel='PCAN_USBBUS1', bitrate=500000)

try:
    while True:

        # msg = can.Message(arbitration_id=0x232, data=[0x00], is_extended_id=False)
        # try:
        #     bus.send(msg)
        #     print("message sent on {}".format(bus.channel_info))
        # except can.CanError:
        #     print("message not sent!")

        msg = bus.recv(None)
        try:

            if msg.arbitration_id == 0x1B2:
                print(msg)

            if msg.arbitration_id == 0x1B3:
                print(msg)

            if msg.arbitration_id == 0x1B4:
                print(msg)

            if msg.arbitration_id == 0x1B5:
                print(msg)

        except AttributeError:
            print("Nothing received this time")

        sleep(0.2)

except KeyboardInterrupt:
    print("Program Exited")
except can.CanError:
    print("Message NOT sent")

bus.shutdown()


if __name__ == '__main__':
    main()

我尝试在每次接收之前发送一条消息,但没有帮助。 与打印接收到的消息后在侦听器上调用can.Listener().stop() 函数相同。

PCAN-view 显示硬件正在工作,我可以看到屏幕上发生的变化。

例如。

  1. 一开始,输入 0 和 1 在单元 0x1B2 上为高电平
  2. bus.recv 返回[00 03],正确
  3. 我清除输入 0 和 1
  4. PCAN-view 显示数据 [00 00]
  5. bus.recv 返回 [00 03],这是不正确的。它没有改变。

我已经多次阅读 readthedocs,但恐怕我错过了一些东西。我需要刷新输入缓冲区吗?我只看到了有关刷新输出缓冲区的函数的信息。

【问题讨论】:

  • 当我在 sleep(0.2) 之前/之后调用 bus.reset() 时,值会更新。所以我猜这是缓冲区没有被刷新的地方

标签: python-3.x python-can


【解决方案1】:

因此,我决定使用缓冲区和通知程序以不同的方式实现它。我还禁用了单位的自动更新功能,这样它们就不会向公共汽车发送垃圾邮件了。

我想出了这门课来使用公共汽车。

import can
import logging


def _get_message(msg):

    return msg


class PCANBus(object):

    RX_SDO = 0x600
    TX_SDO = 0x580
    RX_PDO = 0x200
    TX_PDO = 0x180

    id_unit_a = [120, 121, 122, 123]
    id_unit_b = [124, 125, 126, 127]

    def __init__(self):

        logging.info("Initializing CANbus")

        self.bus = can.Bus(channel="PCAN_USBBUS1", bustype="pcan")
        self.buffer = can.BufferedReader()
        self.notifier = can.Notifier(self.bus, [_get_message, self.buffer])

    def send_message(self, message):

        try:
            self.bus.send(message)
            return True
        except can.CanError:
            logging.error("message not sent!")
            return False

    def read_input(self, id):

        msg = can.Message(arbitration_id=self.RX_PDO + id,
                          data=[0x00],
                          is_extended_id=False)

        self.send_message(msg)
        return self.buffer.get_message()

    def flush_buffer(self):

        msg = self.buffer.get_message()
        while (msg is not None):
            msg = self.buffer.get_message()

    def cleanup(self):

        self.notifier.stop()
        self.bus.shutdown()

    def disable_update(self):

        for i in [50, 51, 52, 53]:

            msg = can.Message(arbitration_id=0x600 + i,
                              data=[0x23, 0xEA, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00],
                              is_extended_id=False)

            self.send_message(msg)

并且可以用作:

pcan = PCANBus()
msg = Message(arbitration_id=pcan.RX_PDO + 50, is_extended_id=False, data=[0x4F, 0x00])
pcan.send_message(msg)
ret = pcan.read_input(0x78)
pcan.cleanup()

'ret' 保存返回消息

【讨论】:

  • 这是一个关于如何使用 NotifierBufferedReader 类的非常棒的教程,因此我们不会错过任何 CAN 总线消息。
  • @SeanMcCarthy 谢谢,很高兴它对其他访问者有用
  • 您能解释一下flush_buffer 是如何证明它的名字的吗?
  • @PeDro 我这样称呼它,因为它会清除消息缓冲区中的所有消息。 python-can.readthedocs.io/en/master/…
猜你喜欢
  • 2021-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-18
  • 2019-10-22
  • 2019-10-31
  • 1970-01-01
相关资源
最近更新 更多