Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

USB-6001 - Synchronized analog and digital reading

Hello,

I have for some time been struggling with a C# application for a USB-6001 device.

The purpose of my application is to:
-    Sample 8 analog inputs at 100 Hz.
-    Read the status 8 digital inputs in a way that analog samples and digital reading are synchronized.

I use following configuration of the device:
            NationalInstruments.DAQmx.Task analogInTaskPendulum = new NationalInstruments.DAQmx.Task();            
            anInputCh_PendulumCylinder = analogInTaskPendulum.AIChannels.CreateVoltageChannel("dev1/ai0", "pendulumAna", AITerminalConfiguration.Rse, -10.0, 10.0, AIVoltageUnits.Volts);
            anReader_PendulumCylinder = new AnalogSingleChannelReader(analogInTaskPendulum.Stream);

            NationalInstruments.DAQmx.Task analogInTaskHeightCylinder = new NationalInstruments.DAQmx.Task();
            anInputCh_HightCylinder = analogInTaskHeightCylinder.AIChannels.CreateVoltageChannel("dev1/ai1", "heightAna", AITerminalConfiguration.Rse, -10.0, 10.0, AIVoltageUnits.Volts);
            anReader_HightCylinder = new AnalogSingleChannelReader(analogInTaskHeightCylinder.Stream);

            NationalInstruments.DAQmx.Task analogInTaskLeftTilt = new NationalInstruments.DAQmx.Task();
            anInputCh_LeftTiltCylinder = analogInTaskLeftTilt.AIChannels.CreateVoltageChannel("dev1/ai2", "leftTiltAna", AITerminalConfiguration.Rse, -10.0, 10.0, AIVoltageUnits.Volts);
            anReader_LeftTiltCylinder = new AnalogSingleChannelReader(analogInTaskLeftTilt.Stream);

            NationalInstruments.DAQmx.Task analogInTaskRightTilt = new NationalInstruments.DAQmx.Task();
            anInputCh_RightTiltCylinder = analogInTaskRightTilt.AIChannels.CreateVoltageChannel("dev1/ai3", "rightTiltAna", AITerminalConfiguration.Rse, -10.0, 10.0, AIVoltageUnits.Volts);
            anReader_RightTiltCylinder = new AnalogSingleChannelReader(analogInTaskRightTilt.Stream);

            NationalInstruments.DAQmx.Task analogInTaskUltra1 = new NationalInstruments.DAQmx.Task();
            anInputCh_Ultra1 = analogInTaskUltra1.AIChannels.CreateVoltageChannel("dev1/ai4", "ultra1Ana", AITerminalConfiguration.Rse, -10.0, 10.0, AIVoltageUnits.Volts);
            anReader_Ultra1 = new AnalogSingleChannelReader(analogInTaskUltra1.Stream);

            NationalInstruments.DAQmx.Task analogInTaskUltra2 = new NationalInstruments.DAQmx.Task();
            anInputCh_Ultra2 = analogInTaskUltra2.AIChannels.CreateVoltageChannel("dev1/ai5", "ultra2Ana", AITerminalConfiguration.Rse, -10.0, 10.0, AIVoltageUnits.Volts);
            anReader_Ultra2 = new AnalogSingleChannelReader(analogInTaskUltra2.Stream);

            NationalInstruments.DAQmx.Task analogInTaskUltra3 = new NationalInstruments.DAQmx.Task();
            anInputCh_Ultra3 = analogInTaskUltra3.AIChannels.CreateVoltageChannel("dev1/ai6", "ultra3Ana", AITerminalConfiguration.Rse, -10.0, 10.0, AIVoltageUnits.Volts);
            anReader_Ultra3 = new AnalogSingleChannelReader(analogInTaskUltra3.Stream);

            NationalInstruments.DAQmx.Task analogInTaskUltra4 = new NationalInstruments.DAQmx.Task();
            anInputCh_Ultra4 = analogInTaskUltra4.AIChannels.CreateVoltageChannel("dev1/ai7", "ultra4Ana", AITerminalConfiguration.Rse, -10.0, 10.0, AIVoltageUnits.Volts);
            anReader_Ultra4 = new AnalogSingleChannelReader(analogInTaskUltra4.Stream);

A thread is setup to read each inputs every 10 msec:                                                       
            analogDataInPendulum = anReader_PendulumCylinder.ReadSingleSample();                
            analogDataInHeightCylinder = anReader_HightCylinder.ReadSingleSample();               
            analogDataInLeftTiltCylinder = anReader_LeftTiltCylinder.ReadSingleSample();                
            analogDataInRightTiltCylinder = anReader_RightTiltCylinder.ReadSingleSample();                
            analogDataInUltra1 = anReader_Ultra1.ReadSingleSample();                
            analogDataInUltra2 = anReader_Ultra2.ReadSingleSample();                
            analogDataInUltra3 = anReader_Ultra3.ReadSingleSample();                
            analogDataInUltra4 = anReader_Ultra4.ReadSingleSample();                                             

            digPortVal = DigInReader.ReadSingleSamplePortByte();

My problem is that each call to "ReadSingleSample" apparently takes more millisconds. Also I have tried to configure the sample behaviour by adding following calls to the configuration:

analogInTaskPendulum.Timing.ConfigureSampleClock("dev1/ai0", 100, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples);
analogInTaskHeightCylinder.Timing.ConfigureSampleClock("dev1/ai1", 100, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples);
analogInTaskLeftTilt.Timing.ConfigureSampleClock("dev1/ai2", 100, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples);
analogInTaskRightTilt.Timing.ConfigureSampleClock("dev1/ai3", 100, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples);
analogInTaskUltra1.Timing.ConfigureSampleClock("dev1/ai4", 100, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples);
analogInTaskUltra2.Timing.ConfigureSampleClock("dev1/ai5", 100, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples);
analogInTaskUltra3.Timing.ConfigureSampleClock("dev1/ai6", 100, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples);
analogInTaskUltra4.Timing.ConfigureSampleClock("dev1/ai7", 100, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples);

Which gives me an exception regarding the sample clock source:

NationalInstruments.DAQmx.DaqException: 'Requested sample clock source is invalid.
Property: NationalInstruments.DAQmx.Timing.SampleClockSource

I hope that somebody can point me to an example of how to do stuff like this correctly.





0 Kudos
Message 1 of 2
(2,341 Views)

The first and biggest obstacle is the USB bus.  You can expect latency on the order of msecs when you do single on-demand reads across the bus.

 

Consequently, it's pretty important to combine all the analog channels into a single task so you can get all 8 channels of data using a single read.  That'll cut the overhead by a factor of 8x.

 

It's not just important but *necessary* to combine all analog channels into a single task if you want to set up hardware timing in continuous sampling mode.  The AI subsystem will only support 1 active hardware timing source at a time.

 

The DI subsystem won't support hardware timing, you can only use on-demand port reads.

 

Finally, it'll help if you explicitly Start your tasks before doing a Read.  This will reduce your overhead too, not sure exactly how much but probably noticeable for the on-demand Reads.

 

 

-Kevin P

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
0 Kudos
Message 2 of 2
(2,326 Views)