07-25-2022 10:56 AM
Hello,
I'm currently trying to realize a data acquisition task in python. So far I have come up with two different approaches with the help of this community (big thanks!). However both solutions have still some problems. Therefore I hope that you might be able to help me again.
The acquisition task is the following. I have a TTL trigger pulse with a frequency of 5 kHz. At each trigger pulse I want to read from three channels several data points to integrate them later in order to improve my signal. The first solution was the usage of a trigger (see code example no. 1 below). However here I have the problem that if i read out the elapsed time for rearming the trigger it gives me roughly 10 ms, which is obviously too slow for the desired trigger. In the code the whole task is always restarted which makes it that slow so my question would be if somebody has an example for me how to accelerate this. The second solution was to use the trigger as an external sample clock (see code example no. 2 below). This is working fine in terms of speed but obviously I acquire only one data point with each trigger and not several as intended. My question here would be if somebody knows if it is possible to acquire more than just one data point which each trigger in this configuration and how to do it.
Cheers
Fabian
Code example no. 1:
import nidaqmx as n
import time
from nidaqmx.constants import (
TerminalConfiguration,
VoltageUnits,
AcquisitionType,
TriggerType,
Edge
)
s_freq = 100000
num_samples = 100
task = n.Task()
task.ai_channels.add_ai_voltage_chan("/Dev3/ai0")
task.ai_channels.add_ai_voltage_chan("/Dev3/ai1")
task.ai_channels.add_ai_voltage_chan("/Dev3/ai2")
startt = time.time()
task.timing.cfg_samp_clk_timing(s_freq, sample_mode=n.constants.AcquisitionType.CONTINUOUS, samps_per_chan=num_samples)
task.triggers.start_trigger.trig_type = TriggerType.DIGITAL_EDGE
task.triggers.start_trigger.cfg_dig_edge_start_trig("PFI0",trigger_edge=Edge.RISING)
for i in range(5):
starttt = time.time()
task.start()
print(time.time() - starttt)
data = task.read(timeout=1.0)
print(data)
task.stop()
print(time.time() - startt)
task.close()
Code example no. 2:
import nidaqmx as n
import numpy as np
import time
import h5py
import os
from nidaqmx.constants import (
TerminalConfiguration,
VoltageUnits,
AcquisitionType,
TriggerType,
Edge,
DigitalWidthUnits
)
s_freq = 10000
num_samples = 10000
task = n.Task()
task.ai_channels.add_ai_voltage_chan("/Dev3/ai0")
task.ai_channels.add_ai_voltage_chan("/Dev3/ai1")
task.ai_channels.add_ai_voltage_chan("/Dev3/ai2")
startt = time.time()
task.timing.cfg_samp_clk_timing(s_freq, "PFI0", active_edge=Edge.RISING, sample_mode=n.constants.AcquisitionType.FINITE, samps_per_chan=num_samples)
task.timing.delay_from_samp_clk_delay_units = nidaqmx.constants.DigitalWidthUnits.SECONDS
task.timing.delay_from_samp_clk_delay = 2.9e-6
data_read = task.read(num_samples)
task.stop()
task.close()
print(time.time() - startt)
07-25-2022 11:18 AM - edited 07-25-2022 11:19 AM
Before getting into implementation let's look at the requirements conceptually, does the below image translate your signals properly?
If you just want an average of the signal between the trigger pulses, using the trigger as a sample clock and a large sampling time/integration time will do the trick (even if returns only one sample, it was integrated over a larger time which is almost the same as averaging)
Could you also describe your application in detail to understand the significance of these signals?
07-26-2022 02:10 AM
Hi Santhosh,
thanks for your reply. It's almost like that I don't want to integrate the complete time between the trigger pulses only maybe something like 5 to 10 µs. Below you can see how my signals look like. The idea behind taking several data points and averaging them later is originated from the fact, that the signals are not of equal length. Because on the first two channels there are two different photodiodes connected with different rising and fall times. On the third channel there is a refernce signal connected, which is close to a sinusodial with a frequency of 12 Hz, therefore it should be almost constant on the timescale of a few microseconds.
Ideally I would like to take several data points after the trigger for roughly 50 µs and average them in the postprocessing to account for the different duration times of the signals. However your idea with this distinct integration time sounds very nice how could I implemet this to test if it works and can one set an arbitrary integration time like for example 5 to 10 µs?
Cheers
Fabian
07-26-2022 08:24 AM
These additional details help understand the requirements better, now on the hardware capabilities - what DAQ device do you use?
In general, I am looking at the re-triggerable acquisition concept as per the below articles,
https://knowledge.ni.com/KnowledgeArticleDetails?id=kA00Z0000019MXxSAM&l=en-US
https://www.ni.com/en-us/support/documentation/supplemental/21/retriggerable-tasks-in-ni-daqmx.html
07-26-2022 08:37 AM
Hi Santhosh,
I'm using a NI BNC-2110 as an interface conntected to a NI USB-6212 card (16 Inputs, 16 bits, 400 kSa/s, Multifunction I/O) which is connected to my computer.
Cheers
Fabian
07-28-2022 07:15 PM
Your M-series device doesn't natively support retriggered AI. But there's an indirect way to accomplish it with a counter task set up as a retriggerable finite pulse train, and an AI task set up to use the counter output as its sample clock.
Sorry, I don't know the Python syntax to make it happen , but that's the basic idea. The links Santhosh provided also describe it.
-Kevin P
07-29-2022 01:43 AM
Hi Kevin,
thanks for your reply. I also noticed with the provided documents, that I have to use this kind of work around with the counters. However I have a question to this procedure. In the document they state one has to use both onboard counters. I am now a bit confused this means for me that one should not use the external trigger directly as sample clock. Does that mean I have to set up basically two sample clocks, one from the external trigger and one to the desired speed of acquisition, and then use the first one to enable the second one? Since I am not getting the described procedure in the documents could you maybe try to explain it to me how to do it then I might be able to translate it to python code. Also if you might explain it in simple labview blocks / or in a block diagram this might help me to translate it.
Thanks,
Fabian
07-29-2022 03:54 PM
2 counters get *used* but you only explicitly program 1 of them. On M-series devices such as your USB-6212, finite pulse trains use up both counters.
The USB-621x devices have some special limitations however, so I'm not 100% sure if the following will be supported. Here's what to try:
Program one of the counters for Finite Sampling, Implicit Timing, 50 samples, 1 MHz frequency. Also configure it to use the external pulse as a Start Trigger. And then further (this is the part I'm not sure is supported), configure it to be retriggerable. It's possible this is an optional parameter when configuring the Start Trigger?
If supported, then for each incoming external pulse, you'll trigger a series of 50 counter pulses at 1 MHz -- a total of 50 microsec worth. It will then internally rearm itself and be ready for the next external pulse. And so on.
Then you'll configure your AI task to use your counter pulses as its sample clock. In the function call to set up sample timing, it may look something like: source="\Dev1\Ctr0InternalOutput"
-Kevin P