06-07-2022 07:34 AM - edited 06-07-2022 07:41 AM
Hello everyone
I'm a new user of NI boards and am a bit lost with a dual stream_writers problem that I can't seem to find a solution to.
I'm trying to use a NI 6229 card with 2 x BNC-2090A (or even a single one) to send periodic simultaneous TTL pulses. One TTL pulse controls a speaker (plays sound waves) the other opens a port for a water release valve.
Independently, these two tasks are easy to do using the
nidaqmx.stream_writers.AnalogSingleChannelWriter()
function and these individual commands:
water_Writer.write_one_sample(5)
audio_Writer.write_many_sample(tone)
But when I run them in series (i.e. without closing the first one), I get this error when the second task tries to write:
DaqWriteError: The specified resource is reserved. The operation could not be completed as specified. Task Name: _unnamedTask<4>
I've added a 2nd BNC-2090A breakout board (see ao2 above) and I get the same error. I do have a 2nd 6229 card - but! my computer doesn't have any more slots to insert it into.
Should I not be using the stream-writers function to write TTL output?
Any advice is much appreciate! As I said, I'm quite new at NI + python configuration and a bit lost.
Thanks so much,
Catalin
Here's the entirety of my code, including a function that converts frequency values to oscillations playable via TTL pulse:
########################################################
#################### HYBRID RUN ########################
########################################################
def make_tone(f, amp, duration):
fs = 200000 # 200kHz (Sample Rate)
T = 1/f
Ts = 1/fs
x = np.arange(int(fs*duration))
y = [ amp*np.sin(2*np.pi*f * (i/fs)) for i in x]
y_new = np.tile(y,1)
return y_new
#
import nidaqmx
# Initialize speaker task;
audio_Task = nidaqmx.Task()
#
audio_Task.ao_channels.add_ao_voltage_chan('Dev3/ao0')
audio_Task.timing.cfg_samp_clk_timing(rate = 200000,
sample_mode=nidaqmx.constants.AcquisitionType.CONTINUOUS)
#
audio_Writer = nidaqmx.stream_writers.AnalogSingleChannelWriter(audio_Task.out_stream,
auto_start=True)
# Initialize water task
water_Task = nidaqmx.Task()
water_Task.ao_channels.add_ao_voltage_chan('Dev3/ao2')
water_Task.timing.cfg_samp_clk_timing(rate = 200000,
sample_mode=nidaqmx.constants.AcquisitionType.CONTINUOUS)
#
water_Writer = nidaqmx.stream_writers.AnalogSingleChannelWriter(water_Task.out_stream,
auto_start=True)
####################################################
# realtime streaming with callback
amp = 0.003 # tone amplitude in ?
duration = 0.1 # tone duration in seconds;
ctr=0
freq = 1000
tone = make_tone(freq, amp, duration)
#
duration = 50000 # time in 100000Hz time base (?)
for k in range(25):
for p in range(duration):
water_Writer.write_one_sample(5)
audio_Writer.write_many_sample(tone)
#
water_Task.stop()
water_Task.close()
audio_Task.stop()
audio_Task.close()
C:\Users\rg-fd02-user\anaconda3\envs\bmi\lib\site-packages\nidaqmx\task.py:98: ResourceWarning: Task of name "_unnamedTask<1>" was not explicitly closed before it was destructed. Resources on the task device may still be reserved. warnings.warn( C:\Users\rg-fd02-user\anaconda3\envs\bmi\lib\site-packages\nidaqmx\task.py:98: ResourceWarning: Task of name "_unnamedTask<2>" was not explicitly closed before it was destructed. Resources on the task device may still be reserved. warnings.warn( C:\Users\rg-fd02-user\anaconda3\envs\bmi\lib\site-packages\nidaqmx\task.py:98: ResourceWarning: Task of name "_unnamedTask<3>" was not explicitly closed before it was destructed. Resources on the task device may still be reserved. warnings.warn(
--------------------------------------------------------------------------- DaqWriteError Traceback (most recent call last) Input In [6], in <cell line: 47>() 49 for p in range(duration): 50 water_Writer.write_one_sample(5) ---> 51 audio_Writer.write_many_sample(tone) 53 # pause and give 0 pluse 54 for q in range(100000-duration): File ~\anaconda3\envs\bmi\lib\site-packages\nidaqmx\stream_writers.py:234, in AnalogSingleChannelWriter.write_many_sample(self, data, timeout) 229 self._verify_array(data, False, True) 231 auto_start = (self._auto_start if self._auto_start is not 232 AUTO_START_UNSET else False) --> 234 return _write_analog_f_64( 235 self._handle, data, data.shape[0], auto_start, timeout) File ~\anaconda3\envs\bmi\lib\site-packages\nidaqmx\_task_modules\write_functions.py:28, in _write_analog_f_64(task_handle, write_array, num_samps_per_chan, auto_start, timeout, data_layout) 18 cfunc.argtypes = [ 19 lib_importer.task_handle, ctypes.c_int, c_bool32, 20 ctypes.c_double, ctypes.c_int, 21 wrapped_ndpointer(dtype=numpy.float64, flags=('C')), 22 ctypes.POINTER(ctypes.c_int), ctypes.POINTER(c_bool32)] 24 error_code = cfunc( 25 task_handle, num_samps_per_chan, auto_start, timeout, 26 data_layout.value, write_array, 27 ctypes.byref(samps_per_chan_written), None) ---> 28 check_for_error(error_code, samps_per_chan_written=samps_per_chan_written.value) 30 return samps_per_chan_written.value File ~\anaconda3\envs\bmi\lib\site-packages\nidaqmx\errors.py:191, in check_for_error(error_code, samps_per_chan_written, samps_per_chan_read) 189 raise DaqReadError(error_buffer.value.decode("utf-8"), error_code, samps_per_chan_read) 190 elif samps_per_chan_written is not None: --> 191 raise DaqWriteError(error_buffer.value.decode("utf-8"), error_code, samps_per_chan_written) 192 else: 193 raise DaqError(error_buffer.value.decode("utf-8"), error_code) DaqWriteError: The specified resource is reserved. The operation could not be completed as specified. Task Name: _unnamedTask<4> Status Code: -50103
Solved! Go to Solution.
06-07-2022 08:02 AM
You said:
One TTL pulse controls a speaker (plays sound waves)
No. TTL pulses != sound waves. However the code is more correct than the description -- you've correctly used an analog output task to generate your sound waveform.
You get errors b/c the 2 tasks are contending for the same hardware resource -- access to the D/A converter. You can resolve this by using a Digital output task to generate a TTL signal to control the water release valve. Note: the DAQ device won't source enough current to operate a valve directly, you need the low-current TTL logic signal to drive something capable of sourcing more current. This might be your valve controller, it could be a simple low-current-demand relay.
-Kevin P
06-08-2022 12:07 AM
Oh, great, thanks so much for the quick reply. So
1. I can't really use 2 streamwriters to output to the same analog channel.
2. Re: "Digital output task to generate a TTL signal to control the water release valve." I can handle the pull up to 5V (probably through an arduino or teensy), butI don't understand how to do create the "digital" output. Should I initialize the analog port (ao2 in my case) as a digital output channel? How do I do that exactly? There are no "digital" channels on the BNC 2090A as far as I can see...
Thanks so much.
06-08-2022 08:21 AM
The BNC 2090A has spring terminals for digital i/o. See pages 2-6 & 2-7 in the manual.
-Kevin P