Counter/Timer

cancel
Showing results for 
Search instead for 
Did you mean: 

Capturing a time stamp train in .NET from a 6602

Solved!
Go to solution

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?

0 Kudos
Message 1 of 15
(5,760 Views)

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)

JY
Application Engineer, RF and Communications
National Instruments
0 Kudos
Message 2 of 15
(5,738 Views)

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

0 Kudos
Message 3 of 15
(5,730 Views)

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""

0 Kudos
Message 4 of 15
(5,704 Views)

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/

JY
Application Engineer, RF and Communications
National Instruments
0 Kudos
Message 5 of 15
(5,693 Views)

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?

  • The pulse widths will vary from 200 to 100,000 ticks depending on the speed of the motor
  • The 2 arrays need to be collected simultaneously and started at the same time
  • I will collect blocks of data up to 1 min long

 

0 Kudos
Message 6 of 15
(5,686 Views)

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.

JY
Application Engineer, RF and Communications
National Instruments
0 Kudos
Message 7 of 15
(5,664 Views)

>> 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"

0 Kudos
Message 8 of 15
(5,644 Views)

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?

0 Kudos
Message 9 of 15
(5,635 Views)
Solution
Accepted by MrSethT

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,

  • the error msg is right, you'll need to configure sample timing to be "implicit".  Implicit timing means that the timing is implicit in the signal being measured.  It's commonly used for Period, Freq, Semi-Period, and Pulse Width measurements.
  • you'll need to configure the counter tasks so they count edges of the 80 MHz internal clock and then buffer that count value on encoder edges.  I'm not near a daq machine now and don't recall the right terminology.  But your encoder PFI pins will be treated as your DAQmx physical channel for period measurement, and your 80 MHz internal clock is configured as something like either the timebase, the timebase source, or the counter source.
  • as mentioned earlier, you'll need to use an "Arm Start" trigger and *not* use a regular Start trigger.

 

-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.
Message 10 of 15
(5,622 Views)