System Control Implementation Using LabVIEW 8.0 Michael Kleinigger, RPI Undergraduate Engineering Student Dr. Kevin Craig, Professor of Mechanical Engineering RPI Mechatronics Laboratory – UPDATED 1/18/2007 In this tutorial we will explore the process of implementing a previously-developed control scheme within LabVIEW. As an example, we will walk through the necessary steps to implement a controller, for both swing-up and balancing, for the Rotary Inverted Pendulum system, pictured below. The Engineering System Investigation Process was followed to thoroughly understand the system and then design several controllers to swing up and balance the inverted pendulum. LabVIEW allows one to quickly prototype a controller on the hardware system, as the controller previously developed and simulated in LabVIEW is quickly and effortlessly effortlessl y implemented on the actual hardware system. This tutorial shows you how this is done. What would have taken days or weeks to implement if programmed on a microcontroller can be accomplished in a matter of hours with National Instruments’ LabVIEW.
+ I m1121 + I1 + m 2 12 + m 2 221 cos 2 φ + I2 cos 2 φ + I2 sin 2 φ θ + I2 − m 2 1 21 sin φφ 2 I2 − m 2 221 − I2 ( 2 cos φ sin φ ) φ θ = T − B θθ + Tfθ sgn ( θ ) z1
z2
y2
m2 221 + I2 φ + I2 x2
x 2y 2
y2
x 2 y2
x 2y 2
− m 2 1 21 cos φφ +
2
z2
2 2 − m 2 1 21 sin φθ + m 2 21 − I2y + I2z ( cos φ sin φ ) θ + m 2g 21 cos φ = − B φφ + Tfφ sgn ( φ )
2
2
1
The Rotary Inverted Pendulum was first developed by students in Professor Kevin Craig’s Mechatronics System Design course in the spring of 1999. It has gone through numerous revisions since. Classical, state-space, and fuzzy logic controllers for balancing, as well as an energy-based swing-up controller, were originally designed using Matlab / Simulink and implemented using dSpace. We will be implementing both state-space and classical controllers, as well as a swing-up controller, in LabVIEW. Then we will configure our virtual instrument (VI) so that we can switch between state-space and classical control on the fly in order to compare the two controls. Step 1 - Beginning First, open LabVIEW 8.0. Once the “Getting Started” screen has appeared (Figure 1), select “Blank VI” under the “New” menu. You should soon see a blank front panel and behind it an empty block diagram (Figure 2).
Figure 1
2
Figure 2
Step 2 – Simulation Loop Switch to the block diagram by clicking the block diagram window or pressing Ctrl +E. This same keyboard shortcut can also be used to return to the front panel.
We will begin building our control system by adding a simulation loop. You will need the simulation module installed in order to use this. If the simulation loop is not available, a possible solution is to use a simple while loop or a timed loop. However, the simulation loop typically provides much better performance and accuracy. To add the simulation loop, right-click in any white space on the block diagram. You will now see the functions palette (Figure 3). If you’d like, click the thumbtack in the top left corner of this window to fix it in place. Now move your mouse over “Control Design and Simulation” → “Simulation”, then select the simulation loop. Your cursor will change its icon and you can then click and drag to place the simulation loop onto the block diagram (Figure 4). If at a later time you wish to adjust the size of the loop, you may click to select it, then click and drag the boxes which appear on its edges to adjust the size.
3
Figure 3
Figure 4
4
To set the simulation loop parameters, right-click anywhere on the thick black border of the loop and select “Configure Simulation Parameters.” In the window that appears, make the following changes. • • • • •
Simulation Final Time: “Inf” (click in the box, then type) ODE Solver: “Runge-Kutta 1 (Euler)” Time step: 0.005 Under the “Timing Parameters” tab, uncheck “Software Timing” and select “1 kHz” under “Loop Timing Source” Set the loop timing period to 5, then click OK.
These settings, as you might guess, cause the simulation loop to run indefinitely, executing all blocks within it every 5 milliseconds. Step 3 – Sensor Input Next we will add our DAQ Assistant input block, which will allow us to receive data from our two position encoders. To add this block, right-click in any white space on the block diagram. Move your mouse over “Express” → “Input” and from the resulting window click “DAQ Assistant” (Figure 5).
Figure 5
5
Place the “DAQ Assistant” block within the simulation loop on the block diagram. A window will now appear which will allow you to configure your input (Figure 6). At this point, make sure you have connected your data acquisition device and have connected your sensors as appropriate. Note that to find out where on your device or breakout board you must connect your input sensors, open the Measurement and Automation Explorer (Start → All Programs → National Instruments → Measurement and Automation). Once this is opened, expand the list to the left to find your DAQ device and from the toolbar on the top right select “Device Pinouts”. We will be using the National Instruments USB-6211 DAQ device, which can be configured to convert the encoder pulses to angular positions. We will now select Counter Input → Position → Angular.
Figure 6
Note that for other systems, an analog or digital input may be appropriate depending on the type of sensor you are using. For example, this system was at one time tested with an external device that produced a voltage output proportional to velocity. In order to read that voltage, we created a DAQ Assistant block which was configured for Analog Input → Voltage.
6
Next, you should see a list of your attached DAQ devices. We are using the USB-6211 and will select “ctr0” from the list. Click “Finish” and LabVIEW will present you with another window in which you can configure the DAQ Assistant block (Figure 7). • • • •
Set the value of “Pulses / Rev” to 1250 Set “Initial Angle” to -3.14159, and “Units” to “Radians” Set “Decoding Type” to “X4” Make sure that “1 Sample (On Demand)” is selected under “Task Timing.” This is important since we will be acquiring single data points at each iteration of the simulation loop, rather than groups or at hardware-specified frequencies.
When creating an input for your own system, you may want to click the “Test” button to verify that input is being properly read. For an analog input voltage, a common mistake is to leave the “Terminal Configuration” set to “Differential” (the default choice), which tells LabVIEW to make differential voltage measurements, instead of measurements with respect to ground. To make measurements with respect to ground, select “RSE” instead. Once finished, click OK and LabVIEW will build the DAQ Assistant block.
Figure 7
7
For our system, we will repeat step 3 once more to add another counter input. This time we will select “ctr1” from the “Create New…” DAQ Assistant window. For this encoder, which will return the angle of the horizontal arm, we will set our “Initial Angle” to 0, and our “Pulses / Rev” to 512. In general, a unique DAQ Assistant block must be created for each counter input. However, several analog or digital inputs (or outputs) can be grouped into a single DAQ Assistant block by holding the control key and selecting multiple inputs from the “Create New…” DAQ Assistant window. Then, to read those inputs on the block diagram, you will need to add a “Split Signals” block, which can be found on the functions palette under “Express” → “Signal Manipulation”. Connect this block to the output of your DAQ Assistant block and increase its size to the number of channels in your DAQ Assistant block. The output from the split signals block will be in the same order, top to bottom, as the DAQ input channels. For DAQ Assistant output blocks using multiple channels, you will need to add a “Marge Signals” block, also found under “Express” → “Signal Manipulation”. Step 4 – Angle Normalization Now that we have our input blocks, we need to “normalize” the angles we read from our encoders. This will be done such that, in the case of the pendulum, one revolution begins at - π, reaches zero at the balancing point, then increases back to π as the pendulum falls, and immediately flips back to - π.
• • •
• • • • •
• •
First, open the functions palette and select “Express” → “Signal Manipulation” → “From DDT” Click to place this block, then from the window which appears, select “Single scalar” from the list of resulting data types and click OK. Wire the input to this block to the output from our DAQ Assistant block by left-clicking on the small blue arrow to the right of the word “data” on the DAQ block, then again leftclicking on the left side of the “From DDT” block. Next, add the “Quotient and Remainder” block, found on the functions palette under “Programming” (opened by default) → “Numeric” Wire the output from the “From DDT” block to the “x” input of the Q&R block (top left terminal). Now open the functions palette and select “Express” → “Arithmetic and Comparison” → “Express Numeric” → “Express Math and Scientific Constants” → “2*π” Wire the 2*π block to the “y” input of the Q&R block. Next, add a subtraction block (“Programming” → “Numeric”) and connect the remainder output from the Q&R block (top right) to the “x” input of the subtraction block. Create a second wire branch from the 2* π block by clicking once on its output line, then clicking on the “y” input to the subtraction block. Add a switch block (“Control Design and Simulation” → “Simulation” → “Nonlinear Systems” → “Switch”) Create two more wire branches from the remainder output of the Q&R block and connect them to the “control input” and “input 2” terminals of the switch block.
8
• • •
Connect the output from the subtraction block to the “input 1” terminal of the switch block. Double-click the switch block to open its configuration page. Change the “Parameter source” dropdown box to read “Terminal” and click OK. Finally, add the “ π” block, also found under “Express” → “Arithmetic and Comparison” → “Express Numeric” → “Express Math and Scientific Constants” → “π.” Connect this to the “threshold” terminal of the switch block.
Rather than repeating this procedure for the second encoder input, click and drag a box around the blocks you have just created. Then, while holding the control key, click and drag the selected blocks to create a copy of them (Figure 8).
Figure 8
Also note that it is possible to name these blocks to make it easier to differentiate between them later. Double-click on the words “DAQ Assistant” and you will be able to type in a new name. You can also double-click anywhere on the block diagram to add a text label. Step 5 – Encapsulation We have now completed all the steps necessary to accept and process data from our position encoders. In order to keep our block diagram neat, we will create a subsystem from the blocks we have created thus far. This will also allow us to re-use this set of blocks quickly and easily.
We must first add indicators to our system to let LabVIEW know which values we would like to set as outputs from our subsystem. To do this, move your mouse over the “output” terminal on one of the switch blocks. Right-click and select “Create” → “Indicator.” You may type to label this indicator as shown in Figure 9. Repeat this procedure for the other switch block output as well as the wires connecting the “From DDT” blocks to the Q&R blocks (Figure 9).
9
Figure 9
•
• • • •
Next, click in a blank space above and to the left of the DAQ Assistant blocks, but still within the simulation loop. While holding your left mouse button, move your cursor diagonally across the blocks until they are all within a dashed-line rectangle. Release your mouse button. If you were unable to select all of the blocks in one pass, hold the Shift key and click to select other blocks and wires. Finally, click the “Edit” menu then choose “Create Simulation Subsystem.” For easier viewing, right-click the subsystem block which has just been created and select “Icon Style” → “Text Only” (Figure 10). Select the four indicators and press the delete key, since they will not be needed. If there are any disconnected wires remaining, press Ctrl+B to quickly delete them.
Figure 10
10
Step 6 – Velocity Computation We will now begin the implementation of the state-space controller. For the Rotary Inverted Pendulum System, we account for four states: arm position, pendulum position, arm velocity and pendulum velocity. Since we cannot read velocity directly from the encoders, we will need to take the derivative of position in order to compute velocity. However, since the position signals from the encoders are given in discrete steps, we will first need to “smooth” our input signals using a transfer function low-pass filter (otherwise we would see large spikes in velocity at every count of the encoder).
• • • • • •
Right-click in any blank space on the block diagram and select “Control Design and Simulation” → “Simulation” → “Continuous Linear Systems” → “Transfer Function”. Place this block close to the output from your encoder subsystem. Double-click this block to open the configuration window (Figure 11). Change the value listed under Denominator → a1 from “1” to “0.03” as shown. Click OK. Hold down the control key and click and drag the transfer function block we just configured to create a copy with identical configuration.
Figure 11
11
Once you have finished configuring the transfer functions, connect their input terminals to the “arm angle” and “pendulum angle” terminals of your formula block. Your block diagram should now look similar to Figure 12.
Figure 12
Next, we will add the derivative block, which completes our velocity computation. • •
Right-click in any blank space on the block diagram and select “Control Design and Simulation” → “Simulation” → “Continuous Linear Systems” → “Derivative”. Place this block close to the output from one of your transfer function blocks.
You may notice that when you bring the derivative block close to your transfer function block a wire automatically appears to connect the two. This is standard LabVIEW behavior and is often quite convenient. If a wire did not appear, create one connecting the transfer function block output and the derivative block input. Step 7 – State Space Now that we have all of the necessary inputs, we can add gain blocks and a summation block to compute the control effort needed to balance the pendulum arm.
• •
•
Right-click to bring up the functions palette and select “Control Design and Simulation” → “Simulation” → “Simulation Arithmetic” → “Gain” Place this block to the right of the derivative blocks, still within the simulation loop. You may need to expand the simulation loop at this point by placing your mouse over its edge, then clicking and dragging the small gray boxes which appear. Double-click the Gain block you just added.
12
• • •
Under “Parameter source” select “Terminal” from the drop-down box. Click OK. Make four copies of this block by holding the control key while dragging the block to a new position (Figure 13).
Figure 13
Now we need to connect the inputs to the gain blocks (located on the left side, close to the “k”) to the sensor outputs. • • •
Connect the top gain block to the “arm angle normalized” terminal of our subsystem. Connect the third gain block similarly to the “pendulum angle normalized” terminal. Finally, connect the second and fourth gain blocks to the respective outputs from the derivative blocks.
Next, we will add controls so that we can set the values of our gains via the front panel. • • • •
Move your mouse over any one of the gain blocks so that the orange terminals appear. Right-click the top, center terminal which should now be labeled “gain” Select Create → Control. A new orange box will appear and you can type to label it. Repeat this procedure for the other three gain blocks (Figure 14).
13
Figure 14
At this point, if you switch to the front panel you will see four text boxes, whose default value is 1. If you’d like, you can replace these with any type of control you’d like. To do this, right-click on the control you wish to change and select “Replace” then choose the control you wish to use. Next, we will add a block to sum the outputs from the gain blocks. The output from this block will ultimately be fed to an output DAQ Assistant to control our motor. •
• •
•
Bring up the functions palette and select “Control Design and Simulation” → “Simulation” → “Simulation Arithmetic” → “Summation.” Place this block to the right of the gains. Double-click the summation block. From the window that appears, set the number of inputs to 4 and click the symbols around the circle until they are all + signs (Figure 15). Wire the output from each of the gain block into one of the inputs on the summation block.
Figure 15
14
Step 8 – Output At this point the state-space control is essentially complete. We will now add another DAQ Assistant block to send output to our motor control hardware.
• • • • •
Right-click on an empty part of the block diagram to open the functions palette. Select “Express” → “Output” → “DAQ Assistant” From the window that appears, select “Analog Output” → “Voltage” Select “ao0” from the list of supported channels, then click “Finish.” Configure the DAQ Assistant with an output range of -5 to 5 volts, task timing “1 Sample (On Demand)” and click OK (Figure 16).
Figure 16
15
Once LabVIEW has created the DAQ Assistant block, we are ready to continue. In order to prevent the control system from sending a value outside the -5 to 5 range we must add a saturation block (if this block were not added, the VI could stop unexpectedly during execution). • Bring up the functions palette again and select “Control Design and Simulation” → “Simulation” → “Nonlinear Systems” → “Saturation” • Place this block to the left of the DAQ Assistant output block and then double-click it to open the configuration window. • For our system, we will set the output’s lower limit at -4.8 and the upper limit at 4.8 volts. Once the saturation block has been configured, connect the output from the sum block created in step 6 to the input of the saturation block. Then, connect the output from the saturation block to the input of the DAQ Assistant output block (Figure 17).
Figure 17
We should now switch to the front panel and enter values for each of our state-space gains. Once these have been entered, we can make them default by right-clicking the control and selecting “Data Operations” → “Make Current Value Default.” Now we are ready to run our VI and test the operation of our state-space balancing controller. We will run the VI (by clicking the “Run” button on the front panel toolbar) with the pendulum hanging straight down. Then we will move the pendulum by hand to its balancing position and turn on motor power. If we have done everything correctly, the pendulum should balance. If the system does not react as expected, one possible mistake is to reverse the polarity of the motor output or of one of more state-space gains. Note that the state-space controller we’ve just created can easily be adapted to fit the needs of any system. This can be done by changing the type and/or number of DAQ Assistant input and gain blocks.
16
Step 9 – Graphing I/O In order to observe the system’s behavior more precisely, we need to create a graphical indication of certain values versus time. LabVIEW makes creating graphs quite simple.
• •
From the functions palette, add the “SimTime Waveform” blocks (“Control Design and Simulation” → “Simulation” → “Graph Utilities”) Connect the input to the SimTime Waveform block to whichever value you wish to graph.
Figure 18
• • • •
• • •
If you wish to view multiple values on the graph simultaneously (Figure 18), first delete the wire between the SimTime Waveform block and the Waveform graph. Next, copy the SimTime Waveform block (hold the control key, then click and drag). Add a “Merge Signals” block (under “Express” → “Signal Manipulation”) Connect the outputs from the SimTime Waveform blocks to the inputs on your “Merge Signals” block. Connect the output from the “Merge Signals” block to the input of your waveform graph. Finally, connect the SimTime Waveform blocks to the values you wish to graph. Switch to the front panel by pressing Ctrl+E. Right-click on the new waveform graph and select “Properties.” Here you may adjust the format of the graph, scale, etc as you wish.
If, when you run your VI, you find that the last part of the graph tends to disappear after a short period of time, you may need to increase your chart history length. To do this, go to the front panel and right-click on the waveform graph. Select “Chart History Length” and increase the value as needed. Step 10 –Swing-Up Now that we have successfully implemented our state-space controller, we will briefly describe the steps taken to implement our swing-up algorithms. Since the swing-up controller is an energy-based system, we will be using five formula blocks to compute the total energy of the system, then several numeric blocks which determine the proper motor output voltage (Figure 19).
17
Figure 19
•
•
• •
The blocks with the calculator symbol are formula blocks, identical (with the exception of their internal formulae) to the blocks we created in step 4. However, they have been configured to be viewed as icons in order to save space. This can be accomplished by right-clicking a block and selecting “View as Icon.” The “cos” (cosine) block in the lower left can be found on the functions palette under “Express” → “Arithmetic and Comparison” → “Express Math” → “Express Trigonometric Functions.” The “x” (multiplication) blocks, the “–” (subtraction) blocks, and the sign block (directly beneath the lowest formula block) can be found under “Programming” → “Numeric.” To create the numeric constants you see in orange boxes, right-click on the input terminal to any block and select “Create” → “Constant.” Then you can enter any numeric value.
We will now create subsystems for our state-space and swing-up controllers (Figure 20). See step 5 for a detailed description of this process.
Figure 20
18
Step 11 – Control Switching Next, we need to add blocks to switch between swing-up and balancing control based on pendulum position. The Rotary Inverted Pendulum is designed to operate in swing-up mode at any point below 25 degrees from vertical. At any point less than 20 degrees from vertical, the balancing controller takes over. Between 20 and 25 degrees, the motor receives no power. This “dead-zone” is designed to prevent the pendulum from building up too much energy and thus swinging past the balance point.
Figure 21
• • • • • • •
• • •
First open the functions palette by right-clicking in a blank space on the block diagram. Select “Programming” (opened by default) → “Numeric” → “Absolute Value” Place this block within the simulation loop, then wire its input to the “pendulum angle normalized” wire. Next, open the functions palette and select “Programming” → “Comparison” → “Greater?” Place this block to the right of the absolute value block. Wire the output from the absolute value block to the “x” input (top left) of the greaterthan block. Right-click on the greater-than block “y” input (bottom left) and select “Create” → “Constant.” Enter “0.436” (radians) for this value. Next, add a switch block (“Control Design and Simulation” → “Simulation” → “Nonlinear Systems” → “Switch”). Double-click on the switch block to open its configuration page. Set the threshold value to 0.5 then click OK. Wire “input 1” to the swing-up subsystem output, then wire “input 2” to the output from the balance controller (before the saturation block). Add a Boolean to numeric conversion block (“Programming” → “Boolean” → “Bool to (0, 1)”). Connect the input to the conversion block to the output from the greater-than block. Wire the output from the conversion block to the “control input” of the switch block (Figure 21).
As it is configured now, the system will switch between balancing and swing-up controllers at 20 degrees. However, we need to add a second switch to cut power to the motor between 20 and 25 degrees (Figure 22).
19
Figure 22
• •
• • • • • • •
Open the functions palette again and select “Less?” (under “Programming” → “Comparison”) Create a second wire branch from the absolute value block and connect it to the “x” input of the less-than block. Right-click on the “y” terminal of this block and select “Create” → “Constant.” Enter “0.349” for this value. Next, we will add the “AND” block (“Programming” → “Boolean”). Wire the outputs from the greater-than block and the less-than block to the two inputs of the “AND” block. Add another switch block by selecting the block added in the previous section, holding the control key, and dragging. Right-click the “input 1” terminal and select “Create” → “Constant”. Leave the value as 0. Connect the output from the previous switch block to the “input 2” terminal of this new switch block. Add another Boolean to numeric conversion block by selecting the block added in the previous step, holding the control key, and dragging. Connect the conversion block’s input terminal to the output from the “AND” block then connect its output to the new switch’s “control input” terminal. Finally, connect the output from the new switch to the input to the saturation block.
We have now completed the control system for the Rotary Inverted Pendulum. At this point the system can be run to test the functionality of our swing-up algorithms as well as our switching logic.
20
Step 12 – Adding the Classical Controller (optional)
In order to determine which control scheme best balances the pendulum, we have chosen to implement a classical controller alongside the state-space control. The implementation of this controller involves many of the same steps we have taken to develop other parts of this VI (Figure 23).
Figure 23
As you can see, the classical controller implementation is somewhat simpler, with only two gain blocks, two transfer functions, and an addition block. We have added this to a subsystem, then created a switch block identical to that used in step 10 but controlled on the front panel (Figure 24).
Figure 24
Note that with its two transfer functions, classical control is quite computationally intense. In experiment we see evidence of this. When the pendulum is balancing with the classical control, even a simple action taken by the control computer’s user (switching windows, opening files, etc) can cause the arm to move suddenly, often knocking the pendulum out of its balanced position. In order to improve this behavior, we could try to run this VI on a PXI or other “Real-time” LabVIEW system. Doing so is quite simple, and only requires changing the DAQ Assistant input and output ports. As you can see, developing a controller within LabVIEW is both simple and efficient. It also allows quick testing and comparison of different control methods.
21