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.