NI DAQmx-当波的振幅超过阈值时,如何开始收集信号(python)



我在使用Python和nidaqmx库正确读取N个样本时遇到问题。我使用的是NI USB-6366数据采集卡。简而言之,我的目标是获得总共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()

我不能说你是否可以硬件做到这一点,因为我不知道具体的USB卡,但我相信你可以在数据表上检查可行性。就python代码而言,触发采集必须以异步方式进行:一旦数据可用(即触发事件发生时的N个样本(,nidaqmx就会调用您的采集函数。

注:

  • 据我从doc了解,cfg_alg_edge_ref_trig使nidaq在触发事件发生前至少为您提供N个样本:触发事件发生后,您真的需要N个样本吗

    在对文档进行更深入的研究后,cfg_alg_edge_ref_trig允许您指定pretrigger_samples,即在触发之前获取的样本数。在POST-TRIGGER中获取的样本数量将作为numberOfSamples(在对task.timing.cfg_samp_clk_timing的调用中指定的样本总数(和pretrigger_samples之间的差值

请查看文档,了解有关回调注册和nidaq stram读取器的更多信息。

注意:由于目前我没有可用的nidaq卡,因此未对代码进行测试。很抱歉给您带来不便

import nidaqmx
# This is an object that manage the samples stream acquisition
from nidaqmx import stream_readers
import numpy as np
import matplotlib.pyplot as plt
import time
# This var is initialized during task creation and is needed by your callback
nidaq_reader: stream_readers.AnalogMultiChannelReader = None

def do_something_with_data(data):
# Just for convenience
plt.plot(data)
plt.xlabel('time [samples]')
plt.ylabel('voltage [V]')
plt.grid()
plt.show()

def callback(task_handle, every_n_samples_event_type, number_of_samples, callback_data):
try:
# Allocate your numpy array (I'm assuming just one channel!)
data = np.empty((number_of_samples,))
# Now read the acquired samples
number_of_samples_read = nidaq_reader.read_many_sample(data, number_of_samples)
except Exception as e:
print(f'Something went wrong reading samples: {e}')
else:
do_something_with_data(data)
finally:
# Always needed by nidaqmx to return 0!
return 0
def hardwareFiniteVoltage():
sampleRate = 2E5   # Sample Rate in Hz
secsToAcquire = 1    # Number of seconds over which to acquire data
numberOfSamples = int(secsToAcquire * sampleRate)

pretrigger_samples = 10000
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',pretrigger_samples,trigger_level=0.1)

# Here you register your callback into nidaqmx event loop
task.register_every_n_samples_acquired_into_buffer_event(numberOfSamples, callback)

# Initialize the stream_readers nidaq_reader to be used by your callback to get your actual data
global nidaq_reader
nidaq_reader = stream_readers.AnalogSingleChannelReader(task.in_stream)

task.start()


if __name__ == '__main__':
hardwareFiniteVoltage()

while True:
# Event loop. Don't use `pass`! It will saturate the CPU
time.sleep(0.001)

最新更新