Controlador PID Genérico que se parametriza por medio de un encoder rotatorio- Sp (Set-point), Kp(Ganancia proporcional) ,Ki(Constante integral), Kd(Constante Derivativa), usa dos pulsadores adicionales

Dependencies:   QEI TextLCD mbed

Este programa es un control PID genérico que se parametriza usando un encoder manual. Se puede ajustar. Set-Point Kp Ki Kd

Emplea el pulsador central del encoder para cambiar de parámetro y otro adicional para consolidar los parámetros y ejecutar el controlador

Se puede probar por medio de un sistema de primer orden conformado por una red RC. de 11K y un condensador de 22uF desde la salida hasta la entrada. que se ve en el mini protoboard de la figura siguiente

a continuación mostramos la respuesta del controlador PID a esos parámetros trabajando en lazo cerrado. que da cero error

Donde se ve, Error (Er), Medida(Me), Setpoint(Sp), Control o salida(Co) de voltaje. /media/uploads/tony63/pidok1.png

Se aprecia la izquierda el encoder manual y en la entrada análoga se aplicó un anillo de ferrita o balum; ya que estas entradas análogas son muy sensibles al ruido.

Abajo se aprecia el esquemático. Las conexiones del LCD se deducen de los listados de programa y de la guia del CookBook de esta webb, en la parte de LCD. /media/uploads/tony63/planta1.png

Si quiere ver la respuesta del sistema a cambios de carga, coloque de forma temporal una resistencia de 100K en paralelo con el condensador de 22uF.

Bug del esquemático (intercambie los puertos de los dos pulsadores)

Committer:
tony63
Date:
Sun Apr 24 18:32:52 2016 +0000
Revision:
1:058b8f5c135d
Parent:
0:4e0dfcf0e7ce
Control PID gen?rico que se parametriza con un encoder rotatorio. Todos los c?lculos se procesan en coma flotante. Se imprimen sin cifras significativas por dificultades de impresi?n en la LCD.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tony63 0:4e0dfcf0e7ce 1 #include "mbed.h"
tony63 0:4e0dfcf0e7ce 2 #include "QEI.h"
tony63 0:4e0dfcf0e7ce 3 #include "TextLCD.h"
tony63 0:4e0dfcf0e7ce 4
tony63 0:4e0dfcf0e7ce 5 TextLCD lcd(PTB10, PTB11, PTE2, PTE3, PTE4, PTE5); // rs, e, d4-d7
tony63 0:4e0dfcf0e7ce 6 QEI encoder (PTA13, PTD5, NC, 624);
tony63 1:058b8f5c135d 7 AnalogIn y(PTB3);//entrada analoga
tony63 0:4e0dfcf0e7ce 8 AnalogOut u(PTE30);//salida analoga OJO solo se le pueden drenar 1.5mA en circuitos use un Buffer
tony63 0:4e0dfcf0e7ce 9 //si se ignora esto se arruina la FRDMKL25Z
tony63 0:4e0dfcf0e7ce 10 DigitalOut led1(LED1);
tony63 0:4e0dfcf0e7ce 11 DigitalOut led2(LED2);
tony63 0:4e0dfcf0e7ce 12 DigitalOut led3(LED3);
tony63 0:4e0dfcf0e7ce 13
tony63 0:4e0dfcf0e7ce 14 DigitalIn button3(PTC16);//cambia ingreso de los 4 parametros
tony63 0:4e0dfcf0e7ce 15 DigitalIn button4(PTC17);//termina y consolida valores de 4 parametros y sale del loop
tony63 0:4e0dfcf0e7ce 16
tony63 0:4e0dfcf0e7ce 17
tony63 0:4e0dfcf0e7ce 18 //codigos movimiento del curzor
tony63 0:4e0dfcf0e7ce 19
tony63 0:4e0dfcf0e7ce 20 //int C1=0x0E; // solo muestra el curzor
tony63 0:4e0dfcf0e7ce 21 int C2=0x18; // desplaza izquierda
tony63 0:4e0dfcf0e7ce 22 int C3=0x1A; // desplaza derecha
tony63 0:4e0dfcf0e7ce 23 int C4=0x0C; // quito cursor bajo
tony63 0:4e0dfcf0e7ce 24
tony63 0:4e0dfcf0e7ce 25 int C1=0x0F;
tony63 1:058b8f5c135d 26 int cambio=0, diferencia=0;
tony63 1:058b8f5c135d 27 float pid,o,ai,ad,ap,med,err;
tony63 1:058b8f5c135d 28 float err_v;
tony63 0:4e0dfcf0e7ce 29 int spnum=0,kinum=0,kpnum=0,kdnum=0,pos=1;
tony63 0:4e0dfcf0e7ce 30
tony63 0:4e0dfcf0e7ce 31 int main()
tony63 0:4e0dfcf0e7ce 32 {
tony63 0:4e0dfcf0e7ce 33 lcd.locate(0,1);
tony63 0:4e0dfcf0e7ce 34 lcd.printf("**Control PID**");
tony63 0:4e0dfcf0e7ce 35 wait(2);
tony63 0:4e0dfcf0e7ce 36 lcd.cls(); // Borrar Pantalla
tony63 0:4e0dfcf0e7ce 37 lcd.writeCommand(C1);//escribimos un comando segun el manual del modulo LCD
tony63 0:4e0dfcf0e7ce 38
tony63 0:4e0dfcf0e7ce 39 lcd.locate(8,0);
tony63 0:4e0dfcf0e7ce 40 lcd.printf("Kp=%d",kpnum);
tony63 0:4e0dfcf0e7ce 41 lcd.locate(0,1);
tony63 0:4e0dfcf0e7ce 42 lcd.printf("Ki=%d",kinum);
tony63 0:4e0dfcf0e7ce 43 lcd.locate(8,1);
tony63 0:4e0dfcf0e7ce 44 lcd.printf("Kd=%d",kdnum);
tony63 0:4e0dfcf0e7ce 45 lcd.locate(0,0);
tony63 0:4e0dfcf0e7ce 46 lcd.printf("Sp=%d",spnum);
tony63 0:4e0dfcf0e7ce 47
tony63 0:4e0dfcf0e7ce 48 while(1)
tony63 0:4e0dfcf0e7ce 49 {
tony63 0:4e0dfcf0e7ce 50 //lcd.locate(8,0);
tony63 0:4e0dfcf0e7ce 51 //lcd.printf("Kp=%d",encoder.getPulses());
tony63 0:4e0dfcf0e7ce 52 //wait(.5);
tony63 0:4e0dfcf0e7ce 53
tony63 0:4e0dfcf0e7ce 54 diferencia=encoder.getPulses()-cambio;
tony63 0:4e0dfcf0e7ce 55 cambio=encoder.getPulses();
tony63 0:4e0dfcf0e7ce 56
tony63 0:4e0dfcf0e7ce 57 if (diferencia==0)
tony63 0:4e0dfcf0e7ce 58 {
tony63 0:4e0dfcf0e7ce 59 //nada
tony63 0:4e0dfcf0e7ce 60 }
tony63 0:4e0dfcf0e7ce 61 else if(diferencia>0)
tony63 0:4e0dfcf0e7ce 62 {
tony63 0:4e0dfcf0e7ce 63 if(pos==1)
tony63 0:4e0dfcf0e7ce 64 {
tony63 1:058b8f5c135d 65 if(spnum+diferencia>=999)
tony63 0:4e0dfcf0e7ce 66 {
tony63 1:058b8f5c135d 67 spnum=999;
tony63 0:4e0dfcf0e7ce 68 lcd.locate(3,0);
tony63 0:4e0dfcf0e7ce 69 lcd.printf(" ");
tony63 0:4e0dfcf0e7ce 70 lcd.locate(3,0);
tony63 0:4e0dfcf0e7ce 71 lcd.printf("%d", spnum);
tony63 0:4e0dfcf0e7ce 72 }
tony63 0:4e0dfcf0e7ce 73 else
tony63 0:4e0dfcf0e7ce 74 {
tony63 0:4e0dfcf0e7ce 75 spnum+=diferencia;
tony63 0:4e0dfcf0e7ce 76 lcd.locate(3,0);
tony63 0:4e0dfcf0e7ce 77 lcd.printf("%d", spnum);
tony63 0:4e0dfcf0e7ce 78 }
tony63 0:4e0dfcf0e7ce 79 }
tony63 0:4e0dfcf0e7ce 80 else if(pos==2)
tony63 0:4e0dfcf0e7ce 81 {
tony63 1:058b8f5c135d 82 if(kpnum+diferencia>=999)
tony63 0:4e0dfcf0e7ce 83 {
tony63 1:058b8f5c135d 84 kpnum=999;
tony63 0:4e0dfcf0e7ce 85 lcd.locate(11,0);
tony63 0:4e0dfcf0e7ce 86 lcd.printf(" ");
tony63 0:4e0dfcf0e7ce 87 lcd.locate(11,0);
tony63 0:4e0dfcf0e7ce 88 lcd.printf("%d", kpnum);
tony63 0:4e0dfcf0e7ce 89 }
tony63 0:4e0dfcf0e7ce 90 else
tony63 0:4e0dfcf0e7ce 91 {
tony63 0:4e0dfcf0e7ce 92 kpnum+=diferencia;
tony63 0:4e0dfcf0e7ce 93 lcd.locate(11,0);
tony63 0:4e0dfcf0e7ce 94 lcd.printf("%d", kpnum);
tony63 0:4e0dfcf0e7ce 95 }
tony63 0:4e0dfcf0e7ce 96 }
tony63 0:4e0dfcf0e7ce 97 else if(pos==3)
tony63 0:4e0dfcf0e7ce 98 {
tony63 1:058b8f5c135d 99 if(kinum+diferencia>=999)
tony63 0:4e0dfcf0e7ce 100 {
tony63 1:058b8f5c135d 101 kinum=999;
tony63 0:4e0dfcf0e7ce 102 lcd.locate(3,1);
tony63 0:4e0dfcf0e7ce 103 lcd.printf(" ");
tony63 0:4e0dfcf0e7ce 104 lcd.locate(3,1);
tony63 0:4e0dfcf0e7ce 105 lcd.printf("%d", kinum);
tony63 0:4e0dfcf0e7ce 106 }
tony63 0:4e0dfcf0e7ce 107 else
tony63 0:4e0dfcf0e7ce 108 {
tony63 0:4e0dfcf0e7ce 109 kinum+=diferencia;
tony63 0:4e0dfcf0e7ce 110 lcd.locate(3,1);
tony63 0:4e0dfcf0e7ce 111 lcd.printf("%d", kinum);
tony63 0:4e0dfcf0e7ce 112 }
tony63 0:4e0dfcf0e7ce 113 }
tony63 0:4e0dfcf0e7ce 114 else if(pos==4)
tony63 0:4e0dfcf0e7ce 115 {
tony63 1:058b8f5c135d 116 if(kdnum+diferencia>=999)
tony63 0:4e0dfcf0e7ce 117 {
tony63 1:058b8f5c135d 118 kdnum=999;
tony63 0:4e0dfcf0e7ce 119 lcd.locate(11,1);
tony63 0:4e0dfcf0e7ce 120 lcd.printf(" ");
tony63 0:4e0dfcf0e7ce 121 lcd.locate(11,1);
tony63 0:4e0dfcf0e7ce 122 lcd.printf("%d", kdnum);
tony63 0:4e0dfcf0e7ce 123 }
tony63 0:4e0dfcf0e7ce 124 else
tony63 0:4e0dfcf0e7ce 125 {
tony63 0:4e0dfcf0e7ce 126 kdnum+=diferencia;
tony63 0:4e0dfcf0e7ce 127 lcd.locate(11,1);
tony63 0:4e0dfcf0e7ce 128 lcd.printf("%d", kdnum);
tony63 0:4e0dfcf0e7ce 129 }
tony63 0:4e0dfcf0e7ce 130 }
tony63 0:4e0dfcf0e7ce 131 }
tony63 0:4e0dfcf0e7ce 132
tony63 0:4e0dfcf0e7ce 133 else if(diferencia<0)
tony63 0:4e0dfcf0e7ce 134 {
tony63 0:4e0dfcf0e7ce 135 if(pos==1)
tony63 0:4e0dfcf0e7ce 136 {
tony63 0:4e0dfcf0e7ce 137 if(spnum+diferencia<0)
tony63 0:4e0dfcf0e7ce 138 {
tony63 0:4e0dfcf0e7ce 139 //No ocurre nada
tony63 0:4e0dfcf0e7ce 140 }
tony63 0:4e0dfcf0e7ce 141 else
tony63 0:4e0dfcf0e7ce 142 {
tony63 0:4e0dfcf0e7ce 143 spnum+=diferencia;
tony63 0:4e0dfcf0e7ce 144 lcd.locate(3,0);
tony63 0:4e0dfcf0e7ce 145 lcd.printf(" ");
tony63 0:4e0dfcf0e7ce 146 lcd.locate(3,0);
tony63 0:4e0dfcf0e7ce 147 lcd.printf("%d", spnum);
tony63 0:4e0dfcf0e7ce 148 }
tony63 0:4e0dfcf0e7ce 149 }
tony63 0:4e0dfcf0e7ce 150 else if(pos==2)
tony63 0:4e0dfcf0e7ce 151 {
tony63 0:4e0dfcf0e7ce 152 if(kpnum+diferencia<0)
tony63 0:4e0dfcf0e7ce 153 {
tony63 0:4e0dfcf0e7ce 154 //No ocurre nada
tony63 0:4e0dfcf0e7ce 155 }
tony63 0:4e0dfcf0e7ce 156 else
tony63 0:4e0dfcf0e7ce 157 {
tony63 0:4e0dfcf0e7ce 158 kpnum+=diferencia;
tony63 0:4e0dfcf0e7ce 159 lcd.locate(11,0);
tony63 0:4e0dfcf0e7ce 160 lcd.printf(" ");
tony63 0:4e0dfcf0e7ce 161 lcd.locate(11,0);
tony63 0:4e0dfcf0e7ce 162 lcd.printf("%d", kpnum);
tony63 0:4e0dfcf0e7ce 163 }
tony63 0:4e0dfcf0e7ce 164 }
tony63 0:4e0dfcf0e7ce 165 else if(pos==3)
tony63 0:4e0dfcf0e7ce 166 {
tony63 0:4e0dfcf0e7ce 167 if(kinum+diferencia<0)
tony63 0:4e0dfcf0e7ce 168 {
tony63 0:4e0dfcf0e7ce 169 //No ocurre nada
tony63 0:4e0dfcf0e7ce 170 }
tony63 0:4e0dfcf0e7ce 171 else
tony63 0:4e0dfcf0e7ce 172 {
tony63 0:4e0dfcf0e7ce 173 kinum+=diferencia;
tony63 0:4e0dfcf0e7ce 174 lcd.locate(3,1);
tony63 0:4e0dfcf0e7ce 175 lcd.printf(" ");
tony63 0:4e0dfcf0e7ce 176 lcd.locate(3,1);
tony63 0:4e0dfcf0e7ce 177 lcd.printf("%d", kinum);
tony63 0:4e0dfcf0e7ce 178 }
tony63 0:4e0dfcf0e7ce 179 }
tony63 0:4e0dfcf0e7ce 180 else if(pos==4)
tony63 0:4e0dfcf0e7ce 181 {
tony63 0:4e0dfcf0e7ce 182 if(kdnum+diferencia<0)
tony63 0:4e0dfcf0e7ce 183 {
tony63 0:4e0dfcf0e7ce 184 //No ocurre nada
tony63 0:4e0dfcf0e7ce 185 }
tony63 0:4e0dfcf0e7ce 186 else
tony63 0:4e0dfcf0e7ce 187 {
tony63 0:4e0dfcf0e7ce 188 kdnum+=diferencia;
tony63 0:4e0dfcf0e7ce 189 lcd.locate(11,1);
tony63 0:4e0dfcf0e7ce 190 lcd.printf(" ");
tony63 0:4e0dfcf0e7ce 191 lcd.locate(11,1);
tony63 0:4e0dfcf0e7ce 192 lcd.printf("%d", kdnum);
tony63 0:4e0dfcf0e7ce 193 }
tony63 0:4e0dfcf0e7ce 194 }
tony63 0:4e0dfcf0e7ce 195 }
tony63 0:4e0dfcf0e7ce 196
tony63 0:4e0dfcf0e7ce 197 if (!button3) //cambia la posicion de ingreso de parametros
tony63 0:4e0dfcf0e7ce 198 {
tony63 0:4e0dfcf0e7ce 199 led3 =!led3;
tony63 0:4e0dfcf0e7ce 200 if(pos==4)
tony63 0:4e0dfcf0e7ce 201 {
tony63 0:4e0dfcf0e7ce 202 pos=1;
tony63 0:4e0dfcf0e7ce 203 lcd.locate(3,0);
tony63 0:4e0dfcf0e7ce 204 lcd.printf("%d", spnum);
tony63 0:4e0dfcf0e7ce 205 }
tony63 0:4e0dfcf0e7ce 206 else if (pos==1)
tony63 0:4e0dfcf0e7ce 207 {
tony63 0:4e0dfcf0e7ce 208 pos++;
tony63 0:4e0dfcf0e7ce 209 lcd.locate(11,0);
tony63 0:4e0dfcf0e7ce 210 lcd.printf("%d", kpnum);
tony63 0:4e0dfcf0e7ce 211 }
tony63 0:4e0dfcf0e7ce 212 else if(pos==2)
tony63 0:4e0dfcf0e7ce 213 {
tony63 0:4e0dfcf0e7ce 214 pos++;
tony63 0:4e0dfcf0e7ce 215 lcd.locate(3,1);
tony63 0:4e0dfcf0e7ce 216 lcd.printf("%d", kinum);
tony63 0:4e0dfcf0e7ce 217 }
tony63 0:4e0dfcf0e7ce 218 else if(pos==3)
tony63 0:4e0dfcf0e7ce 219 {
tony63 0:4e0dfcf0e7ce 220 pos++;
tony63 0:4e0dfcf0e7ce 221 lcd.locate(11,1);
tony63 0:4e0dfcf0e7ce 222 lcd.printf("%d", kdnum);
tony63 0:4e0dfcf0e7ce 223 }
tony63 0:4e0dfcf0e7ce 224 wait(0.25);
tony63 0:4e0dfcf0e7ce 225
tony63 0:4e0dfcf0e7ce 226 }
tony63 0:4e0dfcf0e7ce 227
tony63 0:4e0dfcf0e7ce 228 if (!button4)
tony63 0:4e0dfcf0e7ce 229 {
tony63 0:4e0dfcf0e7ce 230 break; //sale del bucle si pisan suiche4
tony63 0:4e0dfcf0e7ce 231 }
tony63 0:4e0dfcf0e7ce 232 wait(0.1);
tony63 0:4e0dfcf0e7ce 233 }
tony63 0:4e0dfcf0e7ce 234
tony63 0:4e0dfcf0e7ce 235
tony63 0:4e0dfcf0e7ce 236 //Transicion
tony63 0:4e0dfcf0e7ce 237 lcd.writeCommand(C4);//escribimos un comando segun el manual del modulo LCD para quitar cursor bajo
tony63 0:4e0dfcf0e7ce 238 lcd.cls(); //borra la pantalla
tony63 0:4e0dfcf0e7ce 239 lcd.printf(" GUARDADOS!");
tony63 0:4e0dfcf0e7ce 240 wait(1);
tony63 0:4e0dfcf0e7ce 241 lcd.cls();
tony63 0:4e0dfcf0e7ce 242 lcd.printf(" INICIA EL PID");
tony63 0:4e0dfcf0e7ce 243 wait(1);
tony63 0:4e0dfcf0e7ce 244 // se imprimen los parches del control *****************************************
tony63 0:4e0dfcf0e7ce 245 lcd.cls();
tony63 1:058b8f5c135d 246 lcd.printf("Er=%3.0f",err);
tony63 0:4e0dfcf0e7ce 247 lcd.locate(8,0);
tony63 1:058b8f5c135d 248 lcd.printf("Me=%3.0f",med);
tony63 0:4e0dfcf0e7ce 249 lcd.locate(0,1);
tony63 1:058b8f5c135d 250 lcd.printf("Sp=%3.0f",spnum);
tony63 0:4e0dfcf0e7ce 251 lcd.locate(8,1);
tony63 1:058b8f5c135d 252 lcd.printf("Co=%3.0f",pid);
tony63 1:058b8f5c135d 253 wait(1);
tony63 0:4e0dfcf0e7ce 254
tony63 0:4e0dfcf0e7ce 255 // CICLO PRINCIPAL CONTROLADOR PID
tony63 1:058b8f5c135d 256 lop1: med = y.read()*999;
tony63 0:4e0dfcf0e7ce 257 err = (spnum-med); //se calcula el error
tony63 1:058b8f5c135d 258 ap = kpnum*err*0.01f; //se calcula la accion proporcinal
tony63 1:058b8f5c135d 259 ai =(kinum*err*0.01f)+ai; //calculo de la integral del error
tony63 1:058b8f5c135d 260 ad = kdnum*(err-err_v)*0.01f; //calculo de la accion derivativa
tony63 0:4e0dfcf0e7ce 261 pid = (ap+ai+ad);
tony63 0:4e0dfcf0e7ce 262 // se verifica que pid sea positivo **************************************
tony63 0:4e0dfcf0e7ce 263 if(pid<=0)
tony63 0:4e0dfcf0e7ce 264 {
tony63 0:4e0dfcf0e7ce 265 pid=0;
tony63 0:4e0dfcf0e7ce 266 }
tony63 0:4e0dfcf0e7ce 267
tony63 0:4e0dfcf0e7ce 268 // se verifica que pid sea menor o igual la valor maximo *****************
tony63 0:4e0dfcf0e7ce 269 if (pid > 999)
tony63 0:4e0dfcf0e7ce 270 {
tony63 0:4e0dfcf0e7ce 271 pid=999;
tony63 0:4e0dfcf0e7ce 272 }
tony63 0:4e0dfcf0e7ce 273
tony63 1:058b8f5c135d 274
tony63 0:4e0dfcf0e7ce 275 //se muestran las variables******************************************
tony63 0:4e0dfcf0e7ce 276 lcd.locate(3,0);
tony63 0:4e0dfcf0e7ce 277 lcd.printf(" ");
tony63 0:4e0dfcf0e7ce 278 lcd.locate(3,0);
tony63 1:058b8f5c135d 279 lcd.printf("%3.0f",err);
tony63 0:4e0dfcf0e7ce 280 lcd.locate(11,0);
tony63 1:058b8f5c135d 281 lcd.printf(" ");
tony63 0:4e0dfcf0e7ce 282 lcd.locate(11,0);
tony63 1:058b8f5c135d 283 lcd.printf("%3.0f",med);
tony63 0:4e0dfcf0e7ce 284 lcd.locate(3,1);
tony63 1:058b8f5c135d 285 lcd.printf(" ");
tony63 0:4e0dfcf0e7ce 286 lcd.locate(3,1);
tony63 0:4e0dfcf0e7ce 287 lcd.printf("%d",spnum);
tony63 0:4e0dfcf0e7ce 288 lcd.locate(11,1);
tony63 1:058b8f5c135d 289 lcd.printf(" ");
tony63 0:4e0dfcf0e7ce 290 lcd.locate(11,1);
tony63 1:058b8f5c135d 291 lcd.printf("%3.0f",pid);
tony63 1:058b8f5c135d 292
tony63 1:058b8f5c135d 293
tony63 1:058b8f5c135d 294
tony63 0:4e0dfcf0e7ce 295
tony63 0:4e0dfcf0e7ce 296 //Normalizacion de la salida
tony63 1:058b8f5c135d 297 // se actualizan las variables *******************************************
tony63 1:058b8f5c135d 298 err_v = err;
tony63 1:058b8f5c135d 299 o = pid/999;
tony63 1:058b8f5c135d 300 u.write(o);
tony63 0:4e0dfcf0e7ce 301 // se envia el valor pid a puerto analogico de salida (D/A) **************
tony63 1:058b8f5c135d 302
tony63 0:4e0dfcf0e7ce 303 // se repite el ciclo
tony63 1:058b8f5c135d 304 wait_ms(300);
tony63 1:058b8f5c135d 305 goto lop1;
tony63 0:4e0dfcf0e7ce 306 }