Showing results for 
Search instead for 
Did you mean: 

Problem with Measuring Duty Cycle of a PWM Signal on cRIO9053 via NI9401



I'm currently trying to measure the duty cycle of an incoming PWM-Signal inside a Simulation Loop using NI cRIO9053 and NI9401 Digital I/O Module.

The solution i found:

- Measuring the width of the high pulse

- Measuring the width of the low pulse

- Dividing high pulse width by the sum of both (high and low pulse width).


This works by setting the "Specialty Digital Configuration" of the 9401 Module to Counter, Pulse Width Measurement and Low/High Pulse. 


The measurement itself works just fine, but as soon as i switch off the PWM signal (which should lead to a Duty Cycle of zero), the VI seems to memorize the last measurement instead of setting the measured Duty Cycle to 0.  Is there a way I can solve this issue?


Thanks in advance!


0 Kudos
Message 1 of 5

Hi Peet,


You said the VI "seems to memorize the last measurement" - is this true, or just close to true?

I'd expect based on your code that provided the loop keeps running, one of the counter values will keep increasing and the other will remain at the same value - leading to a (maybe slowly) increasing or decreasing duty cycle (depending on the last value of the input).


If the code is working how I understand it, then the key point that you might have missed (or not, but here goes) is that the CTR{0,1} values aren't being reset when you read them - if you probe the values they probably are both increasing in turn.


This means that for long measurement times, you're not getting the latest duty cycle but the average of all duty cycles so far.


Consider modifying your code to use some form of memory between iterations (e.g. Shift Register) to store the previous value of each counter, and then subtract this from the next reading to get the change in counter value. That will give you the latest measurements.

Be careful that if your loop runs quickly, this will be pretty jittery - and that the error on this measurement can be not insignificant depending on the ratio between loop iteration period and PWM period.


If you need a more accurate measurement, I'd suggest making use of the FPGA that you have to directly read the boolean values of the lines and add to a "counter" in a shift register (here I mean use Increment and a numeric value on the SR, not a counter in the context of DAQmx/hardware). This will allow you to output a duty cycle value (e.g. to a DMA FIFO) every time you get a specific transition (e.g. high to low) to ensure that a measurement is over one (or more, if you choose to count several cycles) full period and not an unknown (non-integer) number of periods.

This depends on the FPGA Single-Cycle Timed Loop rate being faster than your PWM though - I think the standard value is 40MHz for cRIO SCTL, and your inputs on the 9401 look like they can update at a rate that depends on the number of channels you're reading(?). You might need to take care to not read every iteration (or to underclock your SCTL - but you should definitely use the SCTL if you go the FPGA route).

Message 2 of 5

Hello cbutcher,


thanks for your reply!

It is true that the VI keeps the last value.

Reason is, that if you switch off the pwm signal, the state switches from High to Low one last time. From that point on, the vi counts the time of the low pulse, which never ends. The Counter also doesn't know the PWM frequency, so it thinks, that the period is just getting longer als longer.

The value of the High Pulse will only change, if another transition from low to high occurs.

You get a new measurement, everytime a pulse is finished. When there is no high pulse, it memorizes the last measurement.


I tried, to set up a second counter which counts rising edges. Afterwords i compare the value with a memorized value from 20ms earlier. If there is no difference, you know, that you either have 0% or 100% Duty Cycle. Theoretically it works, but how can you tell, if it is 0 or 100%?


I have never worked with FPGA before.. could you possibly set up a VI for me, which also transfers the calculated Duty Cycle value to a real time VI (also on the target)


Thanks in advance!!


0 Kudos
Message 3 of 5

Leaving aside for a moment the issue of 0/100% duty cycle, what's the typical period of your signal? (Or what are typical high and low frequencies/periods of the setup, if it varies a lot?).


How often do you want an update? I found when making counter measurements that a regular measurement (i.e. an update every 1ms/10ms/1s etc) was much easier to make use of than sporadic updates (depending on the input frequency), but of course this necessitates some sort of averaging/buffering/interpolation/smoothing/pick your poison... (The NI-9361 handles this really nicely, but that doesn't help since you're using a 9401 🙂 )


Returning to the 0/100% problem, here you just can't know. You have to set a maximum measurable period/minimum measurable frequency, and then anything above that (period)/below that (frequency) will look like infinity/0. This controls the sampling frequency you can use (but if you do this 'manually' with the 9401 and FPGA, you can set the rules however you like - output last value, or 0, or a 'not valid' indication, etc).


0 Kudos
Message 4 of 5

The frequency of the signal is 2kHz and also stays 2kHz. The period length therefore is 500µs. 

The duty cycle varies from 0 to 100%.. therefore the high pulse can be anything from 0 to 500µs long.

The simulation loop runs with a frequency of 1kHz, so un update is performed every 1ms.

Can you please show me, how you would implement the 0/100% solution? It would be perfect without the use of fpga.

0 Kudos
Message 5 of 5