olas a todos que tal me parece muy interesante este foro ya que puedes compartir muxas ideas y cosas mas weno io queria contar y preguntar a la vez es que io hice una tarea en mi univ de un controlador de velocidad de un motor dc la velocidad es vista en un lcd y mi velocidad de referencia la escojo con un potenciometro ,mediante el pic16f876A corrijo el error ante una perturbacion en el eje mediante un pid programado en el pic weno el trabjo si me flipa pero mi problem es que mi valor de refencia que me aparece en el lcd de mi trabajo no es igual ami valor de salida de mi lcd mm y no se si seran los parametros de mi motor que esten mal o sera mis valores kp ki kd habe si alguien me dice alguito de como corregir esto pls mayor inf les puedo pasar mi simulacion en proteus si entienden mi idea gracias ahi les va el programa de formacion del pid.
#include <16F876A.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz)
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG
//No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#use delay(clock=20000000)
#include <lcd.c>
#define factor 3000/1023
#define f2 0.23
#use fast_io(a)
#use fast_io(c)
#use fast_io(b)
float rpm,vel_m;
int cont_t0;
int16 vel,vref,duty,aux;
signed long duty_c,uk_int;
float uk,uk_1,ek,ek_1,ek_2,f_vref;
int Kp,Ki,Kd;
void set_pwm1_dc(unsigned long duty_pwm);
#int_TIMER0
void TIMER0_isr()
{
set_timer0(61); // para contar 10 ms
cont_t0++;
if(cont_t0==10)
{
cont_t0=0;
vel=get_timer1(); // contamos cuanros pulsos pasaron
vel=vel*6; // son 100 pulsos por revolucion
// asi obtenemos en revoluciones cada 100 milisegundos
// vel = #p/deci * 1rev/100p * 10 deci/1 seg * 60 seg/min
// vel esta en rpm
lcd_gotoxy(9,2);
printf(lcd_putc,"Vm=%Lu",vel);
set_timer1(0);
}
}
void main()
{
set_tris_a(0xff);
setup_adc(ADC_CLOCK_DIV_8);
setup_adc_ports(AN0);
set_adc_channel(0);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);
setup_timer_2(T2_DIV_BY_4,0XFF,4);
setup_ccp1(CCP_PWM);
set_pwm1_duty(0);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
set_timer0(61);
set_timer1(0);
clear_interrupt(INT_TIMER0);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
set_tris_c(0b11111011);
set_tris_b(0);
output_b(0);
lcd_init();
set_pwm1_dc(700);
lcd_putc(" CONTROL PID\n");
delay_ms(1000);
output_b(0);
uk=0;
uk_1=0;
ek=0;
ek_1=0;
ek_2=0;
Kp=10;
Ki=10;
Kd=5;
for(;
{
aux=read_adc();
if(aux!=vref)
{
vref=aux;
f_vref=vref;
rpm=vref*factor;
lcd_gotoxy(1,2);
printf(lcd_putc,"Vr=%4.0f",rpm);
}
vel_m=vel;
ek=rpm-vel_m;
uk=Kd*ek_2+(Kp+2*Kd)*ek_1+(Kp+Ki+Kd)*ek-uk_1; // controlador pid
ek_1=ek;
ek_2=ek_1;
uk_1=uk;
uk_int=uk;
duty_c=uk_int*f2;
if(duty_c>1023)
duty_c=1023;
else if(duty_c<=0)
duty_c=0;
duty=duty_c;
set_pwm1_dc(duty);
}
}
void set_pwm1_dc(unsigned long duty_pwm)
{
#byte CCP1CON=0x17
#byte CCPR1L=0x15
bit_clear(CCP1CON,4);
bit_clear(CCP1CON,5);
if(bit_test(duty_pwm,0))
bit_set(CCP1CON,4);
if(bit_test(duty_pwm,1))
bit_set(CCP1CON,5);
duty_pwm>>=2; //rota dos veces
duty_pwm&=0x00FF; // dejamos solo un byte
CCPR1L=duty_pwm;
}
graxias ojala me puedan ayuda xD