Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:
Hola,
Como sabréis estamos intentando construir un velocista en ARDE Madrid. Seguro que habréis visto las fotos o videos del driver o de la estructura con la reductora para un motor económico.
Bien, pues como no todo siempre queda perfecto una de las reductoras tiene menor rendimiento que la otra y eso hace que para una de las ruedas con una tensión de 0.5 V en el motor hace girar la rueda y en el otro pues hace falta hasta 0.8 V (además un motor está alimentado digamos en "directa" y el otro en "inversa"). El driver que hemos realizado tiene para tomar medidas de la corriente que circula por el motor y la tensión aplicada en el motor en cada momento, también sería fácil tener una lectura de las vueltas que da la rueda. Creo que con estas entradas se podrá realizar el control.
Mi intención es realizar pruebas de velocidad en línea recta, pero sin colocar los sensores para detectar la línea. Sería interesante compensar los distintos rendimientos de las reductoras y hacer que el avance de ambas ruedas del robot sea el mismo, en este caso el robot irá en línea recta.
Controlando esto podremos realizar pruebas de velocidad para el robot.
Si alguien tiene información sobre fórmulas, página web donde este bien explicado el tema o algún pdf bastante completo sería de ayuda. Y ya se que en google se encuentra todo, pero es mejor ir a leer directamente al lugar adecuado y no estar recopilando poco a poco la información y mirando decenas de sitios.
Gracias.
Creo que la idea de 3 PID es la mejor...
Este código lo tengo para probar, falta definir el tipo de las variables y la escala de los valores de acuerdo con el hardware que se use.
//=============================================================================
// interrupcion de cambio de estado del puerto B para los encoder incrementales
// Optimizado para velocidad
#int_RB
RB_isr()
{
static int8 EncoderAnt;
int8 Encoder,tmp, tmp2;
// Esto es para direccionar los bits individuales
#bit tmp_6 = tmp.6
#bit tmp_4 = tmp.4
Encoder=input_b (); // Lee todas las entradas de encoder a la vez
// Procesa el encoder Derecho, de esta forma rara usa 4 instrucciones menos
tmp=(EncoderAnt>>1)^Encoder;
tmp2=(Encoder^EncoderAnt)&0xC0;
if (tmp2==0xC0) goto NOEncoderD; // imposible, son dos pulsos
if (tmp2==0x00) goto NOEncoderD; // no se ha movido
if (tmp_6) PulsosD--;
else PulsosD++;
NoEncoderD:
// Procesa el encoder izquierdo de la misma forma
tmp2=(Encoder^EncoderAnt)&0x30;
if (tmp2==0x30) goto NOEncoderI; // imposible, son dos pulsos
if (tmp2==0x00) goto NOEncoderI; // no se ha movido
if (tmp_4) PulsosI--;
else PulsosI++;
NoEncoderI:
EncoderAnt=Encoder;
}
//=============================================================================
// interrupcion cada 6.55 ms para calcular la velocidad de los pulsos del
// encoder. *2 es el escalado, depende del tipo de encoder
#int_TIMER0
TIMER0_isr()
{
// output_low(PIN_B0); // Test de velocidad poner en tris_b salida
PosicionI+=PulsosI; //
VelocidadI=PulsosI*2; // Escalado, depende del encoder y los ms de interrupcion
PulsosI=0; //
PosicionD+=PulsosD;
VelocidadD=PulsosD*2; // Escalado, depende del encoder y los ms de interrupcion
PulsosD=0;
ProcesaPID=1;
// output_high(PIN_B0); // Test de velocidad poner en tris_b salida
} // Esto tardaba 12 us en completarse
//=============================================================================
// Inicializacion y bucle principal
void main()
{
signed int16 Vel, TempVI, TempVD; // Temporal para la salida a los PWM
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_128); // genera una interrupcion cada 6,55 ms
// Time = ((256 * 4) / 20.000.000) * 128 = 6.55 ms
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DIV_BY_4,255,1); // Pone T2 para PWM a 4,8 Khz (204,8 us) 8 bit (1/20000000)*4*4*256
// El L293D solo acepta hasta 5 Khz de frecuencia
setup_ccp1(CCP_PWM); // El ciclo de los PWM es (1/clock)*4*t2div*(period+1)
setup_ccp2(CCP_PWM);
enable_interrupts(INT_RB);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
// Lee los parámetros del PID de Eprom
KVprop=Read16Eeprom (0);KVint=Read16Eeprom (2);KVder=Read16Eeprom (4);
while (TRUE) // Bucle principal
{
if (ProcesaPID)
{
ProcesaPID=0;
// Proceso PID de velocidad del motor Izquierdo -------------------------------------------
ErrorVI=ConsignaVI-VelocidadI;
IntegralVI+=ErrorVI; // Poner aqui anti windup
SalidaVI = (ErrorVI*KVprop) + (IntegralVI*KVint) + ((ErrorAntVI-ErrorVI)*KVder);
ErrorAntVI=ErrorVI;
// Proceso PID de velocidad del motor Derecho ---------------------------------------------
ErrorVD=ConsignaVD-VelocidadD;
IntegralVD+=ErrorVD; // Poner aqui y anti windup
SalidaVD = (ErrorVD*KVprop) + (IntegralVD*KVint) + ((ErrorAntVD-ErrorVD)*KVder);
ErrorAntVD=ErrorVD;
// Salida de velocidad al motor Derecho
if (Vel>0) { set_pwm1_duty((int8)Vel); output_high(PIN_B2); }
else { set_pwm1_duty((int8)-Vel); output_low(PIN_B2); }
// Salida de velocidad al motor Izquierdo
if (Vel>0) { set_pwm2_duty((int8)Vel); output_high(PIN_B1); }
else { set_pwm2_duty((int8)-Vel); output_low(PIN_B1); }
}
}
}
Hay que tener en cuenta que las constantes del PID son proporcioanles al tiempo de muestreo, en este caso 5,5ms. Si se cambia esto, para pruebas, hay que escalar las variables en proporción.
Mirad esto, a mi me ayudó mucho: http://www.mundobot.com/tecnica/pid/sppid.htm " onclick="window.open(this.href);return false;
Si hay alguna estoy aquí para resolverla.
Muy bueno el enlace del amigo mundobot, no lo conocía.
Buenas chicos !
El año que viene en 2º de Ing. Electronica ya empezaré el tema este de los micros y la electronica digital en general, por lo tanto todavia no se bien que es eso del PID, a ver si me podriais pasar alguna que otra pagina web donde explicara que es el PID y como implementarlo. Sobre PIC's se lo basico, hacer un programa para el seguidor de linea no es muy complicado, lo complicado es que siga la linea suavemente.
A ver si me podeis brindar esa información, Gracias.
Buenas, el PID es una forma de controlar un sistema. Cada letra hace referencia a un tipo de corrección según el error. Supongamos que en un sistema tenemos una referencia a seguir y que en cualquier momento, si medimos la entrada, tenemos que actualmente estamos en 4, por tanto tendremos que actuar para corregir ese error. Ya tenemos definido el error como referencia-medida_actual.
Ahora es donde actúa el PID con cada una de sus letras:
P -> corregimos de forma proporcional al error, a más error, más corregimos, ya que no es lo mismo que tengamos error de 1 que de 4.
D -> corregimos de forma proporcional a la velocidad que cambia el error. Piensa en una curva, si es suave el error cambiará lentamente, si es muy cerrada cambiará el error de forma muy brusca, por tanto a mayor cambio de error, mayor correción aplicamos.
I -> siempre habrá oscilaciones con este método, así que añadimos un término que será proporcional a la acumulación de error hasta el momento. Es el término integral y que a largo plazo nos permitirá alcanzar de forma estable la referencia.
Espero que te sirva la mini-explicación.
Un saludo.
Me da la impresión que el encoder va a ser obligatorio.
He estado mirando en Farnell y tengo algunas ideas de como podría conseguirlo.
Como opciones he barajado lo siguiente:
1- http://es.farnell.com/avago-technologies/aedr-8300-1q2/encoder-2channel-smd-180lpi/dp/1161103
Parece bastante interesante, es incremental, tiene dos canales y la frecuencia máxima es de 32 KHz. Este habría qeu construirlo de uan manera casera.
Ventaja: Precio, 3.31 €
Inconveniente: Tienes que crearte el disco, imprimiendo a 2500 dpi seguro que sale muy muy profesional, el problema es que la tinta que se use cunpla con el 10 de reflexión para el "0" y entre el 40 y 80 para el "1". Otro inconveniente es ajustar el disco al eje del motor y tener todo perfectamente alineado, aunque todo se puede conseguir de una u otra manera.
2- http://es.farnell.com/avago-technologies/hedr-5420-es211/encoder-200cpr-ears-4mm/dp/1161168
Este es muy interesante, pero debe ser para el eje de la rueda, el que lleva la corona (D 3 mm) ya que tiene una resolución de 200 CPR y con una frecuencia máxima de 16 KHz, eso te da como mucho unas 4800 rpm para el eje que quiera medir, osea que el de 2 mm de diametro para el motor (6000 rpm) no se puede usar habría que usarlo para la rueda que gira a unas 1200 rpm. El precio no es muy adecuado unos 18 €. Además tampoco se si lo podré acoplar adecuadamente al eje de la rueda, habría que analizarlo. La resolución es muy alta para lo que quiero, pero siempre se puede usar uno de los timers como counter y reducir la resolución.
3- http://es.farnell.com/avago-technologies/heds-5600-c06/encoder-2channel-100cpr-1-4in/dp/1161211
Este es muy interesante para obtener la H(s) de un motor, ya que soporta 32000 rpm y eso está muy bien, además con bastante resolución los hay hasta 1000 CPR. Bueno este el precio se va bastante 47 €. Pero merece la pena tener uno para realizar pruebas. Si tomas datos cada milisegundo y los envías por RS232 al PC, tendrías un vector con las cuentas para cada milisegundo que sería muy sencillo procesarl para obtener una gráfica de la respuesta impulsional h(t).
Bueno esto es lo que he mirado hasta ahora que os parece???
Saludos.