hola a todos, les cuento que me he decidido a realizar un control PID en pic16f877a para un carrito con pendulo invertido (mi primer controlador digital), ya que el profe que me da clase de control digital dice que esa materia es solo teorica y que no es para estar haciendo proyectos y demas cosas, bueno... volviendo al tema, realice el codigo en CCS COMPILER y aunque tuve muchas dificultades logre hacer algo, al armar todo y conectar el pic el carrito empezaba a tambalear tan pronto le aplicaba una perturbacion y aunque unas cuantas veces intento estabilizarse, la mayoria de las veces o el programa se perdia o el carrito oscilaba tanto que era imposible volver a la posicion de equilibrio.... por eso acudo a ustedes con el animo de encontrar respuestas a mis dudas, adjunto el codigo en CCS, disculparan el programita ya que es mi primer controlador y no tengo muy claras las ideas.. una cosa es la teoria y otra cosa es la practica.... de antemano muchas gracias.
#include <16F877a.h>
#device adc=10
#use delay(clock=4000000)
#fuses XT,NOWDT,NOPUT,NOLVP,NOBROWNOUT,NOWRT,NOPROTECT,NODEBUG
#include <lcd.c>
int start=0;
int kp,Ti,Td;
float T=0.001;
int16 valor;
int16 control; //valor del PWM
float a,b,c;
float rT,eT,iT,dT,yT,uT;
float iT0=0.0;
float eT0=0.0; //variables de ecuaciones
float max=1020.0;
float min=-1020.0; //límites máximo y mínimo de control.
#INT_EXT
void inicializacion(){
set_adc_channel(0);
delay_us(150);
rT=5.0*(read_adc())/1024.0;
a=500;
b=1000;
c=1;
start=1;
control=0;
output_high(PIN_C0);
setup_ccp1(ccp_pwm); //Módulo CCP a modo PWM
setup_ccp2(ccp_pwm); //Módulo CCP a modo PWM
}
void main ( )
{
rt=a=b=c=0;
set_tris_c(0);
set_tris_b(255);
set_tris_b(255);
setup_timer_2(t2_div_by_16,255,1); //periodo de la señal PWM a 1ms
setup_ccp1(ccp_off); //Módulo CCP a modo PWM
setup_ccp2(ccp_off); //Módulo CCP a modo PWM
setup_adc_ports(all_analog); //Puerto A analógico
setup_adc(ADC_CLOCK_INTERNAL); //reloj convertidor AD interno
ext_int_edge( H_TO_L );
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
lcd_init();
output_c(0);
set_pwm1_duty(0);
set_pwm2_duty(0);
while(1){
while(start==1){
set_adc_channel(0);
delay_us(50);
valor=read_adc(); //Lectura adc posicion angular
yT= 5.0*valor/1024.0; //posicion angular actual
lcd_gotoxy(1,1);
printf(lcd_putc,"%4.2g %4.2g %4.2g",a,b,c);
lcd_gotoxy(1,2);
printf(lcd_putc,"%lu %4.2g %4.2g",control,eT,iT);
eT=rT-yT; //Cálculo error
iT=b*eT+iT0; //Cálculo del término integral
if(iT>5000){iT=5000;}
if(iT<-5000){iT=-5000;}
dT=c*(eT-eT0); //Cálculo del término derivativo
uT=iT+a*eT+dT; //Cálculo de la salida PID
if(uT<0){uT=(-1)*uT;}
if (uT>max) { //Salida PID si es mayor que el MAX
uT=max;}
else {
if (uT<min){ //Salida PID si es menor que el MIN
uT=min;}
}
control=uT; //Transferencia de salida PID a señal PWM
if(eT>0)
{set_pwm1_duty(control);
set_pwm2_duty(0);}
if(eT==0)
{uT=iT=eT=0;
set_pwm1_duty(0);
set_pwm2_duty(0);}
if(eT<0)
{set_pwm2_duty(control);
set_pwm1_duty(0);}
iT0=iT; //Guardar variables
eT0=eT;
}
}
}
saludos