python中的动态类

python中的动态类,python,class,simulation,Python,Class,Simulation,这可能是错误的标题,但这是我的问题 我有一个由微控制器(MCU)、串行接口(SPI)、DAC(数字/模拟转换器)、电极(E)组成的系统。在python建模中,每个元素都定义为一个类 作为第一步,当我在微控制器中输入一些东西时,我想监控电极上的输出 我们考虑如下: 输入:1ms内电极上的2mA MCU通过SPI发送新的DAC值:30 us DAC更新其寄存器和输出:400 us MCU向电极发送打开命令:1us 电极现在正在输出 1 ms后,向电极发送关闭命令:1us 电极不再输出 我最大的两

这可能是错误的标题,但这是我的问题

我有一个由微控制器(MCU)、串行接口(SPI)、DAC(数字/模拟转换器)、电极(E)组成的系统。在python建模中,每个元素都定义为一个类

作为第一步,当我在微控制器中输入一些东西时,我想监控电极上的输出

我们考虑如下:

  • 输入:1ms内电极上的2mA
  • MCU通过SPI发送新的DAC值:30 us
  • DAC更新其寄存器和输出:400 us
  • MCU向电极发送打开命令:1us
  • 电极现在正在输出
  • 1 ms后,向电极发送关闭命令:1us
  • 电极不再输出
我最大的两个问题是1。如何考虑这个时间成分和2。如何监控SPI线路以确定是否必须执行某些操作

class Electrode:
    def __init__(self, id):
        self.id = id
        self.switch = False
        self.value = 0

    def output(self):
        if self.switch:
            return self.value
        else:
            return 0

class SPI:
    def __init__(self):
        self.msg = None

class MCU:
    def __init__(self):
        self.name = "MicroController"

    def send_SPI_msg(self, SPI, msg):
        SPI.msg = msg

class DAC:
    def __init__(id):
        self.id = id
        self.cs = 1
        self.register = None
        self.output = None

    def read_SPI_msg(self, SPI):
        message = SPI.msg
        # update register and output
我的系统实际上有16个DAC、电极和一个现场可编程门阵列,它们都在听同一个SPI。我上面描述的是一个相当简化的版本

问题是:如何让组件定期检查
SPI.msg
中的值并采取相应的行动?

实际上,每个组件都在完成其生命周期。因此,操作是并行执行的。因为我试图模拟时间轴和执行的操作,所以我不介意使用每个元素的时间轴变量(属性)连续地执行所有操作。我只是有一些问题需要弄清楚如何让我的类相互作用

i、 e.我不能在python中执行以下操作,否则我会被卡住:

class DAC:
    def __init__(id):
        # init

    def read_SPI_msg(self, SPI):
        while True:        
            message = SPI.msg
            # update register and output if needed
也许可以使用事件触发。。。但我不知道怎么做

也许使用多线程,定义一个线程/元素

编辑:当前状态:

class SPI:
    def __init__(self):
        self.attached_dacs = []
        self.attached_fpga = []
        self.attached_mcu = []

    def attach_device(self, device):
        if type(device) == DAC:
            self.attached_dacs.append(device)
        elif type(device) == FPGA:
            self.attached_fpga.append(device)
        elif type(device) == MCU:
            self.attached_mcu.append(device)

    def send_message(self, msg):
        for device in self.attached_dacs + self.attached_fpga:
            device.on_spi_message(self, msg)

class SpiAttachableDevice:
    def on_spi_message(self, SPI, message):
        if self.cs:
            self.execute_SPI_message(message)
        else:
            return None

class DAC(SpiAttachableDevice):
    def __init__(self, id):
        self.id = id
        self.cs = False # Not listening

    def execute_SPI_message(message):
        # Do stuff

class FPGA(SpiAttachableDevice):
    def __init__(self):
        self.electrodes = list()
        self.cs = False # Not listening

    def execute_SPI_message(message):
        # Do stuff

class MCU:
    def __init__(self):
        self.electrodes = list()

我假设您希望保持单线程,而不使用asyncio。在这种情况下,您可能希望在实现SPI时使用observer或pub/sub模式:

class SPI:
    def __init__(self):
        self.attached_devices = []

    def attach_device(self, device):
        self.attached_devices.append(device)

    def send_message(self, msg):
        for device in self.attached_devices:
            device.on_spi_message(self, msg)

class SpiAttachableDevice:
    def on_spi_message(self, spi_instance, message):
        raise NotImplementedError('subclass me!')
所以你可以这样使用它:

spi = SPI()
device_1 = Device()
device_2 = Device()
spi.attach_device(device_1)
spi.attach_device(device_2)
spi.send_message('hello')

我没有做任何事情来从
设备
对象发送SPI消息,但是您可以相应地更新抽象。

我假设您希望保持它为单线程,而不使用asyncio。在这种情况下,您可能希望在实现SPI时使用observer或pub/sub模式:

class SPI:
    def __init__(self):
        self.attached_devices = []

    def attach_device(self, device):
        self.attached_devices.append(device)

    def send_message(self, msg):
        for device in self.attached_devices:
            device.on_spi_message(self, msg)

class SpiAttachableDevice:
    def on_spi_message(self, spi_instance, message):
        raise NotImplementedError('subclass me!')
所以你可以这样使用它:

spi = SPI()
device_1 = Device()
device_2 = Device()
spi.attach_device(device_1)
spi.attach_device(device_2)
spi.send_message('hello')

我还没有做任何事情来从
设备
对象发送SPI消息,但是您可以相应地更新抽象。

您可以将
while
循环移动到外部:

class SPI:

    def __init__(self, msg):
        self.msg = msg

class Component:

    def __init__(self, spi):
        self.spi = spi

    def tick(self, t):
        msg = self.spi.msg
        if msg = "...":
            ...
spi = SPI()
components = [Component(spi), ...]

for t in range(TOTAL_TIME):
   for component in components:
       component.tick(t)
正如你在评论中所说的那样,你希望更多地了解正在发生的事情。您可以有一个明确的时间表,组件可以与之交互。外部输入(状态更改)可以以相同的方式预先设置。为了订购timemline,我每次只运行sort,但使用类似于

这主要不同于Vovanrock2002答案,因为它不在每个时间步中递归,并且有一个明确的时间线

class Component:
   def __init__(self, timeline):
       self._timeline = timeline
       self._out = [] #all connected components

   def poke(self, changed_object, time):
       return []

class Clock(Component):

    def __init__(self, timeline):
        Component.__init__(self, timeline)
        self._out.append(self)
        self.msg = "tick"
        self._timeline.append((200, self, msg))

   def poke(self, time, changed_object, msg):
       self._timeline.append((time + 200, self, self.msg))

timeline = []
spi = SPI(timeline)
components = [spi, Clock(timeline), ComponentA(timeline), ...]

timeline.append((500, spi, "new DAC value"))

while timeline:
    timeline.sort(key=lambda event: event[0], reverse=True)
    event = timeline.pop()
    time, changed_component, msg:
    for connected_component in changed_component._out:
        connected_component.poke(time, changed_component, msg)

这样,您就有了一个明确的时间线(您也可以“记录”,只需将每个弹出的事件添加到某个列表中),并且您可以拥有任意连接的组件(例如,如果您想要有多个SPI)。

您可以移动
,而
只需在外部循环:

class SPI:

    def __init__(self, msg):
        self.msg = msg

class Component:

    def __init__(self, spi):
        self.spi = spi

    def tick(self, t):
        msg = self.spi.msg
        if msg = "...":
            ...
spi = SPI()
components = [Component(spi), ...]

for t in range(TOTAL_TIME):
   for component in components:
       component.tick(t)
正如你在评论中所说的那样,你希望更多地了解正在发生的事情。您可以有一个明确的时间表,组件可以与之交互。外部输入(状态更改)可以以相同的方式预先设置。为了订购timemline,我每次只运行sort,但使用类似于

这主要不同于Vovanrock2002答案,因为它不在每个时间步中递归,并且有一个明确的时间线

class Component:
   def __init__(self, timeline):
       self._timeline = timeline
       self._out = [] #all connected components

   def poke(self, changed_object, time):
       return []

class Clock(Component):

    def __init__(self, timeline):
        Component.__init__(self, timeline)
        self._out.append(self)
        self.msg = "tick"
        self._timeline.append((200, self, msg))

   def poke(self, time, changed_object, msg):
       self._timeline.append((time + 200, self, self.msg))

timeline = []
spi = SPI(timeline)
components = [spi, Clock(timeline), ComponentA(timeline), ...]

timeline.append((500, spi, "new DAC value"))

while timeline:
    timeline.sort(key=lambda event: event[0], reverse=True)
    event = timeline.pop()
    time, changed_component, msg:
    for connected_component in changed_component._out:
        connected_component.poke(time, changed_component, msg)

这样,您就有了一个明确的时间线(您也可以“记录”,只需将每个弹出的事件添加到一些列表中),并且您可以拥有任意连接的组件(例如,如果您想要有多个SPI)。

您使用的是什么数学?你有连续时间还是离散时间?我猜这些元素是将输入映射到输出的函数?@syntonym消息由16位组成。MCU不包括浮点单元。这些元件是电气元件,即DAC、电极等。。。我把它定义为阶级。时间是离散的,时钟以8兆赫的频率滴答作响。我不需要重现计时方面,例如,我可以进行以下操作:
ticks=range(8000000)
,它对应于1秒。希望有帮助:)你在用什么数学?你有连续时间还是离散时间?我猜这些元素是将输入映射到输出的函数?@syntonym消息由16位组成。MCU不包括浮点单元。这些元件是电气元件,即DAC、电极等。。。我把它定义为阶级。时间是离散的,时钟以8兆赫的频率滴答作响。我不需要重现计时方面,例如,我可以进行以下操作:
ticks=range(8000000)
,它对应于1秒。希望它有帮助:)真的很有趣,让我试着实现:)所以我确实设法让它工作。通过替换raise语句,将对每个设备执行操作(例如
print(self.id)
),这样说对吗?如果一个设备上的操作影响到另一个设备怎么办?i、 e.如果DAC值正在改变,我需要400 us才能打开电极。@Mathieu是的,
NotImplementedError
只是一个占位符。我的印象是,建模SPI是您的主要关注点,否则您已经有了及时管理关系的策略。假设这是主要关注点之一^^消息总是从MCU发送到设备,因此我不需要从设备对象发送SPI消息的方法。你能用当前的实现检查编辑,看看我是否理解你的答案吗