1 个不稳定版本
0.1.0 | 2023 年 9 月 7 日 |
---|
#11 in #ni
51KB
549 行
niexpctrl_backend
- NI 实验控制和流
niexpctrl_backend
提供了一个无缝的接口来控制和流式传输涉及 National Instruments (NI) 设备的实验。它扩展了 nicompiler_backend
遗留库的基本功能,以定义与 NI 硬件交互的行为,同时为用户提供优化和友好的界面。
核心功能
-
NI 设备流和控:使用
experiment
模块,用户可以访问来自nicompiler_backend
的改进版本的Experiment
结构,该结构集成了 NI 特定的功能,使可以直接流式传输到 NI 设备及其重置。 -
NI-DAQmx 特定操作:
nidaqmx
模块提供了一套功能,用于与 NI-DAQmx C 库接口,将 Rust 调用转换为 NI-DAQmx 特定任务。 -
工具和辅助函数:
utils
模块提供了额外的工具和辅助函数。
与 nicompiler_backend
的集成
此包旨在成为 nicompiler_backend
的自然扩展。主要的 Experiment
结构体依赖于并扩展了 nicompiler_backend
中的对应结构体,保持了一般的实验行为,并引入了特定于 NI 设备管理的额外方法。 请参阅 nicompiler_backend
以获取与 NI 流行为无关的通用实现。
如何开始
-
实验设计和控制:
experiment
模块提供了如何并发流式传输设备任务的实现。 -
设备管理:
device
模块实现了流式传输和同步行为。 -
NI-DAQmx 操作:
nidaqmx
模块提供了调用 NI-DAQmx C 库的 Rust 包装方法,以实现无缝的 NI 设备操作。 -
工具:有关通用工具和辅助功能,请探索
utils
模块。
带有流式传输的示例用法
Rust
回想一下之前在 nicompiler_backend
中的相同示例代码片段。
我们在设计并编译实验后,额外调用了 exp.stream_exp((50., 2));
以通过50毫秒的流缓冲区和两次重复来流式传输实验。有关流行为的更多信息,请参阅 StreamableDevice::stream_task
。
use niexpctrl_backend::*;
let mut exp = Experiment::new();
// Define devices and associated channels
exp.add_ao_device("PXI1Slot3", 1e6);
exp.add_ao_channel("PXI1Slot3", 0);
exp.add_ao_device("PXI1Slot4", 1e6);
exp.add_ao_channel("PXI1Slot4", 0);
exp.add_do_device("PXI1Slot6", 1e7);
exp.add_do_channel("PXI1Slot6", 0, 0);
exp.add_do_channel("PXI1Slot6", 0, 4);
// Define synchronization behavior:
exp.device_cfg_trig("PXI1Slot3", "PXI1_Trig0", true);
exp.device_cfg_ref_clk("PXI1Slot3", "PXI1_Trig7", 1e7, true);
exp.device_cfg_trig("PXI1Slot4", "PXI1_Trig0", false);
exp.device_cfg_ref_clk("PXI1Slot4", "PXI1_Trig7", 1e7, false);
exp.device_cfg_samp_clk_src("PXI1Slot6", "PXI1_Trig7");
exp.device_cfg_trig("PXI1Slot6", "PXI1_Trig0", false);
// PXI1Slot3/ao0 starts with a 1s-long 7Hz sine wave with offset 1
// and unit amplitude, zero phase. Does not keep its value.
exp.sine("PXI1Slot3", "ao0", 0., 1., false, 7., None, None, Some(1.));
// Ends with a half-second long 1V constant signal which returns to zero
exp.constant("PXI1Slot3", "ao0", 9., 0.5, 1., false);
// We can also leave a defined channel empty: the device / channel will simply not be compiled
// Both lines of PXI1Slot6 start with a one-second "high" at t=0 and a half-second high at t=9
exp.high("PXI1Slot6", "port0/line0", 0., 1.);
exp.high("PXI1Slot6", "port0/line0", 9., 0.5);
// Alternatively, we can also define the same behavior via go_high/go_low
exp.go_high("PXI1Slot6", "port0/line4", 0.);
exp.go_low("PXI1Slot6", "port0/line4", 1.);
exp.go_high("PXI1Slot6", "port0/line4", 9.);
exp.go_low("PXI1Slot6", "port0/line4", 9.5);
exp.compile_with_stoptime(10.); // Experiment signal will stop at t=10 now
assert_eq!(exp.compiled_stop_time(), 10.);
exp.stream_exp(50., 2);
Python
功能上与上述代码相同,此外还采样并绘制了 PXI1Slot6/port0/line4
的信号。 Experiment
对象的主要目标是提供一组完整的快速 Rust 实现的接口方法,用于与 NI 实验进行交互。可以通过在 Python 代码中包装 nicompiler_backend
模块来轻松自定义语法糖和高级抽象,请参阅我们的 项目页面 以查看此类示例之一。
# Instantiate experiment, define devices and channels
from nicompiler_backend import Experiment
import matplotlib.pyplot as plt
exp = Experiment()
exp.add_ao_device(name="PXI1Slot3", samp_rate=1e6)
exp.add_ao_channel(name="PXI1Slot3", channel_id=0)
...
# Define synchronization behavior
exp.device_cfg_trig(name="PXI1Slot3", trig_line="PXI1_Trig0", export_trig=True)
exp.device_cfg_ref_clk(name="PXI1Slot3", ref_clk_line="PXI1_Trig7",
ref_clk_rate=1e7, export_ref_clk=True)
...
# Define signal
# Arguments of "option" type in rust is converted to optional arguments in python
exp.sine(dev_name="PXI1Slot3", chan_name="ao0", t=0., duration=1., keep_val=False,
freq=7., dc_offset=1.)
...
exp.compile_with_stoptime(10.)
exp.stream_exp(50., 2)
依赖关系
~9–16MB
~207K SLoC