Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: DebouncedIn QEI TextLCD_encoder mbed
Fork of PID_Encoder by
Revision 5:ad88703dc6d3, committed 2014-06-12
- Comitter:
- Gregorio
- Date:
- Thu Jun 12 16:43:28 2014 +0000
- Parent:
- 4:d42fe3777735
- Commit message:
- PID for ramp temperature control using LM35 temperature sensor and two actuators, a bulb and a ventilator.
Changed in this revision
| main.cpp | Show annotated file Show diff for this revision Revisions of this file |
| mbed.bld | Show annotated file Show diff for this revision Revisions of this file |
--- a/main.cpp Sat May 24 15:05:40 2014 +0000
+++ b/main.cpp Thu Jun 12 16:43:28 2014 +0000
@@ -1,248 +1,517 @@
#include "mbed.h"
#include "DebouncedIn.h"
#include "TextLCD.h"
-#include "QEI.h"
+#include "QEI.h"
-TextLCD lcd(PTB10, PTB11, PTE2, PTE3, PTE4, PTE5); // rs, e, d4-d7
-QEI wheel (PTD5, PTD0, NC, 100);
-AnalogIn y(PTB1);
-AnalogOut u(PTE30);
-DigitalOut led1(LED1);
-DigitalOut led2(LED2);
-DigitalOut led3(LED3);
-DebouncedIn button1(PTC12);
-DebouncedIn button2(PTC13);
-DebouncedIn button3(PTC16);
-DebouncedIn button4(PTC17);
+TextLCD lcd(PTB10, PTB11, PTE2, PTE3, PTE4, PTE5); // rs, e, d4-d7 entradas del LCD
+QEI wheel (PTD5, PTD0, NC, 100); // entradas para el ENCODER
+AnalogIn LM(PTB1); // temperatura leida por un LM35
+PwmOut bomb(PTD4); //salida para activar un bombillo
+PwmOut vent(PTA12); //salida para activar un ventilador
+DigitalOut led3(LED3); // Led para indicar que los botones se presionan
+DebouncedIn button3(PTC16); //boton 3 es el pulsador del ENCODER
+DebouncedIn button4(PTA13); // boton 4 es para la configuración de las constantes del pid, de tiempo de rampa y de temperatura del horno
- //codigos movimiento del curzor
- //18 para izquierda
- //1A para derecha
-
-//int C1=0x0E; // solo muestra el curzor
+//codigos movimiento del curzor LCD
int C2=0x18; // desplaza izquierda
int C3=0x1A; // desplaza derecha
int C4=0x0C; // quito cursor bajo
-int C1=0x0F;
+int C1=0x0F; // solo muestra el curzor
+
-int i; // indice de la variable
-int j; //variable controla cambio 4 posiciones
-int kp, ki, kd, sp;
-float yr, ap, ai, ad, err, med, err_v, cycle, pid;
-int b=0;
+//definicion de varibles
+int i=1; // i controla cambio de "modo" del boton 4. i=1 -> (constantes PID), i=2 -> (Tiempo y temperatura)
+int j=1; //j controla cambio de posiciones para cambiar variable (con el boton del ENCODER)
+int kp=40, ki=40, kd=40, sp; //constantes del pid y del setpoint
+int t1=60, t2=60, t3=60; //tiempos de la rapmpa de subida, temperatura estable y tiempo de bajada t1=t2=t3 [segundos]
+int temp=45; // temp:temperatura final a la que llega el horno[ºC]
+float ta, avg, a[10]; // ta: temperatura ambiente que se lee con el LM35, antes de empezar control, avg, promedio de temperatura para minimizar error
+float yr, ap, ai, ad, err, med, err_v, cycle, pid; //
+float dt1, dt2, dt3,c=0; // variables para ciclos de control en tiempos t1, t2 y t3
+int b=0; // Se usa para imprimir datos en la LCD
float pidn;
Timer t;
-int main() {
- lcd.cls();
- lcd.writeCommand(C1);//escribimos un comando segun el manual del modulo LCD
- lcd.locate(0,0);
- lcd.printf("Sp%d",sp);
- lcd.locate(8,0);
- lcd.printf("Kp%d",kp);
- lcd.locate(0,1);
- lcd.printf("Ki%d",ki);
- lcd.locate(8,1);
- lcd.printf("Kd%d",kd);
-
+// Inicia el código
+int main()
+{
while(1) {
-
- led3 =1;
- if (button3.falling()) { //INCREMENTA POSICION DEL MENU CON BOTON 3 (Switche encoder)
- led3 =!led3;
- ++j;
- }
-
- if (j==0){
- sp=sp+wheel.getPulses();
- wheel.reset();
- if (sp>999){
- sp=999;
- }
- if (sp<0){
- sp=0;
- }
- lcd.locate(2,0);
- lcd.printf(" ",sp);
- lcd.locate(2,0);
- lcd.printf("%d",sp);
- wait(0.2);
-
- if(button3.falling()){
- j=1;
- led3=0;
- wait(0.3);
- wheel.reset();
- }
-
- }
-
- if (j==1) {
- kp=kp+wheel.getPulses();
- wheel.reset();
- if (kp>999){
- kp=999;
- }
- if (kp<0){
- kp=0;
- }
- lcd.locate(10,0);
- lcd.printf(" ");
- lcd.locate(10,0);
- lcd.printf("%d",kp);
- wait(0.2);
-
- if(button3.falling()){
- j=2;
- led3=0;
- wait(0.3);
- wheel.reset();
- }
-
- }
-
- if (j==2) {
- ki=ki+wheel.getPulses();
- wheel.reset();
- if (ki>999){
- ki=999;
- }
- if (ki<0){
- ki=0;
- }
- lcd.locate(2,1);
- lcd.printf(" ");
- lcd.locate(2,1);
- lcd.printf("%d",ki);
- wait(0.2);
-
- if(button3.falling()){
- j=3;
- led3=0;
- wait(0.3);
- wheel.reset();
- }
-
- }
-
- if (j==3) {
- kd=kd+wheel.getPulses();
- wheel.reset();
- if (kd>999){
- kd=999;
- }
- if (kd<0){
- kd=0;
- }
- lcd.locate(10,1);
- lcd.printf(" ");
- lcd.locate(10,1);
- lcd.printf("%d",kd);
- wait(0.2);
-
- if(button3.falling()){
- j=0;
- led3=0;
- wait(0.3);
- wheel.reset();
- }
-
- }
-
- if (j==4) {
- j=0;
- }
-
- if (!button4){
- break; //sale del bucle si pisan suiche4
- }
- } //cierro while(1)
-//%---------------------------------------------------------------------
-
-
- lcd.writeCommand(C4);//escribimos un comando segun el manual del modulo LCD para quitar cursor bajo
- lcd.cls(); //borra la pantalla
- lcd.printf("GUARDAMOS \nVALORES |m|");
- wait(2);
-
- // se imprimen los parches del control *****************************************
- lcd.cls();
- lcd.printf("Er%d",err);
- lcd.locate(8,0);
- lcd.printf("Me%d",med);
- lcd.locate(0,1);
- lcd.printf("Sp%d",sp);
- lcd.locate(8,1);
- lcd.printf("Co%d",pid);
- wait(1);
-
-
- // CICLO PRINCIPAL CONTROLADOR PID
- b=0;
- while(1) {
- med=1000*y.read(); //leer puerto analogo y asignar a med
- err = (sp-med);
- ap = kp*err;
-
- // se verifica que la accion integral no sea muy grande
- if(ai<100)
- {
- ai =(ki*err)+ai; //calculo de la integral del error
- }
- //else{
- //Dejo de sumar la accion integral
- // }
-
- ad = kd*(err-err_v); //calculo de la accion derivativa
- pid = (ap+ai+ad);
-
-
-
- // se verifica que pid sea positivo **************************************
- if(pid<=0){pid=0;}
- // se verifica que pid sea menor o igual la valor maximo *****************
- if(pid>=1000){pid=1000;}
-
- // se actualizan las variables *******************************************
- err_v = err;
-
- //se muestran las variables******************************************
-
- if (b==0)
- {
- t.start();
- b=1;
- }
- if(t>=0.01)
- {
- wait(0.2);
- lcd.locate(2,0);
- lcd.printf(" ");
- lcd.locate(2,0);
- lcd.printf("%d",err);
- lcd.locate(10,0);
- lcd.printf(" ");
- lcd.locate(10,0);
- lcd.printf("%d",med);
- lcd.locate(2,1);
- lcd.printf(" ");
- lcd.locate(2,1);
- lcd.printf("%d",sp);
- lcd.locate(10,1);
- lcd.printf(" ");
- lcd.locate(10,1);
- lcd.printf("%d",pid);
- }
-
- //Normalizacion de la salida
- pidn=pid/1000;
- // se envia el valor pid a puerto analogico de salida (D/A) **************
- u.write(pidn);
-
- // se repite el ciclo
- wait(0.1);
- }
-
-
+ if(i==1) {
+ lcd.cls();
+ lcd.writeCommand(C1);//escribimos un comando segun el manual del modulo LCD
+ lcd.locate(0,0);
+ lcd.printf(" PID");
+ lcd.locate(8,0);
+ lcd.printf("Kp:%d",kp);
+ lcd.locate(0,1);
+ lcd.printf("Ki:%d",ki);
+ lcd.locate(8,1);
+ lcd.printf("Kd:%d",kd);
+
+ led3 =1;
+ if (button3.falling()) { //INCREMENTA POSICION DEL MENU CON BOTON 3 (Switche encoder)
+ led3 =!led3;
+ }
+
+ if (j==1) {
+ kp=kp+wheel.getPulses();
+ wheel.reset();
+ if (kp>999) {
+ kp=999;
+ }
+ if (kp<0) {
+ kp=0;
+ }
+ lcd.locate(11,0);
+ lcd.printf(" ");
+ lcd.locate(11,0);
+ lcd.printf("%d",kp);
+ wait(0.2);
+
+ if(button3.falling()) {
+ j=2;
+ led3=0;
+ wait(0.3);
+ wheel.reset();
+ }
+ }
+ if (j==2) {
+ ki=ki+wheel.getPulses();
+ wheel.reset();
+ if (ki>999) {
+ ki=999;
+ }
+ if (ki<0) {
+ ki=0;
+ }
+ lcd.locate(3,1);
+ lcd.printf(" ");
+ lcd.locate(3,1);
+ lcd.printf("%d",ki);
+ wait(0.2);
+
+ if(button3.falling()) {
+ j=3;
+ led3=0;
+ wait(0.3);
+ wheel.reset();
+ }
+ }
+ if (j==3) {
+ kd=kd+wheel.getPulses();
+ wheel.reset();
+ if (kd>999) {
+ kd=999;
+ }
+ if (kd<0) {
+ kd=0;
+ }
+ lcd.locate(11,1);
+ lcd.printf(" ");
+ lcd.locate(11,1);
+ lcd.printf("%d",kd);
+ wait(0.2);
+
+ if(button3.falling()) {
+ j=1;
+ led3=0;
+ wait(0.3);
+ wheel.reset();
+ }
+ }
+ if (j==4) {
+ j=1;
+ }
+ if(button4.falling()) {
+ i=2;
+ j=0;
+ }
+ }//CIERRA EL MODO i=1 -> constantes PID
+ if(i==2) { //INICIA EL MODO i=2 -> tiempos y temperatura
+ lcd.cls();
+ lcd.writeCommand(C1);//escribimos un comando segun el manual del modulo LCD
+ lcd.locate(0,0);
+ lcd.printf("T1:%d",t1);
+ lcd.locate(8,0);
+ lcd.printf("T2:%d",t2);
+ lcd.locate(0,1);
+ lcd.printf("T3:%d",t3);
+ lcd.locate(8,1);
+ lcd.printf("Tm:%d",temp);
+
+
+ led3 =1;
+ if (button3.falling()) { //INCREMENTA POSICION DEL MENU CON BOTON 3 (Switche encoder)
+ led3 =!led3;
+ }
+ if (j==0) {
+ t1=t1+wheel.getPulses();
+ wheel.reset();
+ if (t1>5*60) { // Tiempos no mayores a 6 minutos
+ t1=5*60;
+ }
+ if (t1<60) {
+ t1=60;
+ }
+ lcd.locate(3,0);
+ lcd.printf(" ",t1);
+ lcd.locate(3,0);
+ lcd.printf("%d",t1);
+ wait(0.2);
+
+ if(button3.falling()) {
+ j=1;
+ led3=0;
+ wait(0.3);
+ wheel.reset();
+ }
+ }
+
+ if (j==1) {
+ t2=t2+wheel.getPulses();
+ wheel.reset();
+ if (t2>5*60) {
+ t2=5*60;
+ }
+ if (t2<60) {
+ t2=60;
+ }
+ lcd.locate(11,0);
+ lcd.printf(" ");
+ lcd.locate(11,0);
+ lcd.printf("%d",t2);
+ wait(0.2);
+
+ if(button3.falling()) {
+ j=2;
+ led3=0;
+ wait(0.3);
+ wheel.reset();
+ }
+ }
+ if (j==2) {
+ t3=t3+wheel.getPulses();
+ wheel.reset();
+ if (t3>5*60) {
+ t3=5*60;
+ }
+ if (t3<60) {
+ t3=60;
+ }
+ lcd.locate(3,1);
+ lcd.printf(" ");
+ lcd.locate(3,1);
+ lcd.printf("%d",t3);
+ wait(0.2);
+
+ if(button3.falling()) {
+ j=3;
+ led3=0;
+ wait(0.3);
+ wheel.reset();
+ }
+ }
+ if (j==3) {
+ temp=temp+wheel.getPulses();
+ wheel.reset();
+ if (temp>60) {
+ temp=60;
+ }
+ if (temp<20) {
+ temp=20;
+ }
+ lcd.locate(11,1);
+ lcd.printf(" ");
+ lcd.locate(11,1);
+ lcd.printf("%d",temp);
+ wait(0.2);
+
+ if(button3.falling()) {
+ j=0;
+ led3=0;
+ wait(0.3);
+ wheel.reset();
+ }
+ }
+ if (j==4) {
+ j=0;
+ }
+ if (button4.falling()) {
+ break;
+ }
+ }//CIERRE MODO i=2 -> tiempo y temperatura
+ }// Cierre del while(1)
+//%---------------------------------------------------------------------
+
+
+ lcd.writeCommand(C4);//escribimos un comando segun el manual del modulo LCD para quitar cursor bajo
+ lcd.cls(); //borra la pantalla
+ lcd.printf("Valores \nGuardados");
+ wait(1);
+
+ avg=0;
+ for(i=0; i<10; i++) {
+ a[i]=LM.read();
+ wait(.001);
+ }
+ for(i=0; i<10; i++) {
+ avg=avg+(a[i]/10);
+ }
+
+ ta=(avg*3.10143686*100);
+
+ lcd.cls(); //borra la pantalla
+ lcd.printf("T Ambiente:%.2f",ta);
+ wait(2);
+
+ // se imprimen los parches del control *****************************************
+ lcd.cls();
+ lcd.printf("Er:%.2f",err);
+ lcd.locate(8,0);
+ lcd.printf("Me:%.2f",med);
+ lcd.locate(0,1);
+ lcd.printf("dt:%.2f",dt1);
+ lcd.locate(10,1);
+ lcd.printf("t:%.0f",0);
+ wait(1);
+
+ // CICLO PARA CONTROL DE RAMPA ASCENDENTE (T1)
+ b=0;
+ t.start();
+ // Comienza el ciclo for para la primera parte del control(Rampa ascendente)
+ for(dt1=ta; dt1<=temp; dt1+=(temp-ta)/t1) {
+ avg=0;
+ for(i=0; i<10; i++) {
+ a[i]=LM.read();
+ wait(.001);
}
-
\ No newline at end of file
+ for(i=0; i<10; i++) {
+ avg=avg+(a[i]/10);
+ }
+ med=(avg*3.10143686*100); //leer puerto analogo y asignar a med (*100 ya que LM35 da 10mV/ºC)
+ err = (dt1-med);
+ // Para activar la bombilla en el tiempo de ascenso
+ if(err>=0) {
+ vent=0;
+ ap = kp*err; //calculo de la acción proporcional
+ // se verifica que la accion integral no sea muy grande
+ if(ai<100) {
+ ai =(ki*err)+ai; //calculo de la integral del error
+ }
+ ad = kd*(err-err_v); //calculo de la accion derivativa
+ pid = (ap+ai+ad);
+ // se verifica que pid sea positivo **************************************
+ if(pid<=0) {
+ pid=0;
+ }
+ // se verifica que pid sea menor o igual la valor maximo *****************
+ if(pid>=100) {
+ pid=100;
+ }
+ err_v = err;
+ //Normalizacion de la salida
+ pidn=pid/100;
+ // se envia el valor pid a puerto analogico de salida (D/A) **************
+ bomb.write(pidn);
+ }
+ // Para activar ventilador en el tiempo de ascenso
+ if(err<0) {
+ bomb=0;
+ err=-1*err;
+ ap = kp*err;
+ if(ai<100) {
+ ai =(ki*err)+ai;
+ }
+ ad = kd*(err-err_v);
+ pid = (ap+ai+ad);
+ if(pid<=0) {
+ pid=0;
+ }
+ if(pid>=100) {
+ pid=100;
+ }
+ err_v = err;
+ pidn=pid/100;
+ vent.write(pidn);
+ }
+ // se repite el ciclo
+ lcd.cls();
+ lcd.locate(0,0);
+ lcd.printf("Er:%.2f",err);
+ lcd.locate(8,0);
+ lcd.printf("Me:%.2f",med);
+ lcd.locate(0,1);
+ lcd.printf("dt:%.2f",dt1);
+ lcd.locate(10,1);
+ lcd.printf("t1:%.0f",t.read());
+ wait(1);
+ }
+ bomb=0;
+ vent=0;
+ // Comienza el segundo ciclo para la segunda parte del control (Temperatura estable)
+ t.start();
+ while(t<=t2) {
+ avg=0;
+ for(i=0; i<10; i++) {
+ a[i]=LM.read();
+ wait(.001);
+ }
+ for(i=0; i<10; i++) {
+ avg=avg+(a[i]/10);
+ }
+
+ med=(avg*3.10143686*100); //leer puerto analogo y asignar a med (*100 ya que LM35 da 10mV/ºC)
+ err = (temp-med);
+ // Para activar la bombilla en el tiempo de ascenso
+ if(err>=0) {
+ vent=0;
+ ap = kp*err; //calculo de la acción proporcional
+ // se verifica que la accion integral no sea muy grande
+ if(ai<100) {
+ ai =(ki*err)+ai; //calculo de la integral del error
+ }
+ ad = kd*(err-err_v); //calculo de la accion derivativa
+ pid = (ap+ai+ad);
+ // se verifica que pid sea positivo **************************************
+ if(pid<=0) {
+ pid=0;
+ }
+ // se verifica que pid sea menor o igual la valor maximo *****************
+ if(pid>=100) {
+ pid=100;
+ }
+ err_v = err;
+ //Normalizacion de la salida
+ pidn=pid/100;
+ // se envia el valor pid a puerto analogico de salida (D/A) **************
+ bomb.write(pidn);
+ }
+ // Para activar ventilador en el tiempo de ascenso
+ if(err<0) {
+ bomb=0;
+ err=-1*err;
+ ap = kp*err;
+ if(ai<100) {
+ ai =(ki*err)+ai;
+ }
+ ad = kd*(err-err_v);
+ pid = (ap+ai+ad);
+ if(pid<=0) {
+ pid=0;
+ }
+ if(pid>=100) {
+ pid=100;
+ }
+ err_v = err;
+ //Normalizacion de la salida
+ pidn=pid/100;
+ // se envia el valor pid a puerto analogico de salida (D/A) **************
+ vent.write(pidn);
+ }
+ lcd.cls();
+ lcd.locate(0,0);
+ lcd.printf("Er:%.2f",err);
+ lcd.locate(8,0);
+ lcd.printf("Me:%.2f",med);
+ lcd.locate(0,1);
+ lcd.printf("Tm:%.2d",temp);
+ lcd.locate(10,1);
+ lcd.printf("t2:%.0f",t.read());
+ wait(1);
+ }
+ bomb=0;
+ vent=0;
+ // Comienza el tercer ciclo para la ultima parte del control (Descenso de rampa)
+ t.start();
+ for(dt3=temp; dt3>=ta; dt3-=((temp-ta)/t3)) {
+ avg=0;
+ for(i=0; i<10; i++) {
+ a[i]=LM.read();
+ wait(.001);
+ }
+ for(i=0; i<10; i++) {
+ avg=avg+(a[i]/10);
+ }
+
+ med=(avg*3.10143686*100);//leer puerto analogo y asignar a med (*100 ya que LM35 da 10mV/ºC)
+ err = (med-dt3);
+ if(err>=0) {
+ bomb=0;
+ ap = kp*err; //calculo de la acción proporcional
+ // se verifica que la accion integral no sea muy grande
+ if(ai<100) {
+ ai =(ki*err)+ai; //calculo de la integral del error
+ }
+ ad = kd*(err-err_v); //calculo de la accion derivativa
+ pid = (ap+ai+ad);
+ // se verifica que pid sea positivo **************************************
+ if(pid<=0) {
+ pid=0;
+ }
+ // se verifica que pid sea menor o igual la valor maximo *****************
+ if(pid>=100) {
+ pid=100;
+ }
+ // se actualizan las variables *******************************************
+ err_v = err;
+ lcd.cls();
+ lcd.locate(0,0);
+ lcd.printf("Er:%.2f",err);
+ lcd.locate(8,0);
+ lcd.printf("Me:%.2f",med);
+ lcd.locate(0,1);
+ lcd.printf("dt:%.2f",dt3);
+ lcd.locate(10,1);
+ lcd.printf("t3:%.0f",t.read());
+
+ //Normalizacion de la salida
+ pidn=pid/100;
+ // se envia el valor pid a puerto analogico de salida (D/A) **************
+ vent.write(pidn);
+ // se repite el ciclo
+ wait(1);
+ }
+ if(err<0) {
+ err=-1*err;
+ vent=0;
+ ap = kp*err; //calculo de la acción proporcional
+ // se verifica que la accion integral no sea muy grande
+ if(ai<100) {
+ ai =(ki*err)+ai; //calculo de la integral del error
+ }
+ ad = kd*(err-err_v); //calculo de la accion derivativa
+ pid = (ap+ai+ad);
+ // se verifica que pid sea positivo **************************************
+ if(pid<=0) {
+ pid=0;
+ }
+ // se verifica que pid sea menor o igual la valor maximo *****************
+ if(pid>=100) {
+ pid=100;
+ }
+ // se actualizan las variables *******************************************
+ err_v = err;
+ lcd.cls();
+ lcd.locate(0,0);
+ lcd.printf("Er:%.2f",err);
+ lcd.locate(8,0);
+ lcd.printf("Me:%.2f",med);
+ lcd.locate(0,1);
+ lcd.printf("dt:%.2f",dt3);
+ lcd.locate(10,1);
+ lcd.printf("t3:%.0f",t.read());
+
+ //Normalizacion de la salida
+ pidn=pid/100;
+ // se envia el valor pid a puerto analogico de salida (D/A) **************
+ bomb.write(pidn);
+ // se repite el ciclo
+ wait(1);
+ }
+
+ }
+ bomb=0;
+ vent=0;
+ lcd.cls();
+ lcd.printf("Control\nTreminado");
+}
--- a/mbed.bld Sat May 24 15:05:40 2014 +0000 +++ b/mbed.bld Thu Jun 12 16:43:28 2014 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/mbed_official/code/mbed/builds/a9913a65894f \ No newline at end of file +http://mbed.org/users/mbed_official/code/mbed/builds/0b3ab51c8877 \ No newline at end of file
