【问题标题】:High level / Abstract Canbus Interface in PythonPython中的高级/抽象Canbus接口
【发布时间】:2016-05-07 16:02:40
【问题描述】:

我正在使用 python (Pcan basic api) 中的 canbus,并希望使其更易于使用。

通过总线连接了许多设备/模块。他们都被允许发送数据,如果发生冲突,最低 ID 将获胜。

数据被组织在具有 ID、SubID、十六进制值的框架中

为了说明我试图解决的问题,想象一下信号的幅度。

读取帧发送到的值

  • QuestionID QuestionSUBID QuestionData

如果没有更高优先级(=lowerID)的消息,则将答案写入总线:

  • AnswerID AnswerSubID AnswerData

由于允许任何模块/设备写入总线,因此您事先不知道接下来会得到哪个答案。设置值的方式相同,只是使用不同的 ID。所以对于上面的例子,幅度将是:

  1. 4 个 ID 和 SubId 与读/写问题/答案关联
  2. 此外,必须指定 /stored 的数据长度 (0-8)。
  3. 由于数据都是十六进制值,因此必须指定解析器才能获得人类可读的值(例如十进制表示的电压)

为了存储这些信息,我使用嵌套字典:

parameters = {'Parameter_1': {'Read': {'question_ID': ID, 
                                       'question_SUBID': SubID,
                                       'question_Data': hex_value_list,
                                       'answer_ID': ...,
                                       'answer_subID': ..., 
                                       'answer_parser': function},
                               'Write': {'ID': ...,
                                         'SubID': ...,
                                         'parser' ..., 
                                         'answer_ID': ...,
                                         'answer_subID': ...}},
               'Parameter_2': ... }} 

有很多工具可以显示何时设置了哪个值,但对于硬件控制,只要参数是最新的,读取参数的顺序就无关紧要。因此,一种可能的解决方案的一部分是将整个流量存储在一个字典中:

busdata = {'firstID' : {'first_subID': {'data': data, 
                                        'timestamp': timestamp},
                      'second_subID': {'data': data, 
                                        'timestamp': timestamp},

                      }, 
            secondID': ...}

由于总线的性质,我得到了很多其他设备询问的答案 - 总线已满 - 这些不应该被忽略,因为它们可能是我接下来需要的值,并且不需要创建额外的流量- 我可能会使用带有到期日期的时间戳,但到目前为止我并没有考虑太多。

这可行,但使用起来很糟糕。一般来说,我想我将有大约 300 个参数。最终目标是通过 (pyqt) Gui 控制设备,读取序列号等一些值,同时运行测量任务。

所以最大的问题是如何定义更好的易于访问和理解的数据结构?我期待任何关于简洁设计的建议。

主要目标是摆脱基于整个消息的方法。

编辑:我的目标是摆脱整个基于 CAN 特定消息的方法:

我假设我需要一个线程进行通信,它应该:

  1. 读取缓冲区并更新我的变量
  2. 发送请求(消息)以获取其他值/变量
  3. 定期发送一些值

所以从 gui 我希望能够:

  1. 按名称获取参数 --> 发送带有参数名称的字符串
  2. 设置参数信号 --> str(name), value(在 gui 中显示)
  3. 定期获取值 --> 名称、间隔、持续时间(10 秒或无限)

线程必须:

  1. 记录总线上的所有数据以供内部存储
  2. 通过从名称、值和读取中生成消息来处理请求,直到获得结果
  3. 发送周期性信号

我希望这个设计独立于实际硬件:

  • 我想到的解决办法,就是上面的parameters_dict

对于内部存储,我考虑了 bus_data_dict

我还是不知道该怎么做

  1. 将数据从总线线程传递到 gui(所有值与新值/请求值)
  2. 如何在pyqt中用信号和槽来实现
  3. 在内部存储数据(dict 的dict 或一些新的更好的想法)
  4. 如果这个设计是一个不错的选择

【问题讨论】:

  • 创建一个抽象出来的类...canbus完全基于消息包所以我不认为你可以消除它......但你当然可以抽象它......
  • 是的,当然。也许我确实已经足够清楚地说明了这一点。问题是如何实现这一点。我考虑了具有适当 getter 和 setter 的属性 - 我仍然需要数据的内部表示。

标签: python python-3.x hardware can-bus


【解决方案1】:

使用python-can 库将为您提供网络线程 - 为您提供传入消息的缓冲队列。该库支持 PCAN 接口等。

然后,您将创建一个中间件层,将这些can.Message 类型转换和路由为 pyqt 信号。将此视为事件/信号的一对多来源。

我会使用另一个控制器来负责向总线发送消息。它可以执行诸如从总线请求定期测量以及由 gui 驱动的按需请求等任务。

关于在内部存储数据,这实际上取决于您的编程风格和复杂性。我见过每个 CAN 消息都有自己的类的项目。

最后,队列是你的朋友!

【讨论】:

  • 谢谢。我采取了非常相似的路线,仍在尝试将其抽象为 mvc 模式。 Python-can only 适用于,与峰值系统示例相同。我通过将 Unicode 转换为字节字符串来修复他们的代码。
  • 你所说的“Python-只能使用”是什么意思?在任何系统中,您都必须确保将字节发送到总线。
【解决方案2】:

同意@Hardbyte 使用python-can。太棒了。

就应用程序层之间的消息传递而言,Zero MQ 让我很幸运——您可以将模块设置为基于事件,从 canbus 消息事件一直到更新 UI 或其他任何东西.

对于数据存储/持久性,我将消息放入 SQLite,并并行(使用 ZMQ Pub/Sub 模式)将数据传递到 IoT 中心(通过 MQTT)。

【讨论】:

    【解决方案3】:
    class MySimpleCanBus:
          def parse_message(self,raw_message):
              return MyMessageClass._create(*struct.unpack(FRAME_FORMAT,msg))
          def recieve_message(self,filter_data):
              #code to recieve and parse a message(filtered by id)
              raw = canbus.recv(FRAME_SIZE)
              return self.parse_message(raw)
          def send_message(msg_data):
              # code to make sure the message can be sent and send the message
              return self.recieve_message()
    
    class MySpecificCanBus(MySimpleCanBus):
        def get_measurement_reading():
             msg_data = {} #code to request a measurement
             return self.send_message(msg_data)
        def get_device_id():
             msg_data = {} # code to get device_id
             return self.send_message(msg_data)
    

    我可能没有正确理解您的问题...也许您可以使用更多详细信息对其进行更新

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-22
      • 2010-09-27
      • 1970-01-01
      • 2018-07-17
      • 1970-01-01
      相关资源
      最近更新 更多