04-23-2016 10:18 PM
I am trying to use a 6602 PCI to collect an array of time stamps of pulses using DAQmx.dll i.e. .NET. c#
I have so far used the CountDigEventsBufContinuous_ExtClk.2010 example, and it works without error, but I am not sure what the array of doubles represetns. All I get are 0s. My real problem is that when I alter the code to capture what I would really like, an array CiDataTicks or time stamps, I get the following error : "Read cannot be performed because this version of DAQmx Read does not match the type of channels in the task. \n\nUse the version of DAQmx Read that corresponds to the channel type.\n\nTask Name: _unnamedTask<0>\n\nStatus Code: -200525" when it gets to the following line: "data = myCounterReader.EndMemoryOptimizedReadMultiSamplePulseTicks(ar, out actualNumberOFSamplesRead);" in the AsyncCallback.
First, am going about this wrong? Second, if not, then what is wrong with my readers that they can't perform the reading of an array of times or ticks?
Solved! Go to Solution.
04-25-2016 10:40 AM
Hey MrSethT,
I'm not sure if what you are doing is right or wrong, but here are some questions that might help clarify things for the forum.
Do you know what version of the DAQmx driver you are using? Also what excatly are you changing in the example (e.g. file, function call, etc.)?
Determine the Version of the NI Software Installed on My Computer - (http://digital.ni.com/public.nsf/allkb/2266B58A5061E86A8625758C007A4FE3)
04-25-2016 02:21 PM
Yes, thanks.
The verion of DAQmx.dll that I am referencing is 14.5.45.122
I have extracted the critical lines of code from the sample and (as far as I can tell) only changed the lines that reference a Double to now referece PulseTicks/CiDataTicks
04-26-2016 09:14 AM
I have upgraded to DAQmx.dll v15.5.40.109 and am still getting same results.
I have also noticed that I only get this error if I am generating a signal (the motor is spinning). If it is not spinning, I get the following:
""Some or all of the samples requested have not yet been acquired.\n\nTo wait for the samples to become available use a longer read timeout or read later in your program. To make the samples available sooner, increase the sample rate. If your task uses a start trigger, make sure that your start trigger is configured correctly. It is also possible that you configured the task for external timing, and no clock was supplied. If this is the case, supply an external clock.
Property: NationalInstruments.DAQmx.DaqStream.ReadRelativeTo
Corresponding Value: NationalInstruments.DAQmx.ReadRelativeTo.CurrentReadPosition
Property: NationalInstruments.DAQmx.DaqStream.ReadOffset
Corresponding Value: 0
Task Name: _unnamedTask<0>
Status Code: -200284""
04-26-2016 04:10 PM
Thanks for the updates.
I guess I am not fully understanding your application. I am confused as the where the motor is coming into play and inhibits the application from running properly.
Some more information that might help is if the forum could see your main function (you could upload the text or paste it into a reply) and see the sequence of calls you are trying to make. In addition, could you maybe explain you application a bit further so the forum can understand what you are trying to accomplish and possibly see other sources of error that might present themselves.
As for this second error, if I were to guess I would say that your DAQ is getting an error when your motor is not running since somehow the motor running is tied to the counter sampling and gathering data. So when the DAQ tries to gather samples from the counter, there is no data to gather because the motor is not running and the software throws this error.
Also if hardware seems to be an issue in developing your software, maybe try simulating the device and testing your code to see if the issue with the hardware still persists.
NI-DAQmx Simulated Devices - http://www.ni.com/tutorial/3698/en/
04-26-2016 09:25 PM
I have 2 encoders attached to motors that generates pulses. I would like to start them simultaneously and compare the time that pulse N happened on encoder 1 to the time that pulse N happened on encoder 2.
I have no issues with motor noise. The error I was getting had something to do with the setup being in a bad way, but it was only evident when there were actually pulses being generated.
I have resorted to changing to a channel that will measure pulse widths. I use the arrays of widths that are collected to generate the necessary timestamps by using the accumulating values. (ie [200, 300, 200, 150, ...] = [200, 500, 700, 850, ...])
Considering the following requirements, does this seem like a good solution?
04-27-2016 06:25 PM
That's great to hear that you've been able to self-correct your setup. To answer your question this seems like a perfectly fine way to acquire that data that you're after.
Be sure to look up some of the examples on synchronizing your counters though since they need to be started at the same time and not drift apart.
04-28-2016 09:04 AM
>> I would like to start them simultaneously and compare the time that pulse N happened on encoder 1 to the time that pulse N happened on encoder 2
Look at retriggerable regeneration.
First motor continuously generates pulses. The other motor (start trigger on) generates single pulse with Start Trigger -> Retriggerable true, Start Trigger -> Source -> /Dev1/CtrXInternalOutput (X=0 - counter that generates for the first motor). Low number of ticks (pulse low time) determines delay of the second pulse relative to the first. When you stop the first motor, the second one does not see pulses to retrigger and does not generate.
If everything programmed correctly, separation between pulses is maintained with time base precision. Precision is something around 50 ps, much better than 12.5 ns resolution. And it does not accumulate with time,
About errors you had
>> "Read cannot be performed because this version of DAQmx Read does not match the type of channels in the task"
It looks like you configured the task as count pulses as in example. If you try to read anything else other than 1 D array of U32, it will give you error. Ticks (CiDataTicks), pulse time are results of measuring pulse properties (width, period, etc).
>> The 2 arrays need to be collected simultaneously and started at the same time
Configure start trigger for both tasks. It can be /Dev1/CtrXInternalOutput. Start both read tasks (Call start task) before you start to generate pulses.
>> If it is not spinning, I get the following: ""Some or all of the samples requested have not yet been acquired..."
Read has timeout property. If data (pulses) do not arrive within timeout (counters do not generate data), it says "Some of the samples have not been acquired"
04-28-2016 02:27 PM
Thanks so much alexander, very helpful
I am sorry to be ignorant, but I am not exactly understanding what you described. I will add more detail and tell you my guess of an approach.
I have the 2 motors each with an 18000 pulse/rev encoder. Motor A and Motor B. Motor A is the primary and Motor B is the secondary. Motor A spins 3x faster than Motor B. They are brought up to speed, and then I am to begin collecting X pulse widths from Motor B and 3X pulse widths from Motor A starting at the same time. I am developing this solution in c#. I would like to sample at 80Mhz. The input pins of interest are
PFI38 - EncoderA 18000/rev
PFI34 - EncoderB 18000/rev
PFI30 - EncoderA 1/rev
PFI26 - EncoderB 1/rev
My guess for an approach is the following:
Create taskA and taskB
Create an array to hold the data dataA and dataB
Create sampleCounts samplesA, samplesB where samplesA = 3 x samplesB
TaskA.CIChannels.CreatePulseWidthChannel("...ctr0", "", 240, 100000, CIPulseWidthStartingEdge.Rising, CIPulseWidthUnits.Ticks);
TaskA.Timing.ConfigureSampleClock("/Dev1/PFI38", 1000.0, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples, samplesA);
myCounterReaderA = new CounterSingleChannelReader(TaskA.Stream);
//setup callback method
TaskB.CIChannels.CreatePulseWidthChannel("...ctr1", "", 240, 100000, CIPulseWidthStartingEdge.Rising, CIPulseWidthUnits.Ticks);
//this throws an exception but seems like the right thing to be doing,
//if I leave this line out, the creation of the task does not error, but running them creates an
//"Invalid timing type for this channelStatus Code: -200300" message indicating that only implicit timing is available
TaskB.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger("/Dev1/Ctr0InternalOutput", DigitalEdgeStartTriggerEdge.Rising);
//
TaskB.Timing.ConfigureSampleClock("/Dev1/PFI34", 1000.0, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples, samplesB);
myCounterReaderB = new CounterSingleChannelReader(TaskB.Stream);
myCounterReaderA.BeginMemoryOptimizedReadMultiSampleDouble(samplesA, mycallbackA, TaskA, dataA);
myCounterReaderB.BeginMemoryOptimizedReadMultiSampleDouble(samplesB, mycallbackB, TaskB, dataB);
//wait for the callbacks
What am I missing?
04-28-2016 05:19 PM
1. You'll want to measure Periods rather than Pulse Widths. Periods measure a full pulse cycle from (for example) rising edge to next rising edge. Pulse Widths are going to measure half cycles from (for example) rising edge to falling edge. Your cumulative sum notion will work just fine with periods, but be sure to convert to 64-bit int or floating point for the summation. With an 80 MHz timebase, a 32-bit int will roll over in less than a minute.
2. You'll need to configure an "Arm Start" trigger for each counter task to make the two counter *input* tasks start simultaneously. This is unique for counter tasks and is distinct from the normal Start trigger available to many other daq tasks.
3. Using a 6602, the first measured period for each task will represent the time from the Arm Start trigger edge until the first encoder edge. All subsequent measurements will be full encoder periods. (Note that the behavior is different for counters on X-series boards, where the first partial interval is never returned).
4. I'm no help on the c# syntax, I only program from LabVIEW. That said,
-Kevin P