Servos de modelismo o RC
Control de un servo - Prueba 01: Control básico
por Eduardo J. Carletti


Servo utilizado: Hitec HS-311
Esta es la primera de un grupo de pruebas de laboratorio en las que, partiendo desde cero, implementaremos el control de servos de modelismo por medio de un microcontrolador PIC. El microcontrolador elegido es el PIC16F628A, que tiene una distribución de patas igual a las del histórico y archiconocido PIC16F84A, aunque con mejores prestaciones. Las razones de elegir este PIC para las pruebas de aprendizaje en lugar del PIC16F84A las he desarrollado en el artículo Prueba de conexión serie entre un PIC y una PC y no tiene sentido repetirlas aquí.

A los servos de modelismo también se les llama servos RC (por Radio Control) o, en inglés, RC servos. En estas pruebas utilizaremos el servo HS-311 de Hitec, que se consigue en Argentina a mejor precio que otros similares de Futaba, por ejemplo.

La forma de controlar el posicionamiento de este tipo de servos es bastante sencilla, y como ya la hemos descripto en detalle en el artículo Servos, Características básicas, no voy a extenderme aquí. A aquellos que aún no han profundizado en el método que se utiliza para controlar los servos de modelismo —que tiene mucho que ver con las características del radiocontrol— les recomiendo dar una ojeada a este artículo antes de seguir.

A continuación se puede observar el primer circuito que vamos a utilizar:

Primera prueba de control de un servo RC

En el circuito se pueden apreciar los pocos elementos que estamos utilizando en esta primera prueba. Se trata del PIC, que como funciona con su generador interno de reloj de 4 MHz no requiere de un cristal; el enchufe para el servo; y tres pequeños pulsadores. Los resistores son para polarizar a un valor positivo, o valor lógico 1, las entradas del PIC que se utilizan para "leer" los pulsadores. Los pulsadores llevan este nivel a lógico 0, o tierra, cuando se los presiona.

Montaje del circuito básico de control de un servo RC


Como se ve en la foto, al servo le hemos colocado un círculo de cartulina con una línea negra que nos servirá como indicador de su posición. Los tres pulsadores que se observan en la foto corresponden, de izquierda a derecha, a "pulsador 1", "pulsador 2" y "pulsador 3" en el circuito. El pulsador 1 servirá para llevar al servo a su posición central, o "neutra". Con el pulsador 2 se hará avanzar lentamente al servo en sentido antihorario, y con el pulsador 3 se lo hará girar, de a poco, en sentido horario.

Este circuito, y el programa asociado en el PIC, no cumplen otro propósito que el de dar una primera aproximación al método de programa utilizado para controlar a este tipo de servos. En las pruebas siguientes iremos avanzando hasta llegar a una sofisticación y utilidad mucho mayor.

Programa básico de control de servos RC


;**********************************************************************
; MANEJO DE SERVOS - Programa Básico 1
; Por Eduardo J. Carletti, Robots Argentina, 2007
;**********************************************************************

	list      p=16F628A	; definir procesador

#include <p16F628A.inc>		; definiciones de variables específicas del procesador

	ERRORLEVEL 1;-302	; para evitar los mensajes de cambio de
				; banco en el resultado del compilador

	__CONFIG   _CP_OFF & _WDT_OFF & _LVP_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF

;***** DEFINICIÓN DEL NOMBRE DE ENTRADAS Y SALIDAS

#define SERVO1	 	PORTA,0		; puerto de salida de servo 1
#define PULSADOR1 	PORTA,1		; puerto de entrada de pulsador 1
#define PULSADOR2 	PORTA,2		; puerto de entrada de pulsador 2
#define PULSADOR3 	PORTA,3		; puerto de entrada de pulsador 3

;***** VARIABLES

	CBLOCK	0x20
	acum_A		; variable momentánea
	Posic		; posición servo
	ENDC

;***********************************************************************************

	org	0x000
	goto	principal

;***********************************************************************************
; Principal
;***********************************************************************************

principal
		movlw b'00000111' 	; deshabilita comparadores. Esto es
		movwf CMCON		; algo importante en el PIC 16F628A

		clrf PORTA		; inicia ports
		clrf PORTB		; inicia ports

		bsf STATUS,RP0		; Apunta a banco 1

		movlw b'00001110' 	; PORTA 
		movwf	TRISA		; salidas menos 1, 2 y 3, entradas

		MOVLW b'00000000' 	; PORTB 
		movwf	TRISB		; salidas

		movlw	b'00000010'	; Configuración para TMR0
		movwf	OPTION_REG	; preescaler 2, 1:8 con CLK interno (que es
					; de 1 MHz si el oscilador es de 4 MHz).
					; El contador cuenta cada 8 useg

	        bcf STATUS,RP0          ; Apunta a banco 0

		clrf TMR0		; inicia registro de timer en 0

		movlw d'133'		; inicia valor de posición de servo (centro)
		movwf Posic

;***********************************************************************************
; Lazo principal
;***********************************************************************************

lazo

; Los servos actúan con un pulso de control que va entre 0,5 ms y 2,5 ms.
; En el bloque que sigue se inicia en 1 el pulso de control y se espera un 
; retardo fijo de aproximadamente 0,5 ms, que es el valor mínimo del pulso.
; Con este valor de longitud de pulso y una longitud cero en la parte variable, 
; el servo está parado al máximo hacia la izquierda (sentido antihorario).

		bsf	SERVO1		; pone la señal de servo en 1
		bcf	INTCON,T0IF	; borra el flag de timer
		movlw	d'192'		; (256-192 = 64) 64 * 8 us = 0,512 ms
		movwf	TMR0		; valor al registro de timer
		btfss	INTCON,T0IF	; espera por timer = ff -> 00
		goto	$-1
		bcf	INTCON,T0IF	; borra el flag de timer

; A continuación, comienza el tiempo variable del pulso. Esto permite 
; que el recorrido completo, de 180 grados (valores de pulso entre 0,5 ms
; y 2,5 ms), se divida en 256 segmentos (256 * 8 us = 2,048 ms).
; La parte variable del pulso de control varía entre 0 y 2 ms

		movf	Posic,w		; 256-nn x 8 uS = 1 ms, 1,5 ms, 2,5 ms
		movwf	TMR0		; valor al registro de timer
		btfss	INTCON,T0IF	; espera por timer = ff -> 00
		goto	$-1
		bcf	SERVO1		; pone la señal de servo en 0
		bcf	INTCON,T0IF	; borra el flag de timer

; Retardo de 20 ms, que es el tiempo estándar que debe separar los pulsos 
; de control para los servos comunes de RC

		movlw	d'9'		; cantidad de veces: 9 x 2 ms = 18 ms + 2 ms
		movwf	acum_A
retardo		bcf	INTCON,T0IF	; borra el flag de timer
		movlw	d'6'		; (256-6 = 250) 250 * 8 us = 2 ms
		movwf	TMR0		; valor al registro de timer
		btfss	INTCON,T0IF	; espera por timer = ff -> 00
		goto	$-1
		decfsz	acum_A		; decrementa cantidad de veces
		goto	retardo

pulsadores				; lee órdenes a través de pulsadores
		btfss	PULSADOR1
		goto iniciaPos		; servo en posición central
		btfss	PULSADOR2
		goto incPos		; incrementa Posic
		btfss	PULSADOR3
		goto decPos		; decrementa Posic

		goto lazo

iniciaPos	movlw d'133'		; 256-133 = 123, 123 * 8 us = 984 us + 512 us
		movwf Posic		; posición central en esta disposición
		goto lazo		; y sale
					
decPos		movf Posic,f		; se fija si Posic ya es cero
		bz sale1		; si es cero no decrementa
		decf Posic,f		; si no es cero, decrementa
sale1		goto lazo		; y sale


incPos		movlw 0xFF		; se fija si Posic no es 0xFF
		xorwf Posic,w		; que es el valor máximo
		bz sale2		; si es el valor máximo, no incrementa
		incf Posic,f		; si no es el valor máx, incrementa
sale2		goto lazo		; y sale

		END

Bajar el programa en formato ASM (puede usar el botón derecho de su mouse)
Bajar el programa en formato HEX (puede usar el botón derecho de su mouse)
Por las dudas, el archivo incluido P16f628a.inc (puede usar el botón derecho de su mouse)

Diagrama de flujo del programa de control de un servo RC

Espero que en este programa se pueda ver con claridad la manera de generar el pulso con los tiempos correctos. De hecho, lo hemos escrito lo más simple posible por esta razón. Pero la verdad es que esta forma de hacerlo tiene el defecto de que mientras se producen los retardos, el microcontrolador está en un lazo cerrado, dedicado exclusivamente a esperar que se cumplan los tiempos.

¿Cómo se soluciona esto? Haciendo que los retardos se produzcan mientras el microcontrolador está haciendo otra cosa. Y para hacer esto se debe utilizar una de las herramientas más potentes y necesarias en un sistema que debe ser sensible a sucesos producidos en el mundo real: las interrupciones.


Los invito, entonces, a continuar esta prueba de laboratorio en la segunda parte de este trabajo: Control de servos con interrupciones.

Algunas cosas que observé en la parte 1

  • En algunas posiciones el servo queda temblando en lugar de quedar firme en su posición. Supongo que se debe a imprecisión en el contacto de su potenciómetro de posicionamiento más que a un pulso de control irregular.
  • Importante: el temblor y el calentamiento del servo crecen mucho si se supera el retardo de 20 ms entre pulsos de control.
  • Al pulsar los controles para mover continuamente el servo en uno u otro sentido, tal como está hecho el programa, el pulsador es leído cada 20 ms, es decir, unas 50 veces por segundo, lo que da una velocidad razonable de actualización y el servo se mueve con suficiente lentitud.

Datos adicionales:

Microcontrolador PIC16F628A

El PIC16F628A se puede comprar en Cika.

Servo de modelismo o RC

Utilizamos el servo Hitec HS-311 porque era el más barato disponible en ese tipo al momento de encarar el proyecto.

Recomendamos ver, para completar esta información -> Servos, Características básicas