Integral Control

Proportional is just one way to react to an error in the system. The problem with proportional control is that it can't detect trends and adjust to them. This is the job of integral control.

There is another example graph of the error in a system over time on the left of Figure 6. Again, it might be the distance of a robot from an object, or it could be fluid level in a tank, or the temperature in a factory oven. Perhaps the target the robot is following keeps on going away from the robot at a speed that the robot isn't catching up with. Maybe the oven door seal is worn; maybe the fluid draw from the tank is unusually large. Regardless of the cause, since proportional is not designed to react to trends it can't detect and correct the problem. That's where integral control comes into the picture.

Integral measures the area between the error values and the time axis. If the error doesn't return to zero, the area of the error gets larger and larger. The right side of Figure 6 shows how the integral output can react to this kind of trend. As the area between the error curve and the time axis increases, the output increases proportional to this area. As a result, the output drives the actuator harder and harder to correct the error.

So what happens when the error isn't a straight line, like the curve shown in Figure 8? That's what the calculus operation of integration determines, the area between a curve and an axis. In the case of integral control, as more time passes with an error, the area under the curve grows, and so does the value that the integral calculation will use to drive against the system error. If the error curve drops below the time axis, the buildup of negative area subtracts from the buildup of positive area. When tuned correctly, integral control can help the system hone in on an error of zero.

The BASIC Stamp can approximate the error under the curve with numerical integration. Figure 9 shows how you can approximate the error under a curve by adding up the area of a bunch of little rectangles between the error curve and the time axis. The area of each box is the error multiplied by the time between measurements. By adding up all the box areas, you get an approximation of the area under the curve.

So long as your measurements are evenly spaced, you can call the width of each box a value of 1. This makes the math much simpler than trying to account for 20 ms between samples, 5 minutes between samples, or whatever your sampling rate turns out to be. Instead of multiplying error by the time increment between samples and then adding to the next error multiplied by time, you can just multiply each error sample by a time of 1. The result is that you can just keep a running total of error measurements for your integral calculation. Here is an example of how to do this with PBASIC:

' Calculate integral term.
error(Accumulator) = error(Accumulator) + error(Current)
i = Ki * error(Accumulator)

The next example program performs numerical integration on the error signal and adjusts the output accordingly. As with proportional control, there is a constant that scales the integration output to the desired value. For simplicity's sake, we'll use 10 again for Ki. Figure 10 shows a block diagram of the control loop. The term Kp ∫ edt refers to Kp multiplied by the integral of the error over time. In other words, Kp multiplied by the accumulated area between the error curve and the time axis.

Example Program - IntegralAlgorithm.bs2

  • Enter, save, and run IntegralAlgorithm.bs2.
  • Enter this sequence of values into the Debug Terminal's transmit windowpane: 3 3 3 3 3 3 3 3 3. Notice how the integral output gets larger every time the 3 is repeated. That's integral's job, to detect trends and increase the drive to correct it as needed.
  • Now try this sequence: 1 2 3 4 5 4 3 2 1 0 -1 -2 -3 -4 -3 -2 -1 0. The area under this curve is 0 since the negative area is the same as the positive area. That is also what the integral calculation will arrive at when you have finished entering the sequence.
' IntegralAlgorithm.bs2
' Demonstrates how integral control influences error correction
' in a feedback loop.
' {$STAMP BS2}
' {$PBASIC 2.5}
SetPoint       CON     0                     ' Set point
Ki             CON     10                    ' Integral constant
Current        CON     0                     ' Array index for current error
Accumulator    CON     1                     ' Array index for accumulated error
sensorInput    VAR     Word                  ' Input
error          VAR     Word(2)               ' Two element error array
i              VAR     Word                  ' Integral term
drive          VAR     Word                  ' Output
  DEBUG "Enter sensor input value: "
  DEBUGIN SDEC sensorInput
  ' Calculate error.
  error(Current) = SetPoint - sensorInput
  ' Calculate integral term.
  error(Accumulator) = error(Accumulator) + error(Current)
  i = Ki * error(Accumulator)
  ' Calculate output.
  drive = i
  ' Display values.
        SDEC ? SetPoint, SDEC ? sensorInput, SDEC ? error(Current), CR,
        "INTEGRAL", CR, 
        SDEC ? Ki, SDEC ? error(accumulator), SDEC ? i, CR,
        "OUTPUT", CR, 
        SDEC ? i, SDEC ? drive, CR, CR


How IntegralAlgorithm.bs2 Works

This program is a ProportionalAlgorithm.bs2 modified to perform the integral calculation instead. There are now two different types of errors to keep track of, so there the error variable array was expanded to two elements. The error(0) variable tracks the current error, and error(1) tracks the accumulated error. The constants Current CON 0 and Accumulator CON 1 make the bookkeeping a little more sensible with error(current) and error(accumulator).

The other change that was made is that the error is accumulated and the integral output is calculated with these two statements:

' Calculate integral term.
error(Accumulator) = error(Accumulator) + error(Current)
i = Ki * error(Accumulator)


Your Turn - Clamping the Integral Output

As you may have gathered from repeatedly entering 3 into the Debug Terminal, the integral drive output can really start to run away. You can use the MIN and MAX operators to keep integral control from going overboard with the output. Let's repeat the servo offset activity and limit the output from 650 to 850.

  • Change the drive = i statement to drive = i + Offset MIN 650 MAX 850.
  • Run the program and verify that the integral output is limited to values between 650 and 850. Try entering 2 repeatedly, then -2 repeatedly.