Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

automatically restart analog trigger after samples

Hi,

 

First time user, and a tad overwhelmed.  


I'm using the NI 6366 to measure 8 analog inputs (using VS2010 and standard Measurement Studio).  I have it configured to take 1000 measurements at 1Mhz rate.  I'm currently reading back the unscaled values.  I really need to have the task trigger on the analog trigger source each time it sees it and then send me the data.  Something like this in code...

Create task
start task
read 1000 samples starting at analog trigger
read 1000 samples starting at analog trigger

read 1000 samples starting at analog trigger

.... repeat

stop task

 

I cannot seem to find a trigger method documented that does this.  I can do the following...

1.  I can trigger on the analog signal and read a finite number of samples.  Problem - I need at least 50 of these readings each second not one.


2.  I can trigger on the analog signal and read continuous samples.  Problem - There is too much data and it is not synchronized with the analog trigger.  I really need to keep a rotating buffer of the last 50-100 and process it as it comes in.

3.  I can trigger on the analog signal and read a finite set of samples, stop the task, and then recreate/start the task.  Problem - stopping the task and creating the task again seems to take a very long time (like 500ms).   

Here is the code I'm using to create the task, and to read the data from the measurements.  It is just modified from some of the examples I've found and obviously there are routines missing.

I appreciate any feedback, suggestions, or pointers.

Lon

   

    Private Sub CreateTask()

        numberOfSamples = Convert.ToInt32(samplesPerChannelNumeric.Value)
        If runningTask Is Nothing Then
            Try
                ' Create a new task
                myTask = New Task()

                ' Create a new virtual channel
                myTask.AIChannels.CreateVoltageChannel("Dev1/ai0", "", _
                CType(-1, AITerminalConfiguration), Convert.ToDouble(minimumValueNumeric.Value), _
                Convert.ToDouble(maximumValueNumeric.Value), AIVoltageUnits.Volts)

                ' Create a new virtual channel
                myTask.AIChannels.CreateVoltageChannel("Dev1/ai1", "", _
                CType(-1, AITerminalConfiguration), Convert.ToDouble(minimumValueNumeric.Value), _
                Convert.ToDouble(maximumValueNumeric.Value), AIVoltageUnits.Volts)

                ' Create a new virtual channel
                myTask.AIChannels.CreateVoltageChannel("Dev1/ai2", "", _
                CType(-1, AITerminalConfiguration), Convert.ToDouble(minimumValueNumeric.Value), _
                Convert.ToDouble(maximumValueNumeric.Value), AIVoltageUnits.Volts)

                ' Create a new virtual channel
                myTask.AIChannels.CreateVoltageChannel("Dev1/ai3", "", _
                CType(-1, AITerminalConfiguration), Convert.ToDouble(minimumValueNumeric.Value), _
                Convert.ToDouble(maximumValueNumeric.Value), AIVoltageUnits.Volts)

                ' Create a new virtual channel
                myTask.AIChannels.CreateVoltageChannel("Dev1/ai4", "", _
                CType(-1, AITerminalConfiguration), Convert.ToDouble(minimumValueNumeric.Value), _
                Convert.ToDouble(maximumValueNumeric.Value), AIVoltageUnits.Volts)

                ' Create a new virtual channel
                myTask.AIChannels.CreateVoltageChannel("Dev1/ai5", "", _
                CType(-1, AITerminalConfiguration), Convert.ToDouble(minimumValueNumeric.Value), _
                Convert.ToDouble(maximumValueNumeric.Value), AIVoltageUnits.Volts)

                ' Create a new virtual channel
                myTask.AIChannels.CreateVoltageChannel("Dev1/ai6", "", _
                CType(-1, AITerminalConfiguration), Convert.ToDouble(minimumValueNumeric.Value), _
                Convert.ToDouble(maximumValueNumeric.Value), AIVoltageUnits.Volts)

                ' Create a new virtual channel
                myTask.AIChannels.CreateVoltageChannel("Dev1/ai7", "", _
                CType(-1, AITerminalConfiguration), Convert.ToDouble(minimumValueNumeric.Value), _
                Convert.ToDouble(maximumValueNumeric.Value), AIVoltageUnits.Volts)

                ' Configure Timing Specs 
                myTask.Timing.ConfigureSampleClock("", Convert.ToDouble(rateNumeric.Value), _
                SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples, 1000)

                ' Configure the Analog Trigger
                myTask.Triggers.StartTrigger.ConfigureAnalogEdgeTrigger(triggerSourceTextBox.Text, _
                analogSlope, Convert.ToDouble(triggerLevelNumeric.Value))

                myTask.Triggers.StartTrigger.AnalogEdge.Hysteresis = Convert.ToDouble(hysteresisNumeric.Value)

                ' Verify the Task
                myTask.Control(TaskAction.Verify)

                runningTask = myTask

                '         myTask.ConfigureLogging("myfile", TdmsLoggingOperation.OpenOrCreate, LoggingMode.LogAndRead, "MyFile")

                analogRawReader = New AnalogUnscaledReader(myTask.Stream)
                analogRawReader.SynchronizeCallbacks = True
                analogRawReader.BeginReadUInt16(numberOfSamples, myAsyncCallback, myTask)

            Catch exception As DaqException
                MessageBox.Show(exception.Message)
                myTask.Dispose()
            End Try
        End If


    End Sub

Private Sub AnalogInCallback(ByVal ar As IAsyncResult)
        Try
            If (Not (runningTask Is Nothing)) AndAlso runningTask Is ar.AsyncState Then

                CopyArray = analogRawReader.EndReadUInt16(ar)
                Array.Copy(CopyArray, 0, DataArray, DataArrayIndex * 1000, 8000)
                DataArrayIndex = DataArrayIndex + 1
                If DataArrayIndex > 99 Then
                    DataArrayIndex = 0
                End If
                Counter = Counter + 1

                analogRawReader.BeginReadUInt16(numberOfSamples, myAsyncCallback, myTask)
            End If
        Catch exception As DaqException
            MessageBox.Show(exception.Message)
            stopButton_Click(Nothing, Nothing)
        End Try

    End Sub

 

 

 

0 Kudos
Message 1 of 8
(6,565 Views)

No response in 4 days, perhaps I can re-phrase the problem to solicit some advice...

I've read through the NI-DAQmx help files and have experimented with a number of the sample VS2010 examples provided.  I have determined that...
a.  Configuring a task for finite samples, and repeatedly calling that task, is much slower than using a continuous task. 

b.  Continuous tasks do not repeat, or restart, based on the trigger associated with the task.

I have not found anywhere in the documentation discussions of timing as it relates to the aquisition mode.  If anyone can point me to detailed information I would appreciate it.

I need to quickly take measurements of voltages that occur after a timing signal (connected to APFIO) occurs.  I would like to use unscaled data, as this will reduce the processing of the signals.   The finite task is perfect, but ~20 times too slow for my application.  The continuous task is fast enough, but does not allow me to associate the voltage measurements with the timing signal (APFIO voltage).

If I could speed up finite aquisition, or have continuous aquistion re-trigger on each APFIO signal, I think I'd be set. 

0 Kudos
Message 2 of 8
(6,536 Views)

Hi,

 

Indeed, a continuous acquisition task will be much faster than running a finite task recursively. The reason, as you have mentioned, is that you don’t have to reconfigure and to release the resource every time that you call the function.

 

If you need explicit information about your board I will recommend you to take a look to the X Series User Manual (Chapter 4, maybe page 4-25 will help). I think this is a great resource to find information.

 

I found a KB-4R6D2MMK that mention that it is possible to perform a retriggerable AI task with analog trigger. Also, your board is listed as one of the devices that support this capability (see the related links).

 

I will suggest taking a look to the trigger examples included with the DAQmx ANSI C help (Cont Acq-Int Clk-Anlg Start and Cont Acq-Int Clk-Dig Start-Retriggerable).

C:\Users\Public\Documents\National Instruments\NI-DAQ\Examples\DAQmx ANSI C\Analog In\Measure Voltage

 

Regards,

 

Richard

 

0 Kudos
Message 3 of 8
(6,523 Views)

Richard_Smith,

 

I appreciate the suggestions.  I have spent some time with the manual as well as the specification document, and they have been somewhat helpful.  I think the greater hurdle is wading through the DAQmx functions (etc.) and the trial and error approach to making things work.  At this point I'm pretty far down the rabbit hole.

Here is my latest attempt. 

I am trying to configure the analog input task to accept continuous samples and provide a sample clock from a counter output that fires a burst of 1000 pulses upon receiving an analog start trigger.  Here is how I define the counter task.

                myTask2 = New Task()

                myTask2.COChannels.CreatePulseChannelTime("Dev1/ctr0", "", COPulseTimeUnits.Seconds, COPulseIdleState.Low, 0.0, 0.0000005, 0.0000005)
                myTask2.Triggers.StartTrigger.ConfigureAnalogEdgeTrigger("APFI0", AnalogEdgeStartTriggerSlope.Rising, 5.0)
                myTask2.Timing.ConfigureImplicit(SampleQuantityMode.FiniteSamples, 1000)

                myTask2.Start()

 I can't seem to get the analog edge triggering to work.  The manual says to check the specification document for available triggers and the specification document does not list trigger modes for the counter module.  I'm beginning to think I need to convert the analog trigger to a digital trigger for use with this task, or perhaps route the APFI0 signal to the counter's gate?

I'll take a look at the examples you cited.  I've been mostly sticking to the VB code, but if there is C code that is different I'll see if it helps.

 

Lon 



0 Kudos
Message 4 of 8
(6,514 Views)

Richard_Smith,

 

I appreciate the suggestions.  I have spent some time with the manual as well as the specification document, and they have been somewhat helpful.  I think the greater hurdle is wading through the DAQmx functions (etc.) and the trial and error approach to making things work.  At this point I'm pretty far down the rabbit hole.

Here is my latest attempt. 

I am trying to configure the analog input task to accept continuous samples and provide a sample clock from a counter output that fires a burst of 1000 pulses upon receiving an analog start trigger.  Here is how I define the counter task.

                myTask2 = New Task()

                myTask2.COChannels.CreatePulseChannelTime("Dev1/ctr0", "", COPulseTimeUnits.Seconds, COPulseIdleState.Low, 0.0, 0.0000005, 0.0000005)
                myTask2.Triggers.StartTrigger.ConfigureAnalogEdgeTrigger("APFI0", AnalogEdgeStartTriggerSlope.Rising, 5.0)
                myTask2.Timing.ConfigureImplicit(SampleQuantityMode.FiniteSamples, 1000)

                myTask2.Start()

 I can't seem to get the analog edge triggering to work.  The manual says to check the specification document for available triggers and the specification document does not list trigger modes for the counter module.  I'm beginning to think I need to convert the analog trigger to a digital trigger for use with this task, or perhaps route the APFI0 signal to the counter's gate?

I'll take a look at the examples you cited.  I've been mostly sticking to the VB code, but if there is C code that is different I'll see if it helps.

 

Lon 



0 Kudos
Message 5 of 8
(6,514 Views)

I was finally able to get high speed continuous samples associated with an analog trigger, and avoid the delay caused by restarting an analog task.  Here's what I did...

1. Configured a counter task that with a resetting digital edge trigger.  I fed my analog trigger into PFI0 after conditioning it to be between 0-5V.  This counter task fired finite a burst of timed pulses.
2.  Configured an analog task that aquired data continuously, but sampled on the pulses genereated by the counter task.

This allowed me to read 1000 samples from 8 analog channels 1000 times per second.

I've still got quite a bit of work to do, but the setup code is below. 

 

 

    Private Sub CreateTask()

        If runningTask2 Is Nothing Then
            Try

                'Create(New Task)
                myTask2 = New Task()

                myTask2.COChannels.CreatePulseChannelTime("Dev1/ctr0", "", COPulseTimeUnits.Seconds, COPulseIdleState.Low, 0.0, 0.0000005, 0.0000005)
                myTask2.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger("PFI0", DigitalEdgeStartTriggerEdge.Rising)
                myTask2.Triggers.StartTrigger.Retriggerable = True

                myTask2.Timing.ConfigureImplicit(SampleQuantityMode.FiniteSamples, 900)

                myTask2.Start()

            Catch ex As Exception
                myTask2.Dispose()
            End Try
        End If

        numberOfSamples = Convert.ToInt32(samplesPerChannelNumeric.Value)
        If runningTask Is Nothing Then
            Try
                ' Create a new task
                myTask = New Task()

                ' Create a new virtual channel
                myTask.AIChannels.CreateVoltageChannel("Dev1/ai0", "", _
                CType(-1, AITerminalConfiguration), Convert.ToDouble(minimumValueNumeric.Value), _
                Convert.ToDouble(maximumValueNumeric.Value), AIVoltageUnits.Volts)

                ' Create a new virtual channel
                myTask.AIChannels.CreateVoltageChannel("Dev1/ai1", "", _
                CType(-1, AITerminalConfiguration), Convert.ToDouble(minimumValueNumeric.Value), _
                Convert.ToDouble(maximumValueNumeric.Value), AIVoltageUnits.Volts)

                ' Create a new virtual channel
                myTask.AIChannels.CreateVoltageChannel("Dev1/ai2", "", _
                CType(-1, AITerminalConfiguration), Convert.ToDouble(minimumValueNumeric.Value), _
                Convert.ToDouble(maximumValueNumeric.Value), AIVoltageUnits.Volts)

                ' Create a new virtual channel
                myTask.AIChannels.CreateVoltageChannel("Dev1/ai3", "", _
                CType(-1, AITerminalConfiguration), Convert.ToDouble(minimumValueNumeric.Value), _
                Convert.ToDouble(maximumValueNumeric.Value), AIVoltageUnits.Volts)

                ' Create a new virtual channel
                myTask.AIChannels.CreateVoltageChannel("Dev1/ai4", "", _
                CType(-1, AITerminalConfiguration), Convert.ToDouble(minimumValueNumeric.Value), _
                Convert.ToDouble(maximumValueNumeric.Value), AIVoltageUnits.Volts)

                ' Create a new virtual channel
                myTask.AIChannels.CreateVoltageChannel("Dev1/ai5", "", _
                CType(-1, AITerminalConfiguration), Convert.ToDouble(minimumValueNumeric.Value), _
                Convert.ToDouble(maximumValueNumeric.Value), AIVoltageUnits.Volts)

                ' Create a new virtual channel
                myTask.AIChannels.CreateVoltageChannel("Dev1/ai6", "", _
                CType(-1, AITerminalConfiguration), Convert.ToDouble(minimumValueNumeric.Value), _
                Convert.ToDouble(maximumValueNumeric.Value), AIVoltageUnits.Volts)

                ' Create a new virtual channel
                myTask.AIChannels.CreateVoltageChannel("Dev1/ai7", "", _
                CType(-1, AITerminalConfiguration), Convert.ToDouble(minimumValueNumeric.Value), _
                Convert.ToDouble(maximumValueNumeric.Value), AIVoltageUnits.Volts)

                ''Continuous samples - Configure Timing Specs 
                myTask.Timing.ConfigureSampleClock("PFI12", 2000000, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples, 1000000)

                ' Verify the Task
                myTask.Control(TaskAction.Verify)

                ' Commit the Task
                myTask.Control(TaskAction.Commit)

                runningTask = myTask

                'myTask.ConfigureLogging("myfile", TdmsLoggingOperation.OpenOrCreate, LoggingMode.LogAndRead, "MyFile")

                analogRawReader = New AnalogUnscaledReader(myTask.Stream)
                analogRawReader.SynchronizeCallbacks = True
                analogRawReader.BeginReadUInt16(numberOfSamples, myAsyncCallback, myTask)

            Catch exception As DaqException
                MessageBox.Show(exception.Message)
                myTask.Dispose()
            End Try
        End If


    End Sub

    Private Sub AnalogInCallback(ByVal ar As IAsyncResult)
        Try
            If (Not (runningTask Is Nothing)) AndAlso runningTask Is ar.AsyncState Then

                CopyArray = analogRawReader.EndReadUInt16(ar)
                analogRawReader.BeginReadUInt16(numberOfSamples, myAsyncCallback, myTask)

                storedata()
                Counter = Counter + 1

            End If
        Catch exception As DaqException
            myTask.Stop()
            myTask.Start()
            analogRawReader.BeginReadUInt16(numberOfSamples, myAsyncCallback, myTask)
            MyBox.BackColor = Color.Crimson
        End Try


    End Sub

 

 

 

 

0 Kudos
Message 6 of 8
(6,499 Views)

An important addition.

With the code above I was seeing the signals I was measuring shift everytime I started and stopped my project (created and disposed of tasks).  This was due to me creating the counter task (myTask2) prior to the analog task (myTask).

The analog task takes samples when clocked by pulses generated by the counter task.  By the time I call BeginReadUINT16 a number of samples were already taken.  To make sure start of your analog samples are synchronized with the triggerof the counter, the creation of that task should be moved below the creation of the analog task.

   

0 Kudos
Message 7 of 8
(6,484 Views)

Hi LonSol3,

 

Thanks for the update. That totally make sense, in this case the cunter task acts as a Master task and the AI task as Slave. The slave task should be configured and armed previously than the master.

 

Regards,

 

Richard.

0 Kudos
Message 8 of 8
(6,467 Views)