#include <16F877a.h>
#device adc=10
#use delay(clock=4000000)
#fuses XT,NOWDT
#define WireTX PIN_C6
#define WireRX PIN_C7
#use rs232 (baud = 9600, xmit=WireTX, rcv=WireRX, ERRORS, STREAM=serial)
#USE TIMER(TIMER=1,TICK=1ms,BITS=16,NOISR)
int16 valor; //lectura de temperatura
int control; //valor del PWM
double temp_limit; //temperatura a alcanzar
double rT,yt; //variables de ecuaciones
double out = 10;
double errSum, lastErr;
double kp, ki, kd;
int16 sampletime = 1000;
unsigned int16 current_tick, previous_tick;
unsigned int16 tick_difference(unsigned int16 current, unsigned int16 previous)
{
return(current - previous);
}
void Compute()
{
current_tick = get_ticks();
if(tick_difference(current_tick, previous_tick) > SampleTime)
{
previous_tick = current_tick;
/*Compute all the working error variables*/
double error = temp_limit - yT;
printf("\n\rerror: %f",error);
errSum += error;
printf("\n\rerrSum: %f",errSum);
double dErr = (error - lastErr);
printf("\n\rdErr: %f",dErr);
/*Compute PID Output*/
out = kp * error + ki * errSum + kd * dErr;
printf("\n\rout: %f",out);
/*Remember some variables for next time*/
lastErr = error;
printf("\n\rlastErr: %f",lastErr);
}
}
void SetTunings(double Kp, double Ki, double Kd)
{
double SampleTimeInSec = ((double)SampleTime)/1000;
kp = Kp;
ki = Ki * SampleTimeInSec;
kd = Kd / SampleTimeInSec;
}
void SetSampleTime(int NewSampleTime)
{
if (NewSampleTime > 0)
{
double ratio = (double)NewSampleTime
/ (double)SampleTime;
ki *= ratio;
kd /= ratio;
SampleTime = (unsigned long)NewSampleTime;
}
}
void main()
{
current_tick = previous_tick = get_ticks();
printf("\fReady...\n");
kp=80.75; //constantes del PID
ki=3.375;
kd=150.375;
temp_limit=0.33; //Temperatura a alcanzar
setup_timer_1(t1_internal|t1_div_by_1);
setup_timer_2(t2_div_by_16,249,1); //periodo de la señal PWM a 1ms
setup_ccp1(ccp_pwm); //Módulo CCP a modo PWM
setup_adc_ports(all_analog); //Puerto A analógico
setup_adc(ADC_CLOCK_INTERNAL); //reloj convertidor AD interno
set_adc_channel(0); //Lectura por el canal 0
delay_us (20);
while(true)
{
valor=read_adc(); //Lectura de la temperatura
printf("\n\rAD: %lu",valor);
yT=valor*5.0/1024.0; //conversión a mV (0.25V a 250mV)
printf("\n\ryt: %f",yT);
rT=temp_limit;
SetTunings(kp,ki,kd);
compute();
control = (int)(out);
printf("\n\rcontrol: %u",control);
set_pwm1_duty(control);
//delay_ms(10); //Tiempo de muestreo
}
}