LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Labview temperature PID control w/ NI 6211

Hello,

 

I am relatively new to Labview, so excuse my misunderstandings, but I am trying to construct a PID controller VI.  Basically, I would like to read temperature of a heater from a thermocouple, and use PID to control the voltage powering the heater, such that the heater is maintained at a setpoint temperature (say 100 C).

 

I am using an NI 9213 to measure thermocouple readings, and that VI is successfully running.  For the PID control, I have referred to the PWM-Counter Output example VI.  I understand that I need to change the "proportional gain" VI to the PID VI, and this involves having a few more k-constants (for the proportional, integral, and derivative terms).  My misunderstanding is in how these constants are determined.  Are they simply defined by the user in the front panel, or should they be in a certain general range to deliver quick convergence to the set point?

 

Once I have that running, I will use the output PWM voltage to an H-bridge motor controller in order to drive the heater.

 

- T

0 Kudos
Message 1 of 18
(9,452 Views)

PID tuning is based on the characteristics of the system you're trying to control.  In a heating system, the proximity of the feedback sensor to the heating element is usually the most critical.  Once you get your system built and running, start with a small P term. You'll probably get some overshoot followed by an oscillation around your setpoint.  Add a little I term to settle the oscillations.  Then, iterate.  Add a bit of P, then some I, over several cycles until you tune in your fastest response that does not go unstable.  Pick different setpoints to force the system to move  in both directions and at different magnitudes.  You probably won't need any derivative (damping) with a slow heat loop.

 

PID tuning is kind of an art.  Once you play with an active system for a while it will become second nature.

 

EDIT:  BTW, there are several tutorials on PID tuning out there:  http://www.jashaw.com/pid/tutorial/pid6.html   Or, just Google PID Tuning Tutorial.

LabVIEW Pro Dev & Measurement Studio Pro (VS Pro) 2019
Message 2 of 18
(9,445 Views)

Thank you, that is very helpful information.  I was unclear on how the constants were obtained, but now that I see it's basically through experimentation, I am not worried.

 

The other concern of mine was integrating the previously mentioned two systems.  Right now, I have the VI that reads temperature from the thermocouples (see attached image), and the code runs inside a while loop, reading data at 1 sec intervals and writing to a notepad file.  The other code, involving the PID, runs in a while loop as well (see the PWM-Counter Output example).  Is there an easy way to synchronize the processes such that, at every second, the data will be read from the thermocouple, then passed to the PID loop and iterated until I hit stop.  I was thinking of either incorporating my entire PID VI as a sub-VI in the program attached, or somehow synchronizing the loops to both run at the same increments.  Is one of these methods better or more robust than the other?  I am a bit iffy on the most efficient methods of data flow programming...

 

Thanks again.

 

- T

0 Kudos
Message 3 of 18
(9,436 Views)

I wouldn't say that PID tuning is "basically experimentation."  You might get the reasonable values that way, or you could struggle for a long time without getting good control.  Fine tuning is often experimentation, but you'll get a much better starting point by using one of the standard approaches such as Ziegler-Nichols or Cohen-Coon.

 

There's not enough information in the single image of your code you posted to understand exactly what you're doing.  The easiest way to synchronize them is to put everything in the same loop.   Feed the output of the DAQ Read directly into the PID Process Variable input (with whatever scaling is necessary first), and then wire the PID output into your DAQ output (or PWM).  You can do the logging in the same loop as well.

0 Kudos
Message 4 of 18
(9,428 Views)

I have attached a preliminary version of my VI.  Hopefully this can help clarify things.

 

Everything is in the same loop now.  For the one-second iteration, I have used the While Loop Iteration indicator as I did in the previous temperature-reading VI.  I am just not sure if this timing method will conflict with the Sample Clock that is used with the counter (this I left from the original PWM Counter example), since I see later on that there is a Wait For Next Sample Clock that seems to also tell the program to iterate...

 

Also, I get a runtime error saying "PID: No Owning Project" and I couldn't really find anything describing why this error came up.

 

Thank you for your help and patience.

0 Kudos
Message 5 of 18
(9,413 Views)

I'm not sure where you found the crazy PID function, but try replacing it with the one found in the palette under Control Design & Simulation -> PID -> PID.vi.  You'll need to bundle your PID gains into a single cluster but otherwise the wiring is straightforward.  This should fix the "No Owning Project" error.  Alternatively, create a new project and move your VI into it.

 

You should change the DAQmx Read instance to "DBL" instead of "Waveform" since you're only reading a single point and you don't care about the timing information.

 

You misunderstand the while loop iteration terminal.  It has no effect on the loop timing.  The only wait in your loop is the Wait for Next Sample Clock, and I don't even know if that will work for a single-point software-timed acquisition (in that configuration there's no need for a continuous sample clock).  It would be simpler to remove the Wait for Next Sample Clock, and put a Wait (ms) function in the loop with 1000(ms) wired to it.  That will get you a 1-second cycle time.

 

For pulse train generation, the DAQmx Timing instance should be set for "Implicit," not "Sample Clock."

 

You're only going to record 30 points of data in your array, but your loop will continue to run after that; it just won't add new data because you'll be past the end of the array.  Is that what you intend to do?

0 Kudos
Message 6 of 18
(9,382 Views)

Again, all very helpful points!

 

I see what you are saying about the regular "Wait" function, that is actually what I originally used in that temp-reading VI.  I left it out because I thought the Sample Clock VI took care of it, but apparently that is not the case.

 

So the reason I used waveform is because I wished to record the times along with the data in the excel file, so that later I can plot a temperature vs. time profile.  I know that the time info is not needed for the PID process, but I still wish to record it into a spreadsheet for other purposes.  So in this case, would I still want to change it to data type "Double"?

 

Along those lines, when you say "Single Point acquistion", this means 'one point per iteration', correct?  Because for the timing VI (which I will change to Implicit), I was wondering if the sample mode, currently set to Harware Timed Single Point, is correct?  Or should it be set to Continuous Samples?  Also 30 items in the spreadsheet was just a test value to see if the program would work, I will increase it later on...

 

Finally, to cluster the gains, would I use a regular Bundle function or the Build Cluster Array?

 

- T

0 Kudos
Message 7 of 18
(9,377 Views)

You're a bit confused about the Sample Clocks here.  You have two separate DAQmx tasks.  One is the Analog Input, the other is the Counter Output.  You're waiting on the next sample clock of the Analog Input, but I don't know if that will ever occur because you're not using the hardware to time the acquisition.  Instead you configured the task to acquire a single point of data whenever you tell it to read.  You're not setting a clock rate for the analog input anywhere.  I haven't tested this and cannot do so right now - maybe the sample clock does still run in this configuration, but if so I don't know what frequency it would run at.

 

The Sample Clock VI is wired to the Counter Output task, so it has no effect on the Analog Input.  For a Counter Output task, you should use Implicit timing.  I've never fully understood the details of that function, but that's what the help tells you to do.  The mode should be Continuous Samples, because you want to generate the PWM signal continuously (or at least, I assume that's what you want to do).  Again, this timing is only for the counter output task.  The DAQ Assistant for the analog input probably executes some of the same VIs internally, but that's all hidden from you by the Assistant.

 

If you do intend to use the timing information then the waveform is fine, although at one second resolution, you could equally well just use one of the Time/Date functions to get the current time when you write the data to a file (or to an array that you later write to a file).  It just takes a bit more work to extract a single point of data from a waveform because you have to extract the data array, then index out that single element, and you only want to feed a single point into the PID.

 

You want to use Bundle to build a cluster of the PID gains.  You'd get broken wires if you tried to use Build Cluster Array.

0 Kudos
Message 8 of 18
(9,372 Views)

Hey thimz,

 

Your final VI should look something like this;

 

DAQPID.png

 

This is relatively simple, software timed VI that demonstrates the basic structure of using the PID tools with a DAQmx device. Obviously, your code will have more logic to it, but this would be a good template to jump off from.

 

John B.
Embedded Networks R&D
National Instruments
Certified LabVIEW Developer
0 Kudos
Message 9 of 18
(9,361 Views)

I'm sorry, but this isn't a particularly good example of LabVIEW code.  Why, WHY, would you put that sequence structure there?  It's not doing anything except making the block diagram unnecessarily complicated.  Also, it would probably be a good idea to put the setpoint, and probably the the PID gains, inside the while loop so that they can be changed while the code is running.  It would be reasonable to chain all the error wires since you know the sequence in which the VIs will execute; that is, run a single error wire through the AI Read and the Counter Write.  Finally, there should be a wait somewhere inside that loop to set the loop rate and prevent it from executing as fast as possible.

Message 10 of 18
(9,356 Views)