Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

WaitUntilDone() finishes before pulses written complete

Hi everyone,

 

When I write a finite train of analog pulses, the WaitUntilDone() function goes through without stop, leaves partial generated pulses. If I call Thread.Sleep and wait for the time length equal to the pulse train, everything works out. I know it is not the best practice and is flaw by its nature, so I want to know how to use WaitUntilDone() correctly (or just get things right).

 

    class StimulationPulses
    {
        public static double[] pulses = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 }; // 200Hz pulses, 1ms each, 25ms in total

        public double[] generatePulses(double factor)
        {
            double[] generatedPulses = new double[pulses.Length];

            for (int i = 0; i < pulses.Length; i++)
            {
                generatedPulses[i] = factor * pulses[i];
            }

            return generatedPulses;
        }
    }

    [Serializable]
    class StimulationControlFrame
    {
        public double normalised_current_level;
        public void ApplyControlData(AnalogSingleChannelWriter writer, Task outTask)
        {
            StimulationPulses pulseSignalGenerator = new StimulationPulses();

            writer.WriteMultiSample(false, pulseSignalGenerator.generatePulses(normalised_current_level));
            outTask.Start();
            Thread.Sleep(StimulationPulses.pulses.Length); // without this sleeping stmt, pulses usually generated partially
            outTask.WaitUntilDone();
            outTask.Stop();
        }
    }

 

 the above is the code I am using, let me know if you want to know other part of the code (e.g. channel setup etc.)

0 Kudos
Message 1 of 6
(1,592 Views)

We definitely need the rest  of the code, because we are missing the crucial part of the code - how you configure the DAQmx task

Santhosh
Soliton Technologies

New to the forum? Please read community guidelines and how to ask smart questions

Only two ways to appreciate someone who spent their free time to reply/answer your question - give them Kudos or mark their reply as the answer/solution.

Finding it hard to source NI hardware? Try NI Trading Post
0 Kudos
Message 2 of 6
(1,590 Views)

Thank you for the prompt reply.

 

Channel setup:

 

/* Analog Out Channel setup */
_analogOutTask = new Task();

// Create a virtual channel
_analogOutTask.AOChannels.CreateVoltageChannel(
    "Dev1/ao0",
    "StimulationOutput",
    Convert.ToDouble(-outputChannelMaxVolt),
    Convert.ToDouble(outputChannelMaxVolt),
    AOVoltageUnits.Volts);

// Configure the sample clock
_analogOutTask.Timing.ConfigureSampleClock(
    String.Empty, /* means the internal clock */
    sampleRate,
    SampleClockActiveEdge.Rising,
    SampleQuantityMode.FiniteSamples, StimulationPulses.pulses.Length);

// Verify the task
_analogOutTask.Control(TaskAction.Verify);

// Create the writer
_analogOutWriter = new AnalogSingleChannelWriter(_analogOutTask.Stream);

 

 _analogOutWriter is then passed to StimulationControlFrame.ApplyControlData through:

 

controlFrame.ApplyControlData(_analogOutWriter, _analogOutTask);

 

Sometimes, when the pulses generated partially and is on the high voltage, it just stay there instead of returning to zero. I guess I need to modify Idle state configuration, but I can't find reference on how to do it correctly at this point.

0 Kudos
Message 3 of 6
(1,585 Views)

Few things to ensure,

 

  1. StimulationPulses.pulses.Length equals the size of the array you generate
  2. sampleRate is set to 200Hz (at least that is what you have noted down in array generation)
  3. Last but not the least, does you instrument support 200Hz sample rate? you're assuming that it is generating at 200Hz but it could be any sampling rate based on what is possible on the HW, best method is to read back the sample rate after you verify the task. please share your instrument model.
  4. AO retain the last set voltage, if you want it to get back to 0 immediately after the sequence of voltages, just append a 0 value at the end.
Santhosh
Soliton Technologies

New to the forum? Please read community guidelines and how to ask smart questions

Only two ways to appreciate someone who spent their free time to reply/answer your question - give them Kudos or mark their reply as the answer/solution.

Finding it hard to source NI hardware? Try NI Trading Post
0 Kudos
Message 4 of 6
(1,575 Views)

Thank you for the reply.

 

1. I have double checked it matches the sample size I generated (25 samples in total).

2. sampleRate is set to 1000, it is because I am repeating 1, 0, 0, 0, 0 pattern. So that is 200Hz pulses with sample rate being 1000 per second. 

3. By reading back Task.Timing.SampleClockRate property, it is set to 1000. Everything makes sense except the Task thinks itself done earlier than actual IO completion. I added debug output in comments:

class StimulationPulses
{
    public static double[] pulses = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 }; // 25 samples

    public double[] generatePulses(double factor)
    {
        double[] generatedPulses = new double[pulses.Length];

        for (int i = 0; i < pulses.Length; i++)
        {
            generatedPulses[i] = factor * pulses[i];
        }

        return generatedPulses;
    }
}

[Serializable]
class StimulationControlFrame
{
    public double normalised_current_level;
    public void ApplyControlData(AnalogSingleChannelWriter writer, Task outTask)
    {
        StimulationPulses pulseSignalGenerator = new StimulationPulses();

        Console.WriteLine(outTask.Timing.SampleClockRate.ToString()); // Print 1000
        Console.WriteLine(outTask.Timing.SamplesPerChannel.ToString()); // Print 25
        Console.WriteLine(outTask.IsDone.ToString()); // Print True
        Console.WriteLine(pulseSignalGenerator.generatePulses(normalised_current_level).Length.ToString()); // Print 25
        writer.WriteMultiSample(false, pulseSignalGenerator.generatePulses(normalised_current_level)); // 25 samples
        outTask.Start();
        Console.WriteLine(outTask.IsDone.ToString()); // Can print both False or True
        // Thread.Sleep(StimulationPulses.pulses.Length); Without this command, incomplete pulse generation happens
        outTask.WaitUntilDone();
        Console.WriteLine(outTask.IsDone.ToString()); // Print True
        outTask.Stop();
    }
}

The model we are using is USB-6212 BNC version. 

 

4. Yes, we have 0s in the end as the pattern is 1, 0, 0, 0, 0. The problem is when it happens to be stopped at 1's samples, it retains 1 Volts, which is a huge safety problem. I am thinking to use an ad-hoc solution by writing another 0 to avoid any dangerous things from happening.

0 Kudos
Message 5 of 6
(1,525 Views)

Anyone else have any comments or reminders to bring up? Would be much appreciated. Otherwise I am going to open a bug report case with NI.

0 Kudos
Message 6 of 6
(1,494 Views)