ni / nidaqmx-python

A Python API for interacting with NI-DAQmx
Other
413 stars 155 forks source link

Raw read/write methods fail when input/output range varies by channel #580

Open bkeryan opened 2 months ago

bkeryan commented 2 months ago

Calling task.in_stream.read() with different input/output ranges for each channel returns an error.

Steps to reproduce:

import nidaqmx

with nidaqmx.Task() as task:
    task.ai_channels.add_ai_voltage_chan("Dev1/ai0", min_val=-1.0, max_val=1.0)
    task.ai_channels.add_ai_voltage_chan("Dev1/ai1:3", min_val=-10.0, max_val=10.0)

    data = task.in_stream.read(number_of_samples_per_channel=1)
    print(data)

Expected result: it prints the raw data.

Actual result:

Traceback (most recent call last):
  File "D:\dev\nidaqmx-python\examples\analog_in\ai_raw.py", line 7, in <module>
    data = task.in_stream.read(number_of_samples_per_channel=1)
  File "D:\dev\nidaqmx-python\generated\nidaqmx\task\_in_stream.py", line 1086, in read
    has_negative_range = channels_to_read.ai_rng_low < 0
  File "D:\dev\nidaqmx-python\generated\nidaqmx\task\channels\_ai_channel.py", line 2596, in ai_rng_low
    val = self._interpreter.get_chan_attribute_double(self._handle, self._name, 0x1816)
  File "D:\dev\nidaqmx-python\generated\nidaqmx\_library_interpreter.py", line 2483, in get_chan_attribute_double
    self.check_for_error(error_code)
  File "D:\dev\nidaqmx-python\generated\nidaqmx\_library_interpreter.py", line 6412, in check_for_error
    raise DaqError(extended_error_info, error_code)
nidaqmx.errors.DaqError: Attempt to get property failed, because you specified multiple channels, and the property has different values for different channels.
Get this property one channel at a time.

Property: DAQmx_AI_Rng_Low

Task Name: _unnamedTask<0>

Status Code: -200657

Workaround: set task.ai_channels.all.ai_rng_high/low or task.ao_channels.all.ao_dac_rng_high/low.

zhindes commented 2 months ago

I don't think the first bit of code there works either if you have multi-device tasks. Fun fun!

        samp_size_in_bits = channels_to_read.ai_raw_samp_size
        has_negative_range = channels_to_read.ai_rng_low < 0
bkeryan commented 2 months ago

This also affects read_into. That function doesn't have a number_of_samples_per_channel parameter, so it tries to infer the number of samples per channel based on the ndarray size in bytes and the number of channels to read.

Perhaps read and read_all should have a dtype parameter and read_into should have a number_of_samples_per_channel parameter.