Problema con PID digital

Que tal soy estudiante de electronica y me han pedido la tarea de realizar un control de temperatura usando como fuente de calor un foco, mediante implementacion de pid con microcontrolador de la familia AVR, bien la parte del codigo de la pura accion proporcional, integral y derivativa ya la tengo, pero el profesor comento algo de que necesito detectar el cruce por cero y bien para esto ya me di a la tarea de buscar en la pagina de AVR y encontre que esto se hace con unas resitencias y un codigo sencillo en una interrupcion, pero mi problema es que no entiendo que hago cuando ya detecto el cruce por cero?

es decir, yo lo que ya tengo hecho es mi codigo del pid el cual lee mediante el convertidor A/D un sensor lm35 y realiza las operaciones correspondientes al control, y este me entrega un valor el cual lo ocupo como comparacion para generar una señal de pwm a una frecuencia de 62.5Hz que lo que hace es que mientras mas cerca esta del valor deseado sale un pulso mas pequeño en alto hasta volverce cero cuando el valor es igual y un pulso en alto muy largo mientras mas alejado del valor de comparacion esta, y esta señal de pwm la mando a un moc3020 que a su vez activa un triac 2n6071, que aparentemente funcionan bien, pero mi maestro dice que no, debido a que no tengo sincronizado el cruce de cero y demas, dice que el triac no se esta disparando cada vez que mi señal de pwm esta en alto y que por eso se observa a veces que el foco brilla mas fuerte y otras menos.

entonces mis dudas son..

cual es la relacion entre el detector de cruce por cero que se realiza con la interrupcion y mi señal de pwm???
y cual seria la forma correcta de realizar lo que necesito?.. entiendo que lo que necesito hacer es una especie de dimmer digital controlado por el valor de temperatura en la entrada

espero me puedan ayudar con mi problema y agradesco de ante mano.
 
Tu problema es inentendible:

  1. Vas a hacer un control de temperatura usando una lámpara de AC (?) como calentador...hasta ahí OK?
  2. El actuador es un triac, comandado por un opto, que controla la cantidad de calor que produce la lámpara comandándola por ángulo de fase...OK?
Y yo pregunto:
De cual PWM está hablando? Y para que querés un PWM????
A menos que a lo que le llamás PWM sean los intervalos de tiempo en los cuales la lámpara está encendida y apagada....:confused: :confused: :confused:...pero si la encendés y apagás por completo...para que corno querés el control por ángulo de fase?????? :confused: :confused: :confused:

En resumen: no se entiende un pomo cual es tu problema ni se entiende lo que quiere tu profesor, así que lo mejor es que hables con él y estudies un poco antes de reescribir la pregunta de forma mas coehrente.
 
Hola dkns

Lo que pasa es que para controlar un dispositivo AC debes sincronizar su señal de mando con el cruce por cero de la corriente alterna.

Supongamos que has determinado que debes aplicar el 50% de cada semiciclo para lograr el nivel de calentamiento requerido.

Lo logico es que detectes cuando el valor de la corriente AC es 0 volts y de ahi dispares la señal del MOC3020. Con esto tu señal de control realmente sera efectiva.

Esta claro que si aplicas tu señal de control en cualquier momento sin fijarte en el cruce por cero no estaras cuidando si la corriente esta cayendo por un semiciclo o subiendo o aplicando una cresta de la corriente.

Con esto tambien tienes la ventaja de eliminar las perjudiciales EMF.

Saludos
 
hola compañero dkns.

Lo que estas haciendo no tiene nada que ver con PWM, ya que en realidad lo que estas controlando es el disparo del triac o como lo llamarian un control por corrimiento de fase.

Para sincronizar el disparo tienes que saber exactamente cuando es el cruce por cero de la señal AC, de ahi tendras 2 cruces por cero. Lo que quiere decir que tienes un intervalo para el disparo del triac de aprox unos 8.3ms. El valor que obtengas de el PID es precisamente en que momento de estos 8.3ms tienes que activar el Triac.

Aqui ya se presentan algunos inconvenientes, tienes que definir el periodo de muestreo para tu PID tal que se ejecute siempre en un intervalo fijo y que no afecte la interrupcion del cruce por cero, luego solo pasas el valor del PID para ejecutar un timer y listo tienes el control de temperatura que deseas.

Te recomendaria que primero realizaras el control por corrimiento de fase con un numero de escalas, que controles estas con un par de botones para incrementar y decrementar el tiempo del timer y posteriormente le cambias el control de los botones por el PID. asi puedes probar ambos sin temor a no saber cual no funciona.

saludos
 
Última edición:
Tengo el código de un control PID de temperatura que el autor lo pone con un vídeo en la red funcionando.
Yo lo he armado pero no funciona realmente, y no sé qué esté pasando.

Me gustaría tener su asesoría para hacerlo funcionar como se ve en el vídeo:

Aquí pongo el código, del cual tengo algunas dudas:
Código:
#include <16f877a.h>
         #device adc=10
         #fuses HS,NOWDT
         #use delay(clock=20000000)    
         #include <lcd.c> 
         
         int16 valor;   //lectura de temperatura
         float a=6.0631;
         float b=0.05318;
         float c=172.798;   //constantes del PID
         float temp_limit=400.0;   //temperatura a alcanzar
         float rT,eT,pT,qT,yT,uT;
         float pT_1=0.0;
         float eT_1=0.0; //variables de ecuaciones
         float max=1000.0;
         float min=0.0;     //límites máximo y mínimo de control.
         float pwm1;
         float tempera;   //Para visualizar la temperatura del horno.
         int16  t_l;      //Para visualizar la temperatura límite.
         unsigned int16 fase=24536;
         int1 cambio=1;
 
         void pid ()
         {
         output_bit(pin_c0,0);
         
         valor=read_adc();               //Lectura de la temperatura
         yT=valor*5000.0/1023.0;        //conversión a mV (0.25V a 250mV)
         rT=temp_limit;
         
         eT=rT-yT;            //Cálculo error
         pT=b*eT+pT_1;        //Cálculo del término integral
         qT=c*(eT-eT_1);      //Cálculo del término derivativo
         uT=pT+a*eT+qT;       //Cálculo de la salida PID
         
         if (uT>max) {        //Salida PID si es mayor que el MAX
         uT=max;}
         else {
         if (uT<min){      //Salida PID si es menor que el MIN
         uT=min;}
         }
         pwm1=38.5*uT+24636;         //Transferencia de salida PID a señal PWM
         fase=pwm1;
            
         pT_1=pT;            //Guardar variables
         eT_1=eT;
         }
 
 
         void display()
         {
         tempera=yT/10;
         t_l=temp_limit/10;
         lcd_gotoxy(1,1);
         printf(lcd_putc, "Temp= %3.1F oC\n", tempera);
         lcd_gotoxy(1,2);
         printf(lcd_putc, "SP= %Lu oC   UAP", t_l);
         }
         
         
         void teclado()
         {
         if (input(PIN_B6)==0) temp_limit=temp_limit+10.0;
         if (input(PIN_B7)==0) temp_limit=temp_limit-10.0;
         if (temp_limit > 1000.0) temp_limit=1000.0;
         if (temp_limit < 100.0) temp_limit=100.0;
         }
         
            
         #int_TIMER1
         void TIMER1_isr (void)
         {
         output_high (pin_c2);                  
         }
         
         #int_EXT
         void EXT_isr (void)
         {
         output_low (pin_c2);
         set_timer1(fase);
         enable_interrupts(INT_TIMER1);  //Habilito la interrupción del TIMER1 y salta a su respectiva interrupción
         }
         
         
         void main ()
         {
         lcd_init();
         set_tris_b(0b11111111); 
         port_b_pullups(true);
          ext_int_edge(L_TO_H);
         setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
         enable_interrupts(INT_TIMER1);
         set_timer1(fase);
         enable_interrupts(INT_EXT);
        
         enable_interrupts(GLOBAL);
         setup_adc_ports(ALL_ANALOG);
         setup_adc(ADC_CLOCK_INTERNAL);
         set_adc_channel(0);
         
         while (true)
         {
         pid ();
         display();
         teclado ();
         delay_ms(100);
         }
Por ejemplo en la línea pwm1=38.5*uT+24636;

Sé que el 24636 sale del desborde del Timer1, porque realicé el cálculo a lápiz y me salió 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 dónde saca el valor de 38.5. Yo imagino que es para controlar el disparo del triac, aunque no estoy seguro de eso.


Bueno, como les comento, lo armé 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 a andar con su ayuda.
 
Última edición por un moderador:
Atrás
Arriba