Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

nidaqmx python Synchronize analog output and input in stream

Highlighted

Hi,

 

I am trying to run the multiple analog outputs and inputs simultaneously using the following python codes. But it looks that the reader is delayed and show error with "nidaqmx.errors.DaqError: Requested value is not a supported value for this property. The property value may be invalid because it conflicts with another property.
Property: DAQmx_StartTrig_Type
Requested Value: DAQmx_Val_AnlgEdge
Possible Values: DAQmx_Val_DigEdge, DAQmx_Val_None
Task Name: _unnamedTask<1>
Status Code: -200077"

I believe there is something wrong with trigger, but haven't found a solution yet.

Help is much appreciated,

 

With kind regards,

 

Ho

 

import nidaqmx
import numpy as np
import matplotlib.pyplot as plt
import time
from nidaqmx import constants
from nidaqmx.constants import Edge, Slope
from nidaqmx.stream_readers import AnalogMultiChannelReader
from nidaqmx.stream_writers import AnalogMultiChannelWriter
from nidaqmx.stream_readers import AnalogSingleChannelReader

outputX=np.linspace(10,-10,25000)
outputY=np.linspace(5,-10,25000)
X=np.zeros(25000)

outputData = np.append(outputX,outputY)
outputData=np.append(outputData,outputY)
outputData = outputData.reshape((3,len(outputX)))


inputData=np.zeros(25000*3)
inputData = inputData.reshape((3,25000))
#outputData = np.transpose(outputData)
print(outputData.shape)
print(inputData.shape)

#ao_chan_x=t1.ao_channels.add_ao_voltage_chan("cDAQ1Mod1/ao0")
#ao_chan_y=t1.ao_channels.add_ao_voltage_chan("cDAQ1Mod1/ao1")
#outputChannels = ao_chan_x + "," + ao_chan_y


writingrate1=25000

#while True:
with nidaqmx.Task() as writeTask, nidaqmx.Task() as readTask:
writeTask.ao_channels.add_ao_voltage_chan('cDAQ1Mod1/ao0:2')
readTask.ai_channels.add_ai_voltage_chan('cDAQ1Mod4/ai0:2')

writeTask.timing.cfg_samp_clk_timing(rate=writingrate1,
#source='/cDAQ1/ai/SampleClock',
sample_mode=nidaqmx.constants.AcquisitionType.FINITE, # dont use continuous
samps_per_chan=X.size)

readTask.timing.cfg_samp_clk_timing(rate=writingrate1,
#source='/cDAQ1/ao/SampleClock',
active_edge=nidaqmx.constants.Edge.RISING,
sample_mode=nidaqmx.constants.AcquisitionType.FINITE,
samps_per_chan=X.size)
writeTask.triggers.start_trigger.cfg_anlg_edge_start_trig( trigger_source='/cDAQ1/ai/StartTrigger', trigger_slope=Slope.RISING) # Setting the trigger on the analog input



reader = AnalogMultiChannelReader(readTask.in_stream)
writer = AnalogMultiChannelWriter(writeTask.out_stream)

print("The channels linked to WriteTask are: ")
for i in writeTask.ao_channels:
print(i)


writer.write_many_sample(outputData)
writeTask.start()
reader.read_many_sample(inputData)





#reader.read_many_sample(inputData)
#readTask.start()

#writeTask.start()

writeTask.wait_until_done()
readTask.wait_until_done()

#readTask.start()

print("Done with data")
#print(inputData)

#x=np.linspace(0,25000,25000)
plt.plot(inputData[0])
plt.show()







0 Kudos
Message 1 of 4
(197 Views)
Highlighted

Many devices don't support analog triggering for AI tasks.  I don't know of ANY that support analog triggering for AO tasks, not directly at least.

 

I don't know the Python API into DAQmx, but I can offer up a few ideas.

 

- see this thread where I helped talk through an *indirect* method to provide analog triggering for AO.  All the code parts are LabVIEW though.

 

- if some kind of analog start condition is a key to this app, you need to (try to) configure the AI task for analog triggering

 

- the timing config looks a little confused with the read and write tasks configured to use each other's sample clocks.  This strikes me as a circular definition where both tasks will get stuck waiting for the other to generate its sample clock, but neither one can because they're both stuck waiting for the other task to start.

 

- similarly, the internal signal '/cDAQ1/ai/StartTrigger' is a digital trigger signal *result* that asserts when the ai task's start trigger criteria are satisfied.  It isn't available for analog triggering evaluation.  Plus, the AO task can't (directly) use an analog trigger anyway.

    It *would* be feasible to configure that signal as a *digital* start trigger for the AO task.  But you'll also have to resolve the circularly defined timing config.

 

- finally, since you seem to want AI and AO to sample at the same rate and start at the same time, there's a simpler overall approach.

  • on closer inspection, and I'm not a Python guy, it looks like maybe you commented out the source assignment in the timing config for both tasks.  Good!  I'll assume for now that the syntax works and that DAQmx use its default source (an internal timebase) to derive the sample clocks. 
  • you should set up the AI task for analog triggering not AO, assuming your device supports it.  The trigger source should be one of the analog channels in the task, or, possibly (for some devices) a special analog triggering input.
  • AO could still be configured to be *digitally* triggered by '/cDAQ1/ai/StartTrigger'
  • you should then write data to the AO task and start it
  • after that you should start the AI task before trying to read from it.
  • The order of starts matters!  Because the AO task will be waiting for an internal trigger signal from the AI task, it's important to start the AO task first so it won't *miss* the moment when the AI task's triggering condition is satisfied.

 

-Kevin P

0 Kudos
Message 2 of 4
(152 Views)
Highlighted
import nidaqmx
import numpy as np
import matplotlib.pyplot as plt
import time
from nidaqmx import constants
from nidaqmx.constants import Edge, Slope
from nidaqmx.stream_readers import AnalogMultiChannelReader
from nidaqmx.stream_writers import AnalogMultiChannelWriter
from nidaqmx.stream_readers import AnalogSingleChannelReader

outputX=np.linspace(10,-10,25000)
outputY=np.linspace(5,-10,25000)
X=np.zeros(25000)

outputData = np.append(outputX,outputY)
outputData=np.append(outputData,outputY)
outputData = outputData.reshape((3,len(outputX)))


inputData=np.zeros(25000*3)
inputData = inputData.reshape((3,25000))
#outputData = np.transpose(outputData)
print(outputData.shape)
print(inputData.shape)

#ao_chan_x=t1.ao_channels.add_ao_voltage_chan("cDAQ1Mod1/ao0")
#ao_chan_y=t1.ao_channels.add_ao_voltage_chan("cDAQ1Mod1/ao1")
#outputChannels = ao_chan_x + "," + ao_chan_y


writingrate1=25000

#while True:
with nidaqmx.Task() as writeTask, nidaqmx.Task() as readTask:
writeTask.ao_channels.add_ao_voltage_chan('cDAQ1Mod1/ao0:2')
readTask.ai_channels.add_ai_voltage_chan('cDAQ1Mod4/ai0:2')

writeTask.timing.cfg_samp_clk_timing(rate=writingrate1,
#source='/cDAQ1/ai/SampleClock',
sample_mode=nidaqmx.constants.AcquisitionType.FINITE, # dont use continuous
samps_per_chan=X.size)

readTask.timing.cfg_samp_clk_timing(rate=writingrate1,
#source='/cDAQ1/ao/SampleClock',
active_edge=nidaqmx.constants.Edge.RISING,
sample_mode=nidaqmx.constants.AcquisitionType.FINITE,
samps_per_chan=X.size)
#readTask.triggers.start_trigger.cfg_anlg_edge_start_trig(trigger_source='Voltage')
writeTask.triggers.start_trigger.cfg_dig_edge_start_trig( trigger_source='/cDAQ1/ai/StartTrigger') # Setting the trigger on the analog input



reader = AnalogMultiChannelReader(readTask.in_stream)
writer = AnalogMultiChannelWriter(writeTask.out_stream)

print("The channels linked to WriteTask are: ")
for i in writeTask.ao_channels:
print(i)


writer.write_many_sample(outputData)
writeTask.start()


readTask.start()
reader.read_many_sample(inputData)





#reader.read_many_sample(inputData)
#readTask.start()

#writeTask.start()

writeTask.wait_until_done()
readTask.wait_until_done()

#readTask.start()

print("Done with data")
#print(inputData)

#x=np.linspace(0,25000,25000)
plt.plot(inputData[0])
plt.show()



Hi Kevin,

 

Thanks a lot for your prompt reply.

I do can run the codes without any error following your valuable suggestions. However, when I directly connected the ai and ao channels, the reading data from ai doesn't match the writing data in ao. With NImx software, I can get the reading and writing simultaneously. I believe there is still some delay between reading and writing. Now I am using NI9264 (ao) and NI9205 (ai) incorporated in NI cDAQ9174. You are right that the ai has analog triggering while ao doesn't. 

for the analog triggering of ai, i use the code: 

readTask.triggers.start_trigger.cfg_anlg_edge_start_trig(trigger_source='Voltage')

 and it gives me an error:nidaqmx.errors.DaqError:

An attempt has been made to use an invalid analog trigger source.
Ensure that the trigger source you specify matches the name of the virtual channel in the task or matches the name of a non-scannable terminal that the device can use as an analog trigger source.
Property: DAQmx_AnlgEdge_StartTrig_Src
Corresponding Value: Voltage
Valid Choices: cDAQ1Mod4/ai0
Device: cDAQ1
Task Name: _unnamedTask<1>
Status Code: -200265

 

 
 

Here is the triggering setting of ai:

Capture1.PNG

 

and  here is the ao 

Capture2.PNG

And I believe ai and ao use the same sample clock which I don't need to set it up manually, isn't it?

 

Thanks!

Ho

0 Kudos
Message 3 of 4
(145 Views)
Highlighted

The trigger error message is telling you that you need to identify a physical AI channel on the device as the analog trigger source, namely "cDAQ1Mod4/ai0"

 

AO and AI don't quite exactly use the same sample clock, but they both derive their sample clocks from a common master timebase.  To share the same sample clock you should UN-comment the part of the timing config for the AO task where it used to designate:

source='/cDAQ1/ai/SampleClock'

 

One difference is that the AI task's sample clock signal won't start pulsing until after the AI task has started acquisition.  In this case, that won't be until after the analog triggering conditions have been met.   When you configure this way, you won't need the AO task to be triggered any more.  The shared sample clock alone will accomplish the same thing timing-wise.

 

 

-Kevin P

0 Kudos
Message 4 of 4
(118 Views)