LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Multi-channel PWM generation on M series, CPU usage fluctuates "sawtooth like"

Hi,

 

I am trying to generate ten 1kHz PWMs with 0.1%  resolution for motor control with an update rate of 1kHz on a RT desktop PC, I use a Port0/line0:9 and Ctr0 on a PCI-6229. I started with this example : http://zone.ni.com/devzone/cda/epd/p/id/5043 

 

I removed the event structure and replaced the while loop with a timed one (period of 1000us), I want to control which CPU this will run on. I don t update the counter frequency only the DO array.

 

I monitor the loop execution period; it goes from ex.: ~670us to 970us, stays there for a few seconds and drops back to 550us and again up to 980us, like a sawtooth waveform. At the same time the CPU usage goes from 60% to 100% in the same way.

 

So I thought it might have something to do with the buffer writing, so I disabled regeneration, now the execution period is stable at ~100us (why not 1000us?)  for a few seconds and then slowly increases up to 1ms and it starts doing exactly the same thing as with regeneration turned on. I decided to monitor the output buffer size at the same time and the increased CPU usage corresponds to a drained  buffer. Initially the buffer size dosen t change, but after a few seconds it starts dropping from around 700 ( why not  1000?) to 40, and once at 40 the fluctuation begins. 40 is also the buffer size when regeneration is on.  I increased the buffer to over 1000  and it buys me some time until it drops to 40. I can always set it to something huge but that s not elegant.

 

I can also control the buffer size by adjusting the period of the while loop, -1us drains the buffer faster, +1us replenishes the buffer, I can have some code do this continually, but again not elegant.

 

I also noticed that setting the buffer size to an odd number makes it replenishes itself to a value of ~900 once it reached 40, and CPU stays at 15% all the time, thought while running overnight for a test it stopped on a buffer error... but still strange.

 

Any help greatly appreciated or any other approach to generate those PWMs.

thank you

 

 

Message Edited by L. Andrzejewski on 11-13-2009 11:15 AM
0 Kudos
Message 1 of 5
(3,793 Views)

I found this http://zone.ni.com/devzone/cda/epd/p/id/4197#0requirements

but I can t run it, it s too old...

0 Kudos
Message 2 of 5
(3,786 Views)

Hello,

 

The first question that I have for you is why you decided to remove the event structure? Basically by taking that out, you're making the code execute those DAQmx write VIs over and over in your loop. This would definitely change your loop rate if you're trying to run those VIs each execution of the while loop. Also, why are you using a timed loop? Is it purely to assign a CPU for execution? because the way this code is set up to run is basically to run independently of the OS unless you change the duty cycle values. So, unless you want to monitor whether the duty cycle values are being updated at 1ms loop rate exactly every time, then you don't really need a timed loop. If this is what you're looking for, then a timed loop is a good idea, but you should still keep the event structure.

 

The fact that you're seeing the loop rate fluctuating doesn't mean that the generation is not working properly. Also, disabling "Allow Regeneration" is going to change the way this code executes for the worse. From what it sounds like, you should actually just run the code exactly as it is on the Developer Zone document and it should generate exactly the way you want. Have you tried checking the outputs to see if it looks the way you want? Also, how are you monitoring the buffer size through this execution? It might help if you posted your code with these modifications. I'm happy to take a look.

 

Chris W

0 Kudos
Message 3 of 5
(3,737 Views)

Hello Chris,

 

I disabled the Event structure because  I am running on RT ETS and I want to update my PWM at 1kHz rate, this is also the reason why I am using the timed structures. Another reason is that i actually sample 32 AIs, filter them and close the PID loop with 11 PWMs outputs, all at an update rate of 1kHz. So AI and filtering is done on a different CPU than the PWN generation and communication exchanges, at different rates. I have regeneration disabled because I found it is the fastest way to update the DO for the PWM. I do monitor the buffer and when it runs out the performance suffers, the CPU starts fluctuating, as I said the only solution I have found is to slow down the main writing DO loop by 1us to 999us and let the buffer replenish. it replenishes much faster than drains, so after a few seconds It is full again and I can switch back to 1000us for many minutes...

 

Right now it works and my CPU usage stays below 25% ...but I am still curious if I am doing something wrong or how to do it without handling the buffer.

 

thx for reply

 

Lukasz

Message Edited by L. Andrzejewski on 12-01-2009 03:46 PM
0 Kudos
Message 4 of 5
(3,667 Views)

Hi Lukasz,

 

So, the issue here is that you're monitoring the loop rate of your 1kHz timed loop. This loop is made so that it will execute every millisecond, but the DAQmx API are not deterministic function calls. So, because we can't guarantee their determinism, you will see your loop rate fluctuating. As long as your loop is exectuing every 1ms and you immediately  call the DAQmx Write function to update the output buffer, this is as close to a solid 1kHz update rate that you'll be able to acheive.

 

The issue that seems to be coming up with your loop execution rate that directly affects the CPU usage and replenishing of the buffer, is when the execution of the DAQmx VIs in the while loop cannot execute in under 1ms. This causes some delays in replenishing that buffer, which is why the buffer size is dipping and consequently means that the CPU has to work as hard as it can to execute those actions in an amount of time that will satisfy the timed loop. 

 

Another thing that is going to help with this issue, is allocating a larger buffer size than the 1k that you have. This will provide more wiggle room while writing new data to it.

 

I still think that keeping the event structure in this loop and leaving the "allow regeneration" on will help the performance of this execution because you will only update the buffer when the user (or accompany PID conditions) wants to change the duty cycle. And since the DAQmx API execution is not deterministic within the timed loops, your update rate should as good, if not better, than without the event structure.

 

Also, another option you have is to simply use a counter output task and only update the duty cycle of that counter output when the duty cycle changes. I would have a look at the two example programs that are available on our Developer Zone Community. Take a look HERE and HERE.

 

I hope that helps explain things and gives you good options.

 

Chris W

 

 

0 Kudos
Message 5 of 5
(3,647 Views)