Saltar al contenido

Control PID con microcontrolador PIC

En esta entrada, vamos a aprender como hacer un control PID con PIC paso a paso en lenguaje C con el compilador CCS C. Este control puedes aplicarlo en cualquier sistema y verás ejemplos prácticos de implementación junto con todos los códigos para que los descargues GRATUITAMENTE en este post.

Antes de entender como programar un controlador PID en un microcontrolador PIC, te invito a que revises nuestro curso gratuito de microcontroladores PIC y que te suscribas al canal de Youtube para seguir aprendiendo más de estos asuntos:

Puedes mirar la tabla de contenido y saltar al punto que mas te interesa. 👇👇👇

Control PID

El controlador PID es uno de los controles o compensadores más utilizados actualmente en la industria debido a su fácil sintonía y robustez en los diferentes procesos existentes. Este es utilizado para llevar una variable física (Nivel, temperatura, velocidad, presión, etc) a un punto de operación específico (set point).  

Un diagrama de bloques clásico de un sistema de control puede representarse de la siguiente forma:

Malla cerrada controlador

donde r(k) es nuestra señal de referencia o set point, e(k) es nuestra señal de error (La resta entre r(k) y y(k)), C(z) es nuestro controlador PID discreto, u(k) es nuestra señal de control (Ley de control), P(z) es nuestra planta o proceso en representación discreta, y(k) es nuestra variable de salida a controlar.

La ley de control PID puede representarse por la siguiente ecuación:

u(t)=k_pe(t)+\dfrac{k_p}{t_i}\int_{0}^{t}e(t)dt+k_pt_d\dfrac{de(t)}{dt}

y en dominio de la transformada de laplace es representado por:

u(s)=k_p\left [ 1+\dfrac{1}{t_is}+t_ds \right ]e(s)

El control PID posee tres parámetros (k_p,t_i,t_d) ganancia proporcional, tiempo integral y tiempo derivativo respectivamente.

Existen numerosas técnicas y autores que tratan como sintonizar o ajustar dichos parámetros. En esta entrada, les voy a enseñar TRES formas diferentes de sintonizar este controlador.

Para eso y antes que nada, debemos conocer el modelo matemático o el comportamiento de nuestro proceso que queremos controlar (en el diagrama de arriba seria el bloque P(z)).

Como ejemplo en esta entrada, vamos a controlar la temperatura de un horno con un control PID con PIC, y para eso necesitamos caracterizar o identificar el modelo matemático de nuestro proceso.

Modelado Matemático de un Horno de Temperatura

Típicamente, todo proceso industrial es representado por funciones de transferencia de primer o segundo orden. A continuación es expuesto un modelo de primer orden sobre el cual vamos a trabajar para poder modelar el comportamiento de nuestra planta.

P(s)=\dfrac{Ke^{-\theta s}}{\tau s +1}

El modelo está representado en su forma continua, es decir en el dominio de Laplace. donde K es la ganancia del sistema, \tau es la constante de tiempo del proceso y \theta es el retardo del proceso.

Para entender cómo obtener estos tres parámetros de nuestro proceso, vamos a hacerlo directamente en el ejemplo, para que aprendamos de manera práctica a modelar un proceso rápidamente y posteriormente poder sintonizar o ajustar nuestro control PID con PIC.

En este caso y para facilidad de todos, vamos a usar un proceso virtual para simular la dinámica del horno, utilizando para ello el software de simulación del PROTEUS.

Configuración del Horno en Proteus

En este ejemplo vamos a programar un controlador PID en nuestro PIC, para controlar la temperatura de un horno y poderla mantener en el punto de operación deseado.

En este caso se le pide al ingeniero de control que el horno debe mantener su temperatura constante en torno de los 150.0°C. Se pide además al ingeniero, que adapte un LCD 4×20 para poder visualizar la temperatura actual del horno, y el setpoint.

El circuito a implementar es mostrado a continuación:

Control PID con PIC

Antes que nada vamos a necesitar los siguientes componentes en el PROTEUS para poder simular nuestro proceso: PIC16F887, IRFZ44N, LM044L, CELL, RES, OVEN.

Comencemos primero con nuestro proceso (El horno de temperatura), vamos a buscar el horno en proteus (OVEN) y vamos a darle doble click para configurarle sus parámetros:

Control PID Horno con PIC
  • Temperatura ambiente: 25°C
  • Temperature coefficient (V/°C): da una idea de la temperatura que alcanzará el horno según la tensión aplicada. Valor: 1V/°C.
  • Oven Time Constant (sec): es la constante de tiempo del horno. Para evitar una simulación muy larga, vamos a colocarlo en 10 segundos.
  • Heater time constant (sec): es la constante de tiempo del calefactor. Para evitar simulaciones largas la ponemos en 1 segundo.
  • Thermal resistence to ambient (°C/W): resistencia térmica horno ambiente. Valor por defecto 0.7.
  • Heating Power (W): es la potencia del horno. A fin de que nuestro sensor de temperatura no sobrepase los 5 voltios de tensión, vamos a colocar este parámetro en 52 W.

Como sensor de temperatura se pueden usar termopares, termocuplas, RTD, etc.

Ahora, como el dispositivo OVEN tiene un terminal que dice T, el cual nos indica la temperatura del horno en grados CELCIUS. Para esto es conveniente utilizar un divisor de voltaje por 100 para obtener la señal del horno en milivoltios. Asi, 25°C corresponderán a 250mV.

Entradas relacionadas en este sitio WEB:

Identificación del Horno de Temperatura con PIC

Para identificar el modelo matemático que mas o menos represente la dinámica de nuestra variable de proceso (La temperatura) vamos a tener que tomar unos datos iniciales en nuestro proceso.

Note que en nuestro diagrama, estamos alimentando el horno con una batería de 12V.

Para poder determinar nuestro modelo matemático, vamos a tener que hacer una identificación off-line. Para eso necesitamos estimular nuestro horno y almacenar los datos que este nos da, para poder graficar su comportamiento en el tiempo.

Esta identificación la vamos a hacer sobre el punto de operación del proceso. Por ejemplo, tomando el horno y suponemos que este proceso va a trabajar siempre en 150°C, entonces debemos partir de esa temperatura y hacerle una pequeña perturbación, por ejemplo inyectar un 10% más de energia y ver cuanto aumenta la temperatura.

Como en nuestro caso el sistema es lineal voy a estimular el horno con un valor del 10% al 20% de nuestro valor de alimentación 12V. Entonces vamos a energizar el horno con 2V (16.6%) y graficar la curva que genera.

Curva de Reacción de Temperatura del Horno

Sabemos que si alimentamos el horno con 12VDC directos pues voy a alcanzar la máxima potencia del horno. Pero en la etapa de identificación quiero ver el comportamiento del horno en una región, por eso lo energizo con el 16.6% o 2V.

Malla Abierta

(En el video de youtube, les explicaré como obtener esa gráfica desde el proteus)

Miremos entonces la respuesta que obtuvimos de nuestra gráfica:

Grafica escalón

Vemos que la gráfica comienza en 25°C (0.25 Voltios) y llega hasta 132°C (1.32 Voltios) y que para conseguir esta respuesta tuvimos que alimentar la resistencia con 2V. Así podemos obtener la ganancia del proceso con la siguiente formula:

K=\dfrac{Y_{final}-Y_{inicial}}{U_{final}-U_{inicial}}
K=\dfrac{132-25}{2-0}=53.5°C/v

Si calculamos la ganancia usando las unidades de voltaje, podemos llegar a una ganancia adimensional:

K=\dfrac{1.32v-0.25v}{2v-0}=0.535

Observemos que la temperatura en la gráfica, se comienza a estabilizar mas o menos a los 40 segundos (Linea Roja), así podemos obtener la constante de tiempo de la variable temperatura con la siguiente formula:

T_{establecimieto}=4\tau

O sea que el \tau=10, esto era de esperar, pues nosotros mismos ya habíamos colocado una contaste de tiempo de 10 en los parámetros del horno.

Por último, solo nos falta averiguar el valor del retardo, para eso tenemos que ver cuánto se demora en responder el horno una vez energizamos.

Vemos que el horno responde instantáneamente, o sea que podría tener un retardo nulo.

Para efectos prácticos, vamos a colocar un retardo bien pequeño para la técnica de control por Ziegler y Nichols \theta=1 y un retardo de \theta=0 para las otras dos técnicas que voy a enseñarles.

Así que en términos generales, nuestro proceso del horno está representado por la siguiente función de transferencia:

P(s)=\dfrac{0.535e^{-1 s}}{10 s +1}

Con nuestro proceso identificado podemos calcular los parámetros del controlador (k_p,t_i,t_d), para eso utilizamos cualquiera de estas tres técnicas:

PID sintonia

Control PI por asignación de 2 polos reales

Comenzaremos realizando un proyecto de control usando la técnica del PI por Asignación de Polos.

En este proyecto de controlador PID con el PIC solo utilizamos nuestra parcela Proporcional y integral, colocando la acción derivativa en cero.

La idea básica de este diseño es asignarle polos a nuestro proceso para que actúe de la manera como nosotros deseamos siguiendo el siguiente procedimiento:

  • Seleccionamos una tiempo de establecimiento deseado. Es decir el tiempo en que queremos que se estabilice la temperatura, por ejemplo, vamos a suponer que nosotros queremos que la temperatura se estabilice en más o menos 30 segundos:
T_{ss}=30
  • Calculamos la frecuencia natural de nuestro sistema de forma que no tenga sobreimpulso. (Una forma de hacer esto es asignando 2 polos iguales, a esto se le conoce como un sistema críticamente amortiguado). La frecuencia natural puede determinarse más o menos con la siguiente formula, como detallado en el link inmediatamente anterior:
W_n=\dfrac{5.8335}{T_{ss}}=\dfrac{5.8335}{30}=0.1944
  • Calculamos el polinomio deseado el cual contiene los dos polos iguales que estamos asignando al sistema:
(s+W_n)^2=s^2+p_1s+p_2=s^2+2W_ns+Wn^2
p_1=2W_n=2*0.1944=0.3889
p_2=W_n^2=0.1944^2=0.0378
  • Por ultimo calculamos el parametro kc y ti con las siguientes formulas:
k_p=\dfrac{P_1\tau-1}{K}=\dfrac{0.3889*10-1}{0.535}=5.4
t_i=\dfrac{k_p*K}{P_2*\tau}=\dfrac{5.4*0.535}{0.0378*10}=7.6407

Control PI por Cancelación de Polos

La idea básica del control PI por cancelación de polos es justamente cancelar el polo de la planta con el parámetro integral del controlador. (este controlador principalmente es para fines académicos y de simulación, no es muy recomendable aplicarlo a nivel profesional)

  • Seleccionamos una constante de tiempo deseada. Por ejemplo, seleccionamos una constante de tiempo de 7.5 para que se estabilice el proceso en más o menos 30 segundos (ya sabemos que el tiempo de estabilización es 4 veces la constante de tiempo) [
T_{sMA}=7.5
  • se calcula la ganancia proporcional del control PI:
k_p=\dfrac{\tau}{K*T_{sMA}}=\dfrac{10}{0.535*7.5}=2.492
  • se calcula el tiempo integral del control PI:
t_i=\tau

Control por Ziegler y Nichols

Ziegler y Nichols propusieron unas tablas de sintonia de controladores PID a partir de funciones de transferencias de primer orden con retardo.

Sintonia por Ziegler y Nichols

Controlador PID discreto con PIC

Como vamos a implementar el PID en nuestro microcontrolador PIC, debemos colocar la ley de control en tiempo discreto con un tiempo de muestreo (T) adecuado.

Ziegler y Nichols propusieron determinar el tiempo de muestreo rápidamente de dos formas distintas:

  1. T<\dfrac{\theta}{4}
  2. T=\dfrac{\tau}{20}

Para nuestro caso del horno escogeremos un T=0.1 que corresponde a 100mS y siendo menor que \dfrac{\theta}{4}.

El control discreto PID se obtiene discretizando la ecuación continua (vista al comienzo de esta entrada) aproximando el término integral mediante la sumatoria trapezoidal y el término derivativo mediante la diferencia de dos puntos para de esa forma obtener la función de transferencia pulso del controlador PID digital. Si lo deseas puedes dar click en el siguiente enlace para que entiendas el procedimiento matemático del Controlador PID Discreto.

C(z^{-1})=\dfrac{u(k)}{e(k)}=\dfrac{q_0+q_1z^{-1}+q_2z^{-2}}{1-z^{-1}}

donde:

q_0=k_p\left [ 1+\dfrac{T}{2t_i}+\dfrac{t_d}{T} \right ]
q_1=-k_p\left [ 1-\dfrac{T}{2t_i}+\dfrac{2t_d}{T} \right ]
q_2=\dfrac{k_pt_d}{T}

Con esto, la ley de control que vamos a ingresar a nuestro PIC sale del control PID discreto (Despejando u(k))

u(k)(1-z^{-1})=q_0e(k)+q_1z^{-1}e(k)+q_2z^{-2}e(k)
u(k)-u(k)z^{-1}=q_0e(k)+q_1z^{-1}e(k)+q_2z^{-2}e(k)
u(k)=u(k)z^{-1}+q_0e(k)+q_1z^{-1}e(k)+q_2z^{-2}e(k)

Aplicando transformada inversa Z obtenemos la ecuación en diferencias:

u(k)=u(k-1)+q_0e(k)+q_1e(k-1)+q_2e(k-2)

Así, u(k) quiere decir la ley de control actual, u(k-1) es la ley de control un instante de muestreo atrás,  e(k) es el error actual (Referencia – temperatura), e(k-1) es el error un instante de muestreo atrás,  e(k-2) es el error dos instantes de muestreo atrás.

Curso de Implementación de Controladores en un Microcontrolador

  • Curso de Sistemas de Control en Dispositivos Microcontrolados en UDEMY (PIC y ARDUINO)
  • Certificado de Aprobación una vez finalices el Curso
  • DESCUENTO si accedes directamente con los siguientes botones de acceso.
  • NOTA: Si buscas el curso directamente en UDEMY o si lo adquieres en otra plataforma distintas a las mostradas anteriormente NO OBTENDRÁS NINGUN DESCUENTO sobre el valor final del Curso.

Control de Temperatura PID con Microcontrolador PIC

Ahora ha llegado el momento de hacer el control PID de temperatura con PIC y ver como funciona.

Para implementar el control, debemos hacer uso de un MOSFET de potencia que sea capaz de aguantar la corriente del horno (4,3A), para eso se selecciono el MOSFET de combate IRFZ44N, el cual en el GATE será activado por una señal PWM del PIC a fin de poder regular la potencia del Horno.

Para garantizar el tiempo de muestreo de 100ms, podemos hacer uso de la instrucción delay_ms(100), pero en este caso, como yo quería mayor precisión, emplee el uso del TIMER0 del PIC.

Por último, quiero resaltar que en este primer ejemplo el set-point o referencia será fija a 150°C, sin embargo, en el segundo ejemplo más abajo en este post vamos a adicionar un teclado matricial para poder modificar la referencia.

En el video explico detalladamente todos los pasos y procedimientos a tener en cuenta para implementar el control PID, como por ejemplo el trabajar siempre de manera estandarizada las señales (En este caso, trabajo todo en milivoltios).

Tambien explico el código y como se hace la identificación off-line. No olviden compartir este post si les gustó, delen me gusta y suscribanse a mi canal de Youtube.

Código del Control PID con PIC del Horno de Temperatura

Puedes descargar los archivos del ejemplo o copiar el código directamente en tu compilador:

>> DESCARGAR ARCHIVOS DE PICC Y PROTEUS 8 <<

// ***********************************************************************//
// ***********************************************************************//
// *****       By: Sergio Andres Castaño Giraldo                    ******//
// *****       https://controlautomaticoeducacion.com/              ******//
// *****       Control Engineering                                  ******//
// ***********************************************************************//
// ***********************************************************************//

#INCLUDE <16F887.h>
#DEVICE ADC=10
#USE DELAY(crystal=4000000)
#FUSES XT,NOPROTECT,NOWDT,NOBROWNOUT,PUT,NOLVP
#include <lcd420.c>
//Configura direccion de memoria de los puertos A,B,C,D
#BYTE PORTA= 5
#BYTE PORTB= 6
#BYTE PORTC= 7
#BYTE PORTD= 8
int veces=39,seg=0;
int16 adc,control=0;
float yM=0,R=1500.0,e=0.0,e_1=0.0,e_2=0.0,u=0.0,u_1=0.0;
float kp,ti,td,q0,q1,q2,T=0.1;
float k=0.535,tao=10.0,theta=1.0;
float TsMA,Wn,P1,P2;

//Con esta rutina de desbordamiento del timer 0
//Hago el conteo del tiempo de muestreo
#INT_RTCC //Rutina de interrupción por RTCC
RELOJ()
{

   VECES--;          //Decremento variable veces
   SET_RTCC(246);    //Cargo el timer con 243
   IF(VECES==0)      //La variable veces se carga con 30 y el timer con 243
   {                 //para que entre a la interrupcion cada 100 milisegundos
      VECES=39;
      seg++;         //y incremente el contador 'seg'
   }
   if(seg==1)
   {
    seg=0;
    output_toggle(pin_d0);
    //Comienzo la ley de control
    
    e=R-yM;
    // Controle PID
      u = u_1 + q0*e + q1*e_1 + q2*e_2; //Ley del controlador PID discreto
    
    if (u >= 5000.0)        //Saturo la accion de control 'uT' en un tope maximo y minimo
     u = 5000.0;
    
    if (u <= 0.0)
     u = 0.0;
     
     //escalizo la u de mV a bits, en el caso del PWM ser a 1Khz con una resolucion de 10
     //el valor máximo del pwm es de 1000
     control=u*1000/5000;
     
     //Retorno a los valores reales
     e_2=e_1;
     e_1=e;
     u_1=u;
     
     //La accion calculada la transformo en PWM
     set_pwm1_duty(control);
     
   }
}
void main()
{
   set_tris_c(0);
   set_tris_d(0);
   setup_timer_2(t2_div_by_4,249,1);   //Configuracion de Timer 2 para establecer frec. PWM a 1kHz
   setup_ccp1(ccp_pwm);                //Configurar modulo CCP1 en modo PWM
   set_pwm1_duty(0);                   //Dejo en cero la salida PWM
   
   setup_adc_ports(sAN0);              //Configurar ADC (Lectura de temperatura)
   setup_adc(adc_clock_internal);      //Reloj interno para la conversion analoga digital)
   set_adc_channel(0);                 //Seleccionar Canal 0 para sensor de Temperatura
   
   SET_RTCC(246);                               //Cargo el TIMER0 con 243
   
   // Configuración ANTIGUA del TIMER0
   //SETUP_COUNTERS(RTCC_INTERNAL, RTCC_DIV_256); //Configura interrupcion del timer
   
   // Configuración Recomendada del TIMER0
   SETUP_TIMER_0(RTCC_INTERNAL|RTCC_DIV_256|RTCC_8_bit);    
   
   ENABLE_INTERRUPTS(INT_RTCC);  //Habilito interrupcion por TIMER0
   enable_interrupts(GLOBAL);    //Habilito las interrupciones a nivel global
   
   LCD_INIT();                         //Inicializo el LCD
   LCD_PUTC("\f");                     //Limpio el LCD
   
   //*************************************************************************//
   //*************  DISEÑO POR ASIGNACIÓN DE 2 POLOS REALES   ****************//
   //*************************************************************************//
   
   TsMA=30;                    //Tiempo deseado en Lazo Cerrado    
   Wn=5.8335/(TsMA);               //Frecuencia natural del sistema
   
   //Ubicación de 2 Polos reales
   P1=Wn+Wn;
   P2=Wn*Wn;
   
   kp=(P1*tao-1)/k;        //Calculo de Kc
   ti=(k*kp)/(P2*tao);     //Calculo de ti
   
   //*************************************************************************//
   //*****************   DISEÑO POR CANCELACIÓN DE POLOS    *******************//
   //*************************************************************************//
   /*
   TsMA=7.5;                  //Tiempo deseado en Lazo Cerrado 
   kp=(tao)/(TsMA*k);         //Calculo de Kc
   ti=tao;                    //Calculo de Ti (Igual a la constante de tiempo)
   td=0;
   */
   //*************************************************************************//
   //*****************   SINTONIA POR ZIEGLER y NICHOLS    *******************//
   //*************************************************************************//
   /*
   kp=(1.2*tao)/(k*theta);
   ti=2*theta;
   td=0.5*theta;*/
   
   //*************************************************************************//
   
  // Calculo do controle PID digital
   q0=kp*(1+T/(2*ti)+td/T);
   q1=-kp*(1-T/(2*ti)+(2*td)/T);
   q2=(kp*td)/T;
      
   while(1)
   {

      adc=read_adc(); //Leer ADC
      yM=adc*5000.0/1024.0;

     
      //Muestra mensajes en LCD
      lcd_gotoxy(1,1);
      printf(lcd_putc,"Temp: %f",yM/10);
      lcd_gotoxy(1,2);
      printf(lcd_putc,"SetPoint: %2.2f C   ",R/10);
      lcd_gotoxy(1,3);
      printf(lcd_putc,"Error: %2.2f C   ",e/10);
      lcd_gotoxy(1,4);
      printf(lcd_putc,"u(ley Con): %ld   ",control);
      

      }
}

Controlador PID de Temperatura con PIC + Teclado Matricial

Esta actualización la estamos haciendo en Julio del 2018 y es el anexo del teclado matricial al problema del Control PID con PIC para la temperatura horno, para poder ingresarle el setpoint al sistema. El esquema queda de la siguiente forma:

PID con Microcontrolador PIC

NOTA ACLARATÓRIA: En el minuto 11:18 cuando abro el circuito para determinar la temperatura máxima del horno debemos conectarlo a TIERRA y no a +5V (fue un error mio, le estava restando a la fuente de 12V), con eso, el horno llega hasta 4.9V o sea 490°C, esto no afecta en nada el código del PID, solo podriamos colocar serpoint mayores. Este PID funciona muy bien. Espero les sirva en sus proyectos.

Control PID con PIC del Horno con Teclado Matricial

Puedes descargar los archivos del ejemplo del Compensador PID en PIC usando el teclado matricial dando click en el siguiente enlace o puedes copiar el código directamente en tu navegador:

>> DESCARGAR ARCHIVOS PICC Y PROTEUS 8 <<

Si lo deseas también puedes descargar la librería del LCD 4×20 para el puerto D directamente en el siguiente enlace:

>> DESCARGAR LCD420D.c <<

/*===========================================================================*/
/*=======================       SERGIO CASTAÑO         =======================*/
/*===========================================================================*/

#INCLUDE <16F887.h>
#DEVICE ADC=10
#USE DELAY(CLOCK=4000000)
#FUSES XT,NOPROTECT,NOWDT,NOBROWNOUT,PUT,NOLVP
#DEFINE USE_PORTB_KBD   //Por defecto el teclado se conecta al puerto D,
                        //como el microcontrolador que se esta usando
                        //no tiene puerto D se conecta al puerto B.*/
#INCLUDE <LCD420D.C>
#INCLUDE <KBD4x4.C>  //Incluir en el encabezado el driver para
                      //manejar el teclado telefónico MODIFICADO
#include <stdlib.h>
#include <string.h>

#use     standard_io(b) 
#define  KEYHIT_DELAY   1    //Tiempo de espera del teclado en milisegundos
#byte PORTB= 6
#byte PORTC= 7
#BYTE PORTA= 5
#BYTE PORTD= 8

int16 adc,control=0;
float R=1500;//Referencia de 150 °C por defecto
float yM=0,e=0.0,e_1=0.0,e_2=0.0,u=0.0,u_1=0.0,T=0.1;
float kp,ti,td,q0,q1,q2;
float k=0.535,tao=10,theta=1;
float TsMA,Wn,P1,P2;
char c;
int cont=0;


/*===========================================================================*/
/*=======================       FUNCION TECLA         =======================*/
/*===========================================================================*/
//Funcion encargada de esperar a que se presione una tecla 
char tecla(void)
{
   char c;
   do{ //espera hasta que se presione una tecla
      c=kbd_getc(); //Captura valor del teclado
     }
   while(c=='
/*===========================================================================*/
/*=======================       SERGIO CASTAÑO         =======================*/
/*===========================================================================*/
#INCLUDE <16F887.h>
#DEVICE ADC=10
#USE DELAY(CLOCK=4000000)
#FUSES XT,NOPROTECT,NOWDT,NOBROWNOUT,PUT,NOLVP
#DEFINE USE_PORTB_KBD   //Por defecto el teclado se conecta al puerto D,
//como el microcontrolador que se esta usando
//no tiene puerto D se conecta al puerto B.*/
#INCLUDE <LCD420D.C>
#INCLUDE <KBD4x4.C>  //Incluir en el encabezado el driver para
//manejar el teclado telefónico MODIFICADO
#include <stdlib.h>
#include <string.h>
#use     standard_io(b) 
#define  KEYHIT_DELAY   1    //Tiempo de espera del teclado en milisegundos
#byte PORTB= 6
#byte PORTC= 7
#BYTE PORTA= 5
#BYTE PORTD= 8
int16 adc,control=0;
float R=1500;//Referencia de 150 °C por defecto
float yM=0,e=0.0,e_1=0.0,e_2=0.0,u=0.0,u_1=0.0,T=0.1;
float kp,ti,td,q0,q1,q2;
float k=0.535,tao=10,theta=1;
float TsMA,Wn,P1,P2;
char c;
int cont=0;
/*===========================================================================*/
/*=======================       FUNCION TECLA         =======================*/
/*===========================================================================*/
//Funcion encargada de esperar a que se presione una tecla 
char tecla(void)
{
char c;
do{ //espera hasta que se presione una tecla
c=kbd_getc(); //Captura valor del teclado
}
while(c=='\0'); 
return(c);
}
/*===========================================================================*/
/*=======================    FUNCION TECLA CON TIMER  =======================*/
/*===========================================================================*/
// Pregunta por una Tecla por un tiempo, si no hay actividad, deja de preguntar
// y deja que el PIC continue con su trabajo
char tecla_time(void) {
char c='\0';
unsigned int16 timeout;
timeout=0;
c=kbd_getc(); //Captura valor del teclado
while(c=='\0' && (++timeout< (KEYHIT_DELAY*100)))
{
delay_us(10);
c=kbd_getc(); //Captura valor del teclado
}
return(c);
}
/*===========================================================================*/
/*=======================    FUNCION DEL CONTROL PID  =======================*/
/*===========================================================================*/
void PID(void)
{
e=1*(R-yM);
// Controle PID
u = u_1 + q0*e + q1*e_1 + q2*e_2; //Ley del controlador PID discreto
if (u >= 5000.0)        //Saturo la accion de control 'uT' en un tope maximo y minimo
u = 5000.0;
if (u <= 0.0)
u = 0.0;
control=u/5;
//Retorno a los valores reales
e_2=e_1;
e_1=e;
u_1=u;
//La accion calculada la transformo en PWM
set_pwm1_duty(control);
}
/*===========================================================================*/
/*============   FUNCION PARA DIGITAR ESCALÓN/SETPOINT  =====================*/
/*===========================================================================*/
long escalon(int nd)
{
//Esta funcion captura el escalon desde el teclado, si el proceso está tomando
//datos el escalon sirve para exitar el sistema, por otro lado si el sistema
//está controlando, el escalo sirve para establecer el setpoint del sistema
long val;
int i;
char str[5]; //Variable tipo String
str[0]='0';
for(i=0;i<nd;i++)
{
c=tecla();  //Lee el valor del teclado y espera hasta que alguna tecla se pulse
if(c!='*'){
//Muestra el digito presionado en el LCD
lcd_gotoxy(5+i,4);
lcd_putc(c);
//Almacena el dato presionado en la variable String
str[i]=c;
}
else{i=nd;} //Si se presiona * sale del For      
}
val = atol(str); //Convierte el String en un valor numerico
return(val);
}
void main()
{
port_b_pullups (0xFF);  //Utiliza las resistencias PULL UP internas del puerto B
set_tris_c(0);
set_tris_d(0);
setup_timer_2(t2_div_by_4,249,1);   //Configuracion de Timer 2 para establecer frec. PWM a 1kHz
setup_ccp1(ccp_pwm);                //Configurar modulo CCP1 en modo PWM
set_pwm1_duty(0);                   //Dejo en cero la salida PWM
setup_adc_ports(sAN0);              //Configurar ADC (Lectura de temperatura)
setup_adc(adc_clock_internal);      //Reloj interno para la conversion analoga digital)
set_adc_channel(0);                 //Seleccionar Canal 0 para sensor de Temperatura
LCD_INIT();                         //Inicializo el LCD
LCD_PUTC("\f");                     //Limpio el LCD
//*************************************************************************//
//*************  DISEÑO POR ASIGNACIÓN DE 2 POLOS REALES   ****************//
//*************************************************************************//
TsMA=30;                    //Tiempo deseado en Lazo Cerrado    
Wn=5.8335/(TsMA);               //Frecuencia natural del sistema
//Ubicación de 2 Polos reales
P1=2*Wn;
P2=Wn*Wn;
kp=(P1*tao-1)/k;        //Calculo de Kc
ti=(k*kp)/(P2*tao);     //Calculo de ti
//*************************************************************************//
//*****************   DISEÑO POR CANCELACIÓN DE POLOS    *******************//
//*************************************************************************//
/*
TsMA=7.5;                  //Tiempo deseado en Lazo Cerrado 
kp=(tao)/(TsMA*k);      //Calculo de Kc
ti=tao;                  //Calculo de Ti (Igual a la constante de tiempo)
td=0;
*/
//*************************************************************************//
//*****************   SINTONIA POR ZIEGLER y NICHOLS    *******************//
//*************************************************************************//
/*
kp=(1.2*tao)/(k*theta);
ti=2*theta;
td=0.5*theta;
*/
//*************************************************************************//
// Calculo do controle PID digital
q0=kp*(1+T/(2*ti)+td/T);
q1=-kp*(1-T/(2*ti)+(2*td)/T);
q2=(kp*td)/T;
while(1)
{      
adc=read_adc(); //Leer ADC
yM=adc*5000.0/1024.0;
//Llama la funcion del controlador PID
PID();
//tiempo de muestreo
delay_ms(28);
lcd_gotoxy(2,1);
lcd_putc("CONTROL PID HORNO");
lcd_gotoxy(1,2);
printf(lcd_putc,"Set-Point  : %3.1f C   ",R/10);
lcd_gotoxy(1,3);
printf(lcd_putc,"Temperatura: %3.1f C",yM/10);            
lcd_gotoxy(1,4);
printf(lcd_putc,"Ley Control: %ld   ",control);
; 
c=tecla_time();   //Lee el valor del teclado pero solo espera un tiempo determinado
if(c=='D')
{
lcd_gotoxy(1,2);
LCD_PUTC("Referencia(0-300):");
lcd_gotoxy(1,3);
LCD_PUTC("y presione *");
lcd_gotoxy(1,4);
LCD_PUTC("SP:                     ");
R=escalon(3); //Llama la funcion para digitar el escalon de exitacion
//Valida si R esta entre 0 y 100 (Esto es otra forma de usar el if - else)
R =(R > 300) ? 3000:R*10;
//Muestra el SETPOINT en pantalla
lcd_gotoxy(1,4);
printf(lcd_putc,"SP: %3.1f         ",R/10);
delay_ms(2000);
LCD_PUTC("\f");
}
}
}
'); return(c); } /*===========================================================================*/ /*======================= FUNCION TECLA CON TIMER =======================*/ /*===========================================================================*/ // Pregunta por una Tecla por un tiempo, si no hay actividad, deja de preguntar // y deja que el PIC continue con su trabajo char tecla_time(void) { char c='
/*===========================================================================*/
/*=======================       SERGIO CASTAÑO         =======================*/
/*===========================================================================*/
#INCLUDE <16F887.h>
#DEVICE ADC=10
#USE DELAY(CLOCK=4000000)
#FUSES XT,NOPROTECT,NOWDT,NOBROWNOUT,PUT,NOLVP
#DEFINE USE_PORTB_KBD   //Por defecto el teclado se conecta al puerto D,
//como el microcontrolador que se esta usando
//no tiene puerto D se conecta al puerto B.*/
#INCLUDE <LCD420D.C>
#INCLUDE <KBD4x4.C>  //Incluir en el encabezado el driver para
//manejar el teclado telefónico MODIFICADO
#include <stdlib.h>
#include <string.h>
#use     standard_io(b) 
#define  KEYHIT_DELAY   1    //Tiempo de espera del teclado en milisegundos
#byte PORTB= 6
#byte PORTC= 7
#BYTE PORTA= 5
#BYTE PORTD= 8
int16 adc,control=0;
float R=1500;//Referencia de 150 °C por defecto
float yM=0,e=0.0,e_1=0.0,e_2=0.0,u=0.0,u_1=0.0,T=0.1;
float kp,ti,td,q0,q1,q2;
float k=0.535,tao=10,theta=1;
float TsMA,Wn,P1,P2;
char c;
int cont=0;
/*===========================================================================*/
/*=======================       FUNCION TECLA         =======================*/
/*===========================================================================*/
//Funcion encargada de esperar a que se presione una tecla 
char tecla(void)
{
char c;
do{ //espera hasta que se presione una tecla
c=kbd_getc(); //Captura valor del teclado
}
while(c=='\0'); 
return(c);
}
/*===========================================================================*/
/*=======================    FUNCION TECLA CON TIMER  =======================*/
/*===========================================================================*/
// Pregunta por una Tecla por un tiempo, si no hay actividad, deja de preguntar
// y deja que el PIC continue con su trabajo
char tecla_time(void) {
char c='\0';
unsigned int16 timeout;
timeout=0;
c=kbd_getc(); //Captura valor del teclado
while(c=='\0' && (++timeout< (KEYHIT_DELAY*100)))
{
delay_us(10);
c=kbd_getc(); //Captura valor del teclado
}
return(c);
}
/*===========================================================================*/
/*=======================    FUNCION DEL CONTROL PID  =======================*/
/*===========================================================================*/
void PID(void)
{
e=1*(R-yM);
// Controle PID
u = u_1 + q0*e + q1*e_1 + q2*e_2; //Ley del controlador PID discreto
if (u >= 5000.0)        //Saturo la accion de control 'uT' en un tope maximo y minimo
u = 5000.0;
if (u <= 0.0)
u = 0.0;
control=u/5;
//Retorno a los valores reales
e_2=e_1;
e_1=e;
u_1=u;
//La accion calculada la transformo en PWM
set_pwm1_duty(control);
}
/*===========================================================================*/
/*============   FUNCION PARA DIGITAR ESCALÓN/SETPOINT  =====================*/
/*===========================================================================*/
long escalon(int nd)
{
//Esta funcion captura el escalon desde el teclado, si el proceso está tomando
//datos el escalon sirve para exitar el sistema, por otro lado si el sistema
//está controlando, el escalo sirve para establecer el setpoint del sistema
long val;
int i;
char str[5]; //Variable tipo String
str[0]='0';
for(i=0;i<nd;i++)
{
c=tecla();  //Lee el valor del teclado y espera hasta que alguna tecla se pulse
if(c!='*'){
//Muestra el digito presionado en el LCD
lcd_gotoxy(5+i,4);
lcd_putc(c);
//Almacena el dato presionado en la variable String
str[i]=c;
}
else{i=nd;} //Si se presiona * sale del For      
}
val = atol(str); //Convierte el String en un valor numerico
return(val);
}
void main()
{
port_b_pullups (0xFF);  //Utiliza las resistencias PULL UP internas del puerto B
set_tris_c(0);
set_tris_d(0);
setup_timer_2(t2_div_by_4,249,1);   //Configuracion de Timer 2 para establecer frec. PWM a 1kHz
setup_ccp1(ccp_pwm);                //Configurar modulo CCP1 en modo PWM
set_pwm1_duty(0);                   //Dejo en cero la salida PWM
setup_adc_ports(sAN0);              //Configurar ADC (Lectura de temperatura)
setup_adc(adc_clock_internal);      //Reloj interno para la conversion analoga digital)
set_adc_channel(0);                 //Seleccionar Canal 0 para sensor de Temperatura
LCD_INIT();                         //Inicializo el LCD
LCD_PUTC("\f");                     //Limpio el LCD
//*************************************************************************//
//*************  DISEÑO POR ASIGNACIÓN DE 2 POLOS REALES   ****************//
//*************************************************************************//
TsMA=30;                    //Tiempo deseado en Lazo Cerrado    
Wn=5.8335/(TsMA);               //Frecuencia natural del sistema
//Ubicación de 2 Polos reales
P1=2*Wn;
P2=Wn*Wn;
kp=(P1*tao-1)/k;        //Calculo de Kc
ti=(k*kp)/(P2*tao);     //Calculo de ti
//*************************************************************************//
//*****************   DISEÑO POR CANCELACIÓN DE POLOS    *******************//
//*************************************************************************//
/*
TsMA=7.5;                  //Tiempo deseado en Lazo Cerrado 
kp=(tao)/(TsMA*k);      //Calculo de Kc
ti=tao;                  //Calculo de Ti (Igual a la constante de tiempo)
td=0;
*/
//*************************************************************************//
//*****************   SINTONIA POR ZIEGLER y NICHOLS    *******************//
//*************************************************************************//
/*
kp=(1.2*tao)/(k*theta);
ti=2*theta;
td=0.5*theta;
*/
//*************************************************************************//
// Calculo do controle PID digital
q0=kp*(1+T/(2*ti)+td/T);
q1=-kp*(1-T/(2*ti)+(2*td)/T);
q2=(kp*td)/T;
while(1)
{      
adc=read_adc(); //Leer ADC
yM=adc*5000.0/1024.0;
//Llama la funcion del controlador PID
PID();
//tiempo de muestreo
delay_ms(28);
lcd_gotoxy(2,1);
lcd_putc("CONTROL PID HORNO");
lcd_gotoxy(1,2);
printf(lcd_putc,"Set-Point  : %3.1f C   ",R/10);
lcd_gotoxy(1,3);
printf(lcd_putc,"Temperatura: %3.1f C",yM/10);            
lcd_gotoxy(1,4);
printf(lcd_putc,"Ley Control: %ld   ",control);
; 
c=tecla_time();   //Lee el valor del teclado pero solo espera un tiempo determinado
if(c=='D')
{
lcd_gotoxy(1,2);
LCD_PUTC("Referencia(0-300):");
lcd_gotoxy(1,3);
LCD_PUTC("y presione *");
lcd_gotoxy(1,4);
LCD_PUTC("SP:                     ");
R=escalon(3); //Llama la funcion para digitar el escalon de exitacion
//Valida si R esta entre 0 y 100 (Esto es otra forma de usar el if - else)
R =(R > 300) ? 3000:R*10;
//Muestra el SETPOINT en pantalla
lcd_gotoxy(1,4);
printf(lcd_putc,"SP: %3.1f         ",R/10);
delay_ms(2000);
LCD_PUTC("\f");
}
}
}
'; unsigned int16 timeout; timeout=0; c=kbd_getc(); //Captura valor del teclado while(c=='
/*===========================================================================*/
/*=======================       SERGIO CASTAÑO         =======================*/
/*===========================================================================*/
#INCLUDE <16F887.h>
#DEVICE ADC=10
#USE DELAY(CLOCK=4000000)
#FUSES XT,NOPROTECT,NOWDT,NOBROWNOUT,PUT,NOLVP
#DEFINE USE_PORTB_KBD   //Por defecto el teclado se conecta al puerto D,
//como el microcontrolador que se esta usando
//no tiene puerto D se conecta al puerto B.*/
#INCLUDE <LCD420D.C>
#INCLUDE <KBD4x4.C>  //Incluir en el encabezado el driver para
//manejar el teclado telefónico MODIFICADO
#include <stdlib.h>
#include <string.h>
#use     standard_io(b) 
#define  KEYHIT_DELAY   1    //Tiempo de espera del teclado en milisegundos
#byte PORTB= 6
#byte PORTC= 7
#BYTE PORTA= 5
#BYTE PORTD= 8
int16 adc,control=0;
float R=1500;//Referencia de 150 °C por defecto
float yM=0,e=0.0,e_1=0.0,e_2=0.0,u=0.0,u_1=0.0,T=0.1;
float kp,ti,td,q0,q1,q2;
float k=0.535,tao=10,theta=1;
float TsMA,Wn,P1,P2;
char c;
int cont=0;
/*===========================================================================*/
/*=======================       FUNCION TECLA         =======================*/
/*===========================================================================*/
//Funcion encargada de esperar a que se presione una tecla 
char tecla(void)
{
char c;
do{ //espera hasta que se presione una tecla
c=kbd_getc(); //Captura valor del teclado
}
while(c=='\0'); 
return(c);
}
/*===========================================================================*/
/*=======================    FUNCION TECLA CON TIMER  =======================*/
/*===========================================================================*/
// Pregunta por una Tecla por un tiempo, si no hay actividad, deja de preguntar
// y deja que el PIC continue con su trabajo
char tecla_time(void) {
char c='\0';
unsigned int16 timeout;
timeout=0;
c=kbd_getc(); //Captura valor del teclado
while(c=='\0' && (++timeout< (KEYHIT_DELAY*100)))
{
delay_us(10);
c=kbd_getc(); //Captura valor del teclado
}
return(c);
}
/*===========================================================================*/
/*=======================    FUNCION DEL CONTROL PID  =======================*/
/*===========================================================================*/
void PID(void)
{
e=1*(R-yM);
// Controle PID
u = u_1 + q0*e + q1*e_1 + q2*e_2; //Ley del controlador PID discreto
if (u >= 5000.0)        //Saturo la accion de control 'uT' en un tope maximo y minimo
u = 5000.0;
if (u <= 0.0)
u = 0.0;
control=u/5;
//Retorno a los valores reales
e_2=e_1;
e_1=e;
u_1=u;
//La accion calculada la transformo en PWM
set_pwm1_duty(control);
}
/*===========================================================================*/
/*============   FUNCION PARA DIGITAR ESCALÓN/SETPOINT  =====================*/
/*===========================================================================*/
long escalon(int nd)
{
//Esta funcion captura el escalon desde el teclado, si el proceso está tomando
//datos el escalon sirve para exitar el sistema, por otro lado si el sistema
//está controlando, el escalo sirve para establecer el setpoint del sistema
long val;
int i;
char str[5]; //Variable tipo String
str[0]='0';
for(i=0;i<nd;i++)
{
c=tecla();  //Lee el valor del teclado y espera hasta que alguna tecla se pulse
if(c!='*'){
//Muestra el digito presionado en el LCD
lcd_gotoxy(5+i,4);
lcd_putc(c);
//Almacena el dato presionado en la variable String
str[i]=c;
}
else{i=nd;} //Si se presiona * sale del For      
}
val = atol(str); //Convierte el String en un valor numerico
return(val);
}
void main()
{
port_b_pullups (0xFF);  //Utiliza las resistencias PULL UP internas del puerto B
set_tris_c(0);
set_tris_d(0);
setup_timer_2(t2_div_by_4,249,1);   //Configuracion de Timer 2 para establecer frec. PWM a 1kHz
setup_ccp1(ccp_pwm);                //Configurar modulo CCP1 en modo PWM
set_pwm1_duty(0);                   //Dejo en cero la salida PWM
setup_adc_ports(sAN0);              //Configurar ADC (Lectura de temperatura)
setup_adc(adc_clock_internal);      //Reloj interno para la conversion analoga digital)
set_adc_channel(0);                 //Seleccionar Canal 0 para sensor de Temperatura
LCD_INIT();                         //Inicializo el LCD
LCD_PUTC("\f");                     //Limpio el LCD
//*************************************************************************//
//*************  DISEÑO POR ASIGNACIÓN DE 2 POLOS REALES   ****************//
//*************************************************************************//
TsMA=30;                    //Tiempo deseado en Lazo Cerrado    
Wn=5.8335/(TsMA);               //Frecuencia natural del sistema
//Ubicación de 2 Polos reales
P1=2*Wn;
P2=Wn*Wn;
kp=(P1*tao-1)/k;        //Calculo de Kc
ti=(k*kp)/(P2*tao);     //Calculo de ti
//*************************************************************************//
//*****************   DISEÑO POR CANCELACIÓN DE POLOS    *******************//
//*************************************************************************//
/*
TsMA=7.5;                  //Tiempo deseado en Lazo Cerrado 
kp=(tao)/(TsMA*k);      //Calculo de Kc
ti=tao;                  //Calculo de Ti (Igual a la constante de tiempo)
td=0;
*/
//*************************************************************************//
//*****************   SINTONIA POR ZIEGLER y NICHOLS    *******************//
//*************************************************************************//
/*
kp=(1.2*tao)/(k*theta);
ti=2*theta;
td=0.5*theta;
*/
//*************************************************************************//
// Calculo do controle PID digital
q0=kp*(1+T/(2*ti)+td/T);
q1=-kp*(1-T/(2*ti)+(2*td)/T);
q2=(kp*td)/T;
while(1)
{      
adc=read_adc(); //Leer ADC
yM=adc*5000.0/1024.0;
//Llama la funcion del controlador PID
PID();
//tiempo de muestreo
delay_ms(28);
lcd_gotoxy(2,1);
lcd_putc("CONTROL PID HORNO");
lcd_gotoxy(1,2);
printf(lcd_putc,"Set-Point  : %3.1f C   ",R/10);
lcd_gotoxy(1,3);
printf(lcd_putc,"Temperatura: %3.1f C",yM/10);            
lcd_gotoxy(1,4);
printf(lcd_putc,"Ley Control: %ld   ",control);
; 
c=tecla_time();   //Lee el valor del teclado pero solo espera un tiempo determinado
if(c=='D')
{
lcd_gotoxy(1,2);
LCD_PUTC("Referencia(0-300):");
lcd_gotoxy(1,3);
LCD_PUTC("y presione *");
lcd_gotoxy(1,4);
LCD_PUTC("SP:                     ");
R=escalon(3); //Llama la funcion para digitar el escalon de exitacion
//Valida si R esta entre 0 y 100 (Esto es otra forma de usar el if - else)
R =(R > 300) ? 3000:R*10;
//Muestra el SETPOINT en pantalla
lcd_gotoxy(1,4);
printf(lcd_putc,"SP: %3.1f         ",R/10);
delay_ms(2000);
LCD_PUTC("\f");
}
}
}
' && (++timeout< (KEYHIT_DELAY*100))) { delay_us(10); c=kbd_getc(); //Captura valor del teclado } return(c); } /*===========================================================================*/ /*======================= FUNCION DEL CONTROL PID =======================*/ /*===========================================================================*/ void PID(void) { e=1*(R-yM); // Controle PID u = u_1 + q0*e + q1*e_1 + q2*e_2; //Ley del controlador PID discreto if (u >= 5000.0) //Saturo la accion de control 'uT' en un tope maximo y minimo u = 5000.0; if (u <= 0.0) u = 0.0; control=u/5; //Retorno a los valores reales e_2=e_1; e_1=e; u_1=u; //La accion calculada la transformo en PWM set_pwm1_duty(control); } /*===========================================================================*/ /*============ FUNCION PARA DIGITAR ESCALÓN/SETPOINT =====================*/ /*===========================================================================*/ long escalon(int nd) { //Esta funcion captura el escalon desde el teclado, si el proceso está tomando //datos el escalon sirve para exitar el sistema, por otro lado si el sistema //está controlando, el escalo sirve para establecer el setpoint del sistema long val; int i; char str[5]; //Variable tipo String str[0]='0'; for(i=0;i<nd;i++) { c=tecla(); //Lee el valor del teclado y espera hasta que alguna tecla se pulse if(c!='*'){ //Muestra el digito presionado en el LCD lcd_gotoxy(5+i,4); lcd_putc(c); //Almacena el dato presionado en la variable String str[i]=c; } else{i=nd;} //Si se presiona * sale del For } val = atol(str); //Convierte el String en un valor numerico return(val); } void main() { port_b_pullups (0xFF); //Utiliza las resistencias PULL UP internas del puerto B set_tris_c(0); set_tris_d(0); setup_timer_2(t2_div_by_4,249,1); //Configuracion de Timer 2 para establecer frec. PWM a 1kHz setup_ccp1(ccp_pwm); //Configurar modulo CCP1 en modo PWM set_pwm1_duty(0); //Dejo en cero la salida PWM setup_adc_ports(sAN0); //Configurar ADC (Lectura de temperatura) setup_adc(adc_clock_internal); //Reloj interno para la conversion analoga digital) set_adc_channel(0); //Seleccionar Canal 0 para sensor de Temperatura LCD_INIT(); //Inicializo el LCD LCD_PUTC("\f"); //Limpio el LCD //*************************************************************************// //************* DISEÑO POR ASIGNACIÓN DE 2 POLOS REALES ****************// //*************************************************************************// TsMA=30; //Tiempo deseado en Lazo Cerrado Wn=5.8335/(TsMA); //Frecuencia natural del sistema //Ubicación de 2 Polos reales P1=2*Wn; P2=Wn*Wn; kp=(P1*tao-1)/k; //Calculo de Kc ti=(k*kp)/(P2*tao); //Calculo de ti //*************************************************************************// //***************** DISEÑO POR CANCELACIÓN DE POLOS *******************// //*************************************************************************// /* TsMA=7.5; //Tiempo deseado en Lazo Cerrado kp=(tao)/(TsMA*k); //Calculo de Kc ti=tao; //Calculo de Ti (Igual a la constante de tiempo) td=0; */ //*************************************************************************// //***************** SINTONIA POR ZIEGLER y NICHOLS *******************// //*************************************************************************// /* kp=(1.2*tao)/(k*theta); ti=2*theta; td=0.5*theta; */ //*************************************************************************// // Calculo do controle PID digital q0=kp*(1+T/(2*ti)+td/T); q1=-kp*(1-T/(2*ti)+(2*td)/T); q2=(kp*td)/T; while(1) { adc=read_adc(); //Leer ADC yM=adc*5000.0/1024.0; //Llama la funcion del controlador PID PID(); //tiempo de muestreo delay_ms(28); lcd_gotoxy(2,1); lcd_putc("CONTROL PID HORNO"); lcd_gotoxy(1,2); printf(lcd_putc,"Set-Point : %3.1f C ",R/10); lcd_gotoxy(1,3); printf(lcd_putc,"Temperatura: %3.1f C",yM/10); lcd_gotoxy(1,4); printf(lcd_putc,"Ley Control: %ld ",control); ; c=tecla_time(); //Lee el valor del teclado pero solo espera un tiempo determinado if(c=='D') { lcd_gotoxy(1,2); LCD_PUTC("Referencia(0-300):"); lcd_gotoxy(1,3); LCD_PUTC("y presione *"); lcd_gotoxy(1,4); LCD_PUTC("SP: "); R=escalon(3); //Llama la funcion para digitar el escalon de exitacion //Valida si R esta entre 0 y 100 (Esto es otra forma de usar el if - else) R =(R > 300) ? 3000:R*10; //Muestra el SETPOINT en pantalla lcd_gotoxy(1,4); printf(lcd_putc,"SP: %3.1f ",R/10); delay_ms(2000); LCD_PUTC("\f"); } } }

Eso es todo por la entrada del dia de hoy, espero les haya gustado y hayan aprendido algo nuevo. Si te ha servido el contenido de esta entrada, de los videos y los códigos de implementación y deseas apoyar mi trabajo invitandome a un café super barato, puedes hacerlo en el siguiente link:

👉 Invitar a Sergio a un Café ☕️

Que esten muy bien, nos vemos en la siguiente entrada.

Entradas relacionadas

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Comentarios (145)

Me gustaría saber en que programa compilas los códigos que usas

Responder

Se llama CCS C (PIC C)

Responder

Hola, saludos! excelente contenido, hay alguna forma de implementar el PID digital pero en lugar del set point, que me permita variar los parametros, del PID?

Responder

Hola Luis, claro, de hecho en este mismo ejemplo puedes hacer eso. Solo debes pedirle al usaurio a través de alguna interfaz (teclado, serial, etc) para ingresar los parámetros de sintonia del PID y con esos datos lo reescribes en las variables del código.

Responder

hola buenas tardes , necesito ayuda he estado viendo algunos de tus
videos ,vi el sistema pid que es de un horno usando un pic16f887 ,
este horno lo usas con un lm35 , yo lo utilizo con una termocupla tipo
k que igual vi como la calibras , necesito ayuda para la conexión de
un motor de 24v , que lo quiero conectar a la línea de código
set_pwm1_duty(control), mi codigo el cual es
if (yM >= 800) { output_high(pin_c1); // activar relé y encender motor
} else if (yM = 750) { output_low(pin_c1); // si se llega al
setpoint de 750°C, apagar motor }, estoy usando el codigo de usted el
cual es Control PID con microcontrolador PIC, me podrias ayudar
explicandome a como conectar(en proteus la última parte del del
relevador ) y montar mi código con el tuyo , se lo agradeceria mucho

Responder

El PID va a actuar sobre una resistencia me imagino, y ese motor debe estar en otro pin del PIC para hacer alguna otra lógica. En tu condicional *elif* si quieres preguntar por igualdad, recuerda poner dos ==. En simulación quiazas te funcione pero en la vida real dificilmente tu temperatura siempre será exactamente 750, por lo que debes pensar mejor en hacer un rango. También NO tienes definido que pasa si la temperatura esta por debajo de 750. La conexión solo para ON-OF con un relé se explica en esta entrada de Relé con PIC.

Responder

Hola que tal, Yo tengo el mismo problema. Tengo que usar 2 pics? y si no es el caso como puedo guardar la variable que nos da el termopar k para sustituirla en el código, es que soy de prepa y el profe nos dejo una incubadora con el sensor termopar y no nos explica nada, he aprendido más con usted pero no puedo cambiar el sensor de lm35 a termopar, me gustaría que lo explicara como cambiar de sensor pq la verdad no sé ni cual es la variable que nos da el lm35

Responder

Lo primero que debes hacer es entender como se realiza la lectura del termopar. Puedes dar clic aqui para ver como se hace.

Despues, debes mezclar ambos códigos, por ejemplo si usas el primer código mostrado aquí cuando hayas mezclado los dos códigos basta con reemplazar la linea:

yM=adc*5000.0/1024.0;

por la linea:

yM=do_everything();

Evidentemente, tambien tienes que colocarle el llamado de todas las librerias del termopar, dado que estas fucionando los dos códigos.

Responder

Hola Sergio, para implementar un termopar tipo K en el PID del teclado que ajustes son necesarios para hacer la lectura de la temperatura. Por que solo me funciona con un lm35 Muchas gracias saludos cordiales.

Responder

Hola Santos, el primer paso es poder leer la temperatura del termopar, el cual es un código diferente a la lectura del LM35, dado que aquí ya necesitas leer un conversor ADC propio para lectura de dicho termopar. Con la medida, ya podrías realizar tu controlador PID. Te dejo un ejemplo de como leer termopares con el PIC.

Responder

Hola sergio, estoy intentando hacer una placa caliente para soldadura smd y no se como lograr la curva de perfil de temperatura para la soldadura. Tengo entendido que es con un PID pero no logre llevar este ejemplo a mi caso.
Muchas gracias por todos los videos.

Responder

Hola Sergio, primero que nada te quiero agradecer por el gran trabajo que compartes, eso demuestra lo excelente persona que eres al compartir tu conocimiento, muchas gracias. Otra es tengo una duda la ley de control que se muestra en el display, que indica?. Muchas gracias saludos cordiales

Responder

Hola Antonio, en este caso está indicando la cantidad de energía que el controlador le esta colocando al horno expresado en ancho de pulso del PWM, donde un PWM cerca a los 1000 indica que le está inyectando máxima potencia, en cuanto si esta cerca de 0 no está inyectando nada de potencia. Saludos Antonio.

Responder

hola, se puede hacer control PID con mas de una variable, por ejemplo temperaturia y humedad, utilizando este controlador?

Responder

Si puedes hacerlo, si te quedas sin memoria, puedes probar con un 18F4550 que es muy similar. Ahora, si deseas controlar temperatura y humedad en un mismo proceso, ya entras a lo que es la teoría de control multivariable, donde vas a tener las interacciones entre las variables, para que lo tengas en cuenta en tu proyecto de control. Saludos.

Responder

MUCHASSSSS GRACIASSSS INGENIEROSERGIO ……………..

Responder

De nada Ronald, que bueno que te ha gustado. Saludos!

Responder

Que tal, solo tengo una duda, cuando hice la prueba de tu programa hice comentarios el bloque de DISEÑO POR ASIGNACIÓN DE 2 POLOS REALES y habilite el método de ZIEGLER y NICHOLS la simulación no funciona correctamente, de hecho empieza a oscilar a que crees que se deba?

Responder

Josimar no sé, acabé de verificar los dos archivos, con y sin teclado usando la sintonia de Z&N, y en mi caso funcionó perfectamente, controla bien sin oscilaciones.

Responder

Buenos días, disculpe las molestias, estoy realizando un sistema para estabilizar la temperatura a 36 grados en una cuna, no logro comprender el por qué de tomar el 16.6% de los 12V aplicados al oven.
Por otro lado, quisiera saber cómo encuentro mi punto de operación y si tiene idea de qué valores de thermal resistance to ambient y heating power debo usar.
Muchísimas gracias y saludos.

Responder

Tu punto de operación son los 36 grados, dado que es donde deseas mantener la temperatura. Lo que puedes hacer es aplicar un voltaje que más o menos consiga llegar a los 36 grados, a partir de ahi puedes aplicar un escalón pequeño, para que la temperatura varie poco en torno de los 36, puede ser que suba hasta 38 o 40, la idea es que con ese pequeño cambio en tu punto de operación te sirva para identificar el proceso en ese punto de operación.

Responder

Hola! Quería felicitarte por este maravilloso trabajo que haces, ni te imaginas cuanto me ha ayudado con mis estudios, excelentes explicaciones y muy detallado todo, de verdad muy agradecida de que haya gente como tu dispuestas a ayudar a los demás compartiendo sus conocimientos… Y muy atento como respondes cada comentario con esmero y tratando de explicar lo mejor posible. Felicitaciones y un abrazo desde Venezuela!

Responder

Muchas gracias Fabiola, me alegra que el contenido del sitio web y del canal de YouTube te hayan ayudado. El objetivo de estos dos canales es ayudar compartiendo un poco lo que he aprendido. Saludos y muchos éxitos!

Responder

Hola Sergio, he estado tratando de realizar tu proyecto de PID del primer video sin teclado usando Arduino, dispongo de un arduino uno, pero al momento de correr el código en proteus no me da igual la curva de salida, me quedan unos picos y oscilatorio. Tengo ajustado el dispositivo oven y el modelo del sistema tal cual explicas en el primer vídeo. anexo el código para que le eches un vistazo. Gracias ingeniero!

Responder

Hola Emmanuel, no se si has visto la entrada del CONTROL PID con ARDUINO que está en este sitio WEB. Es lo más actualizado de PID en microcontroladores que he colocado en el sitio web hasta la fecha. Dale un vistazo quizas te sea de utilidad.

Responder

La he visto completita, una maravilla, varias veces, pero la diferencia de aquel código y este, creo que seria la representación gráfica en matlab y que estoy usando el timer2 por registros en vez de la librería timer one. Realmente no se que sucede con el código, se ve bien para mí, pero por alguna razón me queda esta gráfica con un ruido enorme y oscilatoria. El control responde rápido pero pasa el setpoint de los 150 xon un sobre impulso, baja y vuelve a tratar de alcanzar el setpoint. Se parece bastante a la respuesta de un sistema sub-amortiguado pero con ruido.

Responder

Pueden ser tus condiciones de diseño, coloca para los polos reales un tiempo de establecimiento de 30s con TsMA=30, y también trata de verificar si el periodo de muestreo se está ejecutando en el tiempo adecuado.

Responder

Muy buen vídeo, de verdad explicado muy bien, tengo un pregunta de donde sale la ecuación del controlador que se ha usado. yo he usado anteriormente pid para mis diseños de control pero yo uso pid = kp*error + (ki*error*Tmuestreo + error_anterior) + (Kd*(error – error_anterior)/Tmuestreo) esta ecuación se obtiene de la transformada bilateral del s a Z de un PID continuo, me gustaría saber de done sale la que se usa acá muchas gracias.

Responder

Hola Juan, esa ecuación del PID se obtiene discretizando la ecuación continua aproximando el término integral mediante la sumatoria trapezoidal y el término derivativo mediante la diferencia de dos puntos para de esa forma obtener la función de transferencia pulso del controlador PID digital. Saludos!

Responder

Hola buenas noches, primero te felicito y apoyo tu trabajo pocos explican controles de la manera en que tú lo haces.

Tengo una pregunta algunos “PID” que he visto aplicado específicamente en la plataforma Arduino pero de una manera diferente.

Básicamente no lo realizan en tiempo discreto si no utilizan la configuración de un PID en tiempo continuo

PID=Kp*error+Ki*(error anterior)+Kd*(Erro-errorAnterior)/tiempo

Es esta una manera correcta de aplicarlo ??

Gracias de antemano si puedes realiza ejemplos de implementación de controladores

Responder

Realmente es un control discreto también, solo están haciendo la aproximación de la ecuación a tiempo discreto. En esta entrada, se realizo utilizando la teoría de la transformada Z y se implementó a través de ecuaciones en diferencia. Acá en el sitio web ya tenemos algunas implementaciones del control PID.

Responder

Muchas gracias por tu respuesta Sergio desconocía esa aproximación solo conocía la implementación a través de las ecuaciones en diferencia por eso tenía mis dudas si aplicar esa aproximación era correcto. Excelente contenido a la espera de más

Responder

Buenas noches; soy de Argentina y con este tema del corona virus tengo un tiempo para disfrutar de mi joby.
Esta realmente exelente el proyecto del PID pero a mi me sucede que cuando lo compilo me saltan los errores de las librerias #include
#include .
La pregunta es de donde las puedo bajar. Gracias

Responder

Antonio seguramente tienes una versión antigua del ccs c. Trata de bajar una versión más reciente. En este momento yo tengo instalada la versión 5.076.Saludos

Responder

Buenas noches. Gracias por responder mi consulta con tanta rapidez.
Actualice la versión de ccs c y se solucionaron los problemas de compilación, ya no tengo errores.
Muchas gracias.

Responder

Hola Sergio, tengo un problema estoy usando como actuador un servomotor, uso los valores de clock y la configuracion del PWM adecuada:
setup_timer_2(t2_div_by_16,155,1);
Ademas tam bien configure los limites para tener control dentro de mi rango de movimiento del servo 12 a 72 respectivamente de 0 a 180 grados.
pero no logro moverlo. Examine varias veces tiene algo que ver el delay??? No logro hacer que el servo se mueva.

Responder

Hola Eduk. Por lo que entiendo, cuando aplicas el pwm directamente al servo, con el duty de 12 logras los 0 grados y con el duty de 72 logras los 180 grados?? O todavía no logras esa etapa? No entendí si es que no te funciona el servo dentro del código del PID o si directamente no te funciona el pwm en el servo, pues como comentas conseguiste los valores de configuración máximo y mínimo del servo, por lo que intuyo de que aplicado individualmente el pwm consigues mover el servo.

Para el caso del PID verifica inicialmente con un lcd o por una comunicación serial que cuando hay un error grande, el PID coloque tu duty en 72, y que cuando el PID tenga error cero te coloque el duty en 12.

Responder

Hola Sergio, gracias por responder. Si efectivamente con la ayuda del video de servomotor con pic encontre el minimo y maximo de mi servomotor, asi puedo controlar el grado exacto que deseo. La aplicacion del servo en este control PID es para abrir una valvula de forma proporcional. El problema que tengo es como te mencione que el servo no se mueve, la consulta que tengo es que si el delay utilizado en el muestreo tiene que ver algo.

Responder

Hola Eduk, el delay no influye sobre el PWM, este continua trabajando a la frecuencia configurada. Solo va a cambiar el duty cicle al momento de llegar a la parte del código donde se modifica, pero va a mantener siempre la frecuencia a la que fue configurada.

Responder

Hola Sergio si revise el codigo varias veces no existe ningun error, estoy usando un clock de 500k y mi timer2 esta configurado correctamente, probablemente sea un problema de distorsion de la señal PWM, tendre que revisar en laboratorio con osciloscopio para poder implementar algun filtro, al parecer se manda automaticamente a menos de 1 ms el ancho de pulso por eso siempre manda a cero. Gracias por tu respuesta y el gran aporte que haces con las clases y codigos que publicas.

Responder

Hola Sergio, encontre el problema ahora aqui va mi pregunta. Resulta que estaba usando la linea para esepcificar el clock
#USE DELAY(CLOCK=500000)
Al cambiarla por
#USE DELAY(INTERNAL=500000) funciono perfectamente el servo con el PID
Cual es la diferencia que existe entre estos dos y si usar el segundo afecta de alguna forma al algoritmo PID, Gracias

Responder

Son formas de configurar la velocidad del PIC, en la primera que pones, debes antes de declarar el reloj definir el fusible del crital RC interno #fuses INTRC_IO para que puedas configuarar posteriormente el oscilador con la función setup_oscillator(OSC_500KHZ|OSC_INTRC);

La segunda forma es usando directamente la directiva #use delay para definir el tipo de reloj a emplear, en este caso definiste el reloj interno.

El PID no se va a ver afectado desde que respetes el tiempo de muestreo de tu control digital. Si tu tiempo de muestreo es de 1 segundo, quiere decir que obligatoriamente cada segundo se debe enviar la señal de control. Saludos.

Hola Buenas a Todos, tengo una duda con respecto al voltaje que recibe mi resistencia eléctrica en el rele de estado sólido… Después de aplicarle un porcentaje en el PWM, el voltaje que recibe mi resistencia tiene que ser fija? Por qué a la hora de medir dicho voltaje, esté tiene variaciones y no es estable, eso es normal?
Muchas gracias.

Responder

Excelentes videos y mejor la explicación, voy comprendiendo poco a poco el funcionamiento pero aun tengo duda sobre la conexión que se debe realizar para estudiar el comportamiento de un resistencia electrica alimentada en AC a UN PWM del 20% para obtener los valores que iran en la funcion de transferencia..
¿La entrada del ADC con la que manipularé mi PWM a un 20% se controlaria con un pot alimentado a 5 VDC?
La salida del PIC tengo entendido que iria a la entrada de un rele de estado solido ¿ Qué hay de los otros bornes (24-380 VAC)?
¿Cómo alimento mi resistencia? No entendí del todo el cómo conectarlo en SERIE, como mencionas en uno de tus comentarios de abajo.
Espero puedas resolver mis dudas!! Muchas gracias Ingeniero. Feliz por poder terminar mi proyecto con Exito

Responder

Hola Román, la etapa de potencia con el relé la explicamos en otra entrada donde realizamos la implementación física de un horno regulando la resistencia con el relé de estado solido
https://controlautomaticoeducacion.com/microcontroladores-pic/monitoreo-de-temperatura-en-horno-con-pic/

El pic va directo al Relé conectado a través del pin CCP (PWM), para mandar el escalón del 20% debes mandar a través del PIC un duty cicle del 20% y tomar los datos de temperatura para posteriormente identificar tu sistema. Tenemos otra entrada donde explicamos eso y mostramos como obtener la función de transferencia
https://controlautomaticoeducacion.com/microcontroladores-pic/adquisicion-de-datos-e-identificacion-de-un-horno-con-pic/

Responder

hola Sergio imaginate que estoy trabajndo con tu codigo cuando lo simulo solo funciona perfcto pero cuando aplico perturbaciones representada en una bateria de 30 voltiosno logra volver al set point, agradeceria que me pudieras colaborar a ver que se debe modificar para que el sistema resita las perturbaciones.

Responder

Cordial saludo Sergio, estoy desarrollando un controlador PID para el control de emisiones SO2 en una caldera apoyandome de tus tutoriales, para mi proceso cuando las emisiones suben debo mandar a abrir una valvula para lograr que dichas emisiones bajen y esten dentro de un rango legal, mi duda es como hago para obtener el modelo matematico de una planta en donde las variables de control y proceso tienen un comportamiento inversamente proporcional?

Muchas gracias

Responder

Hola John, se hace de la misma forma que lo hicimos aqui, si deseas hacerlo experimentalmente. En tu función de transferencia vas a tener una ganancia negativa, es decir por ejemplo si aplicas un escalon positivo, la planta cresce en la otra dirección. Lo importante a tener en cuenta aqui, es que en tu controlador PID, la ganancia proporcional siempre debe tener el mismo signo de la ganancia de la planta. Saludos!

Responder

agradecido por su enseñanza ingeniero, tengo una duda y es la siguiente: por que elegir el ciclo de trabajo del 10% al 20% y no por ejemplo del 50% al 75%.

Responder

Por nada en especial, lo recomendado es elegir el escalón más próximo al punto de operación del proceso, en este caso donde mas o menos se va a mantener la temperatura del horno, para poder garantizar que el control pueda regular la variable, esto se hace principalmente es porque los sistemas son no lineales, entonces la identificación realmente la estamos haciendo sobre aquel punto de operación, y en muchos casos esa función de transferencia solo nos va a servir para ese escalón en particular. Saludos.

Responder

el modelo y la programación seria el mismo si deseara ocupar una resistencia industrial a 110 v para calentar tubos

Responder

La programación es la misma, los parámetros de la función de transferencia van a variar en tu proceso, por lo tanto primero tendras que identificar tu proceso.

Responder

Muchas Gracias Sergio C, excelente trabajo sobre PID y todo lo demas, queria preguntarte si la ecuacion Uk tambien puede ser obtenida por analisis estadistico a partir del Software CurvExpert, que permite crear un metodo polinomial que refleja las variaciones del proceso. muchas gracias.

Responder

Luis nunca use ese programa. Por otro lado la ley de control del PID u(k) ya es un polinomio, y se resuelve facilmente de forma recursiva dentro del procesador. Saludos

Responder

MUCHAS GRACIAS encerio han sido de inmensa ayuda estos tutoriales, gracias por el tiempo y esfuerzo dedicado.

Responder

De nada Alexis, me alegra que te hayan servido. Un fuerte abrazo.

Responder

MUCHAS GRACIAS por todo el tiempo y dedicacion prestada, encerio han sido de inmensa ayuda estos tutoriales

Responder

Gracias por tus videos, pero no puedo descargar los códigos, he compartido via gmail, pero no libera el link, lo he realizado varias veces, aparece la descarga en negrilla, y no deja descargar, tienes restricciones o estoy haciendo al mal?

A lo mejor me lo puedes enviar a mi e-mail, por favor.

Gracias,

Juan Maureira

Responder

Hola Juan, para desbloquear el código debes hacerlo con alguno de los 3 botones que aparecen en el mensaje. Dale un vistazo que adicione un Video de como hacerlo. te dejo el link, saludos. https://youtu.be/jX0RhZkys-o

Responder

Muy buena página y videos Sergio, felicidades. Tengo una pregunta, que efecto tiene sobre el desempeño del sistema el no poder obtener una constante adimensional tal como la que obtienes K=0.535, te explico rápidamente la situación que tengo,en mi sistema la temperatura la estoy leyendo de un termopar por medio de un MAX6675, y los elementos calefactores los estoy alimentado con AC, estoy considerando variar la potencia de los calefactores por medio de una pwm de muy baja frecuencia digamos 1s o algo por el estilo, entonces al tratar de determinar la ganancia de mi sistema la K estaría expresada en unidades de temperatura sobre tiempo, ¿Qué efecto tienen esto sobre el desempeño de mi sistema?
Muchas gracias por adelantado y nuevamente felicidades por la gran calidad de esta página…

Responder

Hola Raúl. Para variar la temperatura con el pwm vas a necesitar un elemento final de control, lo mejor sería usar reles de estado solido. El pwm va a restringir la potencia entregada al calefactor, entonces en tu caso seria mejor trabajar en porcentaje y la temperatura también en porcentaje. De esa forma tu sistema queda adimensionado. Generalmente se trabaja con la ganancia adimensionada si no el control puede no cumplir tus especificaciones de diseño en caso que los cálculos no sean acordes a sus unidades. Es decir es más probable obtener un control mal programado. Saludos.

Responder

buenas sergio excelentes explicaciones realizas, mi proyecto es el siguiente bassado en tu programacion claro esta, es un controlador de temperatura pero debe ser controlado via teclado matricial, es decir, su setpoint sera escrito en el teclado y esta sera la temperatura a controlar, pero hasta ahora no he logrado que funciones a la perfeccion esta etapa, no se si me estoy pasando por alto algo espero me puedas ayuidar, controlare la temperatura de una resistencia calorifica de 600 W, moc 3032 tria de 10A para el PWM, estoy empezando en esto de la programacion pero ya he leido bastante, y necesito ayuda mas experta en el tema, mientras ubico algun profesor, te muestro el codigo resultante:
bueno lamentablemente no se compio el codigo completo, y mi problema era con el * -enter-, ya que el programa me reconoce los valores otorgados por el teclado pero no el enter, asi que estoy parado en esa ultima etapa y no se como darte el codigo completo..

Responder

Oscar, utiliza la misma función del Ejemplo 2. Ahi esta como capturar el setpoint desde el teclado, usando * como enter. Vi que modificaste esa función y pusiste otras cosas del controlador. Utiliza exactamente la misma función ya que esta funciona. Saludos.

Responder

Ingeniero su ayuda con los ejemplos que publica me ha sido de gran ayuda, quería preguntarle si hay otra manera de contribuir con su proyecto que no sea por medio de tarjeta electrónica, no se si una cuenta en Efecty o Juguemos ?

Responder

Hola Paola, gracias nuevamente por el comentário, que bueno que la página te haya ayudado, eso es lo importante. En cuanto a la contribución, no dispongo de ninguno de esos medios, pero igual puedes ayudar compartiendo el blog y el canal para que más personas conozcan el sitio web, Gracias!!. Saludos.

Responder

Muchas gracias por todos tus videos, te felicito y espero que sigas cosechando muchos triunfos en tu vida.

Te quería hacer una pregunta, es este ejemplo la ganancia la calculas asi: k=delta Temp(C°)/delta voltios(v), es decir que tu ganancia en unidades queda expresada de la siguiente manera:: K=C°(grados centigrados)/v (voltios), por otra parte en el segundo ejemplo de control que controlas la velocidad de un motor utilizas k=delta PV(%)/ delta MV (%); y la ley de control en ese ejemplo la saturas en porcentaje, ahora bien mi pregunta es:
en este ejemplo tu saturas tu controlador en milivoltios, porque la ganancia no la tomas en milivoltios es decir: K = delta temp ( milivoltios)/delta vm (milivoltios), te agradecería mucho tu respuesta.

Responder

Hola Paola, gracias por tu comentário. En este ejemplo la temperatura tiene una relación directa con el voltaje, 25°C son 0.25V. En la época que hice el código estava pensando en la variación de temperatura con la entrada del sistema, hoy en dia no recuerdo mucho el código. Pero ahora que lo expones, queda mucho mejor trabajarlo en MV y es mucho más lógico. Voy a hacer los cambios y lo publico. Gracias por notar eso. Saludos y muchos éxitos.

Responder

Solo quería agradecer por la explicación, me ah servido de mucho, ahora se que un control, no solo es hacerlo, también si es para un uC se tiene que discretear (Cosa que no sabia) en serio muy buen vídeo y de nuevo gracias!

Responder

Gracias Andres, que bueno que te gustó. Saludos.

Responder

Ingeniero muy buenos días, quería hacerle un preguntica, he mirado los dos ejemplos de control PID, y quería preguntar porque en el primer ejemplo (en el que estoy comentando) el error esta entre 0 – 5000 milivoltios y luego lo satura a 1023 para sacar la salida del pwm, y en el segundo el error esta entre 0 -100 porciento, y ahí si lo satura a 100, quería preguntarle porque en el primer ejemplo el esfuerzo de control no se satura a 5000 y luego se escaliza a 1023, le agradezco mucho por su dedicación y su apoyo a nosotros, quedo agradecida

Responder

Hola Liliana, muy buena observación, realmente creo que en la época del código lo hice de esa manera para evitar que el controlador fuera conservador y llegara al setpoint mas rápido sin modificar la sintonia. Pero realmente pienso es mejor dejarlo como comentas tú, saturando en los 5000mV y luego escalando a 1000. Luego para cuestiones de velocidad es mejor hacerlo en los parámetros de sintonia. Voy a cambiarlo para dejarlo así. Saludos y muchas gracias.

Responder

Ingeniero buenos dias, queria pedir su ayuda porque se me ha presentado un inconveniente con mi director de la tesis, en primer lugar implemente el algoritmo de control que usted desarrollo, en MATLAB y no en pic, por otra parte el dia que el director de mi tesis vio el codigo me dijo que no era un control pid porque no se evidenciaban la integral ni la derivada del error y yo le respondi que se habia pasado al dominio S por medio de l’place como lo indica usted en la teoria anterior al codigo, y me dijo que porque el error no lo habia pasado al dominio S y no supe contestarte porque el error lo obtengo solamente de restar la lectura digital de matlab con el set point, Ingeniero ayudeme por favor

Responder

Hola Juan, en realidad lo que esta en el dominio complejo S de Laplace es el modelado del proceso para caracterizar el comportamiento dinámico del horno, pero el Control PID que estamos usando en esta entrada se hace en el dominio discreto usando la transformada Z que posteriormente para su implementación se expresa la ley de control en ecuaciones en diferencias. Todo viene de la teoria del control Digital, la integral del error es aproximada utilizando el método de integración trapezoidal que al final de cuentas termina siendo una suma, y lo mismo para la derivada la cual se hace con una resta del error en el tiempo actual menos el tiempo anterior dividido el tiempo de muestreo. Te recomiendo dar una estudiada en el concepto de control Digital para que tu tesis quede bien fundamentada en la revisión de literatura. Saludos.

Responder

Hola sergio, la verdad que son muy buenos tus videos. Tengo una incognita, quiero hacer un control PID para velocidad de un motor y tengo la duda de como hallar la Funcion de Transferencia de mi motor que viene a ser mi planta, espero de tu ayuda.

Responder

Hola Yvan, espero hayas visto las dos entradas de PID, ésta y la otra entrada que es la práctica del Motor – Generador así tendrás mas o menos las nociones para hacerlo. Para obtener la FT del motor, tendrias basicamente 2 opciones. 1- Es utilizando las ecuaciones fenomenologicas del motor (Ecuaciones diferenciales), realizando una linealización en el punto de interés, estas ecuaciones las puedes encontrar facilmente en google y la linealización la puedes ver en una de mis entradas (Aqui por ejemplo).
2- Puedes obtenerla igual que en el video Motor – Generador. Para eso tendras que medir la velocidad del motor (Aqui hay una entrada que te muestra como hacerlo con un encoder. CLICK ACA), puedes colocar una velocidad del 40% e identificar tu motor. La recomendación es que lo identifiques en la velocidad nominal en la que va a trabajar el motor.

Saludos y muchos éxitos.

Responder

hola sergio tienes idea de como realizar el dimmer para incorporarlo a pid que muestras en tu pagina’ por que he intentado de mil y una marera realizarlo en fisico y nada que me funciona (en fisico) ,,,, en proteus si me funciona a la perfeccion… tendras algun proyecto que hayas realizado en fisico ? por favor ayudame . yo trabajo con el pic 12f, 16 y 18f y ccs pic… no se si sera . se que como configurar el taimer a 8.33 ms en cada interrupcion y detectar el por flanco tanto de bajada como de subida en proteus funciona bien pero como te dije en fisico noda me anda ….. la ituminacion del foco da muchos saltos de intencidad. que materiales debo utilizar para esto que me recomiendas

Responder

QUISIERA SABER SI SE PUDE USAR ESTE MISMO CODIGO PERO EN VES DE UNA RESISTENCIA DE ESE TIPO USAR UNA FOCO Y UN LM35 GRACIAS

Responder

Hola Victor. Puedes hacerlo si. controla la intensidad del foco con un dimmer usando el pic, haciendo la detección por cruce por cero y utilizando la interrupción externa del pic. Y tu variable de control seria el angulo de disparo del triac en lugar del ancho de pulso del pwm. Tu sensor seria el LM35.

Responder

hola buenas tardes, muy bueno tu proyecto, lo implementare! solo tengo la duda de que sensor utilizar… me prodrias recomendar algo?

Responder

Un sensor fácil de utilizar y directo, seria un LM35, con él tienes un rango de medida hasta los 150°C.

Responder

hola sergio muchas gracias por compartir tus conocimientos tienes un muy buen canal .. yo quiero implementar la misma función del PID , pero en este caso con un bombillo de 127v a 100 watts con un sensor lm35 . para identificar el sitema. ¿que es lo mas recomendable hacer ?

1.-tomar mediciones con el foco alimentado directo a los 127 volts ? o reducir el voltaje con un dimmer y empezar a a tomar mediciones ?

Responder

Hola Abraham, lo mas recomendable para identificar tu modelo es disminuir la intensidad del bombillo, principalmente si consigues que este llegue a una intensidad que te proporcione mas o menos la temperatura a la que deseas operar. Tomar las mediciones y levantar tu modelo. Abrazos.

Responder

Hola Sergio, necesito tu ayuda hace mucho tiempo estoy tratando de arreglar el firmware de mi equipo pero no logro que funcione correctamente he migrado a pic16f887 pero no inicializa el lcd es decir no corre el firmware, pero en el proteus si lo hace perfectamente (ya he probado cambiando la frecuencia del reloj, los delays para la inicializacion del lcd todo y de todas las maneras posibles hasta hice 3 placas distintas. aca dejo la parte de configuracion

#include
#device *=16 ADC=10 ICD=true

#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
#FUSES NOPUT //Power Up Timer
#FUSES PROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //Reset when Brown Out Detected, BODEN en ic-prog o BROWNOUT en PCW (resetea el PIC si ve que la alimentación baja hasta casi 0V)
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES CPD //No EE protection
#FUSES NOWRT //Program memory not write protected

#use delay(clock=4000000)

#define LCD_DB4 PIN_D1
#define LCD_DB5 PIN_D0
#define LCD_DB6 PIN_C3
#define LCD_DB7 PIN_C2
#define LCD_RS PIN_D2
//#define LCD_RW PIN_B5
#define LCD_E PIN_D3

#include "flex_lcd_c.c"

#rom 0x2100={0xC8,0x00} // Variables temperatura deseada guardadas en eeprom. Primero va el valor alto y luego el bajo
#rom 0x2110={0X0F,0X00} // Variables tiempo deseado guardadas en eeprom.Primero va el valor alto y luego el bajo
#rom 0x2120={2} // Histeresis.
#rom 0x2130={0x64,0X00} // Variables calibracion deseada guardadas en eeprom.Primero va el valor alto y luego el bajo
#rom 0x2140={1}
// DECLARACION DE FUNCIONES
int16 leer_valor16(int16 posicion);
void guardar_valor16(int16 posicion,int16 valor);
int pulsador(void);
unsigned long adquisicion(void);

//DEFINICIONES
#define on output_high
#define off output_low
#define in input
#define toggle output_toggle
//DEFINICION DE PINES
#define Buzzer PIN_A3 //(15)
#define Rele1 PIN_A6 //(14)
#define Rele2 PIN_A7 //(13)

#define Switch1 PIN_B5
#define Mas PIN_C4
#define Menos PIN_C6
#define Temp_Tiempo PIN_C5

#include

void main()
{
// VARIABLES LOCALES
int8 menu=0; // seleccion de menu
unsigned long Temperatura=0; // Variable que contiene a la temperatura actual
unsigned long Tiempo=0; // Variable que contiene a el tiempo
unsigned long Temperatura_deseada=0; // Variable que contiene a la temperatura deseada
unsigned long Tiempo_deseado=0; // Variable que contiene a el tiempo deseado
signed int histeresis=0; // Variable que contiene a la histeresis de temperatura
unsigned int histeresis_deseada=0; // Variable que contiene a la histeresis deseada de temperatura
unsigned long Activar_Buzzer=0; // Variable que contiene a el tiempo deseado

// CONFIGURACION DEL MICRO
setup_adc_ports(sAN0 | sAN1 | sAN3);
setup_adc(ADC_CLOCK_DIV_32); // Configuro al reloj de conversion
setup_spi(SPI_SS_DISABLED); // Deshabilito el SPI
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1); // Configuro al TIMER0
setup_timer_1(T1_DISABLED); // Deshabilito al TIMER1
setup_timer_2(T2_DISABLED,0,1); // Configuro al TIMER2 para interrupciones cada 10 ms
setup_ccp1(CCP_OFF); // Deshabilito el modulo CCP
setup_comparator(NC_NC_NC_NC); // Deshabilito los comparadores

espero me puedas ayudar un abrazo Guido de Bs As

Responder

Hola Sergio buen día, muy interesante tu proyecto, no se si me puedas ayudar tengo un problema con un controlador C(Z)=4.778 (Z-0.154)(Z-0.945)/((Z-1)(Z-0.0136))=(U(Z))/(E(Z)), Pues obtuve esa ecuacion del matlab el problema es como hallaria mi ecuacion uk, para este controlador que es de segundo orden, por todos lados he encontrado para primer orden, y he visto para segundo orden pero no explican como llegar a la funcion uk para programar en el microcontrolador Pic,
Bueno te según un texto la solucion uk es igual a
uk = 1.0163*uk_1 – 0.0136*uk_2 + 4.778*ek – 5.2606*ek_1 + 0.7044*ek_2; // ecuacion diferencia del controlador.
Pero como llego a eso.

Responder

Alexander para eso debes estudiar transformada inversa Z, es la forma como transformas tu sistema discretos a un sistema de ecuaciones en diferencia. La transformada Z es basicamente lo mismo que la transformada de Laplace, solo que es para el dominio discreto. Debes tomar tu función de transferencia discreta, y expresarla en potencias negativas de z, y separa en un lado de la ecuación las u y en el otro lado las e, haciendo el producto de cada polinomio:
4.778*e(k) – 5.2606*z^-1*e(k) + 0.7044*z^-2*e(k) = 1*u(k)-1.0136*z^-1*u(k)+0.0136*z^-2*u(k)
Las potencias negativas Z, son retrasos en el tiempo k, donde el tiempo k es el tiempo presente, tiempo k-1 es un tiempo en el pasado, tiempo k-2 son dos tiempos en el pasado…
Por lo tanto la las potencias negativas entran en las variables e y u:
4.778*e(k) – 5.2606*e(k-1) + 0.7044*e(k-2)=1*u(k)-1.0136*u(k-1)+0.0136*u(k-2)
Ahora solo basta con despejar u(k) y se llega a la ecuación que mostraste. Saludos.

Responder

Muchas gracias Sergio tenias Razón he perdido tiempo llevando la tranformada inversa de Z por medio de potencias Positivas, Bueno para hacerlo mas fácil es verdad se lleva a Potencias Negativas y aplicar los Teoremas de retraso, y luego depejar uk. Gracias Sergio. Quedo aclarado mi duda Saludos éxitos.

Responder

Hola Sergio! Grandioso tu trabajo pero tengo una duda.
Estoy implementando tu control PID pero quisiera saber como conseguir que en el proceso de ascenso de temperatura dure 1 hora, es decir que mi proceso se tarde 1 hora en llegar al setpoint y que de igual manera lo haga proporcional.
Gracias y saludos

Responder

Hola Erick, cuanto se demora tu proceso en lazo abierto (sin controlador, solo energizando) se demora en llegar al estado estable?, no se si es más rápido o más lento que 1 hora que es lo que tu quieres. Si es más rápido no creo que tengas mucho problema, pues vas a diseñar el controlador de tal forma que atienda tu dinámica de 1 hora. Puedes utilizar la sintonia por asignación de dos polos reales (recomendado) o por cancelamento de polos. Colocando el parámetro de la constante de tiempo deseada TsMA=900 segundos. Ahora si tu proceso es mucho mas lento en lazo abierto, debes hacer exactamente lo mismo, aplicar cualquiera de las dos técnicas, solo que ahora va a depender de tu actuador, si tiene la capacidad de llegar al estado estable en dicho tiempo. Has los ensayos. Saludos.

Responder

hola sergi saludos.. hermano me podrias atudar o guiar en una tranca que tengo…. estoy realizando el pid que tienes en tu pagina, me he propuesto realizar el pwm para controlar una bombilla de 120 volt 100watt…. el pic que utilizo es el 16f877a a 20mhz , el moc3032…..no estoy utilizando detector de cruze por cero… pero no logro conseguir la etenuacion de la iluminocidad de la bombilla…. en ciertos momentos se atenua un poco y en otros brilla mas pero no es progresivo y parpadea mucho . como puedo solucionas esto por favos ayuuda

Responder

Hola Emely. Te recomendaria inicialmente configurar el pwm a parte. Sin el control PID, puedes manipular el ancho de pulso con un potenciometro y ver como se comporta la luminosidad de la lampara. Cuando consigas ajustar eso, puedes incorporarlo al proyecto de PID. Yo particularmente controlaría la intensidad con un dimmer con el pic, haciendo la detección por cruce por cero y utilizando la interrupción externa del pic. Y mi variable de control seria el angulo de disparo del triac en lugar del ancho de pulso del pwm. Saludos.

Responder

hola muy bueno los proyectos y muy bueno el aporte q realizas para los q estan interesados en microcontroladores tengo un problema estoy trabajando con el control pid con las entradas del sensor NTC de temperatura
— con la declaración de variables del sensor NTC (en el código) quiero q me ayudes se lo agradecería mucho….. muy bueno el aporte

Responder

Una duda disculpa, por que se estimula el horno entre el 10% y 20% de su valor nominal??

Responder

Es solo para identificar el proceso. En este caso por ser un proceso Lineal, no interesa mucho donde identifiques el proceso pues va a responder igual en todas partes. Para un proceso real, lo ideal es aplicar un escalón, que haga que la variable llegue mas o menos al punto donde nosotros generalmente vamos a trabajar nuestro proceso.

Responder

Buenas tardes profesor. Estoy haciendo RTL en SistemVerilog, un PID para el robot LEGO, basado en su código. Sin embargo, estoy teniendo problemas para Sintetizar en Quartus II Prime, el código de valores que son de punto flotante, como la derivada e integral. Tengo la punta para tratar de introducir los valores ya mencionados como enteros. Pero no puedo ver este formulario para introducir los valores ya como enteros. ¿Me ayudas con podeira algo que decir o el ejemplo que se puede hacer? Muchas gracias.

Responder

Bom dia Leandro, eu não entendi muito bem teu comentario em espanhol, principalmente a parte de “Tengo la punta para tratar de introducir los valores” e “Pero no puedo ver este formulario para introducir los valores ya como enteros”, pode escrever em português sem problemas.

Olha, o código visto nesta entrada mostra como vc pode implementar um PID, neste caso em linguagem C, mas tu podes utilizar a mesma logica em qualquer outra linguagem de programação. Podes trabalhar com variáveis do tipo float ou do tipo double no teu código. Boa sorte ai com teu projeto. Abç.

Responder

Gracias por la lección. ¿Podría ayudarme a decidir cual es la mejor opción para aplicar el PID en un LEGO® Education – Robótica? O 1) ó 2) o 3)? Si usted puede ayudar a darle las gracias también.

1)

//*************************************************************************//
//************* DISEÑO POR ASIGNACIÓN DE 2 POLOS REALES ****************//
//*************************************************************************//
/*
TsMA=4; //Tiempo deseado en Lazo Cerrado
Wn=3/(TsMA); //Frecuencia natural del sistema

//Ubicación de 2 Polos reales
P1=Wn+Wn;
P2=Wn*Wn;

kp=(P1*tao-1)/k; //Calculo de Kc
ti=(k*kp)/(P2*tao); //Calculo de ti
*/

2)

//*************************************************************************//
//***************** DISEÑO POR CANCELACIÓN DE POLOS *******************//
//*************************************************************************//
/*
TsMA=1; //Tiempo deseado en Lazo Cerrado
kp=(tao)/(TsMA*k); //Calculo de Kc
ti=tao; //Calculo de Ti (Igual a la constante de tiempo)
td=0;
*/

3)

//*************************************************************************//
//***************** SINTONIA POR ZIEGLER y NICHOLS *******************//
//*************************************************************************//

kp=(1.2*tao)/(k*theta);
ti=2*theta;
td=0.5*theta;

Responder

los 3 pueden funcionarte perfectamente, va a depender mucho del modelado de tu proceso. Yo personalmente me inclino más por el diseño entonces prefiero la asignación de polos. Pero son factores que tu debes experimentar. Saludos.

Responder

Gracias profesor. Gracias profesor. Su ayuda está siendo muy importante en mi proyecto.

Responder

muy buen trabajo gracias por compartirlo

Responder

Hola de nuevo Sergio. Sabes que avanze un poco en la realizacion de mi proyecto y tengo una duda y tendria todo listo para terminarlo por completo. Le quiero poner un SETPOINT variable con un POTE obvio y lo plantie asi al codigo:

El tema es que no puedo individualizar las entradas analogicas, o sea separar la entrada del LM35 y la entrada del POTE porque el PIC me toma las 2 juntas y al regular el pote se regula temperatura y el brillo de las lamparas, una macana, pero es asi.
Ayudame porfa con esto mas y creo que ya termino.
Y gracias por tu codigo y publicaciones que tanto me ayudaron hasta ahora a mi y a unos amigos que te recomende, jaja

Responder

Hola IRRA, bueno viendo el código que me mandaste, en realidad es mi código, solo adicionaste la lectura del potenciometro. Tu error es bastante notorio, una recomendación es darle un vistazo a la entrada donde explicamos la lectura análoga – digital en el siguiente link: http://wp.me/p5P46A-7K
Pues estás configurando erroneamente los puertos análogos. La forma correcta seria hacerlo asi, en una sola instrucción los puertos AN0 y AN1 (en formato Hexadecimal):

setup_adc_ports(0x03); //Configura los puertos AN0 y AN1 como ADC 

Y cuando vas a leer los datos, debes primero especificar que puerto análogo deseas leer.

set_adc_channel(0);          //Selecciono el canal 0 (AN0)
delay_ms(1);
adc=read_adc(); //Leer ADC
yM=adc*5000.0/1024.0;

set_adc_channel(1);          //Selecciono el canal 1 (AN1)
delay_ms(1);
adc2=read_adc();
sp=adc2*5000/1024

Con eso podrías solucionar tu problema. Inténtalo para ver como te corre. Saludos y éxitos en tu proyecto.

Responder

Hola de nuevo Sergio, y gracias porque lo que me pasaste me sirvio a la perfeccion.
Pero no solo te escribo para agradecerte, sino porque TENGO UN INCONVENIENTE.
Resulta que asi como me lo diste al codigo unido al mio funciona bien como dije antes, se puede variar el SETPOINT desde el POTE , el SENSOR LM35 tambien lee las temperaturas y se realiza el CONTROL PID correspondiente, estaria casi todo bien digamos y probado todo en la VIDA REAL.
Pero lo malo es que el SETPOINT se varia solo sin que yo mueva la perilla del POTE. Se varia unos cuantos grados para arriba y para abajo no manteniendose fijo, yendo y volviendo a ese valor definido, lo cual al ser un SETPOINT no resulta estar bien. Para mi algo tiene que ver la interrupcion o los tiempos DELAY entre lecturas.
Yo te queria consultar si podes ver el codigo que te mando y darme o ayudarme a encontrar una solucion. Te agradezco de antemano toda tu ayuda y amabilidad y simplemente seria darle esa solucion a mi proyecto y ya estaria completo y lindo para un 10, jaja.

Responder

Hola Irra, el problema que cuentas, es más de hardware que de software. Para que no tengas ese problema, reemplaza tu potenciometro, por un trimer (click aqui para ver imagen), que es un potenciometro pero de precisión, y este no va a variar como varia tu potenciometro. De seguro con esto puedes mejorar mucho tu problema.Comenta cualquier cosa. Saludos.

Responder

Hola Sergio, primero que nada, decirte que tienes un blog, muy completo y con información muy útil, el motivo de mi pregunta es la implementación de un control PID, usando el sensor DS18B20, quiero controlar la temperatura de un foco de 75W, mi duda es ¿Cómo puedo modelar el foco? para posteriormente utilizando alguno de los métodos que muestras obtener las constantes del PID, cabe mencionar que el control del foco lo estoy haciendo usando la técnica de control por fase para realizar una “PWM en AC”, de antemano agradezco tu atención.

saludos

Responder

Alan tienes que aplicar técnicas de identificación, ese es un tema que me han pedido bastante, pero no he tenido el tiempo de hacer las clases. Basicamente debes hacer lo mismo que se hizo con el OVEN, lo que debes hacer es mandar una señal con el PWM a tu foco, ojala cerca de la región que quieres trabajar, es decir si por ejemplo mandando un PWM del 60% tu foco hace que tu temperatura llegue digamos a 30°C y esa es más o menos la temperatura en la que deseas trabajar, seria perfecto. Asi al aplicar un escalón del 60% debes tomar el tiempo y la temperatura cada determinado tiempo, digamos cada segundo o dos segundos he ir almacenando esos datos, para al final generar la grafica de respuesta que se vió en el ejemplo del Oven, asi obtienes la ganancia, la constante de tiempo y el tiempo muerto con los cuales posteriormente podrás obtener los parametros del PID. En sintesis es basicamente hacer lo mismo visto en el ejemplo, solo que en tu caso es un bombillo.
Estoy preparando un video practico de un proceso simple real con PID, donde voy a mostrar como modelar el sistema y controlarlo con el PID, debo estar subiendo ese video en enero, pues ya me han preguntado bastante sobre este tema, y espero con esa practica quede un poco más claro el procedimiento. Saludos y muchos éxitos.

Responder

Hola Sergio, gracias por tu ayuda… entonces si entendí bien, para simular el proceso, puedo configurar el OVEN con los mismos parámetros q se vieron en el video y únicamente cambiaría la entrada escalón de acuerdo a la temperatura de trabajo que deseo ¿verdad?

Responder

Bueno, para configurar el OVEN igual a un bombillo, entra a las configuraciones y colocale 70W al oven, tambien debes saber cual es la máxima temp que alcanza el bombillo cuando lo dejas totalmente encendido y con base en ello tienes que hacer que el oven cuando esta totalmente encendido tambien llegue a la misma temperatura, eso lo logras modificando el voltaje del oven, poniendolo más bajo, talvez de esa forma puedas simularlo.

Responder

Hola, SERGIO. Che la verdad que te pasaste con tu post del PID y con los otros tambien que voy viendo. Yo quiero hacer casi lo mismo que vos hiciste que tanto me ayudo pero agregarle un COOLER o ventilador y que este funcione como enfriador en el sistema.
Se que tendria que armar otro control PID para el motor del cooler que es de continua de 12V, por eso te queria consultar si por algun lugar viste otro post tuyo o ajeno en donde realizen lo que te comente o algo parecido. Y si vos me podes responder obvio, como obtener una realimentacion de un motor DC del COOLER? de esa forma aplicarle el PID, asi como hiciste con el HORNO.
PD: Yo quiero usar un sensor LM35, un COOLER y una LAMPARA DE 12.

Responder

Irra, gracias por visitar la pagina, que bueno que te haya gustado. La verdad no conozco una pagina donde muestre algo de lo que quieres hacer, y no se como puedas obtener facilmente la realimentación del cooler. Yo veo tu problema más en la linea de un problema de control multivariable, (tendras que tener un poco más de conocimiento de control), propiamente tu problema seria un sistema MISO (Multi-Input Single Output, multiples entradas y una salida) tus dos entradas serian el cooler y la lampara, y tu salida seria la temperatura, lo que indica que es un sistema facil de controlar, pues tienes más grados de libertad para manipular tu temperatura. Es decir que solo debes realimentar con el LM35 los 2 PID. Primero debes identificar la temperatura con el bombillo (funcion de transferencia) y luego con el cooler, tendras entonces dos FT, una que relaciona la entrada 1 con la salida, y la otra la entrada 2 con la salida. Te recomiendo des una estudiada en control multivariable, para que hagas tu proyecto. Saludos.

Responder

parcero.

sin comentarios, la verdad es lo mismo que te dije en el control predictivo era lo que estaba buscando, muy completo el vídeo, muy completa la explicacion.

solo resta por decir gracias.

Att: emerson palacio

Responder

Hola Sergio, como puedo cambiar el valor del setpoint y poder mostrarlo en la pantalla LCD? por ejemplo un setpoint de 100.
De antemano gracias por la información.

Responder

El SetPoint ya se esta mostrando en la pantalla LCD en este ejemplo. Para ponerlo en 100, debes colocar la variable R=1000;

Responder

gracias
Saludos

Responder

QUE TAL SERGIO, PRIMERO QUE NADA TE FELICITO POR TU BLOG, ESTA MUY BIEN PENSADO Y MUY COMPLETO… ESTE PROYECTO EN PARTICULAR ESTOY REALIZANDOLO PARA DESPUES ADAPTARLO A CON CONTROL DE MOTOR PWM; PERO UTILIZANDO EL PIC18F2550, AUNQUE NO ENTIENDO PORQUE NO PUEDO HACERLO FUNCIONAR CON EXITO. YA CAMBIE LOS PARAMETROS DEL ENCABEZADO, SIN EMBARGO SIGUE SIN DARME RESPUESTA, PODRIAS AYUDARME? AQUI TE DEJO MI ENCABEZADO PARA VER SI TU ME PUEDES SEÑALAR EL ERROR, SI ES QUE ÉSTE SE ENCUENTRA EN AHI:
#INCLUDE
#DEVICE ADC=8
#USE DELAY(CLOCK=4000000)
#FUSES XT,NOPROTECT,NOWDT,NOBROWNOUT,PUT,NOLVP
#include
//Configura direccion de memoria de los puertos A,B,C,D
#BYTE PORTA=0xF80
#BYTE PORTB=0xF81
#BYTE PORTC=0xF82

basicamente es todo lo que eh cambiado en el programa, me guie por un post de otro usuario en donde te respondiste que unicamente teniamos que cambiar el encabezaddo…
Te agradesco de antemano, espero puedas ayudarme.

Responder

Hola Miguel. Para ese PIC que es más pequeño, pues tiene menos puertos, está correcto tu ebcabezado.
#INCLUDE<18F2550.h>
#DEVICE ADC=8
#USE DELAY(CLOCK=4000000)
#FUSES XT,NOPROTECT,NOWDT,NOBROWNOUT,PUT,NOLVP
#include
//Configura direccion de memoria de los puertos A,B,C,D
#BYTE PORTA=0xF80
#BYTE PORTB=0xF81
#BYTE PORTC=0xF82

Debes ver como no tienes puerto D, debes cambiar la posicion del LED, del ejemplo, o simplemente coloca esas lineas en comentario.
//output_toggle(pin_d0);
//set_tris_d(0);

tambien se modifica la forma como se configura la entrada analoga del PIC, que en este caso estamos usando solo el puerto A0 como entrada analoga:
setup_adc_ports(AN0);

Saludos

Responder

Hola Sergio muy lindo tu trabajo, quería consultarte como haces en mikroc el desbordamiento del timer 0. Saludos y éxitos.

Responder

Hola Cristina, la verdad nunca he usado mikroc, entonces no sabría responderte, imagino yo debe ser muy similar al picc, de igual forma, para generar el periodo de muestreo puedes hacerlo también con retardos o con delays, que también te podría funcionar perfectamente.

Responder

Sergio buen dia molestandote de nuevo.
Disculpa la pregunta. Que condiciones empleas para caracterizar una resistencia AC, me refiero a temperatura, humedad, etc. Lo que sucede es que mi proyecto es una cuna termica de calor radiante, el sensor de temperatura que mide la temperatura de piel del bebe esta a un metro de distancia de la resistencia calefactora y se encuentra abierto, lo que implica que las condiciones de la temperatura ambiente le afectan, por eso preguntaba, si cuando tu caracterizas una resistencia calefactora, empleas algunas condiciones para hacer la caracterizacion los mas precisa posible. DE ANTEMANO GRACIAS.

Responder

Para indentificar el modelo de cualquier proceso existen diferentes técnica. En este caso hicimos una identificación del horno a través de una curva de reacción. Lo más conveniente es que comiences a leer y estudiar sobre identificación de sistemas. Puedes emplear un metodo parametrico para determinar tu modelo. Lo ideal es que lo identifiques en un punto de operación y si tienes la posibilidad de leer las otras variables como la temperatura exterior o la humedad, puedes realizar un controlador FeedForward. La tematica de identificación de procesos es bien interesante y estoy pensando incluirla en el blog. Es mucho tema que me gustaria abordar aqui, pero lastimosamente no tengo disponibilidad exclusiva para montar todo. En unos años espero tener el blog con bastante información. Saludos.

Responder

Hola sergio. Una pregunta
Como obtendrias la ganacia K del sistema para una resistencia calefactora de CA dado que como sabemos la ganancia K se calcula con la formula: k=(Yfinal-Yinicial)/(Ufinal-Uinicial).
Como obtendria los valores de Ufinal y Uinicial, hablando de una resistencia calefactora que se le aplica Corriente Alterna.
Gracias

Responder

Hola Julio. Ese calculo es sumamente parecido con el ejemplo que vimos en esta entrada. En tu caso como tienes una resistencia que digamos está conectada a 120VAC. Tu necesitaras regular la potencia de tu resistencia, para eso lo mas conveniente es usar un Relé de Estado solido, que en la entrada sea de 3VDC – 32 VDC y que la salida sea de 24-380 VAC. Este rele de estado solido debes conectarlo en Serie en tu resistencia y NUNCA en paralelo. Ahora con la salida del PWM del micro lo conectas en la entrada del relé de estado solido. Y por programación puedes colocarle al micro que envie un PWM (1Khz por ejemplo) con un duty cicle del 20%. De esa forma el Relé de estado solido va a swichear rapidamente regulando el voltaje q entra en tu resistencia. Aqui tu Ufinal seria 20 y tu Uinicial=0. De hecho en este ejemplo se podia haber hecho lo mismo con el Mosfet, simplemente pondria el PWM en un ciclo de dureza continuo (duty cicle) en 20% por ejemplo y calculaba la K, para este caso ya no se trabajaria con el U en voltaje, si no que se trabajaria en porcentaje (Ufinal=20, Uinicial=0). Saludos.

Responder

Muy amable por tu asesoria sergio, es que aun sigo con mi proyecto y no me queda, pero voy a obtener el valor de K asi como me comentas. De antemano mil gracias

Responder

felicidades sergio, excelente aporte.
Oye mira te queria hacer unas preguntas, estoy desarrollando un control de temperatura de una resistencia calefactora de CA.
1.- si le aplico un pwm entre el 10 y 20% a esta resistencia alcanzo un temperatura maxima de 36,4 °C, pero yo requiero poder controlarla hasta 39 °C, algo que solo consigo si le aplico el maximo pwm 100% Ciclo de Trabajo, ¿debere caracterizarla aplicando Uinicial=0% y Ufinal=100%? utilizo un pwm de frecuencia igual a 3 Hertz.
2.- tu que me recomiendas¿Controlarla controlarla con un PWM bajo por ejemplo 1Hz o un pwm alto como segun comentaste anteriormente 1000 Hz?
3.-segun he leido, se debe aplicar entre el 10 y el 20% del valor nominal para caracterizarla, significa que debo aplicar entre el 10 y 20% del ciclo de trabajo de mi pwm para caracterizarla?
4.- el valo de la K se obtiene K=(Yfinal-Yinicial)/(Ufinal-Uinicial), los valores de Ufinal y Uinicial tomando el porcentaje de ciclo de trabajo por ejemplo: Ufinal=15% y Uinicial=0%, o se toma la enegia que le llega a la resistencia durante el lapso de tiempo que se aplican los impulsos por pwm, es decir segun la formula U=Voltaje*Corriente*tiempo?

De antemano mil gracias

Responder

Hola Julio, gracias por visitar la pagina y por aportarle al lector joao un codigo PID. En cuanto a tus preguntas te cuento algo. Es bastante preocupante que tu resistencia llegue a la temperatura que deseas al 100% del PWM, eso demuestra que tu resistencia NO está dimensionada para tu proceso y lo más recomendable sería cambiarla. Pues piensalo asi, no tiene sentido colocar un controlador para que el trabaje todo el tiempo en 100%, para eso, simplemente conectas la resistencia directamente. Obviamente perderas todas las ventajas de un control por realimentación, como es el caso del rechazo de perturbaciones, pero de igual forma ese rechazo será imposible pues tu control no tiene más acción para rechazar nada.

2. Yo trabajaria con un PWM de 1Khz.

3. Si ya sabes el punto de trabajo donde quieres trabajar, puedes identificar el proceso en ese punto, osea en tu caso seria un escalón de 0° hasta 39°.De esa forma tendras un modelo linealizado en el punto que vas a trabajar.

4. Uinicial será 0y el Ufinal será el voltaje que le entre a la resistencia en el escalón de 39° de temperatura, igual que en el ejemplo. Donde y es temperatura y u es voltaje.

Espero puedas realizar tu control. Un saludo y muchos éxitos.

Responder

Que es convertir este programa para mikroC

Responder

Olá João, na real eu nunca utilicei o mikroC, mas acho que não deve ser muito diferente do PICC, a ideia é utilizar a mesma logica, só que utilizando os comandos do mikroC. Obrigado por visitar o Site, tomara tu consigas modificar o codigo para o mikroC. Grande abraço.

Responder

ola Joao, te envio el codigo que implemente en mikroC pro for pic, funciona al cien. saludos
el codigo es el siguiente:

//******************************************************************************************************************
int valor, control; //Variables para lectura de ADC y señal de Control a modulo CCP
float coef_a,coef_b,coef_c; //Constantes para parámetros de controlador PID
float TEMPERATURA_LIMITE; //Referencia de Temperatura
float rt,eT,iT,dT,yT,uT,iT0,eT0; //Variables de controlador PID
float max1,min1; //Variables para anti-windup

void main()
{
ADCON1=0b10000000;
TRISC=0;
TRISA=0xff;

min1=0.0;
max1=1000.0;
iT0=0.0;
eT0=0.0;
coef_a=0.1243;
coef_b=0.0062;
coef_c=0.6215;

TEMPERATURA_LIMITE=800.0; //Set Point r(kT)= 120°C
PWM1_Init(1000);
PWM1_Set_Duty(0);
PWM1_Start();

while(1)
{
valor= ADC_Read(0); //Leer ADC
yT=5000.0*valor/1024.0; //Escalizar señal de salida y(kT)
rT=TEMPERATURA_LIMITE;
eT=rT-yT; //Calcular senal de error e(kT)
iT=coef_b*eT+iT0; //Calcular termino integrativo i(kT)
dT=coef_c*(eT-eT0); //Calcular termino derivativo d(kT)
uT=iT+coef_a*eT+dT; //Calcular senal de control u(kT)
if (uT>max1)
{ //Anti-windup
uT=max1;
}
else
{
if (uT<min1)
{
uT=min1;
}
}
control=uT;
PWM1_Set_Duty(control);
iT0=iT;
eT0=eT;
delay_ms(100); //Periodo de muestreo T=0.1s
}
}
//******************************************************************************************************************

Responder

solo una observacion, essolo el codigo para el pid,no despliega valores en un LCD. Espero te sirva dealgo. saludos

Responder

Hola oye poseo el modelo de un motor dc pero solo en velocidad al parecer al integrar se obtiene posición, pero como sintonizas porque estaba viendo y la respuesta en posición al integrar es una linea recta que método usarías tu?

Responder

Hola Nelson. Al agragar una integral a tu modelo para obtener la posición. Tu modelo se transforma en un modelo de tipo 1, debido a la acción integradora y tu respuesta va a ser una linea recta en forma de rampa. Si tu idea es que tu sistema siga un escalón, simplemente por causa del principio del modelo interno que vimos en esta entrada, puedes sintonizar un controlador proporcional únicamente. Claro está, si lo deseas puedes aplicar un PI, claro que no es necesario dado que tu proceso ya tiene la acción integradora, para este caso, yo sintonizaría un PI por asignación de polos. Pero vuelvo y te digo, la forma más sencilla de controlar procesos integradores es colocando una simple ganancia en el controlador (Control Proporcional). Saludos.

Responder

Gracias por tu pronta respuesta.

Esperamos el vídeo que comentas sobre adquirir datos del sistema para obtener el modelo.

¡Mucha suerte y mil gracias!.

Responder

Un saludo Sergio.

Requiero hacer el control PID, pero en lugar de utilizar un Mosfet utilizare un Triac, ya que el control sera por angulo de fase.

Como sé que la tensión de C.A. es de 127 Volts, entonces, para modelar la planta voy a aplicar un escalón al 19% de la tension de C.A. (127 Volts) que seria 24 Volts de C.A.

¿Esto es correcto esto?. ¿Se puede escalar de esta manera la tenscion de C.A. para el modelo de la planta?.

Responder

Hola Manuel, gracias por visitar la página. Con respecto a tu pregunta no puedes hacerlo como estas comentando. Como estas trabajando con CA, y como vas a usar un Triac, aqui tu triac en tu circuito de potencia, está funcionando como un Switche, y él deberia ser activado por la señal de PWM del PIC. Es decir que si aplicas una señal del PWM máxima, el triac estaria como switche abierto y dejaria pasar todo el voltaje. Ahora, si vas a aplicar el escalón de 19%, debes es aplicarlo en tu PWM y no en el voltaje. Es decir, tu voltaje siempre será el mismo 127V, la regulación que estas haciendo va a venir desde el triac, cuando le mandas al triac un PWM del 19%, el solo va a permitir que el voltaje entre en ese corto periodo de tiempo a tu sistema, asi tu variable solamente va a variar segun el voltaje limitado que le estas ingresando. En ese tiempo puedes tomar datos y generar la curva que represente la dinamica del proceso, o aplicar alguna tecnica de identificación. Puedes visitar la sección donde explico el PWM. Yo por ejemplo, crearía un PWM de 1Khz, asi mi valor de PWM para ser máximo segun explico aqui(https://controlautomaticoeducacion.com/15-pwm-ancho-por-modulacion-de-pulso/) seria
set_pwm1_duty(1000);
ahora para realizar la identificación, simplemente colocaria en el ciclo infinito un porcentaje del valor máximo, por ejemplo:
set_pwm1_duty(200);
y tomaria los datos de mi variable. Más adelante haré un video enseñando a hacer una tarjeta de adquisicion de datos, para que aprendan a tomar datos con el pic y a obtener el modelo. Abrazo.

Responder

Un saludo amigo, muy didáctico tu post y el video en YouTube.

Solo me queda una duda:

Según la configuración del horno, el acondicionamiento de señal y el escalamiento de la lectura del ADC, el valor de yM obtenido es 10 veces mayor a la temperatura del horno, la variación de 25 °C a 132 °C, provocaría una variación en yM de 250 a 1320, según esto el valor de K sería K=(1320-250)/(2-0)=535 en lugar de 53.5 que usas en el programa del microcontrolador.

Responder

Hola Edgar. La identificación de la planta consiste en determinar la ecuación matemática que describa el comportamiento dinámico del sistema independientemente del método o del dispositivo que vamos a usar para controlar. Es decir, que la identificación es una cosa y el escalamiento de la lectura ADC es otra. En este ejemplo, estoy intentando modelar el comportamiento de la variable temperatura y no la señal del sensor (que está en mili-voltios), siendo así, se debe colocar 132 grados celcius – 25 grados celcius para que me de la ganancia del sistema en grados celcius por voltio. Osea que si mi sistema le aplico un voltaje con en el ejemplo de 2 voltios, el horno debe llegar a 132 grados celcius en estado estacionario partiendo desde el reposo (25 grados) y no a 1320 grados. Saludos y gracias por visitar la pagina.

Responder

Gracias por responder Sergio C.

Solo una pregunta en el minuto 19:42 del video hablas acerca del retardo θ, al cual diste un valor de 1 por lo rápido que gráfico la respuesta en el proteus, mi pregunta:

¿En un sistema real ese θ quiero suponer que lo obtengo apartir de energizar el sistema y hasta cuando termina θ?.

Una disculpa Sergio, quizás no capto las ideas tan rápido, pero tampoco me gusta quedarme con incógnitas. Me sera de gran ayuda el saberlo..

Responder

Hola Manuel, efectivamente en la simulación para no hacerla muy larga el retardo θ es de 1. Ahora para un sistema real, no va a ser asi, principalmente en procesos tan lentos como la temperatura. Entonces, te doy el ejemplo de un horno real. Si tu tienes un horno que esta a temperatura ambiente 25°C, tu lo energizas y comienzas obviamente a tomar los datos de temperatura cada determinado tiempo (Tiempo de muestreo) por decir algo comienzas a tomar cada 5 segundos datos de temperatura. Podrás observar que al cabo de los primeros 5 segundos el horno continuara en 25°C, luego a los 10 segundos, posiblemente seguirá en 25°C, luego a los 15 segundos continua en 25°C, luego a los 20 segundos ves que la temperatura subió a 26°C, osea que ya comenzó a moverse debido a que energizaste el horno. Osea que el horno se demoró 20 segundo en comenzar a reaccionar después de energizado, quiere decir que tiene un θ=20 segundos. En otras palabras el retardo es el tiempo que le toma al proceso en comenzar a reaccionar después de que tu lo estimulas, por ejemplo en este caso después de que tú lo enciendes.

En la industria hay muchas variables que podemos controlar, y muchas veces vamos a tener proceso que responden instantáneamente, es decir que tendrán un θ=0.

Responder

Muy buena explicación.

Es justa la respuesta a mi pregunta, seguimos atentos a tu paguina y publicaciones para seguir aprendiendo de ti. Gracias.

Responder

Buena aportacion en el mundo de automatizacion todo un experto el ing sergio.
Donde saco la bibliografia del control pid que implementamos en este curso.
busque por muchos lados referencias y ninguno encontre.
por favor podria dar la referencia… sera mucha ayuda gracias.

Responder

📚 Bibliografía:
[1] Control Digital, Teoría y Práctica 2Ed – Luis Eduardo García Jaimes, Medellín 2009
[2] Ogata, Katsuhiko. Sistemas de control tiempo discreto. Prentice Hall, 1996 D. F. México, 2a Edición

Responder

Un saludo Sergio Castaño, tienes unos vídeos excelentes y muchas gracias por compartirlos. Yo soy estudiante y me son de gran ayuda ahora que empiezo a estudiar acerca del control PID.

Me gustaría saber si puedes compartir el vídeo en físico de un PID de temperatura implementando un microcontrolador PIC.

Responder

Hola Manuel, gracias por visitar mi pagina. Que bueno que te sirvan los videos. Por ahora montar uno físico me queda imposible, pues no dispongo de mucho tiempo libre y en este momento ando con otros proyectos. Ya anteriormente he montado varios PID en microcontroladores, he incluso coloque algunos en procesos industriales. A mi siempre me ha funcionado y trabaja muy bien. Monta el tuyo y practica 🙂 Una recomendación importante es en cuanto al Sensor, te debes antes que nada cerciorarte de obtener una buena medición de tu proceso, porque si no tienes una buena medición, tu controlador se va a enloquecer intentando controlar la variable. Saludos y muchos éxitos.

Responder

Gracias Sergio, sigo de muy atento esta página con tus publicaciones. Entiendo tu respuesta. Gracias nuevamente por compartir y grandes exitos.

Responder

Excelente trabajo Sergio, pero tengo dos preguntas
1.- Como sacas al ecuación de transferencia del horno
2.- Tienes alguna información para entender un poco mas a detalle la ley de control PID discretizado indicada en el tutorial.
Gracias y en verdad muy buen aporte.

Responder

Hola Gabriel, mira para la funcion de transferencia, se utiliza la grafica generada por el horno en lazo abierto, puedes ver el video a partir del minuto 17. Aqui hayas los tres parametros que necesitas. La ganancia (K), la constate de tiempo (tao) y el retardo (theta).

La ley de control discreta se obtiene a partir de la función de transferencia discreta del PID:

De esa ley de control discreta, debes despejar el u(k) de la ecuación y luego aplicar transformada inverza Z. Mas adelante podría hacer un video sobre esto.

Responder