Internet Explorer is not a supported browser for TI.com. For the best experience, please use a different browser.
Video Player is loading.
Current Time 0:00
Duration 16:59
Loaded: 0.98%
Stream Type LIVE
Remaining Time 16:59
 
1x
  • Chapters
  • descriptions off, selected
  • en (Main), selected

Welcome to the second video in our series on the C2000 digital control library. In this video, we look at some of the DCL controllers and how to use them. DCL controllers may be classified into two groups-- PID-type controllers are often used in situations where transient response performance is important. These controllers have features such as integrator anti-windup and derivative path filtering built into them.

In addition to the standard linear PID and PI controllers, that DCL also contains a linear PI controller with double integrator, nonlinear PID controllers and, again, scheduler module. The nonlinear PID is the subject of a separate video in this series.

In the context of control, the terms controller and compensator are used interchangeably. However, the name compensator is often reserved for situations where the control loop is specified by its frequency response. And this is how we use it in the DCL.

Compensators fall into two categories according to their structure, direct form one and direct form two. The DCL contains first order and third order direct form one compensators called DF11 and DF13 respectively, and second and third order direct form two compensators called DF22 and DF23 respectively. All compensators are coded in both full and pre-computed forms. These will be described in more detail later.

Before proceeding, it will be helpful to understand the function naming convention used in the DCL. All library functions begin with DCL underscore, which identifies the library they belong to. Then there is a verb-noun construct which identifies which operation is being performed and on which controller. All of the controllers have three standard functions. The run function executes the controller. The reset function restores the dynamic data in the controller structure to its default values. And the update function performs a safe parameter update, a topic which will be explained later.

In many cases, there are other supporting functions which are specific to the controller. An example of the run function is shown for the DF23 compensator. Different forms of the compensator exist depending on which CPU it's being executed on and how it is coded. A letter appended to the compensator identifies the CPU. In this case, the C tells us that the compensator will run on the FPU32. The last digit-- in this case, one-- is a unique identifier which tells us how the compensator is structured and coded. More information can be found in the DCL user's guide.

This slide shows the header file dependency that DCL controllers. Header files are shown in white and source files in yellow. There is a generic library header file named DCL.h shown here in the upper-left. This file contains generic information about the library such as important numeric constants and error enumerations. DCL.h also contains the definition of a common support structure, which is used by all controllers.

In practice, it is not necessary to explicitly include DCL.h. Typically, the user will only include the header file appropriate to the CPU being used. For example, a user who wishes to implement a controller on the CLA would only include the file DCLCLA.H in their project, DCL.h being included in that header file. We'll see an example of this shortly.

If error handling is required, the user must at the source file DCL_error.C to their project. We'll look at error handling later. Similarly, if an assembly coded controller is required, the appropriate assembly source file must be added to the project.

Now let's look at a simple code example. Assume that in this case we want to implement a PID controller on the FPU32 and have decided on the PIDC4. The first step is to include a header file containing the FPU32 controller definitions. The file we need is DCLF32.H, so we must include that. The generic library header file, DCL.h. Is automatically included, so we do not need to explicitly include it.

Next, we must declare an instance of the controller and the input and output variables. We can initialize the controller data to default values on declaration using the default settings in the array PID_defaults as shown here. The user can now load any specific controller parameters directly into the PID structure. These lines would normally be placed near the start of main during the initialization phase of the user program.

The only thing remaining is to add a call to the controller run function. Typically, this would reside in an interrupt service routine to ensure the controller executes at a deterministic rate. We've added code to implement a PID controller. However, we may want to adjust controller parameter from time to time-- for example, as we tune the controller. Let's look at this next.

Before discussing how to update parameters, we need to understand the common support structure, or CSS. The CSS is defined in a generic library header file, DCL.h, and contains important data which is not specific to the controller. The TPT variable is typically used in debugging when users wish to examine an internal signal by assigning it to a spare variable. The T parameter is the update rate of a controller in seconds and is used by several supporting functions. For example, the computation of PID derivative path coefficients from a filter bandwidth specification.

The STS element is a 32-bit status word used to indicate that a parameter update is pending or that a control operation is in progress. The ERR field contains an error code which is used by the error handler. Finally, should an error be detected, the LOC field contains the line number of the source file where it occurred and can be helpful in debugging.

Making adjustments to the controller while the control loop is active is something which should be handled with care. Typically, the run function would execute at a high rate in an ISR while the user manipulates parameters asynchronously, either manually through the IDE or possibly in the background loop.

When more than one parameter is being updated, it is possible that the controller will be run with a partially updated parameter set, in which case normal operation of the loop may be disrupted. To prevent this, the DCL allows the user to interact indirectly with a controller through a shadow parameter set called the SPS. The SPS contains a duplicate copy of the parameter data in the active controller structure.

When the user has loaded all the parameters, contents of the SPS can be transferred to the active structure in such a way that the controller is not called until the transfer is complete. In the DCL, this safe copy is ensured by disabling device interrupts for a short time while the copy takes place.

In this example, we see the user loading KP and Umax parameters into the SPS. The following line, DCL_request_update, sets a bit in the status word in this CSS to indicate that a shadow to active transfer is ready. All that remains is to add a call to the DCL_update PID function to perform the copy. This function first tests the status word to determine whether a copy is pending. If so, global interrupts are disabled, and the copy performed, and then interrupts re-enabled. The pending bit in the status word is then cleared.

The duration of the transfer is important since this detects the length of time for which interrupts are disabled. For best performance, that DCL contains a set of assembly routines in the file DCL_Fupdate.ASM. Further details can be found in the library user's guide.

Now let's adapt the previous C code example to add safe parameter update capability. First, we must declare instances of the supporting SPS and CSS structures, initializing them to their default values if desired. Next, we load the active structure's parameters and initialize the SPS and CSS pointers.

Next, we add a call into the idle loop to update the parameters. This function will test the CSS status word to determine whether an update is pending. Only in that case will interrupts be disabled and the copy take place. The controller is called for an ISR exactly as before.

At this point, all that is necessary to implement the update is to set bit 0 in the CSS status word, which can be done either manually in the watch window or as here in the code itself with the DCL_request_update macro.

The DCL contains basic error handling capabilities which can be disabled to reduce cycle count. Typically, users will develop code with error handling enabled and disable it only after the code is fully tested. To enable error checking, the user must first ensure that the string DCL_error_handling_enabled is defined in the library header file DCL.h.

The CSS contains two fields named ERR and LOC, which respectively capture the error number and the line of the source file where the error occurred. The error number is determined from an enumerated list in DCL.h As seen here. Following the error condition, a user may inspect these two fields to determine which type of error occurred and where it was detected.

C-coded controllers and supporting functions perform checks on the parameters each time they are called. If a check results in the error word being non-zero, a basic error function is called. This function can be found in the source file DCL_error.C. Users may freely edit this file if they wish to perform more elaborate error handling.

Let's now look at some of the controllers in the DCL. This diagram, taken from the DCL user's guide, shows the structure of one of the PID controllers. The generic C structure, shown in the upper-right, contains parametric and dynamic data used by the controller.

In the diagram, variables beginning with a lowercase V are local variables and do not get preserved between function calls. Other variable names prefixed by D or I refer to dynamic data which must be preserved between calls to the controller run function, and are therefore held in the PID structure. Notice the two pointers to this SPS and CSS sub-structures.

Since this particular controller has been coded in assembly, to use it, the file DCL_PID_C4.ASM must be added to the project. Full description of all the DCL controllers can be found in the user's guide in the doc's sub-directory.

By way of contrast, here we see an example of a series PI controller with a tustin integrator. Most PID controllers and DCL use a backwards Euler type of integrator to minimize the cycle count. The backwards Euler is a perfectly satisfactory method for tuning transient response. However, better phase characteristics are available with the tustin integrator at the expense of an additional delay element. This type of controller would be better suited to situations where a user wanted to load controller gains from a 0-plus gain definition. The C6 and C7 controllers have tustin integrators run on the FPU32. The L5 is the equivalent controller for the CLA.

The DCL contains two basic types of compensator. Shown on the left is a third-order direct form one type, which contains two delay lines. On the right is a second-order direct form two compensator structure, which has a single delay line. The DF2 structure executes more efficiently and has the advantage of better numerical robustness compared with DF1. For these reasons, the DF2 is preferred over the DF1 in most situations.

As with the PID, both compensators are configured through C structures and are executed using their respective run functions. They are also supporting functions to load coefficients from a pole-0 description, for example. We'll see an example of this shortly.

Both DF1 and DF2 compensators are available in pre-computed forms. Pre-computation allows the sample to output delay to be minimized by splitting the compensator into two parts-- an immediate part, which computes the controller output quickly, and a pre-computed part, which prepares the delay lines for the next controller cycle. Only the immediate part is time-critical, so by careful structuring of the code, the controller latency can be minimized.

The diagram shows a pre-computed form of the DF22 compensator and a corresponding code example. DF22_C2 is the immediate part, and DF22_C3 the pre-computed part. To prevent windup, the immediate part is computed and its result tested to ensure it lies within the allowable range. If so, the result is used for control of the next partial result pre-computed for use in the next controller cycle. Otherwise, the immediate result is discarded and no pre-computation is necessary. The code snippet on the right shows how this is done.

The library file in DCL.h contains a structure known as ZPK3, which allows the user to specify up to three complex zeros, three complex poles, and one real gain in a single entity. Many of the controllers have supporting functions which load their parameters from a ZPK3 definition. The code at the bottom of this slide shows how a DF22 compensator might be loaded from a ZPK3 description.

Notice that in order to do this, the controller rate must first be loaded into the CSS structure, which is done using the DCL_set_controller_period macro. In this example, all the zeros and poles are real, but it is possible to configure them in complex conjugate pairs if desired. Since we only require two poles and two zeros, the Z3 and P3 elements of the ZPK3 structure are not used.

The function DCL_loadDF22asZPK loads the shadow parameter set from the specified ZPK3 structure. The user then loads these values into the active compensator structure using the update method described earlier.

This concludes our look at DCL controllers. In the next video, we'll look at data logging and other utilities in the DCL. Thanks for watching.

This video is part of a series