Autor Tema: Controlador PID por angulo de fase  (Leído 8228 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Abner_emanuel

  • PIC16
  • ***
  • Mensajes: 160
Controlador PID por angulo de fase
« en: 17 de Enero de 2015, 12:06:51 »
Un saludo amigos del foro TODOPIC. :P

Tengo el código de un control PID de temperatura, que el autor lo pone con un vídeo en la red funcionando, pero yo lo e armado y no funciona realmente y no se que este pasando. Me gustaría tener su accesoria para hacerlo funcionar como se ve en el vídeo:  

Aquí pongo el código, del cual tengo algunas dudas:


Código: Text
  1. #include <16f877a.h>
  2.          #device adc=10
  3.          #fuses HS,NOWDT
  4.          #use delay(clock=20000000)    
  5.          #include <lcd.c>
  6.          
  7.          int16 valor;   //lectura de temperatura
  8.          float a=6.0631;
  9.          float b=0.05318;
  10.          float c=172.798;   //constantes del PID
  11.          float temp_limit=400.0;   //temperatura a alcanzar
  12.          float rT,eT,pT,qT,yT,uT;
  13.          float pT_1=0.0;
  14.          float eT_1=0.0; //variables de ecuaciones
  15.          float max=1000.0;
  16.          float min=0.0;     //límites máximo y mínimo de control.
  17.          float pwm1;
  18.          float tempera;   //Para visualizar la temperatura del horno.
  19.          int16  t_l;      //Para visualizar la temperatura límite.
  20.          unsigned int16 fase=24536;
  21.          int1 cambio=1;
  22.  
  23.          void pid ()
  24.          {
  25.          output_bit(pin_c0,0);
  26.          
  27.          valor=read_adc();               //Lectura de la temperatura
  28.          yT=valor*5000.0/1023.0;        //conversión a mV (0.25V a 250mV)
  29.          rT=temp_limit;
  30.          
  31.          eT=rT-yT;            //Cálculo error
  32.          pT=b*eT+pT_1;        //Cálculo del término integral
  33.          qT=c*(eT-eT_1);      //Cálculo del término derivativo
  34.          uT=pT+a*eT+qT;       //Cálculo de la salida PID
  35.          
  36.          if (uT>max) {        //Salida PID si es mayor que el MAX
  37.          uT=max;}
  38.          else {
  39.          if (uT<min){      //Salida PID si es menor que el MIN
  40.          uT=min;}
  41.          }
  42.          pwm1=38.5*uT+24636;         //Transferencia de salida PID a señal PWM
  43.          fase=pwm1;
  44.            
  45.          pT_1=pT;            //Guardar variables
  46.          eT_1=eT;
  47.          }
  48.  
  49.  
  50.          void display()
  51.          {
  52.          tempera=yT/10;
  53.          t_l=temp_limit/10;
  54.          lcd_gotoxy(1,1);
  55.          printf(lcd_putc, "Temp= %3.1F oC\n", tempera);
  56.          lcd_gotoxy(1,2);
  57.          printf(lcd_putc, "SP= %Lu oC   UAP", t_l);
  58.          }
  59.          
  60.          
  61.          void teclado()
  62.          {
  63.          if (input(PIN_B6)==0) temp_limit=temp_limit+10.0;
  64.          if (input(PIN_B7)==0) temp_limit=temp_limit-10.0;
  65.          if (temp_limit > 1000.0) temp_limit=1000.0;
  66.          if (temp_limit < 100.0) temp_limit=100.0;
  67.          }
  68.          
  69.            
  70.          #int_TIMER1
  71.          void TIMER1_isr (void)
  72.          {
  73.          output_high (pin_c2);                  
  74.          }
  75.          
  76.          #int_EXT
  77.          void EXT_isr (void)
  78.          {
  79.          output_low (pin_c2);
  80.          set_timer1(fase);
  81.          enable_interrupts(INT_TIMER1);  //Habilito la interrupción del TIMER1 y salta a su respectiva interrupción
  82.          }
  83.          
  84.          
  85.          void main ()
  86.          {
  87.          lcd_init();
  88.          set_tris_b(0b11111111);
  89.          port_b_pullups(true);
  90.           ext_int_edge(L_TO_H);
  91.          setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
  92.          enable_interrupts(INT_TIMER1);
  93.          set_timer1(fase);
  94.          enable_interrupts(INT_EXT);
  95.        
  96.          enable_interrupts(GLOBAL);
  97.          setup_adc_ports(ALL_ANALOG);
  98.          setup_adc(ADC_CLOCK_INTERNAL);
  99.          set_adc_channel(0);
  100.          
  101.          while (true)
  102.          {
  103.          pid ();
  104.          display();
  105.          teclado ();
  106.          delay_ms(100);
  107.          }
  108.          }


Por ejemplo en la linea  pwm1=38.5*uT+24636;

Se que el 24636; sale del desborde del tmr1 por que realice el calculo a lápiz y me salio que desborda cada 8.18 ms, de lo cual me doy cuenta que es para detectar el cruce por cero de la red eléctrica.
Pero desconozco de donde saca el valor de 38.5, yo mismo imagino que es para el controlar el disparo del triac aunque no estoy seguro de eso.


Bueno como les comento lo arme y físicamente no realiza el control. Lo que se aprecia es que el foco titila muy poquito pero solo eso. Por favor, podríamos echarlo andar con su ayuda.

« Última modificación: 17 de Enero de 2015, 12:31:05 por Abner_emanuel »
El señor es mi pastor,  nada me faltará.

Desconectado QIQE

  • PIC18
  • ****
  • Mensajes: 335
Re: Controlador PID por angulo de fase
« Respuesta #1 en: 18 de Enero de 2015, 08:10:51 »
Lo has simulado en proteus??
Muchas gracias por vuestro tiempo.

Saludos desde valencia!!!

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Controlador PID por angulo de fase
« Respuesta #2 en: 18 de Enero de 2015, 09:02:13 »
En la simulacion puede andar bien, pero en fisico no...

No podes saber cuando es el cruce por cero. Lo podes estimar con ese valor, pero deberia haber una entrada de red al un pin del PIC para detectar cuando es el cruce por cero.
De la misma forma que tiene tu Dimmer
« Última modificación: 18 de Enero de 2015, 09:04:41 por KILLERJC »

Desconectado ceci_lamorocha

  • PIC12
  • **
  • Mensajes: 94
Re: Controlador PID por angulo de fase
« Respuesta #3 en: 26 de Septiembre de 2015, 12:00:09 »
hola!

entonces esta linea:  pwm1=38.5*uT+24636;   esta estimando el cruce por cero ??

yo tampoco entiendo que esta haciendo ese 38.5 ahi  :mrgreen:


Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Controlador PID por angulo de fase
« Respuesta #4 en: 26 de Septiembre de 2015, 12:21:44 »
El 38.5 y el 24636 son constantes para transformar el valor de "temperatura(diferencial)" en tiempo , o mejor dicho en valores de CLK que entran al timer 1.

si uT= 10 , pwm1 = 385 + 24636 = 25021, clk a 20Mhz son 20ms y algo mas.

El detector de cruce por cero lo hace con la interupcion externa (o deberia). A partir de ahi pone el valor calculado de arriba en el timer, quien es el que va a disparar con mas tiempo o no activando la salida.
Lo que preocupa es que cuando entra al timer este nunca se resetea o deshabilitada la interrupcion, lo cual si no esta bien calculado podria fallar. Y estoy viendo que tiene una carga de 24636 y que se dispararia a 0.02045s
Eso son 20.45ms, lo raro es que la interrupcion externa seria quien detectaria el cruce por 0 y cargaria el timer cada 10ms ( medio ciclo) lo cual eso lo viviria sobreescribiendo.
Si la interrupcion externa no se usa para eso y es un simple boton, ya es un desastre. No podes tener un control de angulo de fase cuando no sabes donde esta el cruce por 0

Desconectado ceci_lamorocha

  • PIC12
  • **
  • Mensajes: 94
Re: Controlador PID por angulo de fase
« Respuesta #5 en: 26 de Septiembre de 2015, 13:26:19 »
A lo mejor me equivoco porque no tengo mucha experiencia  pero me parece que hay otro error

segun veo en la hoja de datos del 16f877 el modulo PWM se sonfigura con el setup_timer_2();
y no con el setup_timer_1(); como figura en el programa


por ejemplo si : setup_timer_2(t2_div_by_4,249,1);
entonces el maximo valor que podemos colocar en el PWM seria (segun la formula de la hoja de datos) :
(PR2=249 en este caso+1)*4 = (250)*4=1000

de aca debe salir este maximo que figura en el programa!! pero nunca configura el timer2 ! entonce de donde saco ese maximo de 1000 !!

mi conclusion es que este programa debe ser una especie de rejunte copy-paste de otros programas habria que reacerlo por completo !

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Controlador PID por angulo de fase
« Respuesta #6 en: 26 de Septiembre de 2015, 13:58:40 »
Es que no usa el PWM. No debe usarlo. esta haciendo un control de fase



es decir detecta el cruce por 0 y luego cuando pasa el tiempo que necesita activa la salida (por un ratito nomas, no hace falta mantenerla todo el ciclo), luego deberias esperar el otro cruce por 0 y activar nuevamente la salida.
Segun donde la actives desde el cruce por 0 va a ser la cantidad de tiempo activa que este la carga. Los dimmer de luz para focos incandescentes funcionan asi. Si queres mas luz deberia conducir desde el cruce por 0, si queres menos luz entonces deberia conducir luego del cruce por 0, mientras mas angulo le des, menos tiempo conduciendo = menos luz

Desconectado ceci_lamorocha

  • PIC12
  • **
  • Mensajes: 94
Re: Controlador PID por angulo de fase
« Respuesta #7 en: 26 de Septiembre de 2015, 14:49:55 »
me confundio que use la variable de nombre PWM -------> fase=pwm1; y los limites maximo minimo que usó

pero luego tendria que haverla introducido en la funcion del pwm : set_pwm1_duty(fase);   //   0<fase<1000   (aca le veia el sentido a esos limites)

pero no esta esa funcion asi que tenes razon !! la proxima veo con mayor profundidad el programa y no me adelanto!   :mrgreen:


Desconectado Abner_emanuel

  • PIC16
  • ***
  • Mensajes: 160
Re: Controlador PID por angulo de fase
« Respuesta #8 en: 28 de Septiembre de 2015, 12:29:51 »
Un saludo a todos. Ceci, que proceso de temperatura deceas tu pid?. Ya realice un control pid un poco diferente al que puse por primera vez en este tema. Pero con un algoritmo del arduino pero implementando un 18f4550 quizás te podría servir.
El señor es mi pastor,  nada me faltará.

Desconectado ceci_lamorocha

  • PIC12
  • **
  • Mensajes: 94
Re: Controlador PID por angulo de fase
« Respuesta #9 en: 28 de Septiembre de 2015, 18:12:02 »
Hola Abner, si puedes ponerlo por aqui asi lo vemos seria muy bueno !!  :mrgreen:

Al final pudiste hacer funcionar el PID que colocaste al comienzo ??


saludos!

Desconectado Abner_emanuel

  • PIC16
  • ***
  • Mensajes: 160
Re: Controlador PID por angulo de fase
« Respuesta #10 en: 28 de Septiembre de 2015, 22:02:24 »
No. Ese no lo hice funcionar y me preguntaba lo mismo que tu preguntas en este tema. Al final de cuentas realice uno que si hace el control aunque el brillo del foco con lo que yo aplicaba temperatura parpadeaba mucho aveces pero el control si lo hacia. Buscó el código y lo comparto.

Algo mas, que frecuencia de redse manejas 50 o 60 hrz?. Es indispensable para el cálculo de cruce por cero.
« Última modificación: 28 de Septiembre de 2015, 22:15:31 por Abner_emanuel »
El señor es mi pastor,  nada me faltará.

Desconectado ceci_lamorocha

  • PIC12
  • **
  • Mensajes: 94
Re: Controlador PID por angulo de fase
« Respuesta #11 en: 29 de Septiembre de 2015, 12:25:38 »
ok !

aca tenemos 220V 50Hz

Desconectado Abner_emanuel

  • PIC16
  • ***
  • Mensajes: 160
Re: Controlador PID por angulo de fase
« Respuesta #12 en: 29 de Septiembre de 2015, 17:47:45 »
Código: Text
  1. #include <16F876.h>
  2. #device adc=10
  3. #use delay(clock=20000000)
  4. #include <math.h>
  5.  
  6. #include "20X2.c"
  7. #fuses HS,NOWDT,NOPROTECT
  8. #use fast_io(A)
  9. #use fast_io(B)
  10. //#use fast_io(C)
  11. #BYTE TRISA=0x85
  12. #BYTE PORTA=0x05
  13. #BYTE TRISB=0x86
  14. #BYTE PORTB=0x06
  15. #BYTE TRISC=0x87
  16. #BYTE PORTC=0x07
  17. //#byte INTCON = 0x0B
  18. #define DOWN PIN_B7
  19. #define UP PIN_B6
  20. #define DOWN1 PIN_B5
  21. #define UP1 PIN_B4
  22. //#bit TMR0IF = INTCON.2
  23. #byte porta=5 //#byte INTCON = 0x0B
  24. #byte portb=7 //#bit TMR0IF = INTCON.2
  25. #byte portc=7
  26.  
  27. #define        minPWM 0
  28. #define        maxPWM 100 //15
  29.  
  30. unsigned int16 preheatset=40,topheatset=45; //,cupla_gpu,uk,tu,pre,top; //preheatset=100
  31. long int uk,pre;
  32. float cupla_pcb;
  33.  
  34. unsigned int16 q,v;
  35. unsigned int8 msec=0;
  36. int8 sec=0,min=0,count=0;
  37. unsigned int16 outPWM,pwm,pwmValue = 0;
  38. int1 bit_zc=0,swicht;
  39. unsigned Pk =15; // Pk =3.500
  40. unsigned Ik =0; //Ik =1.875
  41. unsigned Dk =5; //Dk =3.250
  42.  
  43. unsigned PTerm = 0;
  44. unsigned ITerm = 0;
  45. unsigned DTerm = 0;
  46. unsigned long int millisec,flag;
  47.  
  48. //void pidCompute(void);
  49. #INT_RB
  50.   void keyboard() //keyboard
  51.      {
  52.         {
  53.          if(!input(UP)){preheatset=preheatset+1; if (preheatset>350) {preheatset=350;}}
  54.          if(!input(DOWN)){preheatset=preheatset-1; if (preheatset>350) {preheatset=0;}}
  55.          if(!input(UP1)){topheatset=topheatset+1; if (topheatset>350) {topheatset=350;}}
  56.          if(!input(DOWN1)){topheatset=topheatset-1; if (topheatset>350) {topheatset=0;}}
  57.          //y=PORTB;
  58.          }
  59.     }    
  60.  
  61. #INT_EXT       // Interrupt
  62.  void EXT_isr(void)
  63.  {
  64.   //float pre,top;
  65.   bit_zc=1;
  66.    setup_ccp1(CCP_OFF);
  67.    set_timer1(T1_DISABLED|T1_DIV_BY_4);
  68.    output_low(PIN_C2);
  69.    if (outPWM>0){
  70.    set_timer1(0);
  71.    setup_ccp1(CCP_COMPARE_CLR_ON_MATCH);
  72.    CCP_1=0;
  73.    uk=outPWM;
  74.    pre=13500-uk*135; //maxpwm=15--pre=15000-(uk*1000);  
  75.    CCP_1=(long int)pre; //(long int)pre
  76.    setup_ccp1(CCP_COMPARE_SET_ON_MATCH);
  77.    set_timer1(0);
  78.     }
  79.    
  80.    }
  81. ////////starting system////////
  82. void intro(){                                      
  83.    int i;                          
  84.   for (i=3;i>0;i--){  
  85.   lcd_gotoxy(5,1); printf(lcd_putc," Start");
  86.   lcd_gotoxy(8,2); printf(lcd_putc,"%u",i);
  87.   delay_ms(500);
  88.   lcd_putc("\f");
  89.   delay_ms(500);
  90.     }
  91.   }
  92.  
  93. void countertime(){
  94.  if(swicht==1){
  95.    lcd_gotoxy(17,2);
  96.    printf(lcd_putc,"-On");
  97.    if(bit_zc==1){
  98.           millisec++;
  99.           //msec++;
  100.             bit_zc=0;
  101.           if(msec++>=99){       //incrementa el valor de msec y si es mayor a 999
  102.               msec=0;               //pone msec a 0.
  103.               lcd_putc('\f');
  104.           if(sec++>=59){ sec=0;                                  
  105.           if(min++>60){min=0;}                            
  106.     }
  107.    }        
  108.   }
  109.  }
  110.   else {
  111.   //if(swicht==0){
  112.   setup_ccp1(CCP_OFF);
  113.   set_timer1(T1_DISABLED|T1_DIV_BY_4);
  114.   CCP_1=0;
  115.   outPWM=0;
  116.    lcd_gotoxy(17,2);          
  117.    printf(lcd_putc,"-Off");
  118.    if(bit_zc==1){
  119.       flag++;
  120.       if(flag++>=99){
  121.          flag=0;
  122.          bit_zc=0;        
  123.          msec=0;
  124.          sec=0;
  125.          min=0;
  126.          lcd_putc('\f');}
  127.       }
  128.     //}
  129.   }
  130. }  
  131.  /////switch/////
  132.   void button (void){   //Rutina para transformar un pulsador en un pulsador con enclavamiento
  133.     int limit=3;
  134.  
  135.     if(input(PIN_C5)==0){     //Si la entrada A4 está a 0
  136.     swicht++;                 //Se incrementa la variable swicht
  137.     delay_ms(20);           //Un retraso para evitar rebotes del pulsador
  138.     }
  139.     else if(swicht > (limit-1)){   //Si la variable swicht es mayor que límite -1
  140.     swicht = 0;                // se pone la variable swicht a 0
  141.     }
  142.    }
  143.  ////////////////
  144.    
  145.  void lectura(void){
  146.     q=0,v=0;
  147.     set_adc_channel(0);
  148.     delay_us(20);
  149.     q = read_adc();
  150.     //pretemp=q; //*0.178005
  151.     cupla_pcb = (500.0 * q) / 1023.0;
  152.     //lcd_gotoxy(4,1);
  153.     //lcd_putc('\f');
  154.     lcd_gotoxy(1,1);
  155.     printf(lcd_putc,"Pre=%02.1fC  ", cupla_pcb);
  156.     lcd_gotoxy(1,2);
  157.     printf(lcd_putc,"Set=");
  158.     //printf(lcd_putc, ">%02.1fC   ", cupla_pcb);
  159.    }
  160.    ///
  161.    
  162.  void pidCompute(){
  163.    float error;
  164.     float olderror=0;        
  165.      unsigned long int now,oldTime = 0;
  166.        now = millisec;
  167.        if ((now - oldTime) >= 99){
  168.        error=preheatset-cupla_pcb;    
  169.         if (error < 0) {PTerm = 0;outPWM=0;}    //error <= 0          
  170.                                      
  171.          else {                              
  172.                PTerm = Pk * error ;          
  173.                 ITerm = ITerm + (Ik* error);
  174.                  DTerm = Dk* (error - olderror);
  175.              olderror = error;              
  176.              outPWM = PTerm + ITerm + DTerm;                                                
  177.             if (outPWM > maxPwm){outPWM=maxPWM;}
  178.             if (outPWM < minPWM){outPWM=minPWM;}
  179.              pwmValue = outPWM;
  180.    }
  181.   } //ClrWdt();
  182. }
  183.  //#org DEFAULT  
  184.   void main() {
  185.      lcd_init();
  186.      //delay_ms(10);
  187.      setup_adc_ports(AN0_AN1_AN3);
  188.      setup_adc(ADC_CLOCK_INTERNAL);
  189.      setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);
  190.      ENABLE_INTERRUPTS(INT_RB);
  191.      enable_interrupts(INT_EXT);
  192.      enable_interrupts(GLOBAL);
  193.      set_tris_a(0b11111);
  194.      set_tris_b(0b11110001);
  195.      PORTB =0b00000000;
  196.      set_tris_c(0b00100000);
  197.      PORTC =0b11010000;
  198.      intro();
  199.      
  200.   do {
  201.        button();      
  202.        pidCompute();      
  203.        countertime();
  204.        lectura();
  205.        pwm=outPWM;
  206.        
  207.        lcd_gotoxy(13,1);
  208.        printf(lcd_putc"Pwm=%3.0ld%C",pwm,0x25); //"PRE>%02.1fC PWM=%2.0f", cupla_pcb,pwm //Pwm=%ld%C
  209.        lcd_gotoxy(5,2);
  210.        printf(lcd_putc,"%3ld%C%C", preheatset,0xDF,0x43); //lcd_putc,"%2.0f%C%C time=%02u:%02u", preheatset,0xDF,0x43,min,sec
  211.     /*  
  212.        if(swicht==1){        
  213.           lcd_gotoxy(17,2);
  214.           printf(lcd_putc,"-On");
  215.        }
  216.          else{            
  217.              lcd_gotoxy(17,2);
  218.              printf(lcd_putc,"-Off");
  219.          }
  220.       */
  221.       // printf(lcd_putc," uk:%1.2f     %02u:%02u",uk,min,sec); //lcd_putc," uk:%1.3f     %02u:%02u"
  222.          
  223.   }
  224.     while(1);
  225.  }
  226.      
  227.  
  228.  
  229. Este es el código que me funciono. El sensor de temperatura en un LM35

Mira este video de el funcionando:

https://docs.google.com/file/d/0B4TXDjjuTgn3MXVuaEFpamxuWkk/edit

Disculpa por la resolucion del video pero mi cel no tiene buena camara. Este code esta un poco desordenado e incluso tiene cosas que puedes quitar como lo es el caso de los botones que tiene de mas y como te comento esta basado en un arduino. Pero asi es como funciona en el video
« Última modificación: 29 de Septiembre de 2015, 18:05:23 por Abner_emanuel »
El señor es mi pastor,  nada me faltará.

Desconectado ceci_lamorocha

  • PIC12
  • **
  • Mensajes: 94
Re: Controlador PID por angulo de fase
« Respuesta #13 en: 30 de Septiembre de 2015, 16:57:58 »
Esta muy bueno !! los calculos seran para 50Hz ó 60 Hz ??


Me parece que le faltaria hacer la deteccion de cruce por cero ( o no la estoy viendo) de la que hablaba KILLERJC  para que no tenga fallos inesperados


Desconectado Abner_emanuel

  • PIC16
  • ***
  • Mensajes: 160
Re: Controlador PID por angulo de fase
« Respuesta #14 en: 30 de Septiembre de 2015, 18:20:01 »
La detección de cruce por cero la hace con #INT_EXT en el código que puse. Y si, este código esta para 50 hrz, así que te vendría bien para tu caso. El cruce por cero es indispensable para este control. Esperó te sirva y cualquier cosa mi correo martinez_cvm@hotmail.com   

El diagrama no lo pude subir pero si lo requiere alguien intentaré nuevamente.
« Última modificación: 30 de Septiembre de 2015, 18:23:56 por Abner_emanuel »
El señor es mi pastor,  nada me faltará.


 

anything