You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

NI USB-6366 DAQ基于Python的nidaqmx库实现阈值触发式有限样本采集(含预触发与后触发样本)的问题咨询

问题:使用nidaqmx采集带预触发的有限样本(NI USB-6366)

我在使用Python的nidaqmx库读取NI USB-6366 DAQ的样本时遇到困难,目标是采集总计N个样本,其中包含M个预触发样本和(N-M)个后触发样本。触发条件为信号幅值跨越设定阈值(通过手动冲击激发入射波触发,不使用DAQ的其他通道作为触发源)。当前尝试的代码如下:

def hardwareFiniteVoltage():
    import nidaqmx
    import numpy as np
    import matplotlib.pyplot as plt
    sampleRate = 2E5 # Sample Rate in Hz
    secsToAcquire = 1 # Number of seconds over which to acquire data
    numberOfSamples = int(secsToAcquire * sampleRate)
    print('Acquiring %d data points' % numberOfSamples)
    with nidaqmx.Task('hardwareFiniteVoltage') as task:
        task.ai_channels.add_ai_voltage_chan('Dev1/ai0')
        task.timing.cfg_samp_clk_timing(sampleRate,samps_per_chan=numberOfSamples, sample_mode=nidaqmx.constants.AcquisitionType(10178))
        task.triggers.reference_trigger.cfg_anlg_edge_ref_trig( 'Dev1/ai0',10000,trigger_level=0.1)
        task.start()
        data = task.read(number_of_samples_per_channel=numberOfSamples)
        plt.plot(data)
        plt.xlabel('time [samples]')
        plt.ylabel('voltage [V]')
        plt.grid()
        plt.show()
if __name__ == '__main__':
    hardwareFiniteVoltage()

恳请协助排查代码问题并提供正确的实现方案。


原代码的问题分析

我帮你梳理下代码里的几个关键问题:

  • 触发配置参数错误cfg_anlg_edge_ref_trig的第二个参数应该指定触发沿的斜率(比如上升沿/下降沿),你传入的10000是无效值,这会直接导致触发逻辑失效。
  • 未设置预触发样本数:参考触发需要明确告诉DAQ要保留多少触发前的样本,否则DAQ无法区分预触发和后触发数据的比例。
  • 采样模式的常量使用不规范:直接用数字10178代替枚举nidaqmx.constants.AcquisitionType.FINITE,不仅可读性差,还容易因为版本更新出现错误。
  • 触发逻辑不完整:原代码没有配置触发后的样本采集逻辑,DAQ无法知道触发后需要采集多少样本才能完成总N个样本的目标。

正确的实现方案

下面是调整后的完整代码,我会逐部分解释关键改动:

def hardwareFiniteVoltage():
    import nidaqmx
    from nidaqmx.constants import AcquisitionType, Slope
    import numpy as np
    import matplotlib.pyplot as plt

    # 配置参数:根据你的需求修改
    sample_rate = 200000  # 采样率(Hz)
    total_samples = 200000  # 总采集样本数N
    pretrigger_samples = 50000  # 预触发样本数M(触发前保留的样本)
    trigger_level = 0.1  # 触发阈值(V)
    trigger_slope = Slope.RISING  # 触发沿:上升沿(根据你的冲击信号调整,也可以用Slope.FALLING)
    ai_channel = 'Dev1/ai0'

    print(f'采集总样本数:{total_samples},其中预触发样本:{pretrigger_samples},后触发样本:{total_samples - pretrigger_samples}')

    with nidaqmx.Task('pretrigger_acquisition') as task:
        # 添加模拟输入通道
        task.ai_channels.add_ai_voltage_chan(ai_channel)

        # 配置采样时钟:有限采样模式,总样本数为N
        task.timing.cfg_samp_clk_timing(
            rate=sample_rate,
            samps_per_chan=total_samples,
            sample_mode=AcquisitionType.FINITE
        )

        # 配置模拟边沿参考触发
        # 关键:指定pretrigger_samples参数,告诉DAQ保留M个触发前的样本
        task.triggers.reference_trigger.cfg_anlg_edge_ref_trig(
            trigger_source=ai_channel,
            trigger_slope=trigger_slope,
            trigger_level=trigger_level,
            pretrigger_samples=pretrigger_samples
        )

        # 启动任务:DAQ会先采集预触发样本,等待触发,然后采集剩余的后触发样本
        task.start()

        # 读取所有样本:这里会阻塞直到采集完成
        data = task.read(number_of_samples_per_channel=total_samples)

        # 可视化数据:可以看到触发点在pretrigger_samples的位置
        plt.figure(figsize=(12, 6))
        plt.plot(data)
        # 画一条线标记触发位置
        plt.axvline(x=pretrigger_samples, color='r', linestyle='--', label='触发点')
        plt.xlabel('样本序号')
        plt.ylabel('电压 (V)')
        plt.title('带预触发的采集数据')
        plt.grid(True)
        plt.legend()
        plt.show()

if __name__ == '__main__':
    hardwareFiniteVoltage()

关键改动说明

  1. 参数明确化:把总样本数、预触发样本数单独定义,方便你根据需求调整,避免通过时间计算的模糊性。
  2. 触发配置修正
    • 使用Slope.RISING(或Slope.FALLING)指定触发沿,匹配你的冲击信号特性。
    • 添加pretrigger_samples参数,告诉DAQ在触发发生时,要保留之前采集的M个样本,之后再采集total_samples - pretrigger_samples个样本完成总采集。
  3. 采样模式规范:用AcquisitionType.FINITE代替数字常量,代码更清晰可靠。
  4. 可视化优化:添加了触发位置的标记线,方便你验证预触发和后触发的数据是否正确。

注意事项

  • 确保NI USB-6366的驱动已正确安装,设备在NI MAX中可以正常识别。
  • 根据你的实际冲击信号调整触发斜率(上升沿/下降沿)和阈值,确保触发能可靠触发。
  • 如果预触发样本数设置过大,DAQ的缓冲区可能无法容纳,此时需要调整缓冲区大小(可以用task.in_stream.input_buf_size设置)。

内容的提问来源于stack exchange,提问作者Khan02

火山引擎 最新活动