![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Se realiza un control PID sobre el voltaje de un condensador en un filtro RC. Se transmiten las señales de salida y set-point por medio de Bluetooth para luego ser graficadas en una aplicación de Android.
Dependencies: QEI TextLCD mbed
Fork of PID by
main.cpp
- Committer:
- NicolasV
- Date:
- 2017-06-03
- Revision:
- 4:82ac4b34c3d9
- Parent:
- 3:2e823b16a4a1
File content as of revision 4:82ac4b34c3d9:
/* * Código por: Laura Álvila * Daniela López * Nicolás Villegas */ #include "mbed.h" #include "QEI.h" #include "TextLCD.h" Serial GSM(PTE0,PTE1); // Módulo Bluetooh TextLCD lcd(PTB10, PTB11, PTE2, PTE3, PTE4, PTE5); // rs, e, d4-d7 QEI encoder (PTA13, PTD5, NC, 10); Timer t; AnalogIn y(PTC2); // Entrada análoga: Salida del sistema AnalogOut u(PTE30); // Salida análoga: Señal de control DigitalOut led1(LED1); DigitalOut led2(LED2); DigitalOut led3(LED3); DigitalIn button3(PTC16); // Botón del encoder DigitalIn button4(PTC17); // Pulsador int C1=0x0F; int C2=0x18; int C3=0x1A; int C4=0x0C; int cambio = 0, diferencia = 0; float pid, o, ai, ad, ap, med, err, setpoint; float err_v; int spnum = 0, kinum = 0, kpnum = 0 ,kdnum = 0, pos = 1; int j,k; long t_pid = 0, t_btn = 0; int main() { // Se asigna baudrate y se configura el puerto serie de la USART GSM.baud(9600); GSM.format(8,Serial::None,1); t.start(); // Animación de bienvenida: for (int i = 3; i < 15; ++i) { lcd.cls(); lcd.locate(0,0); lcd.printf("**Control PID**"); wait_ms(1000/i); ++i; lcd.cls(); lcd.locate(1,0); lcd.printf("**Control PID**"); wait_ms(1000/i); ++i; lcd.cls(); lcd.locate(1,1); lcd.printf("**Control PID**"); wait_ms(1000/i); ++i; lcd.cls(); lcd.locate(0,1); lcd.printf("**Control PID**"); wait_ms(1000/i); } init: lcd.cls(); lcd.writeCommand(C1); lcd.locate(8,0); lcd.printf("Ki=%d", kinum); lcd.locate(0,1); lcd.printf("Kd=%d", kdnum); lcd.locate(8,1); lcd.printf("**PID**"); lcd.locate(0,0); lcd.printf("Kp=%d", kpnum); bool state = 1; // Esta variable determina si se están modificando las constantes del controlador o el Set-Point. while(true) { diferencia=(encoder.getPulses() - cambio)*3; cambio=encoder.getPulses(); if (diferencia != 0 && state) { switch (pos) { case 1: kpnum += diferencia; if (kpnum >= 999) kpnum = 999; else if (kpnum < 0) kpnum = 0; lcd.locate(3,0); lcd.printf(" "); lcd.locate(3,0); lcd.printf("%d", kpnum); break; case 2: kinum += diferencia; if (kinum >= 999) kinum = 999; else if (kinum < 0) kinum = 0; lcd.locate(11,0); lcd.printf(" "); lcd.locate(11,0); lcd.printf("%d", kinum); break; case 3: kdnum += diferencia; if (kdnum >= 999) kdnum = 999; else if (kdnum < 0) kdnum = 0; lcd.locate(3,1); lcd.printf(" "); lcd.locate(3,1); lcd.printf("%d", kdnum); break; } } if (diferencia != 0 && !state) { spnum += diferencia; if (spnum >= 999) spnum = 999; else if (spnum < 0) spnum = 0; lcd.locate(10,0); lcd.printf(" "); lcd.locate(10,0); lcd.printf("%d", spnum); } if (!button3) { // Cambia la posición de ingreso de parámetros led2 = !led2; switch(pos++) { case 3: pos = 1; lcd.locate(3,0); lcd.printf("%d", kpnum); break; case 1: lcd.locate(11,0); lcd.printf("%d", kinum); break; case 2: lcd.locate(3,1); lcd.printf("%d", kdnum); break; } wait(0.2); } if (!button4 && state) { lcd.cls(); lcd.locate(8,1); lcd.printf("**PID**"); lcd.locate(0,0); lcd.printf("Set-Point="); lcd.locate(10,0); lcd.printf("%d", spnum); wait(0.2); state = 0; } else if (!button4 && !state) { wait(0.2); break; } wait(0.1); } // Transición lcd.writeCommand(C4); // Escribimos un comando segun el manual del módulo LCD para quitar cursor bajo lcd.cls(); lcd.locate(0,0); lcd.printf("y="); lcd.locate(8,0); lcd.printf("e="); lcd.locate(0,1); lcd.printf("r="); lcd.locate(8,1); lcd.printf("u="); loop: if (t.read_ms() - t_pid > 10) { med = y.read()*999; err = spnum - med; // Se calcula el error ap = kpnum*err*0.01f; // Se calcula la acción proporcional ai += kinum*err*0.01f; // Cálculo de la integral del error ad = kdnum*(err - err_v)*0.01f; // Cálculo de la acción derivativa pid = ap + ai + ad; if (pid <= 0) pid = 0; if (pid > 999) pid = 999; setpoint = spnum; GSM.printf("#%3.0f%3.0f&", med, setpoint); // Se envía una cadena de caracteres por el puerto serial. Se agregan identificadores #...& que denotan el comienzo y la terminación de la misma. // Esto se hace con el fin de evitar errores en la transmisión. Estos identificadores se usan en la aplicación de AppInventor. lcd.locate(3,0); lcd.printf("%3.0f ", med); lcd.locate(3,1); lcd.printf("%3d ", spnum); lcd.locate(11,0); lcd.printf("%3.0f ", err); lcd.locate(11,1); lcd.printf("%3.0f ", pid); err_v = err; o = pid/999; u.write(o); t_pid = t.read_ms(); } else { diferencia=(encoder.getPulses() - cambio)*6; // Es posible cambiar el Set-Point cuando el controlador ya está funcionando. cambio=encoder.getPulses(); if (diferencia != 0) { spnum += diferencia; if (spnum >= 999) spnum = 999; else if (spnum < 0) spnum = 0; } } if (!button4) { // Si se presiona el pulsador se vuelve al menú inicial para configurar de nuevo el controlador. u.write(0); med = 0; err = 0; pid = 0; goto init; } else goto loop; }