bueno creo que ha llegado el momento de implementar un control PID en el codigo de mi programa, hasta ahora el control de velocidad que realizo es bastante basico....
entonces primeramente mostrare el esquema actual con el que estoy trabajando...
a continuacion mostrare mi codigo fuente actual:
/****************************************************************************
By: Amyver - Foro TODOPIC
*****VERSION 1B*****
Funciones:
*Modulo controlado atravez del interface USART
****************************************************************************/
#include <16F877A.h>
#device adc=10 //Definimos un Conversor Analogo/Digital con resolucion de 10 bits
#Fuses XT, NOWDT, NOPROTECT, NOLVP, PUT, BROWNOUT, NOCPD, NOWRT//palabra de configuracion
#Use delay(clock=4000000) //usando un oscilador de 4MHz
#Use RS232(Baud=9600, Xmit=Pin_C6, Rcv= Pin_C7, Parity=N, Bits=8)
#Use Fast_io(B)
#Use Fast_io(C)
#Byte PortB=0x06
#Byte PortC=0x07
//declaracion de variables globales que seran usados en el programa
char var;
signed int16 senialError=0;
signed int16 lecturaBackEmf=0,fijarVelocidad=0,valorPWM=0;
////////////////////////////////////////////////////////////////////////////////
void incrementarVelocidad()
{
OutPut_High(Pin_C5); //Habilitamos el driver L6203
fijarVelocidad+=25; //incrementamos la velocidad en 25
if(fijarVelocidad>=1000) //pregutamos si se llego a la velocidad tope hacia adelante
{
fijarVelocidad=1000; //se fija una velocidad tope
}
if(fijarVelocidad>=0) //Preguntamos si la velocidad es positiva (motor con giro hacia adelante)
{
OutPut_Low(Pin_C4); //Habilitamos driver L6203 para el giro a la derecha
printf("\r\n\r\nVelocidad Programada=%Ld\r\n ",fijarVelocidad);
}
else
{
OutPut_High(Pin_C4); //Habilitamos driver L6203 para el giro a la izquierda
printf("\r\n\r\nVelocidad Programada=%Ld\r\n ",fijarVelocidad);
}
}
void decrementarVelocidad()
{
OutPut_High(Pin_C5); //Habilitamos el driver L6203
fijarVelocidad-=25; //decrementamos la velocidad en 25
if(fijarVelocidad<-1000) //pregutamos si se llego a la velocidad tope hacia atras
{
fijarVelocidad=-1000; //se fija una velocidad tope
}
if(fijarVelocidad>=0) //Preguntamos si la velocidad es positiva (motor con giro hacia adelante)
{
OutPut_Low(Pin_C4); //Habilitamos driver L6203 para el giro a la derecha
printf("\r\n\r\nVelocidad Programada=%Ld\r\n ",fijarVelocidad);
}
else
{
OutPut_High(Pin_C4); //Habilitamos driver L6203 para el giro a la izquierda
printf("\r\n\r\nVelocidad Programada=%Ld\r\n ",fijarVelocidad);
}
}
void pararMotor() //paramos el motor
{
fijarVelocidad=0; //Establecemos la velocidad en cero
OutPut_Low(Pin_C5); //Deshabilitamos el driver L6203
set_pwm1_duty((int16)0); //se establece el PWM1 en Cero
printf("\r\n\r\nPARAR MOTOR=%Ld\r\n ",fijarVelocidad);
}
////////////////////////////////////////////////////////////////////////////////
void verificarRS232() //Funcion encargada de verificar si existen datos en buffer
{ //del USART
if(kbhit()) //Preguntamos si existen datos pendientes a ser procesados
{ //Si, hay algo pendiente de recibir ...
var=getc(); //tomamos el dato ingresado por el usuario y lo almacenamos en
//una variable
if(var==0x0D) //preguntamos si se presiono Enter
{
incrementarVelocidad();//llamamos a la funcion incrementar velocidad
}
if(var==0x08) //preguntamos si se presiono retroceso
{
decrementarVelocidad();//llamamos a la funcion decrementar velocidad
}
if(var==0x20) //preguntamos si se presiono la barra espaciadora
{
pararMotor(); //funcion que para los motores
}
}
}
void testearBackEmf() //Funcion que tomara el valor de la Back-emf
{
delay_ms(10); //tiempo que se enviara la señal PWM
OutPut_Low(Pin_C5); //Enable Motor OFF
delay_ms(1); //tiempo de espera para que la señal Back-emf se estabilice
Set_adc_channel(1); //selecion de canal 1 del modulo ADC
delay_us(50); //Retardo para que se carge la senal analogica
lecturaBackEmf=read_adc();//Se toma el resultado de la convercion y se guarda en nuestra variable de 16bits
printf("\r\nLectura BACK-EMF=%Ld",lecturaBackEmf); //imprimimos un dato por pantalla
OutPut_High(Pin_C5); //Enable Motor ON
}
void ajustarVelocidad() //funcion encargada de realizar el control de velocidad(ES LA QUE PRETENDO MEJORAR)
{
signed int16 auxiliar=0; //Definimos una variable de tipo entero con signo de 16 bits
if(fijarVelocidad>=0) //preguntamos si la velocidad es positiva (Giro Derecho)
{
senialError= fijarVelocidad-lecturaBackEmf; //sacamos el error
}
else //si la velocidad es negativa (Giro Izquierdo)
{
auxiliar=(int16)ABS(fijarVelocidad); //tomamos el valor absoluto de la variable
senialError= auxiliar-lecturaBackEmf; //la almacenamos en una variable para despues usarla
}
printf("\r\nSenial de Error=%Ld",senialError); //Imprimimos por pantalla el valor de la señal de error
if(senialError>5) //Establecemos un desplazamiento maximo de 5 unidades
{
valorPWM+=senialError; //ajustamos el valor del PWM
if(valorPWM>=1000) //preguntamos si se llego al limite maximo del PWM1
valorPWM=1000;
set_pwm1_duty((int16)valorPWM); //establecemos el nuevo valor del PWM1
printf("\r\n\r\nValor del PWM=%Ld\r\n ",valorPWM); //imprimimos el valor del PWM1
}
if(senialError<-5) //Establecemos un desplazamiento maximo de -5 unidades
{
valorPWM+=senialError; //ajustamos el valor del PWM
if(valorPWM<25) //si el valor del PWM1 es menor que 25, apagamos el CCP1
valorPWM=0;
set_pwm1_duty((int16)valorPWM); //establecemos el nuevo valor del PWM1
printf("\r\n\r\nValor del PWM=%Ld\r\n ",valorPWM); //imprimimos el valor del PWM1
}
}
void main()
{
Set_Tris_B(0b11111110); //Configuramos el pin RB0 como salida, los restantes como entradas
Set_Tris_C(0b10001011); //Configuramos los pines RC0,RC1,RC3 y RC7 como entradas, los restantes como salidas
PortB=0x00; //limpiamos el puertoB
PortC=0x00; //limpiamos el puertoC
OutPut_High(Pin_B0); //senializacion de pic ON
////////////////////////////////////Configuracion de CCPx(PWM)/////////////////////////////////////////////////
setup_timer_2(T2_DIV_BY_1,249,1); //configuramos el timer2, Prescaler=1,Periodo=249,Postcaler=1
//con lo que se conseguira: T=250us o f=4Khz
//"setup_timer_2(Prescaler,Periodo,Postcaler)"
setup_CCP1(CCP_PWM); //Escogemos el modo de trabajo de CCP1, lo escojemos como modulacion por ancho de pulso
//NOTA.- Tanto para PWM1 y PWM2 el periodo es establecido por el timer2
//NOTA2.-la resolucion maxima esta dada por: Tpwm=2exp(n) * 1/Fosc
// 250us=2exp(n) * 1/(4exp(6))
// 2exp(n)= 1000
//Entonces el maximo valor que podemos cargar al "value" es de 1000 con lo que se
//conseguira un ciclo de trabajo de 100% "set_pwm1_duty(value)"
////////////////////////////////////Configuracion de CAD////////////////////////////////////////////////////
setup_adc(ADC_CLOCK_INTERNAL); //Se usara un reloj interno
Setup_adc_Ports(AN0_AN1_AN3); //se configuran lo pines: RA0,RA1,RA2 como entradas analogicas
////////////////////////////////////////////////////////////////////////////////////////////////////////////
set_pwm1_duty((int16)0); //se inicializa el PWM en cero
OutPut_High(Pin_C5); //Enable Motor ON
printf("\r\nSystem OK.\r\n"); //Sistema en linea y listo para transmitir
while(true) //ciclo infinito
{
verificarRS232(); //llamamos a la funcion que se encargara de verificar la tecla que se pulso
testearBackEmf(); //funcion que determinara el valor de la Back-emf
ajustarVelocidad(); //FUNCION QUE REALIZA EL CONTROL DE VELOCIDAD (es la que pretendo mejorar)!!!!
}
}
bueno es un codigo bastante sencillo y le puse comentarios para un mejor entendimiento, ojo que la funcion a la cual pretendo mejorar es la llamada "ajustarVelocidad()"
saludos...