The objectives of this exercise are:
The T1 target system will be required, but only the components listed in Chapter B are needed for this lab exercise. Set up each component in accordance with the instructions for your specific T1 version in Section A.1. Connect your components in the manner described in the "Online Resources" section of the web page for this lab exercise: .
In this exercise, a closed-loop control system for the DC motor will be developed. This system is similar to actuators used in many types of positioning systems. The primary drive of one axis of an automated machine tool or of one axis of motion of an industrial robot is often a computer-controlled DC motor.
Our system will control the motor velocity, as shown in Figure 8.18. The control algorithm will repeatedly compare the measured velocity of the motor \(\Omega_J\) with the desired reference velocity \(\Omega_R\), and automatically alter the applied control current to correct any differences. Although this is not a trivial computer control task, we have developed nearly all the required elements in the preceding lab exercises.
The quadrature encoderEncoders!quadrature (through the field-programmable-gate array (FPGA)), the DAC (connected to the current amplifier), and the periodic timer interrupt will be combined to control the DC motor. DC motor Motors!velocity control of Field-programmable gate array (FPGA) Quadrature encoder Digital-to-analog conversion IRQTIMERWRITE IRQTIMERSETTIME Interrupts Basic time interval (BTI)
As in Lab Exercise 7, a separate timer thread will produce an interrupt at the end of each basic time interval (BTI), also called the "sample period." The ISR will load the IRQTIMERWRITE and IRQTIMERSETTIME registers to schedule the next BTI, and then call functions to do the following:
The control system will be "table-driven." That is, the parameters used by the control algorithm (reference speed, system gains, and BTI length) will be kept in a special table of values. Through the keypad and display user interface (UI), the values of the parameters in the table will be altered (interactively) by a "table editor" function called from the main program thread. The only tasks of the table editor will be to change the table values in response to commands from the keypad and to display performance information.
This table-driven structure will allow the user to change any of the control parameters, at any time, without stopping the execution of the control algorithm. It will appear as though two programs, the table editor and the control algorithm, are executing simultaneously.
You will not write the table editor. The required function, ctable2(), is described in Section D.2. It has been included in the T1 C library. Although you will not write this function, it uses the basic keypad/display algorithms that you developed in ph,m5,qv. The prototype for ctable2() is in ctable2.h. ctable2()
Following the controller design discussion of Section 8.6, the control block diagram is shown in Figure 8.19. The motor will be controlled using a PI control law, as shown inside the dashed box. Proportional-integral (PI) control
The PI control law relates the error \(e(t)\) to the output control signal \(u_a(t)\) using the gain constants \(K_P\) and \(K_I\).
Applying Tustin's method to the continuous controller transfer function \[ G_C(s)=K_P+\frac{K_I}{s}, \] the corresponding discrete transfer function is \[ G_C(z) = \frac{U_a(z)}{E(z)}=\frac{b_{0}+b_{1}z^{-1}}{a_{0}+a_{1}z^{-1}}, \] where \[ \begin{aligned} a_{0}&=1, &b_{0}&=K_P+\frac{1}{2}K_I T, \\ a_{1}&=-1,\text{ and} &b_{1}&=-K_P+\frac{1}{2}K_I T, \end{aligned} \] where \(T\) is the sample time, and the error is \[ E(n)=\Omega_R(n)-\Omega_J(n). \] See Section 7.4 on discrete time systems. You will implement the corresponding difference equation using the general-purpose algorithm that you developed in Lab Exercise 7.
Drawing on your previous work, write two threads to (1) communicate with the user and (2) control the motor.
The main program should perform these tasks:
Initialize the table editor variables.
Set up and enable the timer IRQ interrupt (as in Lab Exercise 7).
As in Lab Exercise 7, register the timer thread and create the thread to catch the timer interrupts. In this lab exercise, the timer thread should gain access to the table data through a pointer. Modify the timer thread resource to include a pointer to the table. For example,
typedef struct {
NiFpga_IrqContext irqContext; // context
table *a_table; // table
NiFpga_Bool irqThreadRdy; // ready flag
} ThreadResource;Therefore, before you create the thread, you must initialize the thread resource to point to your table, and set the Thread Ready flag:
irqThread0.a_table = my_table;
irqThread0.irqThreadRdy = NiFpga_True;Call the table editor. The table should contain six values, labeled as shown:
V_R: rpm {edit}
V_J: rpm {show}
VDAout: mV {show}
Kp: V-s/r {edit}
Ki: V/r {edit}
BTI: ms {edit}
All the table edit values should be initialized to zero except for the BTI length, which should be \(5\) ms. Note the units. After the main program calls the table editor, the user may edit and view the table values as desired.
When the table editor exits, signal the timer thread to terminate. Wait for it to do so.
At the beginning of the starting function, declare convenient names for the table entries from the table pointer as follows:
double *Omega_R = &((threadResource->a_table + 0)->value);
double *Omega_J = &((threadResource->a_table + 1)->value);
// etc.As in Lab Exercise 7, the timer thread should include a main loop timed by the IRQ, and terminate only via its ready flag. Before the loop begins do the following:
Aio_Write() (as in Lab Exercise 7).Each time through the loop, it should do the following:
TRUE to the Timer Set Time Register.vel(), from Lab Exercise 5, to measure the velocity of the motor.biquad structure.cascade() to compute the control value from the current error using the difference equation for the PI control law. Important: Limit the computed control value to the range \([-10.0,+10.0]\) V.AOC0 (see Figure 4.12), with Aio_Write().Aio_Write()
Two additional functions are needed. Both functions were developed in previous lab exercises.
cascade()The cascade() function, called once from the ISR during each BTI, implements the general-purpose linear difference equation algorithm from Lab Exercise 7. For this lab, use the same C code that you used in Lab Exercise 7. In this case, there will be 1 biquad section. Note that, as in Lab Exercise 7, all calculations should be made in (double) floating-point arithmetic. cascade()
vel()Use the vel() function, developed in Lab Exercise 5, to read the encoder counter and estimate the angular velocity in units of basic displacement increment/basic time interval (BDI/BTI). vel()
A convenient method of saving the data is to define data arrays in the ISR for both the angular velocity measurement \(\Omega_J\) and \(u_a\), the DAC output voltage (amplifier input). Then, an autoincremented index variable is used to store the data in the arrays during each BTI. Increment the index as needed, stopping when index reaches the length of the arrays. A convenient length would be \(250\) points each.
Because the program runs continuously, you may wish to save the response (see Section D.1) whenever the reference velocity is changed. This is easily accomplished by checking to see if the reference velocity has changed since the last BTI and resetting the index to zero if it has. Since the index is then less than the length of the arrays, the arrays will be refilled. This is equivalent to recording the response to a step input in the reference velocity.
In addition, when the ISR resets the index to zero, save the previous value of the reference velocity. That value, along with other system parameters, will be used for postprocessing the data to predict the theoretical model response.
After the main loop terminates, but while still in the timer thread, write the results to the Lab7.mat file. The results should include the following:
Use the same methods as in Lab Exercise 5 and Lab Exercise 7 to bring the Lab7.mat file to MATLAB.
As an aid in debugging, our T1 C library includes a software "emulation" (a dynamic model) of the analog output, the amplifier, the motor, and the encoder. The emulator allows you to run your code and save the MATLAB file without being connected to the amplifier and motor.
Emulator
To activate the emulator, #include the header file emulate.h. When you want to execute your code on the myRIO using the hardware interfaces, comment out the included emulator header and rebuild the project.
In the following, let the base set of controller parameters be a sample time or BTI of \(T = 5\) ms and the controller gains \(K_P\) and \(K_I\) from Equation 8.31, repeated here: \[ \begin{aligned} K_P &= -\frac{B + 2 J \Re(\psi)}{K_a K_M}\text{ and} \\ K_I &= \frac{Z \left(B + 2 J \Re(\psi)\right)}{K_a K_M}. \end{aligned} \] The T1a target system parameters can be found in es2 and the design point \(\Re(\psi)=-20\) rad/s, which corresponds to \(T_S\approx 0.2\) s, and \(Z = -20\) rad/s. See es for a control systems model and associated transfer functions.
From Equation 8.31, compute the base set of gains \(K_P\) and \(K_I\) for the rest of these laboratory problems. For the T1a specific target system, confirm that they are \(K_P = 0.104\) V\(\cdot\)s/rad and \(K_I = 2.07\) V/rad.
Design a PI controller for your specific T1 target system following the root locus design technique of 94,kb,al,ru,vm. Compare the gains \(K_P\) and \(K_I\) to the base set of gains computed in bu.
Write, test, and debug the program described in k3. For debugging purposes, use the base set of parameters.
Measure the steady state speed of the motor with an optical tachometer. Compare this value to the reference speed that you specified in the table. How close is it?
While the motor is at steady state speed, gently apply a steady manual load torque to the motor shaft. What are the responses that you observe on the display of the measured velocity V_J and control voltage VDAout? Explain.
Beginning with the base set of parameters, explore the effect of varying the proportional gain \(K_P\) on the transient response. Try smaller and larger values of \(K_P\). What are the effects on the oscillation frequency and the damping? Explain this in terms of the closed-loop transfer function parameters described in Section 8.5.2.
Beginning with the base set of parameters, explore the effect of varying the integral gain \(K_I\) on the transient responses. Try smaller and larger values of \(K_I\). What are the effects on the oscillation frequency and the damping? Explain this in terms of the closed-loop transfer function parameters described in Section 8.5.2.
Using the base set of parameters, record the control output voltage \(U_a\) and measured velocity responses for a step change in the reference velocity that starts from \(-200\) RPM and goes to \(+200\) RPM. In MATLAB, compare these experimental responses with the analytical responses for the continuous system approximation. See Lab Exercise 8 Appendix for a summary of the closed-loop model.
The theoretical responses can be calculated using the appropriately scaled MATLAB step() command. The analysis should be plotted over the experimental responses. Use the subplot() command to place both the control value and the measured velocity plots on the same page. What do you conclude?
main.c file.The model shown in Figure 8.20 is a continuous approximation of the discrete control of the DC motor implemented in this lab exercise. Three assumptions are made:
Typically, the effect of the mechanical damping \(B\) is small compared to the effect of the proportional term in the controller. Also, during transient response, the damping torque is small compared to the inertial torque. Therefore, for design purposes, we assume that \(B = 0\) N\(\cdot\)m\(\cdot\)s/rad.
The following three transfer functions are obtained from the block diagram:
Let \(K=K_a K_M\). Then the natural frequency and damping ratio are \[ \omega_n=\sqrt{\frac{K_I K}{J}} \quad\text{and}\quad \zeta=\frac{K_P}{2}\sqrt{\frac{K}{J K_I}} \] where \[ \tau=\frac{K_P}{K_I},\quad K_d=\frac{1}{K_I K},\text{ and}\quad K_u=\frac{J}{K}. \]
When converting the rotational velocity to rad/s, the value of \(\pi\) is needed. The math.h header file includes a macro, M_PI, that equals \(\pi\).↩︎
See Section A.1 for other target systems.↩︎