Autor Tema: Empezando por el principio: Pruebas con el servo HEXTRONIK HXT 900  (Leído 6833 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Cimmerio

  • PIC10
  • *
  • Mensajes: 14
Empezando por el principio: Pruebas con el servo HEXTRONIK HXT 900
« en: 20 de Septiembre de 2009, 06:51:30 »
 Bien, llevo ya largo tiempo queriendo iniciarme en los misterios de la robótica  :D y al final me he decidido a hacer algo sencillo, concretamente un brazo robot. Algo sencillo, como decia: tres articulaciones más la pinza, con un control sencillito, que cuando esté listo y depurado ya se irá complicando y perfeccionando. Así que cogí unos servos que tenía por casa, comprados hace tiempo en una de las ocasiones en que me dió por empezar y finalmente no pudo ser. Concretamente compré dos tipos de motores: HEXTRONIK HXT 900 (De 9 gramos, en principio para la pinza) y HEXTRONIK HX5010 para las articulaciones. Servos baratos, de los que no espero una gran precisión, pero que imagino bastarán para los inicios en este mundillo.

 Como la pereza es muy mala, me he decidido a postear aquí lo que vaya haciendo, así me obligo a poner medianamente ordenados los avances que pueda ir haciendo.

 Este primer post es muy básico, dado que únicamente pretendia obtener ciertos datos con los que comenzar. La poca información que tenía de los servos procedía de la tienda donde los compré en su momento, pero era muy escasa... :

 HXT 900

 HX 5010

 Decidí empezar por el pequeño: por no decir, no dice ni el pinout, aunque parecía claro que el cable rojo era alimentación, el gris masa y el naranja señal. Esto fue el primer problema, ya que hice una pcb (insolada en casa) con la señal en el pin central en lugar del extremo, y no me apetecía demasiado rehacerla, así que tiré de cablecillos para solucionar el problema.

 Para la señal de control estuve buscando por internet, al parecer muchos servos se controlan con pulsos de hasta 20 ms, con dutys que varian desde el 5% al 10%, teniendo el punto medio en 7.5% (Todo el rango es lineal). Fue mi primera prueba, monté un pequeño código, la mar de cutre, todo por programa principal, que fuese variando cada segundo en un 0,05% el duty, esto es, recorriendo el rango entero en 100 pasos en minuto y medio. No tardé en acelerarlo, aquello aburría a cualquiera :D, pero lo principal es que el servo no recorría ni mucho menos los 180º prometidos. Buscando un poco más encontré que los rangos de trabajo no eran estándar, de modo que me puse a hacer pruebas reduciendo el tiempo de inicio, en busca del tiempo en alto para el cual el servo se posicionaba en 0º.

 En este punto decir que en varias de las pruebas se escucharon crujidos... sospechosos... que me hicieron temer por la vida del servo. Afortunadamente mucho ruido y pocas nueces. Seguía vivito y coleando. Del mismo modo, una vez encontrado el punto de 0º, comencé a ampliar el tiempo en alto para encontrar el punto en que se llegaba a los 180º. Debo decir que, al menos en el servo que he probado, no llega realmente a los 180º, aunque se queda bastante cerca. Aun así quizá sea el resultado de los crujidos en las pruebas. en cualquier caso, ya tenía el timing para este servo:
Citar

POSICIÓN 0º

            ton=450 microsegundos
             __                                                             __
 ______/    \_________________________________/    \_______________
                              T= 20 milisegundos
 
POSICIÓN 180º

           ton=2450 microsegundos
             ________                                                  ________
 ______/              \___________________________/               \_________
                              T= 20 milisegundos


Luego hice la prueba con pequeños pasos, para ver que tal se comportaba el servo y la cantidad de pasos que podía darle, vamos, para comprobar la precisión. Paradójico, por que en lugar de hacer un programa preciso, lease mediante ensamblador o por timers, lo hice en c y con delays en el programa principal. Es lo que tiene ser un vago, y realmente tampoco necesitaba tanta precisión para esta prueba. El código de la prueba es este:

Código: C
  1. #include <p18f2550.h>
  2. #include <delays.h>
  3.  
  4.  
  5. #pragma config WDT = OFF
  6. #pragma config MCLRE = OFF
  7. #pragma config PBADEN = OFF
  8. #pragma config FOSC = XT_XT // Normal (4 MHz)
  9.  
  10.  
  11.  
  12.  
  13.  
  14. void main(void)
  15. {
  16.         unsigned char Intensidad, Porcent_Angulo;
  17.         unsigned char Iteraciones;
  18.         PORTA = 0;
  19.         PORTB = 0;
  20.         PORTC = 0;
  21.         LATA = 0;
  22.         LATB = 0;
  23.         LATC = 0;
  24.         ADCON1 = 0x0F;
  25.         CMCON = 0x07;
  26.  
  27.         TRISA = 0xF0; // Servos en RA0 a 3
  28.         TRISB = 0xE3; // Led RGB en RB2,3 y 4
  29.         TRISC = 0xFF;
  30.  
  31.         Porcent_Angulo = 1;
  32.         Iteraciones = 0;
  33.         while(1)
  34.         {
  35.                 // Prueba servos:
  36.                         // 1) 450 useg a nivel alto
  37.                                 LATAbits.LATA0=1;
  38.                                 Delay10TCYx(45); // 45*10*1useg = 450 useg (Aproximadamente)
  39.                         // 2) de 0 a 2000 useg a 1 (de 0 a 180º)
  40.                                 Delay10TCYx(Porcent_Angulo); // Tiempo en alto que determina el ángulo
  41.                                 LATAbits.LATA0=0;                      
  42.                         // 3) Resto hasta 20 mseg a 0
  43.                                 Delay10TCYx(200-Porcent_Angulo); // Compensamos para dejar un tiempo final a bajo de valor fijo
  44.                                 Delay100TCYx(176); // 176*100*1useg =17'5 mseg aprox.
  45.  
  46.                         Iteraciones++;
  47.  
  48.                         if (Iteraciones==5)     // Han pasado 100  milisegundos...
  49.                         {
  50.                                 Porcent_Angulo++; // Incremento el ángulo
  51.                                 Iteraciones=0;
  52.                         }
  53.                         if (Porcent_Angulo==200) Porcent_Angulo=1; // Como la comprobación se hace tras el incremento, nunca se llamará a
  54.                                                                                           // Delay10TCYx(200-Porcent_Angulo); con 200-200 = 0
  55.        
  56.         }

Y bueno, eso es todo, me temo. Corto y sencillo, pero es lo que tiene no disponer de mucho tiempo. De todos modos, haré pruebas similares para el otro servo y me pondré con un programa de control en condiciones. Aunque probablemente no antes del fin de semana que viene, pero bueno, la cosa es que vaya despacio pero sin pausas...

 Y si a alguien le sirven los datos sobre el servo (que como digo son más bien escasos) ya ha valido la pena postear...
[...]
It was so long ago and far away
I have forgot the very name men called me.
The axe and flint-tipped spear are like a dream,
And hunts and wars are shadows. I recall
Only the stillness of that sombre land;
The clouds that piled forever on the hills,
The dimness of the everlasting woods.
Cimmeria, land of Darkness and the Night.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3510
Re: Empezando por el principio: Pruebas con el servo HEXTRONIK HXT 900
« Respuesta #1 en: 20 de Septiembre de 2009, 18:02:52 »
Bienvenido Cimmerido, me quedo a la espera de novedades.
Saludos desde Granada, España.

Desconectado Cimmerio

  • PIC10
  • *
  • Mensajes: 14
Re: Empezando por el principio: Pruebas con el servo HEXTRONIK HXT 900
« Respuesta #2 en: 23 de Septiembre de 2009, 10:13:04 »
Seguimos:

La idea en el programa es utilizar 48 MHz para Fosc, ya que la comunicación será vía USB. A 48 MHz de Fosc, el tiempo por instrucción es de 83,33 nanosegundos. La cosa es, como he visto en algún programa de gestión de servos, generar una interrupción por timer cada 5 milisegundos. Así, tendremos los 20ms de período de señal de control divididos en 4 partes. Esto nos permitirá gestionar los cuatro servos en paralelo, ya que los tiempos en alto estarán desfasados 5ms entre sí, con lo que las señales serán siempre independientes. No es que sea necesario, pero me gusta la solución.

Las señales quedarían:
Código: [Seleccionar]
     _____                 _____
____|     |_______________|     |______________________   Linea A

             _____                 _____
____________|     |_______________|     |______________   Linea B

                    _____                 _____
___________________|     |_______________|     |_______   Linea C

                           _____                 _____
__________________________|     |_______________|     |   Linea D

ton nunca será 5ms (el máximo será 2,5 ms) con lo que me quedarán, tras terminar ton, 2,5 ms mínimo para realizar las tareas que tenga pendientes. Tengo que revisar el tema USB dado que si no recuerdo mal, las especificaciones mencionaban que ha de atenderse a la tarea USB cada ms, al menos al inicializar. Imagino que despues podrá atenderse cada 5ms, si no, pues la interrupción USB será de baja prioridad, los timers de alta, y todo lo que no sea fundamental se hará en un estado del programa principal al final de los 4 ciclos (Antes de actualizar los valores del ton...

Para los timers, funcionando a la citada frecuencia de 48MHz:

 --> 5 milisegundos = 60000 ciclos ==> 60k * 0,000083333 ms = 4,99998 ms
 --> 0'5 milisegundos = 6000 ciclos ==> 6k * 0,000083333 ms = 0,499998 ms
 --> 0,45 milisegundos = 5400 ciclos ==> 5400 * 0,083333 us = 0,4499982 ms
Ergo en principio T   --> timer fijo a 60k ciclos, por 4 pasos
ton --> timer variable de 5400 a 29400 pasos [0,45 ms a 2,45 ms], esto es, 5400 + pos, con pos [0 ... 24000]. Nos quedaría: 24000 / 180 = 133'33 --> 133 pasos por grado, aprox... Lo que en tiempo queda: 2 ms / 180 = 11,1 us.

Con esto, ambos timers necesitarán ser de 16 bits. Esto no supone un problema en el pic 18F2550, con lo cual tengo bastante claro el tema, ahora solo faltan el tiempo y las ganas de escribir el programa :D. A ver si una noche de estas me pongo... que escaquearse del trabajo está muy mal...

Una cuestión para los más experimentados: ¿vale la pena "pensar en grados" a la hora de situar los motores en determinada posición, o es más sencillo limitarse a un valor determinado de pasos (en función de la precisión que deseemos) y utilizarlo pensando en él como en un motor PAP?
Es que, dado que el timer que controla el tiempo a alto me variará del mínimo al máximo en 24000 cuentas, lo primero que me vino a la mente fue limitarme a "fabricar" 200 "pasos" de 120 cuentas, esto es de 10 us aproximadamente. Más sencillo, más preciso (200 en lugar de 180 posiciones) y supongo que después, visualmente, será dificil apreciar si el brazo está exactamente a 75º o a 75.6º (84 pasos de 10us :P) además de que, probablemente, el servo carece de esa precisión...

Vaya, resumiendo, que si esto es como el ADC: que por mucho que te ofrezcan 10 bits en la conversión, en un caso "normal" el ruido te dejará únicamente con 7 u 8 bits significativos... ¿Opiniones al respecto?
[...]
It was so long ago and far away
I have forgot the very name men called me.
The axe and flint-tipped spear are like a dream,
And hunts and wars are shadows. I recall
Only the stillness of that sombre land;
The clouds that piled forever on the hills,
The dimness of the everlasting woods.
Cimmeria, land of Darkness and the Night.