Writes the specified number of samples to the task buffer of a writer task.

Namespace:  Quanser.Hardware
Assembly:  Quanser.Hardware.Hil (in Quanser.Hardware.Hil.dll)

Syntax

Visual Basic (Declaration)
Function Write ( _
	numSamples As Integer, _
	analogBuffer As Double(), _
	pwmBuffer As Double(), _
	digitalBuffer As SByte(), _
	otherBuffer As Double() _
) As Integer
C#
int Write(
	int numSamples,
	double[] analogBuffer,
	double[] pwmBuffer,
	sbyte[] digitalBuffer,
	double[] otherBuffer
)
Visual C++
int Write(
	int numSamples, 
	array<double>^ analogBuffer, 
	array<double>^ pwmBuffer, 
	array<signed char>^ digitalBuffer, 
	array<double>^ otherBuffer
)
JavaScript
function write(numSamples, analogBuffer, pwmBuffer, digitalBuffer, otherBuffer);

Parameters

numSamples
Type: System..::.Int32
The number of samples to write to the task buffer. Each "sample" consists of all the output channels specified when the task was created using TaskCreateWriter(Int32, array<Int32>[]()[], array<Int32>[]()[], array<Int32>[]()[], array<Int32>[]()[]). For example, if numSamples is 5 and the task is configured to write three analog channels and two PWM channels, then the analog input buffer must contain at least 15 elements and the PWM input buffer must contain at least 10 elements.
analogBuffer
Type: array< System..::.Double >[]()[]

An array containing the voltage values to write to the analog outputs. The array must contain numAnalogChannels * numSamples elements, where numAnalogChannels 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 written, than the data must appear in the array as follows, where the numbers correspond to channel numbers:

0 1 3 0 1 3 ...

If no analog channels were specified in the call to TaskCreateWriter(Int32, array<Int32>[]()[], array<Int32>[]()[], array<Int32>[]()[], array<Int32>[]()[]) then this parameter may be set to NoDoubleBuffer or nullptr.

pwmBuffer
Type: array< System..::.Double >[]()[]

An array containing the values to write to the PWM outputs. How these values are interpreted depends on the PWM mode. The PWM mode is configured using the SetPwmMode(array<Int32>[]()[], array<Hil..::.PwmMode>[]()[]) method. The array must contain numPwmChannels * numSamples elements, where numPwmChannels 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 PWM input channels 0, 1 and 3 are being written, than the data must appear in the array as follows, where the numbers correspond to channel numbers:

0 1 3 0 1 3 ...

If no PWM channels were specified in the call to TaskCreateWriter(Int32, array<Int32>[]()[], array<Int32>[]()[], array<Int32>[]()[], array<Int32>[]()[]) then this parameter may be set to NoDoubleBuffer or nullptr.

digitalBuffer
Type: array< System..::.SByte >[]()[]

An array containing the state values to write to the digital outputs. The array must contain numDigitalChannels * numSamples elements, where numDigitalChannels 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 written, than the data must appear in the array as follows, where the numbers correspond to channel numbers:

0 1 3 0 1 3 ...

If no digital channels were specified in the call to TaskCreateWriter(Int32, array<Int32>[]()[], array<Int32>[]()[], array<Int32>[]()[], array<Int32>[]()[]) then this parameter may be set to NoBooleanBuffer or nullptr.

otherBuffer
Type: array< System..::.Double >[]()[]

An array containing the values to write to the other outputs. The array must contain numOtherChannels * numSamples elements, where numOtherChannels 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 written, than the data must appear in the array as follows, where the numbers correspond to channel numbers:

0 1 3 0 1 3 ...

If no other channels were specified in the call to TaskCreateWriter(Int32, array<Int32>[]()[], array<Int32>[]()[], array<Int32>[]()[], array<Int32>[]()[]) then this parameter may be set to NoDoubleBuffer or nullptr.

Return Value

The return value is the number of samples written to the task buffer. This value may be less than the requested number of samples (including 0) if the task buffer does not have sufficient space and the task is stopped or has finished processing the total number of samples indicated in the call to Start(Hil..::.Clock, Double, Int32).

Note that successive calls to Write can write more samples in total then the total number of samples specified in the call to Start(Hil..::.Clock, Double, Int32). However, only the number of samples specified in Start(Hil..::.Clock, Double, Int32) will actually be processed and written to the hardware.

Remarks

The Write method writes the specified number of samples to the task buffer of a task created using the TaskCreateWriter(Int32, array<Int32>[]()[], array<Int32>[]()[], array<Int32>[]()[], array<Int32>[]()[]) method. If there's not enough space in the task buffer, then this method will block until space for the requested number of samples becomes available or the task stops. Since the task removes data from the task buffer and writes it to the hardware at the sampling rate specified in the call to Start(Hil..::.Clock, Double, Int32), this method will never block for longer than the given number of samples times the sampling period.

Note that this method only blocks until there is enough space available in the task buffer. Because the task buffer is depleted at a given sampling rate, calling this function only synchronizes the caller to that sampling rate if the task buffer is kept full. Data must be written to the task buffer before the task buffer is completely depleted or else the next attempt to write to the task buffer will throw a HilExceptionBufferOverflow exception. As a result, Write should be used to put data into the task buffer prior to starting the task!.

Writer tasks are typically used to stream data to HIL hardware. In this case the numSamples parameter is typically half the number of samples in the task buffer to implement double-buffering.

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 SetDigitalDirections(array<Int32>[]()[], array<Int32>[]()[]) method. 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 Write(Int32, array<Double>[]()[], array<Double>[]()[], array<SByte>[]()[], array<Double>[]()[]) method failing to write the digital I/O as expected.

The interpretation of the PWM samples to be written depends upon the PWM mode. Typically the data is interpreted as a duty cycle, in which a magnitude of 0.0 denotes a 0% duty cycle and magnitude of 1.0 indicates a 100% duty cycle. The sign determines the polarity of the output for those boards supporting bidirectional PWM outputs. However, other PWM modes are possible with some boards. Refer to the SetPwmMode(array<Int32>[]()[], array<Hil..::.PwmMode>[]()[]) method for details.

Examples

This example illustrates how to write analog and PWM outputs using a task. The task writes analog channels 0-3 and PWM channels 0-1 every millisecond using a hardware clock. The data to write is computed every 0.1 seconds, with 100 samples being computed at a time. The task runs for 5 seconds before stopping. Exceptions are ignored for simplicity.
C# Copy Code
int [] analogChannels  = { 0, 1, 2, 3 };
int [] pwmChannels     = { 0, 1 };
double frequency       = 1000;
int    samples         = 5000;
int    samplesInBuffer = frequency;
int    samplesToWrite  = 100;

double [] analogBuffer = new double [samplesToWrite * analogChannels.Length];
double [] pwmBuffer    = new double [samplesToWrite * pwmChannels.Length];
Hil.Task task;

/* ... fill buffers with samplesToWrite samples ... */

/* Create task */
task = card.TaskCreateWriter(samplesInBuffer, analogChannels, pwmChannels, nullptr, nullptr);

/* Preload task buffer with first samplesToWrite samples prior to starting task */
task.Write(samplesToWrite, analogBuffer, pwmBuffer, nullptr, nullptr);

/* Start task */
task.Start(Hil.Clock.Hardware0, frequency, samples);
for (int index = samples; index < samples; index += samples_to_write) {
    /* ... fill buffers with next samplesToWrite samples ... */

    /*
        Block (if necessary) waiting to write next samplesToWrite samples.
        However, it only waits for space in the task buffer (which can contain
        samplesInBuffer samples), not for the data to actually be written to
        the hardware. Hence, it will not block until the task buffer is full
        (a little over one second in this example since samplesInBuffer is 1000).
    */
    task.Write(samplesToWrite, analogBuffer, pwmBuffer, nullptr, nullptr);
}

/* Flush to make sure all data has been written to the hardware before stopping task */
task.Flush();
task.Stop();
Visual Basic Copy Code
Dim analogChannels() As Integer = {0, 1, 2, 3}
Dim pwmChannels() As Integer = {0, 1}
Dim frequency as Double = 1000
Dim samples As Integer = 5000
Dim samplesInBuffer As Integer = frequency
Dim samplesToWrite As Integer = 100

Dim analogBuffer(samplesToWrite * analogChannels.Length - 1) As Double
Dim pwmBuffer(samplesToWrite * pwmChannels.Length - 1) As Double
Dim task As Hil.Task
Dim index As Integer

' ... fill buffers with samplesToWrite samples ...

' Create task
task = card.TaskCreateWriter(samplesInBuffer, analogChannels, pwmChannels, Hil.NoChannels, Hil.NoChannels)

' Preload task buffer with first samplesToWrite samples prior to starting task
task.Write(samplesToWrite, analogBuffer, pwmBuffer, Hil.NoBooleanBuffer, Hil.NoDoubleBuffer)

' Start task
task.Start(Hil.Clock.Hardware0, frequency, samples)
For index = 0 To samples - 1 Step samplesToWrite
    ' ... fill buffers with next samplesToWrite sample ...

    ' Block (if necessary) waiting to write next samplesToWrite samples.
    ' However, it only waits for space in the task buffer (which can contain
    ' samplesInBuffer samples), not for the data to actually be written to
    ' the hardware. Hence, it will not block until the task buffer is full
    ' (a little over one second in this example since samplesInBuffer is 1000).
    task.Write(samplesToWrite, analogBuffer, pwmBuffer, Hil.NoBooleanBuffer, Hil.NoDoubleBuffer)
Next

' Flush to make sure all data has been written to the hardware before stopping task
task.Flush()
task.Stop()
Visual C++ Copy Code
array<int>^ analogChannels  = { 0, 1, 2, 3 };
array<int>^ pwmChannels     = { 0, 1 };
double      frequency       = 1000;
int         samples         = 5000;
int         samplesInBuffer = frequency;
int         samplesToWrite  = 100;

array<double>^ analogBuffer = gcnew array<double>(samplesToWrite * analogChannels->Length);
array<double>^ pwmBuffer    = gcnew array<double>(samplesToWrite * pwmChannels->Length);
Hil::Task^ task;

/* ... fill buffers with samplesToWrite samples ... */

/* Create task */
task = card->TaskCreateWriter(samplesInBuffer, analogChannels, pwmChannels, nullptr, nullptr);

/* Preload task buffer with first samplesToWrite samples prior to starting task */
task->Write(samplesToWrite, analogBuffer, pwmBuffer, nullptr, nullptr);

/* Start task */
task->Start(Hil::Clock::Hardware0, frequency, samples);
for (int index = 0; index < samples; index += samplesToWrite) {
    /* ... fill buffers with next samplesToWrite samples ... */

    /*
        Block (if necessary) waiting to write next samplesToWrite samples.
        However, it only waits for space in the task buffer (which can contain
        samplesInBuffer samples), not for the data to actually be written to
        the hardware. Hence, it will not block until the task buffer is full
        (a little over one second in this example since samplesInBuffer is 1000).
    */
    task->Write(samplesToWrite, analogBuffer, pwmBuffer, nullptr, nullptr);
}

/* Flush to make sure all data has been written to the hardware before stopping task */
task->Flush();
task->Stop();

Exceptions

ExceptionCondition
Quanser.Hardware..::.HilException If the write cannot be performed then an exception is thrown. This situtation typically arises if the task buffer underflowed (ran out of data) after the last call to this method.

See Also