vale
//***********Parámetros de posprosesador************************************
#include <16f876A.h>
#device adc=10
//#device ICD=true
#FUSES xt,nowdt,noprotect
#USE delay(clock=4000000)
#define use_portb_lcd TRUE
#include <LCD.C>
#use standard_io (A)
#use standard_io (B)
#use standard_io (C)
//#use RS232(baud=9600, XMIT=pin_C6, RCV=pin_C7, bits=8, parity=N)
#use SPI(MASTER,FORCE_HW,MODE=0,BITS=16)
//****************************Definición de pines**********************************
#define CS PIN_A5
//******************************Variables Globales***********************************
int16 temp=0,buffer=0;
int segundos=0,minutos=0;
long milisegundos=0;
float temperatura_total=0.0;
int1 flag_cronometro=0;
int1 flag_max6675=0;
int1 flag_timer0=0;
int1 flag_limpiarlcd=0;
float temperatura;
int i;
float media[5];
//----variables globales PID------------
int16 control=0;
float a,b,c;
float temp_limit;
float rT,eT,iT,dT,uT,iT0,eT0,yT;
float max,mini;
//****************************Funciones***********************************************
void max6675();
//***************************Interrupciones de los timers**************************
#int_TIMER1
void cronometro(){ //implemetamos un cronómetro en el timer1
set_timer1(64500);
if(++milisegundos > 999){ //Decrementamos milisegundos hasta que sea mayor que 999
milisegundos = 0; //cargamos milisegundos con el valor 999 para un proximo conteo
flag_cronometro=1;
}
if((milisegundos==200)||(milisegundos==400)||(milisegundos==600)||(milisegundos==800)||(segundos == 999)){
flag_max6675=1;
}
if(milisegundos==500){
flag_limpiarlcd=1;
}
}
#int_TIMER0
void timer0_isr(){
flag_timer0=1; //Bandera que marca el tiempo para el PID
}
//****************************Inicialización**************************************
//******************************Subprogramas************************************
void limpiarlcd(){
lcd_putc('\f');
}
void inicio(){
int g;
set_pwm1_duty(0);
for(g=0;g<5;g++){
lcd_gotoxy(3,1);printf(lcd_putc,"Iniciando");
lcd_gotoxy(4,2);printf(lcd_putc,"Sistema");
max6675();
delay_ms(300);
lcd_putc('\f');
delay_ms(300);
}
}
void max6675(){ //leemos el dato de temperatura desde el max6675
int h=0;
int cadena1,cadena2; //delacramos las bariables donde se guardaran el dato que viene del max6675
//el dato viene en dos paquetes separados de 8 bits, por eso se guardan en dos cadenas
output_low(CS); //Se activa la señal de bit_select(CS) a 0 para que el max se active
cadena1 = spi_read(0); //Lee el primer byte que viene del max6675
cadena2 = spi_read(0); //Lee el segundo byte, con eso ya tenemos los 16bits de la lectura del max7765
output_high(CS); //Se pone a 1 la señal de bit_select(CS) para que el max tome otra lectura
// buffer = ((cadena1 * 256) + cadena2); //Se unen las dos cadenas de 1 byte que viene del max6675 y se
//guardan en una variable int16 llamada buffer de 16 bits
buffer = cadena2; // Cargo Byte LB
*((char *)&buffer+1)=cadena1; // Cargo Byte HB. y los uno los dos en una palabra de 16 bits que se llama buffer
if(bit_test(buffer,2)==1){ // Si el bit D2 es igual a 1
lcd_putc('\f'); //Limpiamos la pantalla LCD
lcd_gotoxy(5,1); //Posición del LCD para imprimir el siguiente comando
printf(lcd_putc,"Termopar"); //Se muestra en pantalla que el termopar está desconectado
lcd_gotoxy(3,2);
printf(lcd_putc,"Desconectado"); //Se muestra en pantalla, en la posición 3,2
}
temp = (buffer & 0b0111111111111000)>>3; //Seleccionamos los bits que nos interesan haciendole lo que se llama
//Una máscara, se le hace un AND al dato con un numero en binario, los unos significan los bits que queremos utilizar y los 0 los que desechamos
//Luego le haqcemos un >>3 que significa que rodamos los 1 a la derecha 3 posiciones para eliminar los 0 del final
temperatura = (temp * 0.25); //la resolucion de los 12 bit es de 0,25ºC por bit, 12 bits en decimal equivalen a 4095, para que de los 1023,75 ºC se multiplica 4095 * 0,25 = 1023,75ºC
/* media[i]=temperatura; //cargamos el array con las medidas tomadas por el max6675
i++; //incrementamos la varibale i en cada bucle
if(i==5){ //hasta que el buffer no esté lleno, no se hace la media
temperatura_total=((media[0]+media[1]+media[2]+media[3]+media[4])/5);
}
if(i==6){ //si i llega a 5, ponemos i a 0 para una nueva medida
// for(h=0;h<6;h++){
// media[h]=0; //cargamos el array con 0
i=0;//ponemos a 0 la i para una nueva carga del array
// }
} */
}
void PID(){
yT=temperatura;
rT=temp_limit; //Temperatura límite o setpoint
eT=rT-yT; //Calculo del error
iT=b*eT+iT0; //Cálculo del termino itegral
dT=c*(eT-eT0); //Cálculo del termino derivativo
uT=iT+a*eT+dT; //Cálculo de la señal PID
//******Anti-Windup***************
if(uT>max){
uT=max;
}
else{
if(uT<mini){
uT=mini;
}
}
//****fin anti-windup***************
control=uT;
set_pwm1_duty(control); //Transferencia de uT al actuador
iT0=iT;
eT0=eT;
}
//******************************Función Principal*********************************
void main(){
setup_spi(SPI_MASTER | SPI_L_TO_H); // Configuramos el SPI por hardware del micro, sin esto no rula
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32);
set_timer0(56);
enable_interrupts(INT_TIMER0);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); //Configuración del timer1 para el cronómetro
set_timer1(64500); //cargamos el valor del timer1 para que salte a 1 mls
enable_interrupts(INT_TIMER1);
// setup_timer_2(T2_DIV_BY_16,255,1); //configuración del timer_2 para la señal PWM
setup_timer_2(T2_DIV_BY_4,249,1);
setup_ccp1(CCP_PWM); //Activamos el CCP ósea PWM por hardware
enable_interrupts(global);
lcd_init();
inicio();
//-----------------Control PWM----------------------------------------
mini=0.0; // límite mímimo de control de la PWM
max=1000.0; // límite máxima de control de la PWM
//-----------------Parámetros PID----------------------------------------
iT0=0.0;
eT0=0.0;
a=1.0; //Parámetro para el termino proporcional
b=0.006215; //parametro para el termino integral
c=10.000; //parametro para el termino derivativo
temp_limit=100.00; //set point 100ºC
//---------------------------------------------------------------
while(TRUE){
if(flag_cronometro){
flag_cronometro=0;
if(++segundos > 59){
segundos = 0;
if(++minutos > 59){
minutos = 0;
}
}
}
if(flag_max6675){
flag_max6675=0;
max6675();
}
if(flag_timer0){
flag_timer0=0;
PID();
}
if(flag_limpiarlcd){
flag_limpiarlcd=0;
limpiarlcd();
}
lcd_gotoxy(1,1);printf(lcd_putc,"Temp=%f C",temperatura);
lcd_gotoxy(1,2);printf(lcd_putc,"%02u:%02u",minutos,segundos);
lcd_gotoxy(6,2);printf(lcd_putc," PWM=%Lu",control);
}
}