Control de Servomotor con TMR2
![]() |
Fig1. Soporte de movimiento en 2-ejes |
Un gran saludo a los visitantes de mi blog, donde comparto mi interés en maravilloso mundo de la electrónica digital y en especial la programación de microcontroladores PIC/AVR. En esta ocasión quiero mostrar como hacer uso del modulo Temporizador TMR2 de 8-bit para controlar varios servomotores conectados a unos de los puertos del Microcontrolador.
Esta entrada es complementaria a una publicación previa donde describo como hacer este control con el temporizador TMR1 de 16-bit <Ver Entrada>, por esta razón no voy extender la explicación en el entendido que ya sabes como trabajan los temporizadores de un Microcontrolador, por otra parte te recomiendo revises los siguientes enlaces:
El objetivo que se pretende en esta publicación, es demostrar como se puede llevar a cabo el control de mas de un servomotor con el temporizador TMR2 de un PIC16F, en la practica podemos controlar hasta ocho servomotores conectados a un puerto de salida digital de 8-bit, cada salida de control PWM tiene asignada su ranura de tiempo (slot) con la que establece el rango de movimiento 0 a 180 grados en el servomotor
La programación del microcontrolador PIC se lleva a cabo con el software de diseño MPLABX y el compilador de lenguaje C para PIC XC8, ambos disponibles en la pagina de microchip de forma gratuita. Aquí dejo los enlaces de las versiones utilizadas para nuestro ejemplo:
Introducción
Un
servomotor como por ejemplo el SG90, posee un eje de rotación que puede ser posicionarse desde los 0 hasta los 180° grados de movimiento, este control se lleva a cabo variando el ancho de pulso (1.0-2.0 ms) de una señal digital periódica que posee una frecuencia regular de 50Hz, la figura 2 que
muestra la relación entre el ancho del pulso de control y el movimiento en el eje del servomotor.
![]() |
Fig2. Señal de control de un Servomotor |
La señal de control de un servomotor es en esencia una señal tipo PWM (Pulse Width Modulation), con las siguientes consideraciones:
La señal es de baja frecuencia, de forma general un servomotor trabajar con frecuencia de 50Hz, aunque varios modelos pueden trabajar con frecuencias mayores (400Hz).
El control de un servo requiere que el ciclo activo de la señal PWM este entre 5% y 10%.
Tomando
en cuenta lo citado previamente utilizaremos el temporizador junto al recurso de interrupción, para generar la señal de control en cada pin de control.
Señal de Control PWM
La figura 3 nos ilustra como es la señal de control PWM que requiere un servomotor, en la gráfica se observa que el periodo de 20ms corresponde con una frecuencia de operación de 50Hz y el ancho del pulso varia desde los 1.0 a 2.0 milisegundos, por lo que una variación en el ciclo de trabajo (tc) desde el 5% hasta el 10% establecerá el rango de movimiento en el servomotor.
![]() |
Fig3. Señal de control PWM del servomotor |
Generar la señal de control PWM con un temporizador de 8-bit es algo sencillo si analizamos la figura 4 y tomamos en cuenta lo siguiente:
El slot de tiempo corresponde al valor máximo ajustado al temporizador para generar una interrupción. (recuerde que la interrupción puede ocurrir por desbordamiento o comparación del registro contador). En un registro contador de 8-bit el valor máximo no superara los 255, en el programa este valor se definirá como (SVSLOT)
Los incrementos en el temporizador son pasos de tiempo (tp) que determinan el movimiento del servomotor (Resolución). Por ejemplo si los pasos son de 10us, entonces el control de movimiento con un registro contador de 8-bit sera de (2.000/10)*0.5=100, recuerde que la señal de control esta entre el 1-2ms, es decir que la mitad de este ciclo siempre estará activo, y el resto es variable.
![]() |
Fig4. Control de servo, ancho del pulso |
Con la explicación descrita hasta este punto veremos como generar la señal de control a varios servomotores utilizando solo un temporizador, para esto el programa utiliza un contador de slot de tiempo con las que se establecerá el periodo de la señal PWM, además se debe asociar cada slot de tiempo a un pin de salida por cada servomotor conectado, observe la figura 5 y notara que se deben contar diez slots en un periodo de tiempo(2ms*10=20ms), de los cuales solo ocho se utilizaran para el control de servomotores porque los puertos de 8-bit de un PIC/AVR poseen ocho pines de salida.
![]() |
Fig5. Señal de control para cuatro servomotores |
- MSVNUM. Define la cantidad de servomotores que se utilizaran, este valor debe estar entre 1 a 8 según los servomotores conectados.
- MSVSLOT. Define el valor del registro contador para que el temporizador se ajuste a los 2.0ms de un slot, este valor deberia estar entre 150 y 250, con 250 se tiene mejor resolución para el control de movimiento. Además el valor establecido determinara los pasos del temporizador, por ejemplo si el valor se ajusta a 250 (SVSLOT), entonces los pasos (tp) serán de 8us, ver ecuaciones de la figura 4.
- MSV.svxpos. Es una variable de 8-bit que controla el movimiento del servomotor, por lo que este valor decimal corresponde con el ciclo de trabajo variable (tc_var) de la señal. Considerando las ecuaciones de la figura 4, podemos determinar los valores que se muestran en la siguiente tabla:
![]() |
Tabla1. Ajustes para movimiento en grados |
Revisando la tabla 1, la primera fila para pasos de 16us otorga menor precisión de movimiento en el servomotor, por esto optaremos por usar siempre pasos de 8 a 10us. Para determinar los pasos
en un PIC16F debemos considerar la relación que tiene el ciclo de
instrucción (Tcy) con respecto a la frecuencia de operación de un PIC16F
es Tcy=4/Fosc, por lo sera necesario seleccionar adecuadamente el divisor de pre-escala o post-escala que dispone el temporizador para que los incrementos de registros contador ocurran en pasos de 8us a 10us.
![]() |
Tabla 2. Configuración pasos con TMR2 PIC16F |
Para llevar a cabo la programación de control para los servomotores, utilizaremos dos procedimientos que se encuentran en la librería local <mservo.c>, que se encuentra en la carpeta del proyecto MPLABX, estos procedimientos facilitaran aplicar el proceso de señalización a todas la salidas de control PWM de forma simple utilizando la interrupciones del temporizador TMR2. A continuación resumo una descripción de ambos procedimientos:
TSERVOSetup(): Configura los pines de salida asignado a cada servomotor, esto en base al ajuste de las definiciones que se encuentran en la cabecera <mservo.h>. Este procedimiento debe ser llamado por única vez al momento de inicializar el sistema.
TSERVOHandler(): Esta función es invocada desde la rutina de servicio a la interrupción ISR correspondiente al temporizador TMR2, y permite controlar el estado de la señalización en cada unos de los pines PWM utilizados para el control de un servomotor. La función devuelve el valor de tiempo con la que se actualizara nuevamente el temporizador.
Esquema del Circuito
Para poner en practica lo aprendido utilizaremos la simulación en ISIS Proteus 8.5 con el esquema de circuito que se muestra en la figura 6.
![]() |
Fig6. Esquema de circuito PIC16F |
El
código del programa principal contiene procedimientos adicionales
necesarios para el funcionamiento de este programa, estos incluyen la
lectura ADC y la concurrencia de tareas con el TMR0.
El programa principal ejecuta tareas cada milisegundo, estas tareas permiten destellar un LED y hacer lectura de los dos canales analógico ADC para cargar la variable de control de posición sv1pos y sv2pos. Cabe resaltar que ninguna de estas tareas representa un proceso bloqueante, la codificación utiliza una técnica de programación por estados, si quieres conocer mas detalles al respecto puedes revisar la siguiente publicación.
<Programación por estados con Temporizador>
Programación del PIC
El programa de control se encuentra dentro de la carpeta de proyecto MPLABX, disponible en el siguiente enlace <Click AQUI>, por lo que bastara con abrir el proyecto, proceder a la compilación, carga del firmware al circuito del simulador y proceder con la simulación del programa. Pero a manera de analizar el programa, describiré algunas secciones importantes del mismo.
/* USER PORT DEFINITION */
#define MSVNUM 2 //Numero de servos a conectar, Maximo 8. 20ms/8 > 2.5ms.
#define MSVPIN 0 //Indica el numero de pin indice 0-7
#define MSVSLOT 250U //Maximo desplazamiento 250 x 8us = 2ms
#define MSVPOS0 188U //Posicion central servo 188 x 8us = 1.5ms
#define MSVPORT PORTD //Port <pos6><pos5><pos4><pos3><pos2><pos1>
#define MSVTRIS TRISD //Tris servo port
/* END USER PORT DEFINITIOS*/
Sección 2: Programa principal
#include "mservo.h" //Cabecera de la librería servo
MSV_t MSV; //Declaración de estructura Servo
void main(void)
{
setupMCU(); //Configuración del PIC
MSERVOSetup(); //Configuración del SERVO
MSV.sv1pos = MSVPOS0; //Ajusta servo al 50%
MSV.sv2pos = MSVPOS0; //Ajusta servo al 50%
while(1)
{
if(tickms) //Intervalo para la concurrencia
{
tickms = 0; //Limpia bandera
//Código del programa principal
}
}
}
void setupMCU(void) //Procedimiento de configuracion del MCU
{
OSCCONbits.IRCF = 0b111; //Ajusta frecuencia a 8MHz
while(OSCCONbits.HTS == 0) {};
T2CONbits.T2CKPS = 0b10; //Prescala 1:16 x Tcy = 8us
TMR2 = 0;
PR2 = 125; //Periodo 8uS * 125 = 1.0ms
T2CONbits.TMR2ON = 1; //Activa el temporizador
PIR1bits.TMR2IF = 0; //Limpia bandera
PIE1bits.TMR2IE = 1; //Activa interrupción
INTCONbits.PEIE = 1;
INTCONbits.GIE = 1;
}
void __interrupt() isr(void) //Rutina de servicio de interrupción
{
if(PIR1bits.TMR2IF)
{
PR2 = MSERVOHandler();
PIR1bits.TMR2IF = 0;
}
}
Conclusiones y Recomendaciones
De
manera general vimos realizar el control de varios servomotores conectados al puerto de nuestro microcontrolador PIC16F, el modelo de programación aplicado hace uso de funciones y procedimiento no bloqueantes utilizando interrupciones del microcontrolador, además para este ejemplo en particular se utiliza el modulo TMR2. Mencionar que este ejemplo es solo una de las varias maneras en que existen para este tipo de control, por lo que debes verificar si esta técnica es adecuada para cumplir con los
requisitos particulares que conlleva cada aplicación.
Con relación al programa y la técnica de control utilizada es importante considerar los siguientes puntos:
- Es posible emplear diferentes frecuencias del oscilador como los que se muestran en la tabla2, y considerar también que la frecuencia de control PWM del servomotor que es de 50Hz, esta pueden operar desde los 40Hz, hasta mas allá de 100Hz.
- Si
bien los servomotores vistos en esta sección, se diseñan para operar en
un rango de movimiento que va de los 0 a 180 grados, es recomendable no
alcanzar las limitaciones de movimiento, con el propósito de reducir la fatiga
estructural del mecanismo o fallas en el servomotor.
- La latencia de las interrupciones puede provocar oscilaciones en el movimiento del servomotor cuando en la rutina ISR se atiende otras fuentes de interrupción que requieren mayor tiempo de atención; Debe analizar a detalle la implicación que conlleva atender agregar un nuevo evento a la ISR.
Sin
mas que mencionar agradezco tu visita al blog y espero que el ejemplo
visto pueda ser útil en tu formación y el proyecto que desarrollas.
Atentamente, Pablo Zárate Arancibia email: pablinza@me.com / pablinzte@gmail.com, @pablinzar
Santa Cruz de la Sierra - Bolivia
No hay comentarios.:
Publicar un comentario