我有一个电动平台,可以在特定位置输出触发器。例如,平台从 0.0mm 移动到 5.0mm,每 0.1mm 输出一次触发(在 0.0mm、0.1mm、0.2mm 等处触发)。该阶段从停止位置开始,因此有一个加速阶段,直到达到巡航速度。这意味着触发器在时间上的分布不均匀。无需详细说明,在加速阶段,我的触发器较少,其时间间隔减小。一旦达到巡航速度,触发就会更加规律(几乎均匀的时间间隔),触发之间的最短时间约为 1 毫秒。
我的目标是在每次触发(上升沿)时从模拟输入通道 AI0(以最大时钟速率)采集 2-5 个样本,即使触发间隔仅 1ms。我已将舞台触发器连接到 PFI0。
我有一个触发器的工作代码,其最小触发间隔时间为 17 毫秒。如果我需要更多位置,使得触发间时间低于 17 毫秒,我的代码会跳过一些触发器并且无法完成。
import nidaqmx
with nidaqmx.Task() as task:
clk_rate = 50e3
task.ai_channels.add_ai_voltage_chan("Dev1/ai0")
task.timing.cfg_samp_clk_timing(rate=float(clk_rate), samps_per_chan=5)
data = []
for ii in range(10):
task.triggers.start_trigger.cfg_dig_edge_start_trig("PFI0")
data.append(task.read(number_of_samples_per_channel=5))
print(data)
我读过有关 NI-DAQmx 中的可重新触发任务的内容,并且我知道 USB-6002 不支持这些任务。不过,文章还解释了:“如何使用板载计数器实现与上一代 DAQ 设备类似的功能”。这个想法是计数器对触发器进行计数,并且同一计数器可以用作模拟输入任务的时钟源。我编写了另一个代码来测试计数器。
import nidaqmx
import time
with nidaqmx.Task() as task:
task.ci_channels.add_ci_count_edges_chan("Dev1/ctr0")
task.start()
time.sleep(5)
print(task.read())
如果我在 5 秒睡眠时间内运行阶段,阶段就会完成翻译。然后,我计算正确的触发器数量,即使触发器之间的间隔低于 1 毫秒,这对于我的应用程序来说已经足够了。我的问题是我不知道如何使用这个计数器作为我在 Python 中的 AI 任务的时钟源。有人可以帮助我或向我指出相关资源吗?
预先感谢您的帮助。
我在这里询问了NI LabView社区,这在带有USB-6002的LabView中似乎不可能。我假设这在 Python 中也是不可能的。我实现了NI社区ZYOng的解决方案,即将触发记录为额外的模拟输入,然后进行离线处理,根据模拟输入触发从我感兴趣的模拟输入中选择样本。我分割了触发信号,这样我仍然可以使用第一个触发器作为单个数字触发器来启动这两个任务。最后,我使用
threading
模块开始触发 USB-6002,同时我的代码将命令发送到舞台。代码如下。我创建了一个函数,该函数将通过线程来启动 DAQ 触发器:
import nidaqmx
def arm_daq(data):
with nidaqmx.Task() as task:
task.ai_channels.add_ai_voltage_chan("Dev1/ai0:1")
task.timing.cfg_samp_clk_timing(rate=25000, samps_per_chan=9000)
task.triggers.start_trigger.cfg_dig_edge_start_trig("PFI0")
data[:] = task.read(number_of_samples_per_channel=9000)
在我的主代码中,我使用
arm_daq
函数启动一个线程,并向其传递一个数组,以便可以就地修改它:
import threading
data = np.zeros((2, 9000))
t1 = threading.Thread(target=arm_daq, args=(data,))
# Send motor commands, which generates a trigger signal
t1.join()
最后,我使用这篇文章执行离线分析并根据触发器的位置(在模拟输入通道上)检索模拟输入数据。
我仍然不确定这一切是否真的是最佳的或Pythonic的,但它对我有用。很高兴听到有关此工作流程的一些评论。
保重,
大卫