Implementing A PID Controller Using A PIC
Implementing A PID Controller Using A PIC
INTRODUCTION:
Continuous processes have been controlled by feedback loops since the late
1700’s. In 1788, James Watt used a flyball governor on his steam engine to
regulate its speed. The Taylor Instrument Company implemented the first fully
functional Proportional, Integral and Derivative (PID) controller in 1940.
Although feedback control has come a long way since James Watt, the basic
approach and system elements have not changed. There are several elements
within a feedback system; for discussion purposes, we will use a motor position
control system as our model in the descriptions below.
• Plant
• Sensors
• Setpoint
• Error Signal
• Controller – Intentionally left for last, this is the most significant element of a
control system. The Controller is responsible for several tasks and is the link that
connects together all of the physical and nonphysical elements. It measures the
output signal of the Plant’s Sensors, processes the signal and then derives an error
based on the signal measurement and the Setpoint. Once the sensor data has
been collected and processed, the result must be used to find PID values, which
then must be sent out to the Plant for error correction. The rate at which all of this
happens is dependent upon the Controller’s processing power. This may or may
not be an issue depending on the response characteristic of the Plant. A
temperature control system is much more forgiving on a Controller’s processing
capabilities than a motor control system. Figure 1 shows a basic block diagram of a
feedback control system.
OBJECTIVES:
General: Implementing a tuned PID motor position Controller using a PIC
Material:
Software:
-CCS C Compiler.
-Proteus.
-PICkit 2 ( programmer )
Hardware:
Equation 1:
In this system, the sign of the controller’s output, C(t), always will be positive
For determine the direction in which the motor will turn, is necessary to use
additional flags (front direction, rear direction) in order to control Driver L298D
The magnitude of C(t) directly corresponds to the duty cycle of the PWM in the
ECCP module, determining the speed at which the motor will turn.
Proportional
The proportional term is the simplest of the three and is also the most commonly
found control technique in a feedback system. The proportional gain (kp) is
multiplied by the error. In this application note, the error is a 10-bit value, error. The
amount of correction applied to the system is directly proportional to the error. As
the gain increases, the applied correction to the Plant becomes more aggressive.
This type of Controller is common for driving the error to a small, but non-zero
value, leaving a steady state error. This is the reason for proportional control not
being enough in some systems, thereby requiring integral and derivative control to
come into play, separately or together (i.e., PI, PD or PID Controller).
Equation 2
Derivative
Equation 3:
Where E(n) is the current error, E(n-1) is the previous error and TS is our sampling
period. Equation 2 is the approximate slope of the tangent line at E(t) (rise/run).
The derivative term makes an adjustment based on the rate at which the Plant
output is changing from its Setpoint.
A notable characteristic in this type of control is when the error is constant, or at
the maximum limit, the effect is minimal. There are some systems where
proportional and/or integral do not provide enough control. In these systems,
adding in the derivative term completes the control requirements.
Equation 4
Integral
Unlike proportional control, which looks at the present error, integral control looks
at past errors. Given this, the accumulative error (sum of all past errors) is used to
calculate the integral term, but at fixed time intervals.
Basically, every time the fixed interval expires, the current error at that moment is
added to the error variable. A motor system would require a shorter sample period
than a temperature system, because the time of response
Equation 5
If the integral sample period was too fast or the integral constant was too big in the
system, the accumulative error would add too quickly to give the system a chance
to respond, thereby not allowing it to ever stabilize. Another element in integral
control to consider is ‘wind-up’.
Wind-up occurs when the accumulative error keeps increasing because the Plant
output is saturated. This event can be avoided by setting limits to the accumulative
error. It can also be eliminated by not executing the integral term when the Plant
output is saturated.
Another characteristic is excessive gain that can create an unstable condition
within the system, causing it to oscillate. The integral gain must be thoroughly
tested for all possible situations to find the best overall value.
In conclusion, as the accumulative error increases, the integral term has a greater
effect on the Plant.
Equation 6
There are several different ways to tune a PID Controller for system optimization.
The code in this application note is loosely defined, giving it the flexibility to be
tuned for a specific application (i.e., motor control, temperature, actuator, etc.).
Tuning a PID Controller can be somewhat difficult and time consuming and should
be completed in a systematic fashion.
1. Run the system in an open loop and measure its response over time. Based on
the measured response, you will get an idea for which PID term is needed most.
2. Determine the application requirements: Plant response time, which PID term
will have the most affect and accumulative error limits.
Example tuning:
With a tuned proportional and integral gain, the system does settle to its Setpoint,
which is why PI control is adequate in many systems. The disadvantage is the time
required for it to settle (t = 3), which brings us to PID control.
Figure 7 shows the graphic response of a PID Controller. This graph is very similar
to the PI graph (Figure 6), except that the PID control takes half as long as the PI
control to settle (t = 1.5) as the Setpoint.
PID Output
The PID output is calculated after the proportional, integral and derivative terms
have been determined. In addition to this calculation the user must modify flags
(front direction, rear direction) to decide which direction the Plant will be driven.
Equation 7
//---Anti-windup
if (PID_F > Lim_Max) //Ajusta Salida PID_F si mayor que Lim_Max
{PID_F = Lim_Max;}
//---Sentido de giro
output_high(PIN_C0); //Mt Front enable
output_low(PIN_C1); //Mt Rear disable
//---Actualiza variables
Ti_Anterior_F = Ti_F;
Error_Anterior_F = Error_F;
}
Schematic Capture (Proteus 8)
Full code c
#include <PID_SPI__USB_18F4550.h>
#device ADC=10
#use delay(crystal=40000000)
#include <lcd.c>
void main()
{//Void main
//------------Variables-----------------------
float SetPoint =102.4; //Valor Posicion Deseada
float Kp = 1; //Constante Proporcional
float Ki = 1; //Constante Integral
float Kd = 1; //Constante Diferencial
//-----------Configuracion Modulos----------------
//Entradas Salidas Proposito General
SET_TRIS_E (0x0F); // E3,E2,E1,E0 are inputs
//---Modulo CAD
setup_adc_ports (AN0_TO_AN5);//Para ADC
setup_adc(ADC_CLOCK_INTERNAL);//Relog de ADC
//---Modulo Comunicacion SPI
//---Modulo PWM
//Period_PWM = [(PR2+1)*4*Tosc*Prescale]
//Tocs = 1/Value_crystal
//Resolution "Bits" = {log[4(PR2+1)]} / {log(2)}
int Postscaler = 1;//Nota: No se usa para el PWM
int PR2 = 0xFF; //Period_PWM=204.8us
setup_timer_2(T2_DIV_BY_4,PR2,Postscaler);//Frecuencia_PWM=4.882MHz
setup_ccp1(CCP_PWM); //Resolucion 10 bits
//---Periferico LCD
lcd_init();
printf(lcd_putc, "\f Motor CC Pos\nSintonizador PID");
delay_ms(3000);
//----------Programa-----------
while(TRUE)
{//Ciclo Infinito
if (input(pin_d3) == TRUE)
{Div_Error=1;
}
else
{Div_Error=10;
}
if (input(pin_E1) == TRUE)
{//Sintoniza PID
//pwm off
set_adc_channel(0); //Selecciona CH0
delay_us(20); //Retardo para obtener lectura completa 8 Bits
SetPoint = read_adc(); //Guarda Set_Point
SetPoint = (SetPoint) / (Div_Error);
set_adc_channel(1); //Selecciona CH1
delay_us(20); //Retardo para obtener lectura completa 8 Bits
Kp = read_adc(); //Guarda Kp
Kp = ((Kp) / (64)) + (1);
set_adc_channel(2); //Selecciona CH2
delay_us(20); //Retardo para obtener lectura completa 8 Bits
Ki = read_adc(); //Guarda Ki
Ki = ((Ki) / (1024)) + (0.01);
set_adc_channel(3); //Selecciona CH3
delay_us(20); //Retardo para obtener lectura completa 8 Bits
Kd = read_adc(); //Guarda Kd
Kd = ((Kd) / (16)) + (1);
set_adc_channel(5); //Selecciona CH4
delay_us(20); //Retardo para obtener lectura completa 8 Bits
Time = read_adc(); //Guarda time ms
Time = (Time) / (2);
printf(lcd_putc, "\fSp=%3.1f t=%lums\nPID %2.1f %1.2f %2.0f",SetPoint,Time,Kp,Ki,Kd);
delay_ms(100);
}