LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

CI PWM - Period Read on Continuous measurement

Hey fancy folk,

 

As the title states, I am trying to perform a periodic read on a continuous CI PWM signal.  Based on what I've been googling around, I am not sure if I'll be able to do this based on how the PWM signal operates.

 

Background:

I have an encoder and a PWM signal that I am trying to sample at the same time.  I have the encoder running to an FPGA card (FPGA relevant later for my potential work around) to create a clock that is running to my PXI back plane which would gate my ENC and PWM read.  I am using a PXI 6602 to perform both the ENC and PWM read in LV 2015 (🙄 cuz if its not broke why fix... 😐)

 

Problem:

When I initialize my code, I am setting the sample clock and starting triggers for both tasks to a PXI backplane pins.  When I press run I get "error -200300. Property: SampTimingType. Request Value: Sample clock. Possible value: Implicit, On Demand".  I understand that this means that I can not use the sample clock to acquire my data at a constant rate, so I'll need to figure out an alternate solution.  I also understand that counter in tasks have to be set to implicit because the task itself basically runs a clock behind the scene, incrementing a counter when PWM high, then multiplying the counter by the clock period to get the PWM signal.

 

Side question:

With implicit timing set to a continuous read, I am assuming that every time my PWM goes "high -> low -> high", I am getting a new value in the read buffer (due to the "high -> low" and being sent to the buffer on the "low -> high").  Is this correct?  I ask for personal knowledge for how things work.

 

Potential Solution 1:

Since I have an FPGA card already, I was thinking about performing my own PWM read and when my clock goes high, send that value to my main code (I can see an issue with this that I'll address later).  My logic being if I set a timed loop to say 10 MHz, I can count the number of clocks pulses when high, then once it goes low, multiple the ctr by my clock (.1u * ctr) and store that until the next "high -> low" occurs.  Once the next "low -> high" occurs, I will reset the counter, and start counting again.  The catch is, I plan on keeping what my PWM read until a new valid read occurs.  

 

Basically, the issue that I see is that when my "sample clock" goes "give me your read[i] value", my FPGA code would return an [i-1] read.  I dont think I'm too worried about that, things are going to be moving slowly and I don't think a couple .1us will effect the results in any meaningful way, but I wanted to address the problem I see with this solution.

 

Potential Solution 2:

Another solution that I could see is running an on demand task for my PWM signal and have the error line of the ENC read wire directly to the PWM read.  I could set up my read loop in a sub VI and put the PWM read in a secondary sub VI.  I could set the read loop's subvi priority to high and the PWM to highest.  Theoretically, this should give me "as close as possible to sync read" without having to go down the FPGA route. 

 

I could use timed loops as well (IIRC, they have priority settings), but from what I remember I was told to stay away from using them unless I was doing RT stuff because they can "jankify" the code.  I remember a coworker getting into a problem with timed loops because they shared the same ID and LV was not happy about that one.  However, with this code specifically, I'd only have 1 timed loop, so my coworkers problem wouldn't effect mine.  

 

Anyways, any help/advice would be great. Thanks,

Matt

0 Kudos
Message 1 of 4
(91 Views)

The FPGA will give you a ton more options, but I'm not really able to give you any guidance there.  So I'll focus on things you can do with just the PXI-6602.

 

I don't know whether the 6602 supports the "pulse" measurement mode or whether that's only supported on newer DAQ devices like X-series or the 6612.  It's a nice convenience for clarity's sake to separate freq & duty cycle (or high and low time) in a cluster.

   Back when I was dabbling around with the 6602, there wasn't yet a pulse measurement mode available.  And strictly speaking, it really isn't necessary.  Instead you can configure for semi-period measurement and do the separation yourself.  You literally get an array that alternates between high intervals and low intervals.  Then you can use the function "Decimate 1D Array" to separate them.   Note: it's possible to set a starting polarity so you can identify which are the high and which are the low times.

 

Now here's the beauty of semi-period measurement -- it's kind of the "keys to the kingdom" for counter measurements. 

 

Assuming semi-period high and low times in seconds:

  • Need to know freq(i)?  That's just 1 / ( high(i) + low(i) ).
  • Duty cycle?  That's high / (high + low).  Or simply high * freq.
  • Time of a given edge?  That's the cumulative sum of all intervals leading up to that edge.  (And you *have* all those intervals in your arrays.)

 

So I would be inclined to use the PWM signal as the master timing signal.  The PWM task would do implicit semi-period measurement.  And the Encoder task would use the PWM signal as a sample clock.  This gives you one ENC sample for every 2 PWM samples (1 for low time, 1 for high).

 

More details: both tasks should be configured for an "Arm Start" trigger that you control.  With so many counters on a 6602, I'd just generate a single pulse with one of them to act as an "Arm Start" trigger that'll sync the start times of the two tasks.  After that, you can use the semi-period data to calculate times of all the other samples.

 

At that point you'll know ENC vs time, Freq vs time, and Duty Cycle vs time.  If need be, you can interpolate to express those same relationships with data that's equally spaced in time (if PWM doesn't give you that already).

 

 

-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 4
(64 Views)

Kevin,

 

Thanks for responding!

 


@Kevin_Price wrote:

So I would be inclined to use the PWM signal as the master timing signal.  The PWM task would do implicit semi-period measurement.  And the Encoder task would use the PWM signal as a sample clock.  This gives you one ENC sample for every 2 PWM samples (1 for low time, 1 for high).

 

More details: both tasks should be configured for an "Arm Start" trigger that you control.  With so many counters on a 6602, I'd just generate a single pulse with one of them to act as an "Arm Start" trigger that'll sync the start times of the two tasks.  After that, you can use the semi-period data to calculate times of all the other samples.


 

I'm gunna paraphrase what you said to make sure I understand things properly.  It sounds like this would sync my ENC to my PWM signal and since the implicit timing of the Semi Period read rising edge would tell the ENC task when to sample.  This would be time based measurements and my sampling frequency would be based on the frequency of my PWM signal.  To make sure things start at the same time, I'd want to set both arm triggers to a 6602's DO pin and set that high after initializing the tasks (I am using my Z index from my encoder as my start trigger, so I think I'm covered on this front).  I'd also want to use the CI.SemiPeriod.StartingEdge property and set that to rising, so I always know that my first read is the rising edge (and I'd set that before starting the Semi Period task).  Is this correct?  

 

Question, would it be possible to instead sync things via position based sampling of the ENC with this method?   Ideally I'd like to keep my reads at a consistent position because the test itself is trying to measure magnetic flux and compare the flux with the magnet at set positions from the sense board.  I think position based sampling with the z trigger as my start will give me "the most repeatable data" that I can get.  However, I dont want perfection to get in the way of progress, ya know?

 

Additional question regarding semi period measurements.  I'd like to digress to the time based solution for my question since I think that'll be the easiest way for me to ask it.  In this method, I am using the implicit PWM signal to gate my ENC read based on the PWM going high.  If my read loop is set to say 100 ms and my PWM signal has a period of say 6 ms, that would theoretically give me 16.66 samples per iteration through the loop for the semi period task.  That means that sometimes when I read the semi period task, I'll get 16 reads and other times Ill get 17 reads.  If I am telling my code to "read all samples" would that mean that my "0th" sample read would be high or low time, since I theoretically could read 17 samples which would be an additional high or low time?  I understand that I can query the PWM signal for number available at port, do a %2 and request quotientx2 samples, thus giving me an even number of samples every time.  I just wanted to make sure I am understanding the semi period implicit read properly.

 

Possible solution to syncing position based sampling with implicit semi period:

If I wanted to do position based sampling, I could run through my read loop faster than the ENC reads new data, then request 1 sample of the ENC per loop (which would be using the timeout as my loop time).  I'd have the ENC read's error routed to the PWM error in and request all samples read (potentially the available samples % 2 * 2 sample numbers from the previous paragraph instead).  From there, I could find the last 2 elements in the implicit continuous PWM read data array, which should theoretically be my "most recent" read (IIRC, 0th element is "oldest" and last element is "newest").  I am not sure if this is a "good enough" solution for "syncing PWM to ENC for position based sampling".

 

Thanks,

Matt

0 Kudos
Message 3 of 4
(47 Views)

Overall you've got an excellent grasp of all this stuff.  I have just a couple little things to address and maybe a few thoughts to expand further.

 

To make sure things start at the same time, I'd want to set both arm triggers to a 6602's DO pin and set that high after initializing the tasks (I am using my Z index from my encoder as my start trigger, so I think I'm covered on this front).

 

Almost, but maybe not *quite*.  It's conceivable (and with enough trials, inevitable) that the Z-index could occur between the instants when you call Start Task for the two tasks.  Then the tasks would trigger 1 rev apart.   Using a DO pin that you can control programmatically would solve *that* problem but wouldn't sync your ENC data to the Z-index.  My recommendation would be to use another counter set to trigger off Z-index and generate a short pulse following a minimal initial delay (could be < 1 usec).  Then config your measurement tasks to use that counter's output pulse as their Arm Start trigger.  And again, make sure that single pulse task isn't started until *after* both other tasks are started.

    Other than that, your first paragraph sounds spot-on.

 

 

As to syncing according to ENC position, there are some options that are probably suitable provided that you run your tests with *unidirectional* motion.  There's *not* a good hardware-based mechanism for syncing samples to specific positions when there are direction reversals.  Something like *that* would require FPGA.   But it sounds to me like the unidirectional assumption is safe to make for your situation.

    What gets tricky is figuring out what kind of time correlation you need between ENC data, Flux data, and PWM data.  ENC and Flux tasks are hardware clocked by encoder pulses, so they correlate nicely.  But PWM is getting clocked by the PWM signal itself.  Very likely *NONE* of the PWM samples will exactly correspond in time to any of the ENC or Flux samples.  So the big question is, how would you want to deal with that?

    You proposed an idea based on reading 1 ENC / Flux sample per loop followed by reading ~all_available samples from PWM and only keeping the most recent one.  That basic idea is ok only if your read loop can definitely keep up with your encoder pulse rate and your PWM freq is definitely greater than your pulse rate.   What range of encoder rates do you anticipate?  Anything approaching or exceeding 1 kHz would make me pretty doubtful about your loop keeping pace reliably enough. 
    Note: it definitely won't be perfectly regular under Windows, but I've seen "good enough" results running a 100 Hz PID loop under Windows.  The timing variation just became another perturbation for the controller to suppress.  For your situation, the anomalies will be mostly-very-small timing irregularities in your PWM data.  The ENC and Flux data should be fine, it's clocked and buffered in sync so it doesn't matter if you retrieve it from the buffer at slightly irregular time intervals.  But the PWM data will be *assumed* to occur at a specific rate that isn't quite the truth.
    If your ENC pulse rate is too fast for 1 sample per read, you could try something like the following.  Let's just say the rate is nominally 2 kHz so you want to read 200 samples per loop.   Let's further suppose that PWM is at 25 kHz so you can expect about 2500 pairs of samples available.  Well, you could run a little decimation algorithm on your PWM data to reduce it down to 200 pairs of pretty-equally spaced samples.  Just be a litt le careful that you don't try to force the inclusion of *both* the beginning and ending of the data set because that won't leave the right time spacing between the last kept pair from one loop iteration to the first kept pair from the next iteration.  My inclination is that it's best to bias the spacing such that you end up keeping the very last pair from a set which is the very most recent data.  So the first pair will not be at index 0 but rather at an index something like 12.
    This is getting kinda complex too though.  Maybe not worth trying to do on-the-fly in near real time?   Would it be sufficient to capture data with a sync'ed start time and sample timing that's either known or can be calculated, and then do all the learning offline after post-processing?

 

 

Some general semi-period info.  Yes, you'd want to always deal with the data using even numbers of samples because the array gets filled in literally in sequence as the intervals end - high time, low time, high time, low time, high time...

    But there IS one subtle catch.  You should very likely ignore and discard the very first value captured by the task.  On the 6602, that very first value will be the time from task start (the assertion of the Arm Start trigger) until the first "Starting Edge".   Every sample after that is an interval where both endpoints are defined by the PWM signal, but the very first interval starts its measurement at an arbitrary time relative to PWM edges.   (This behavior was changed in later hardware such as X-series and 6612 counters.  That can lead to a different, albeit more rare problem.)

 

 

-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 4 of 4
(37 Views)