Counter/Timer

cancel
Showing results for 
Search instead for 
Did you mean: 

PCIe6612: Inverted PWM duty cycle reported by PWM measurement.

Hello,

 

Using the NI API, I have output a PWM signal which I then measure with another counter on the same card.  Works fine.  Without too much effort, I can introduce a disturbance such as disconnecting and then reconnecting the running PWM signal.  This disturbance causes the PWM measurement to report an inverted duty cycle.  An external oscilloscope will show a 20% duty cycle, the NI API will return and 80% duty cycle.  I can then change the duty cycle on the fly to 70%.  The oscilloscope will show a 70% duty cycle, but the NI API will return and 30% duty cycle.  Any way to stop this or recognize that it is happening in the software?

 

Thanks for any info.

0 Kudos
Message 1 of 6
(2,420 Views)

What DAQ device are you using?  And please post the code (back-saved to ~LV 2018 or earlier, if necessary) for your measurement task.

 

Long long ago, E-series devices with old legacy DAQ drivers didn't support the ability to specify the polarity of the first edge for a semi-period measurement.  So attempts to measure duty cycles could be ambiguous.   I don't know whether it was a hardware or driver limitation, but any devices I know of designed in the last couple decades and using DAQmx are configurable and unambiguous. 

 

 

-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 6
(2,390 Views)

I am using a PCIe6612 on a Windows 10 OS with NIDAQmx

 

Request Code Attached.

 

ScanNI.cpp is a thread that is ticked every 10ms and it process the NI counters via vProcessCounter

NIControlService maps the counters (boMapPwm and boMapPwmMeasurement) and sets up the ScanNI thread.

PCIe6612.h contains class with member functions

Download All
0 Kudos
Message 3 of 6
(2,380 Views)

Mea culpa, I wrongly assumed LabVIEW.  That's what I know, not C++ or its API for DAQmx.  I can only follow the broad strokes, not so much any of the details.  So with that caveat up front, here goes...

 

1.  You have a bunch of commented-out code labeled as "Finite Data Working Version".  Is that "working" as in "work in progress", experimental, or "working" as in verified good?   

 

2.  I notice that you use Pulse measurement mode in your Continuous code while using Semiperiod measurement mode in your Finite code.   Reasons?

 

3.  Most of my substantive counter work pre-dates X-series boards and any notion of "pulse" measurement mode.  I haven't need to experiment with it this past decade or so that it's been around, so I can't speak from experience about any caveats or quirks (if any).

    I *did* use semiperiod a good bit though, hence my comments in a previous msg about very old hardware that gave ambiguous data b/c it didn't support polarity selection, i.e., there was no way to know whether the first value in the buffer would be a low time or a high time.

    I checked in LabVIEW and both modes allow you to define this explicitly.  I can't say for sure what the default behavior would be when you don't, but I wouldn't rule out the possibility that DAQmx might react to the first edge *whatever it is*.

    In the case of semiperiod measurement, DAQmx returns a buffer with alternating high and low times.  Or possibly low and high times, depending on where it starts.   In the case of Pulse Frequency measurement, I cannot say for sure whether it *always* considers duty cycle to be high/(high+low) or whether it might consider it to be 1st/(1st+2nd) interval.

    In any event, try being explicit about the "starting edge" configuration.  In LabVIEW, the property node to set it looks like this:

                                                  Kevin_Price_0-1674038473491.png

 

4.  It appears to me that you want your Continuous task to buffer measurements, overwrite old ones when the buffer fills, and return only the single most recently captured pulse measurement each time you want to read from it.   That can be a valid approach when you don't ever want to wait for new data to arrive, and don't mind losing some of the data and possibly retrieving the same value many times. 

    Just be aware that there are also approaches that let you prevent waiting without a serious risk of losing or repeating data.

 

5.  I'd encourage you to do more experiments, especially after incorporating the ability to explicitly define the "starting edge" polarity.  Report back with findings.

 

 

-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 6
(2,362 Views)

Thanks for the help and information.  Answering questions and reporting results below based on your numbering.

 

  1.  The finite data was working to a certain extent.  Meaning I could measure PWM signals.  However,
    1. Over scans occurred.  I have 10 milliseconds to complete the reading and writing of all I/O in our system.  I cannot wait around for a read to come back.  I believe the over scans were because I had to start and stop the task each time I wanted a reading.
    2. There was no way to detect a zero time out.  In other words, how do I know when the PWM signal actually stopped if the last reading is always in the buffer when I read it.  I want to know when the PWM signal stops without using another counter.
  2. I could not get continuous working with the SemiPeriod. I had to stop and start task to get new reading.  Do you think there is a way to get SemiPeriod to continuously update without stopping and starting the task?
  3. Tried two ways to be explicit about starting edge.  I believe both calls probably just do the same thing.  Neither fixed the inversion issue.

 

DAQmxSetCIPulseFreqStartEdge(hTask, sName, DAQmx_Val_Rising)

 

DAQmxSetChanAttribute(hTask, sName, DAQmx_CI_Pulse_Freq_Start_Edge, DAQmx_Val_Rising)

 

  1. You are correct. I don’t mind losing data and possibly retrieving the same value many times. I just need a 10ms snapshot that is synchronous with all my other I/O.  I am open for other approaches that prevent waiting.
  2. Reporting back.
0 Kudos
Message 5 of 6
(2,298 Views)

After more consideration, I'm pretty stuck. 

 

Semiperiod measurement mode would deliver alternating high and low times in a single array.  Calculation of freq and duty cycle are up to the application code, and an off-by-one error when indexing into the array would result in an apparent PWM inversion.  

 

But you're using Pulse Frequency measurement mode, putting DAQmx in charge of tracking the distinction between rising and falling edges, high and low times so it can determine freq and duty cycle.  There's no way to accidentally misinterpret the data on the app side.  

 

All I can think of is that there may be extremely fast digital transitions or "ringing" caused by the abrupt signal disconnect, faster than the device can properly latch.  So perhaps somehow an extremely brief high time like 2 nanosec is missed and the next low time of, say, 80 nanosec is captured.  But now the FIFO holds 2 adjacent low times that will be delivered up to the task buffer, causing DAQmx to become "off-by-one" for subsequent data and mixing up which times are high times and which are low.  And thus, duty cycle inversion.

 

That's just a highly speculative thought trail without enough basis to consider it a theory.  But try configuring your PWM measurement task to add digital filtering on the input PFI pin.  Try setting it for something in a range like 100-500 nanosec.  That should suppress transients that are too fast for the board.  If the digital filter helps, maybe my speculation wasn't so far off after all.

 

 

-Kevin P

 

 

-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 6 of 6
(2,289 Views)