by JM » Sun Apr 18, 2010 10:12 pm
Hola, gracias por el comentario, me alegro de que sea útil.
A ver si he entendido bien lo que quieres hacer, quieres hacer una controladora de servomotores en la que controlar la posición final de cada servo y la velocidad con la que el servo llega a la posición final deseada desde una posición inicial.
No entiendo muy bien lo que dices de esperar 2 milisegundos en cada pequeño desplazamiento, en un servomotor tienes que mandarle un pulso entre 0.3 y 2.1 ms (que le indica la posición deseada) cada 10-30 ms. Es decir que das un pequeño paso y el siguiente pequeño paso de ese servomotor no tendrá lugar hasta 10 ms después como mínimo. Si usas un período mayor de 30 ms o menor de 10 ms el servo se moverá de forma brusca, y si es analógico y sobrepasas el pulso max y min de posición vibrará con fuerza para esos periodos.
Dividiendo los 20 ms en periodos de 2.5 ms para controlar 8 servos está bien, yo también lo haría así, puedes subir el período de 20 ms a 30 ms y así tienes ventanas de tiempo más grandes. Lo que no haría es utilizar un búcle para mover el servo paso a paso, usaría timers y sus interrupciones.
En el ATmega16 si no recuerdo mal tienes dos timers de 8 bits y uno de 16 bits. Usas un timer para configurarte una interrupción cada 2.5 ms (2.5x8 = 20 ms) y vas pasando de ventana a ventana de forma secuencial según salta la interrupción cada 2.5 ms para dar su posición a todos los servos.
Una vez que entras en una ventana temporal has de usar otro timer para contar el tiempo del ancho de pulso, es decir cargas el valor correspondiente a la posición del servo de la ventana temporal en la que te encuentras en el segundo timer, pones la salida a 1 del micro que va al servo, lanzas el timer y cuando alcance su cuenta salta su interrupción que pone a cero el pin del micro, de esta forma se le da al servo el ancho de pulso requerido cada 20 ms sin molestar mucho al micro.
Si no se usan interrupciones para hacer ésto el micro está ocupado la mayor parte de la ventana temporal contando el tiempo, es decir si tenemos que dar un pulso de 2 ms cada 2.5 ms sin usar interrupciones pues el micro estaría ocupado un 80% del tiempo en mover los servos, lo que puede ser excesivo.
Es decir tenemos 2 timers, uno con la interrupción principal de 2.5 ms de manera constante, y otro segundo timer que se modifica cada 2.5 ms con el valor del servo correspondiente a mover en cada ventana temporal, un vector con las 8 posiciones de los servos y una variable global que vaya seleccionando el servo a mover por ejemplo mediante un switch en c en cada salto de la interrupción principal de 2.5 ms.
Por ejemplo vamos a mover el servo 3 desde 10 grados a 90 grados y queremos que tarde en llegar 5 segundos, tenemos un vector con la posición final de los 8 servos y otro vector con su posición actual. Cuando entramos en la ventana temporal del servo 3 en lugar de cargar en el timer que controla el ancho de pulso el valor correspondiente a 90 grados, cargamos el valor de 10 grados más un incremento, ese incremento es una constante que has de calcular y que determina la velocidad del movimiento.
Es decir queremos ir de 10 a 90 grados en 5 segundos y el período de la señal de control del servomotor es de 20 ms, desplazamiento total 80 grados en 5 segundos. 5 segundos entre 20 ms = 250, 80 grados entre 250 = 0.32 grados, es decir cada 20 ms incrementaríamos el ancho de pulso que controla el servomotor 3 en 0.32 grados cada vez que entramos en su ventana temporal (seguimos moviendo los 8 servos a la vez en ventanas de 2.5 ms). Para los cálculos has de tener en cuenta el movimiento mínimo del servo (tu precisión) y el tiempo que tarda en realizar ese movimiento que no lo he tenido en cuenta en el ejemplo.
Por lo que con dos timers y tres vectores, uno que guarde la posición final, otro la posición actual y otro los incrementos de cada servo quizás puedas hacer lo que quieras, cada vez que entras en una ventana temporal cargas en el timer del ancho de pulso la posición actual del servo más el incremento correspondiente que representa la velocidad del movimiento, si el servo está parado el incremento es cero. Cuando la posición actual sea mayor o igual a la final el incremento se vuelve cero.
Lo que has de cálcular es el incremento para la velocidad deseada, que depende del ángulo total a girar en el tiempo y la precisión y velocidad total de tu servomotor.
No sé es lo primero que se me ha venido a la cabeza de como hacerlo (no sé si funcionará o me dejo algo), lo que si te aconsejo es que teniendo timers e interrupciones no cuentes el tiempo mediante búcles, ya que es tener ocupado al micro sin necesidad.
Este blog más que para futuros usuarios es para mi y ese es el motivo por el que lo hago, viene muy bien para documentar y organizar lo que vas haciendo y tenerlo en la cabeza en un momento, si no se hace con el tiempo se van olvidando las cosas, con un blog con código, explicaciones, imagenes y videos es muy fácil retomar lo que se hizo hace meses... Aunque parezca mentira se ahorra más tiempo haciendo ésto que si tienes que ponerte a buscar y recordar lo que hicistes hace meses, yo estoy convencido de que hacerlo de esta manera me hace ganar mucho tiempo.
Saludos