Read Functions

HIL.task_create_analog_reader(samples_in_buffer, channels, num_channels)

Creates a task for reading from the specified analog input channels. The task allows other operations to be performed while the analog inputs are being read “in the background”. The data is read into an internal circular “task buffer” from which it can be read at any time using the task_read_analog function. The size of this task buffer is determined by the samples_in_buffer parameter.

The task does not actually start reading from the analog inputs until the task_start function is called. The task must be deleted when it is no longer in use using the task_delete function, in order to free the system and hardware resources used by the task.

Parameters
  • samples_in_buffer (int) – The number of samples in the task buffer. The task_read_analog function cannot read more samples than this in a single call. If the task buffer overflows because task_read_analog has not been called in time to remove the data from the task buffer, then the next call to task_read_analog will return a HIL_BUFFER_OVERFLOW error.

  • channels (array_like) – An array containing the channel numbers of the analog inputs to be read by the task.

  • num_channels (int) – The number of channels specified in the channels array.

Returns

A handle to the created task.

Return type

handle

Raises

HILError – On non-zero return code. A suitable error message may be retrieved using get_error_message.

Examples

Create a task to read from the first four analog input channels.

Using array:

>>> from array import array
>>> from quanser.hardware import HIL
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   samples_in_buffer = 1000
>>>   channels = array('I', [0, 1, 2, 3])
>>>   num_channels = len(channels)
>>>   card.task_create_analog_reader(samples_in_buffer, channels, num_channels)
>>>   # ...
...
>>> finally:
>>>   card.close()

Using numpy:

>>> import numpy as np
>>> from quanser.hardware import HIL
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   samples_in_buffer = 1000
>>>   channels = np.array([0, 1, 2, 3], dtype=np.uint32)
>>>   num_channels = len(channels)
>>>   card.task_create_analog_reader(samples_in_buffer, channels, num_channels)
>>>   # ...
...
>>> finally:
>>>   card.close()
HIL.task_create_encoder_reader(samples_in_buffer, channels, num_channels)

Creates a task for reading from the specified encoder input channels. The task allows other operations to be performed while the encoder inputs are being read “in the background”. The data is read into an internal circular “task buffer” from which it can be read at any time using the task_read_encoder function. The size of this task buffer is determined by the samples_in_buffer parameter.

The task does not actually start reading from the encoder inputs until the task_start function is called. The task must be deleted when it is no longer in use using the task_delete function, in order to free the system and hardware resources used by the task.

Parameters
  • samples_in_buffer (int) – The number of samples in the task buffer. The task_read_encoder function cannot read more samples than this in a single call. If the task buffer overflows because task_read_encoder has not been called in time to remove the data from the task buffer, then the next call to task_read_encoder will return a HIL_BUFFER_OVERFLOW error.

  • channels (array_like) – An array containing the channel numbers of the encoder inputs to be read by the task.

  • num_channels (int) – The number of channels specified in the channels array.

Returns

A handle to the created task.

Return type

handle

Raises

HILError – On non-zero return code. A suitable error message may be retrieved using get_error_message.

Examples

Create a task to read from the first four encoder input channels.

Using array:

>>> from array import array
>>> from quanser.hardware import HIL
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   samples_in_buffer = 1000
>>>   channels = array('I', [0, 1, 2, 3])
>>>   num_channels = len(channels)
>>>   card.task_create_encoder_reader(samples_in_buffer, channels, num_channels)
>>>   # ...
...
>>> finally:
>>>   card.close()

Using numpy:

>>> import numpy as np
>>> from quanser.hardware import HIL
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   samples_in_buffer = 1000
>>>   channels = np.array([0, 1, 2, 3], dtype=np.uint32)
>>>   num_channels = len(channels)
>>>   card.task_create_encoder_reader(samples_in_buffer, channels, num_channels)
>>>   # ...
...
>>> finally:
>>>   card.close()
HIL.task_create_digital_reader(samples_in_buffer, channels, num_channels)

Creates a task for reading from the specified digital input channels. The task allows other operations to be performed while the digital inputs are being read “in the background”. The data is read into an internal circular “task buffer” from which it can be read at any time using the hil_task_read_digital function. The size of this task buffer is determined by the samples_in_buffer parameter.

The task does not actually start reading from the digital inputs until the task_start function is called. Before starting the task, the directions of the digital I/O lines should be set using the set_digital_directions function. The task must be deleted when it is no longer in use using the task_delete function, in order to free the system and hardware resources used by the task.

Parameters
  • samples_in_buffer (int) – The number of samples in the task buffer. The task_read_digital function cannot read more samples than this in a single call. If the task buffer overflows because task_read_digital has not been called in time to remove the data from the task buffer, then the next call to task_read_digital will return a HIL_BUFFER_OVERFLOW error.

  • channels (array_like) – An array containing the channel numbers of the digital inputs to be read by the task.

  • num_channels (int) – The number of channels specified in the channels array.

Returns

A handle to the created task.

Return type

handle

Raises

HILError – On non-zero return code. A suitable error message may be retrieved using get_error_message.

Warning

Many cards allow the digital I/O lines to be programmed as inputs or outputs. The digital I/O lines are configured as inputs or outputs using the set_digital_directions function. All the channels which will be used as digital inputs or outputs must be configured accordingly using this function. Failure to configure the digital I/O may result in the task_read_digital function failing to read or write the digital I/O as expected.

Examples

Create a task to read from the first four digital input channels.

Using array:

>>> from array import array
>>> from quanser.hardware import HIL
>>> card = HIL("q8_usb", "0")
>>>  try:
>>>   samples_in_buffer = 1000
>>>   channels = array('I', [0, 1, 2, 3])
>>>   num_channels = len(channels)
>>>   card.task_create_digital_reader(samples_in_buffer, channels, num_channels)
>>>   # ...
...
>>> finally:
>>>   card.close()

Using numpy:

>>> import numpy as np
>>> from quanser.hardware import HIL
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   samples_in_buffer = 1000
>>>   channels = np.array([0, 1, 2, 3], dtype=np.uint32)
>>>   num_channels = len(channels)
>>>   card.task_create_digital_reader(samples_in_buffer, channels, num_channels)
>>>   # ...
...
>>> finally:
>>>   card.close()
HIL.task_create_other_reader(samples_in_buffer, channels, num_channels)

Creates a task for reading from the specified other input channels. The task allows other operations to be performed while the other inputs are being read “in the background”. The data is read into an internal circular “task buffer” from which it can be read at any time using the task_read_other function. The size of this task buffer is determined by the samples_in_buffer parameter.

The task does not actually start reading from the other inputs until the task_start function is called. The task must be deleted when it is no longer in use using the task_delete function, in order to free the system and hardware resources used by the task.

Parameters
  • samples_in_buffer (int) – The number of samples in the task buffer. The task_read_other function cannot read more samples than this in a single call. If the task buffer overflows because task_read_other has not been called in time to remove the data from the task buffer, then the next call to task_read_other will return a HIL_BUFFER_OVERFLOW error.

  • channels (array_like) – An array containing the channel numbers of the other inputs to be read by the task.

  • num_channels (int) – The number of channels specified in the channels array.

Returns

A handle to the created task.

Return type

handle

Raises

HILError – On non-zero return code. A suitable error message may be retrieved using get_error_message.

Examples

Create a task to read from the first two other input channels.

Using array:

>>> from array import array
>>> from quanser.hardware import HIL
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   samples_in_buffer = 1000
>>>   channels = array('I', [0, 1])
>>>   num_channels = len(channels)
>>>   card.task_create_other_reader(samples_in_buffer, channels, num_channels)
>>>   # ...
...
>>> finally:
>>>   card.close()

Using numpy:

>>> import numpy as np
>>> from quanser.hardware import HIL
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   samples_in_buffer = 1000
>>>   channels = np.array([0, 1], dtype=np.uint32)
>>>   num_channels = len(channels)
>>>   card.task_create_other_reader(samples_in_buffer, channels, num_channels)
>>>   # ...
...
>>> finally:
>>>   card.close()
HIL.task_create_reader(samples_in_buffer, analog_channels, num_analog_channels, encoder_channels, num_encoder_channels, digital_channels, num_digital_channels, other_channels, num_other_channels)

Creates a task for reading from the specified input channels. The task allows other operations to be performed while the inputs are being read “in the background”. The data is read into an internal circular “task buffer” from which it can be read at any time using the task_read function. The size of this task buffer is determined by the samples_in_buffer parameter.

The task does not actually start reading from the inputs until the task_start function is called. Before starting the task, the directions of the digital I/O lines should be set using the set_digital_directions function. The task must be deleted when it is no longer in use using the task_delete function, in order to free the system and hardware resources used by the task.

Parameters
  • samples_in_buffer (int) – The number of samples in the task buffer. The task_read function cannot read more samples than this in a single call. If the task buffer overflows because task_read has not been called in time to remove the data from the task buffer, then the next call to task_read will return a HIL_BUFFER_OVERFLOW error.

  • analog_channels (array_like or None) – An array containing the channel numbers of the analog inputs to be read by the task. If no analog channels are required, then this parameter may be None. In this case, num_analog_channels must be zero.

  • num_analog_channels (int) – The number of channels specified in the analog_channels array.

  • encoder_channels (array_like or None) – An array containing the channel numbers of the encoder inputs to be read by the task. If no encoder channels are required, then this parameter may be None. In this case, num_encoder_channels must be zero.

  • num_encoder_channels (int) – The number of channels specified in the encoder_channels array.

  • digital_channels (array_like or None) – An array containing the channel numbers of the digital inputs to be read by the task. If no digital channels are required, then this parameter may be None. In this case, num_digital_channels must be zero.

  • num_digital_channels (int) – The number of channels specified in the digital_channels array.

  • other_channels (array_like or None) – An array containing the channel numbers of the other inputs to be read by the task. If no other channels are required, then this parameter may be None. In this case, num_other_channels must be zero.

  • num_other_channels (int) – The number of channels specified in the other_channels array.

Returns

A handle to the created task.

Return type

handle

Raises

HILError – On non-zero return code. A suitable error message may be retrieved using get_error_message.

Warning

Many cards allow the digital I/O lines to be programmed as inputs or outputs. The digital I/O lines are configured as inputs or outputs using the set_digital_directions function. All the channels which will be used as digital inputs or outputs must be configured accordingly using this function. Failure to configure the digital I/O may result in the task_read function failing to read or write the digital I/O as expected.

Examples

Create a task to read from the first four analog input channels and the first two encoder input channels.

Using array:

>>> from array import array
>>> from quanser.hardware import HIL
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   samples_in_buffer = 1000
>>>   analog_channels = array('I', [0, 1, 2, 3])
>>>   encoder_channels = array('I', [0, 1])
>>>   num_analog_channels = len(analog_channels)
>>>   num_encoder_channels = len(encoder_channels)
>>>   card.task_create_reader(samples_in_buffer,
...                           analog_channels, num_analog_channels
...                           encoder_channels, num_encoder_channels,
...                           None, 0,
...                           None, 0)
>>>   # ...
...
>>> finally:
>>>   card.close()

Using numpy:

>>> import numpy as np
>>> from quanser.hardware import HIL
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   samples_in_buffer = 1000
>>>   analog_channels = np.array([0, 1, 2, 3], dtype=np.uint32)
>>>   encoder_channels = np.array([0, 1], dtype=np.uint32)
>>>   num_analog_channels = len(analog_channels)
>>>   num_encoder_channels = len(encoder_channels)
>>>   card.task_create_reader(samples_in_buffer,
...                           analog_channels, num_analog_channels
...                           encoder_channels, num_encoder_channels,
...                           None, 0,
...                           None, 0)
>>>   # ...
...
>>> finally:
>>>   card.close()
HIL.task_read_analog(task, num_samples, buffer)

Reads the specified number of samples from the task buffer of a task created using task_create_analog_reader. If there’s not enough samples in the task buffer, then this function will block until the requested number of samples becomes available or the task stops. Since the task reads the hardware at the sampling rate specified in the call to task_start, and stores the data in the task buffer, this function will never block for longer than the requested number of samples times the sampling period.

Because this function blocks until enough data is available and the task buffer is filled at a given sampling rate, calling this function synchronizes the caller to that sampling rate (provided the task buffer is not being filled faster than we can read the data). Thus, the task_read_analog function may be used to implement control systems, system identification, synchronous data streaming, and other operations requiring a fixed sampling rate. For control systems, the num_samples parameter is typically 1, since control calculations need to be performed on each sample. For data streaming, the num_samples parameter is typically half the number of samples in the task buffer to implement double-buffering.

Parameters
  • task (handle) – A handle to the task, as returned by one of the task creation functions.

  • num_samples (int) – The number of samples to read from the task buffer. Each “sample” consists of all the analog input channels specified when the task was created using task_create_analog_reader. For example, if num_samples is 5 and the task is configured to read 3 channels, then the output buffer will contain 15 elements.

  • buffer (array_like) – An array for receiving the voltage values read from the analog inputs. The array must contain num_channels * num_samples elements, where num_channels is the number of channels specified when the task was created. The array is organized as a linear array of samples, with each sample consisting of a group of channels. For example, if analog input channels 0, 1 and 3 are being read, then the data appears in the array as follows, where the numbers correspond to channel numbers: [0, 1, 3, 0, 1, 3, …].

Returns

The number of samples read from the task buffer. This value may be less than the requested number of samples (including 0) if the task is stopped or has finished processing the total number of samples indicated in the call to task_start.

Return type

int

Raises

HILError – On non-zero return code. A suitable error message may be retrieved using get_error_message.

Examples

Reads 5000 samples at 1 kHz from the first four analog input channels, using SYSTEM_CLOCK_1.

Using array:

>>> from array import array
>>> from quanser.hardware import HIL, Clock
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   channels = array('I', [0, 1, 2, 3])
>>>   num_channels = len(channels)
>>>   frequency = 1000.0
>>>   samples = 5000
>>>   samples_in_buffer = int(frequency)
>>>   samples_to_read = 1
>>>   buffer = array('d', [0.0] * num_channels)
>>>   task = card.task_create_analog_reader(samples_in_buffer, channels, num_channels)
>>>   card.task_start(task, Clock.SYSTEM_CLOCK_1, frequency, samples)
>>>   for index in range(samples):
>>>     card.task_read_analog(task, samples_to_read, buffer)
>>>     # ...
...
>>>   card.task_stop(task)
>>>   card.task_delete(task)
>>> finally:
>>>   card.close()

Using numpy:

>>> import numpy as np
>>> from quanser.hardware import HIL, Clock
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   channels = np.array([0, 1, 2, 3], dtype=np.uint32)
>>>   num_channels = len(channels)
>>>   frequency = 1000.0
>>>   samples = 5000
>>>   samples_in_buffer = int(frequency)
>>>   samples_to_read = 1
>>>   buffer = np.zeros(num_channels, dtype=np.float64)
>>>   task = card.task_create_analog_reader(samples_in_buffer, channels, num_channels)
>>>   card.task_start(task, Clock.SYSTEM_CLOCK_1, frequency, samples)
>>>   for index in range(samples):
>>>     card.task_read_analog(task, samples_to_read, buffer)
>>>     # ...
...
>>>   card.task_stop(task)
>>>   card.task_delete(task)
>>> finally:
>>>   card.close()
HIL.task_read_encoder(task, num_samples, buffer)

Reads the specified number of samples from the task buffer of a task created using task_create_encoder_reader. If there’s not enough samples in the task buffer, then this function will block until the requested number of samples becomes available or the task stops. Since the task reads the hardware at the sampling rate specified in the call to task_start, and stores the data in the task buffer, this function will never block for longer than the requested number of samples times the sampling period.

Because this function blocks until enough data is available and the task buffer is filled at a given sampling rate, calling this function synchronizes the caller to that sampling rate (provided the task buffer is not being filled faster than we can read the data). Thus, the task_read_encoder function may be used to implement control systems, system identification, synchronous data streaming, and other operations requiring a fixed sampling rate. For control systems, the num_samples parameter is typically 1, since control calculations need to be performed on each sample. For data streaming, the num_samples parameter is typically half the number of samples in the task buffer to implement double-buffering.

Parameters
  • task (handle) – A handle to the task, as returned by one of the task creation functions.

  • num_samples (int) – The number of samples to read from the task buffer. Each “sample” consists of all the encoder input channels specified when the task was created using task_create_encoder_reader. For example, if num_samples is 5 and the task is configured to read 3 channels, then the output buffer will contain 15 elements.

  • buffer (array_like) – An array for receiving the count values read from the encoder inputs. The array must contain num_channels * num_samples elements, where num_channels is the number of channels specified when the task was created. The array is organized as a linear array of samples, with each sample consisting of a group of channels. For example, if encoder input channels 0, 1 and 3 are being read, then the data appears in the array as follows, where the numbers correspond to channel numbers: [0, 1, 3, 0, 1, 3, …].

Returns

The number of samples read from the task buffer. This value may be less than the requested number of samples (including 0) if the task is stopped or has finished processing the total number of samples indicated in the call to task_start.

Return type

int

Raises

HILError – On non-zero return code. A suitable error message may be retrieved using get_error_message.

Examples

Reads 5000 samples at 1 kHz from the first four encoder input channels, using SYSTEM_CLOCK_1.

Using array:

>>> from array import array
>>> from quanser.hardware import HIL, Clock
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   channels = array('I', [0, 1, 2, 3])
>>>   num_channels = len(channels)
>>>   frequency = 1000.0
>>>   samples = 5000
>>>   samples_in_buffer = int(frequency)
>>>   samples_to_read = 1
>>>   buffer = array('i', [0] * num_channels)
>>>   task = card.task_create_encoder_reader(samples_in_buffer, channels, num_channels)
>>>   card.task_start(task, Clock.SYSTEM_CLOCK_1, frequency, samples)
>>>   for index in range(samples):
>>>     card.task_read_encoder(task, samples_to_read, buffer)
>>>     # ...
...
>>>   card.task_stop(task)
>>>   card.task_delete(task)
>>> finally:
>>>   card.close()

Using numpy:

>>> import numpy as np
>>> from quanser.hardware import HIL, Clock
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   channels = np.array([0, 1, 2, 3], dtype=np.uint32)
>>>   num_channels = len(channels)
>>>   frequency = 1000.0
>>>   samples = 5000
>>>   samples_in_buffer = int(frequency)
>>>   samples_to_read = 1
>>>   buffer = np.zeros(num_channels, dtype=np.int32)
>>>   task = card.task_create_encoder_reader(samples_in_buffer, channels, num_channels)
>>>   card.task_start(task, Clock.SYSTEM_CLOCK_1, frequency, samples)
>>>   for index in range(samples):
>>>     card.task_read_encoder(task, samples_to_read, buffer)
>>>     # ...
...
>>>   card.task_stop(task)
>>>   card.task_delete(task)
>>> finally:
>>>   card.close()
HIL.task_read_digital(task, num_samples, buffer)

Reads the specified number of samples from the task buffer of a task created using task_create_digital_reader. If there’s not enough samples in the task buffer, then this function will block until the requested number of samples becomes available or the task stops. Since the task reads the hardware at the sampling rate specified in the call to task_start, and stores the data in the task buffer, this function will never block for longer than the requested number of samples times the sampling period.

Because this function blocks until enough data is available and the task buffer is filled at a given sampling rate, calling this function synchronizes the caller to that sampling rate (provided the task buffer is not being filled faster than we can read the data). Thus, the task_read_digital function may be used to implement control systems, system identification, synchronous data streaming, and other operations requiring a fixed sampling rate. For control systems, the num_samples parameter is typically 1, since control calculations need to be performed on each sample. For data streaming, the num_samples parameter is typically half the number of samples in the task buffer to implement double-buffering.

Parameters
  • task (handle) – A handle to the task, as returned by one of the task creation functions.

  • num_samples (int) – The number of samples to read from the task buffer. Each “sample” consists of all the digital input channels specified when the task was created using task_create_digital_reader. For example, if num_samples is 5 and the task is configured to read 3 channels, then the output buffer will contain 15 elements.

  • buffer (array_like) – An array for receiving the values read from the digital inputs. The array must contain num_channels * num_samples elements, where num_channels is the number of channels specified when the task was created. The array is organized as a linear array of samples, with each sample consisting of a group of channels. For example, if digital input channels 0, 1 and 3 are being read, then the data appears in the array as follows, where the numbers correspond to channel numbers: [0, 1, 3, 0, 1, 3, …].

Returns

The number of samples read from the task buffer. This value may be less than the requested number of samples (including 0) if the task is stopped or has finished processing the total number of samples indicated in the call to task_start.

Return type

int

Raises

HILError – On non-zero return code. A suitable error message may be retrieved using get_error_message.

Warning

Many cards allow the digital I/O lines to be programmed as inputs or outputs. The digital I/O lines are configured as inputs or outputs using the set_digital_directions function. All the channels which will be used as digital inputs or outputs must be configured accordingly using this function. Failure to configure the digital I/O may result in the task_read_digital function failing to read or write the digital I/O as expected.

Examples

Reads 5000 samples at 1 kHz from the first four digital input channels, using SYSTEM_CLOCK_1.

Using array:

>>> from array import array
>>> from quanser.hardware import HIL, Clock
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   channels = array('I', [0, 1, 2, 3])
>>>   num_channels = len(channels)
>>>   frequency = 1000.0
>>>   samples = 5000
>>>   samples_in_buffer = int(frequency)
>>>   samples_to_read = 1
>>>   buffer = array('b', [0] * num_channels)
>>>   task = card.task_create_digital_reader(samples_in_buffer, channels, num_channels)
>>>   card.task_start(task, Clock.SYSTEM_CLOCK_1, frequency, samples)
>>>   for index in range(samples):
>>>     card.task_read_digital(task, samples_to_read, buffer)
>>>     # ...
...
>>>   card.task_stop(task)
>>>   card.task_delete(task)
>>> finally:
>>>   card.close()

Using numpy:

>>> import numpy as np
>>> from quanser.hardware import HIL, Clock
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   channels = np.array([0, 1, 2, 3], dtype=np.uint32)
>>>   num_channels = len(channels)
>>>   frequency = 1000.0
>>>   samples = 5000
>>>   samples_in_buffer = int(frequency)
>>>   samples_to_read = 1
>>>   buffer = np.zeros(num_channels, dtype=np.int8)
>>>   task = card.task_create_digital_reader(samples_in_buffer, channels, num_channels)
>>>   card.task_start(task, Clock.SYSTEM_CLOCK_1, frequency, samples)
>>>   for index in range(samples):
>>>     card.task_read_digital(task, samples_to_read, buffer)
>>>     # ...
...
>>>   card.task_stop(task)
>>>   card.task_delete(task)
>>> finally:
>>>   card.close()
HIL.task_read_other(task, num_samples, buffer)

Reads the specified number of samples from the task buffer of a task created using task_create_other_reader. If there’s not enough samples in the task buffer, then this function will block until the requested number of samples becomes available or the task stops. Since the task reads the hardware at the sampling rate specified in the call to task_start, and stores the data in the task buffer, this function will never block for longer than the requested number of samples times the sampling period.

Because this function blocks until enough data is available and the task buffer is filled at a given sampling rate, calling this function synchronizes the caller to that sampling rate (provided the task buffer is not being filled faster than we can read the data). Thus, the task_read_other function may be used to implement control systems, system identification, synchronous data streaming, and other operations requiring a fixed sampling rate. For control systems, the num_samples parameter is typically 1, since control calculations need to be performed on each sample. For data streaming, the num_samples parameter is typically half the number of samples in the task buffer to implement double-buffering.

Parameters
  • task (handle) – A handle to the task, as returned by one of the task creation functions.

  • num_samples (int) – The number of samples to read from the task buffer. Each “sample” consists of all the other input channels specified when the task was created using task_create_other_reader. For example, if num_samples is 5 and the task is configured to read 3 channels, then the output buffer will contain 15 elements.

  • buffer (array_like) – An array for receiving the values read from the other inputs. The array must contain num_channels * num_samples elements, where num_channels is the number of channels specified when the task was created. The array is organized as a linear array of samples, with each sample consisting of a group of channels. For example, if other input channels 0, 1 and 3 are being read, then the data appears in the array as follows, where the numbers correspond to channel numbers: [0, 1, 3, 0, 1, 3, …].

Returns

The number of samples read from the task buffer. This value may be less than the requested number of samples (including 0) if the task is stopped or has finished processing the total number of samples indicated in the call to task_start.

Return type

int

Raises

HILError – On non-zero return code. A suitable error message may be retrieved using get_error_message.

Examples

Reads 5000 samples at 1 kHz from the first two other input channels, using SYSTEM_CLOCK_1.

Using array:

>>> from array import array
>>> from quanser.hardware import HIL, Clock
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   channels = array('I', [0, 1])
>>>   num_channels = len(channels)
>>>   frequency = 1000.0
>>>   samples = 5000
>>>   samples_in_buffer = int(frequency)
>>>   samples_to_read = 1
>>>   buffer = array('d', [0.0] * num_channels)
>>>   task = card.task_create_other_reader(samples_in_buffer, channels, num_channels)
>>>   card.task_start(task, Clock.SYSTEM_CLOCK_1, frequency, samples)
>>>   for index in range(samples):
>>>     card.task_read_other(task, samples_to_read, buffer)
>>>     # ...
...
>>>   card.task_stop(task)
>>>   card.task_delete(task)
>>> finally:
>>>   card.close()

Using numpy:

>>> import numpy as np
>>> from quanser.hardware import HIL, Clock
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   channels = np.array([0, 1], dtype=np.uint32)
>>>   num_channels = len(channels)
>>>   frequency = 1000.0
>>>   samples = 5000
>>>   samples_in_buffer = int(frequency)
>>>   samples_to_read = 1
>>>   buffer = np.zeros(num_channels, dtype=np.float64)
>>>   task = card.task_create_other_reader(samples_in_buffer, channels, num_channels)
>>>   card.task_start(task, Clock.SYSTEM_CLOCK_1, frequency, samples)
>>>   for index in range(samples):
>>>     card.task_read_other(task, samples_to_read, buffer)
>>>     # ...
...
>>>   card.task_stop(task)
>>>   card.task_delete(task)
>>> finally:
>>>   card.close()
HIL.task_read(task, num_samples, analog_buffer, encoder_buffer, digital_buffer, other_buffer)

Reads the specified number of samples from the task buffer of a task created using task_create_reader. If there’s not enough samples in the task buffer, then this function will block until the requested number of samples becomes available or the task stops. Since the task reads the hardware at the sampling rate specified in the call to task_start, and stores the data in the task buffer, this function will never block for longer than the requested number of samples times the sampling period.

Because this function blocks until enough data is available and the task buffer is filled at a given sampling rate, calling this function synchronizes the caller to that sampling rate (provided the task buffer is not being filled faster than we can read the data). Thus, the task_read function may be used to implement control systems, system identification, synchronous data streaming, and other operations requiring a fixed sampling rate. For control systems, the num_samples parameter is typically 1, since control calculations need to be performed on each sample. For data streaming, the num_samples parameter is typically half the number of samples in the task buffer to implement double-buffering.

Parameters
  • task (handle) – A handle to the task, as returned by one of the task creation functions.

  • num_samples (int) – The number of samples to read from the task buffer. Each “sample” consists of all the input channels specified when the task was created using task_create_reader. For example, if num_samples is 5 and the task is configured to read 3 analog channels and 2 encoder channels, then the analog output buffer will contain 15 elements and the encoder output buffer will contain 10 elements.

  • analog_buffer (array_like) – An array for receiving the voltage values read from the analog inputs. The array must contain num_channels * num_samples elements, where num_channels is the number of channels specified when the task was created. The array is organized as a linear array of samples, with each sample consisting of a group of channels. For example, if analog input channels 0, 1 and 3 are being read, then the data appears in the array as follows, where the numbers correspond to channel numbers: [0, 1, 3, 0, 1, 3, …].

  • encoder_buffer (array_like) – An array for receiving the count values read from the encoder inputs. The array must contain num_channels * num_samples elements, where num_channels is the number of channels specified when the task was created. The array is organized as a linear array of samples, with each sample consisting of a group of channels. For example, if encoder input channels 0, 1 and 3 are being read, then the data appears in the array as follows, where the numbers correspond to channel numbers: [0, 1, 3, 0, 1, 3, …].

  • digital_buffer (array_like) – An array for receiving the values read from the digital inputs. The array must contain num_channels * num_samples elements, where num_channels is the number of channels specified when the task was created. The array is organized as a linear array of samples, with each sample consisting of a group of channels. For example, if digital input channels 0, 1 and 3 are being read, then the data appears in the array as follows, where the numbers correspond to channel numbers: [0, 1, 3, 0, 1, 3, …].

  • other_buffer (array_like) – An array for receiving the values read from the other inputs. The array must contain num_channels * num_samples elements, where num_channels is the number of channels specified when the task was created. The array is organized as a linear array of samples, with each sample consisting of a group of channels. For example, if other input channels 0, 1 and 3 are being read, then the data appears in the array as follows, where the numbers correspond to channel numbers: [0, 1, 3, 0, 1, 3, …].

Returns

The number of samples read from the task buffer. This value may be less than the requested number of samples (including 0) if the task is stopped or has finished processing the total number of samples indicated in the call to task_start.

Return type

int

Raises

HILError – On non-zero return code. A suitable error message may be retrieved using get_error_message.

Warning

Many cards allow the digital I/O lines to be programmed as inputs or outputs. The digital I/O lines are configured as inputs or outputs using the set_digital_directions function. All the channels which will be used as digital inputs or outputs must be configured accordingly using this function. Failure to configure the digital I/O may result in the task_read_digital function failing to read or write the digital I/O as expected.

Examples

Reads 5000 samples at 1 kHz from the first four analog input channels and the first two encoder input channels, using SYSTEM_CLOCK_1.

Using array:

>>> from array import array
>>> from quanser.hardware import HIL, Clock
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   analog_channels = array('I', [0, 1, 2, 3])
>>>   encoder_channels = array('I', [0, 1])
>>>   num_analog_channels = len(analog_channels)
>>>   num_encoder_channels = len(encoder_channels)
>>>   frequency = 1000.0
>>>   samples = 5000
>>>   samples_in_buffer = int(frequency)
>>>   samples_to_read = 1
>>>   analog_buffer = array('d', [0.0] * num_analog_channels)
>>>   encoder_buffer = array('i', [0] * num_encoder_channels)
>>>   task = card.task_create_reader(samples_in_buffer,
>>>                                  analog_channels, num_analog_channels,
>>>                                  encoder_channels, num_encoder_channels,
>>>                                  None, 0,
>>>                                  None, 0)
>>>   card.task_start(task, Clock.SYSTEM_CLOCK_1, frequency, samples)
>>>   for index in range(samples):
>>>      card.task_read(task, samples_to_read, analog_buffer, encoder_buffer, None, None)
>>>      # ...
...
>>>   card.task_stop(task)
>>>   card.task_delete(task)
>>> finally:
>>>   card.close()

Using numpy:

>>> import numpy as np
>>> from quanser.hardware import HIL, Clock
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   analog_channels = np.array([0, 1, 2, 3], dtype=np.uint32)
>>>   encoder_channels = np.array([0, 1], dtype=np.uint32)
>>>   num_analog_channels = len(analog_channels)
>>>   num_encoder_channels = len(encoder_channels)
>>>   frequency = 1000.0
>>>   samples = 5000
>>>   samples_in_buffer = int(frequency)
>>>   samples_to_read = 1
>>>   analog_buffer = np.zeros(num_analog_channels, dtype=np.float64)
>>>   encoder_buffer = np.zeros(num_encoder_channels, dtype=np.int32)
>>>   task = card.task_create_reader(samples_in_buffer,
>>>                                  analog_channels, num_analog_channels,
>>>                                  encoder_channels, num_encoder_channels,
>>>                                  None, 0,
>>>                                  None, 0)
>>>   card.task_start(task, Clock.SYSTEM_CLOCK_1, frequency, samples)
>>>   for index in range(samples):
>>>     card.task_read(task, samples_to_read, analog_buffer, encoder_buffer, None, None)
>>>     # ...
...
>>>   card.task_stop(task)
>>>   card.task_delete(task)
>>> finally:
>>>   card.close()