03-15-2018 10:49 AM
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.
03-15-2018 12:18 PM
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