Hola!!!
Cuando vi el robot ápodo del compañero
AKENAFAB quise construirme uno

Al empezar la programación vi que los servomotores se controlan por PWM de una manera muy extraña. Los futaba 3003, que son los que utilizo, al alimentar el terminal de control con una onda de 20ms de periodo y 0,3ms en alto, se posiciona en un extremo; y si se cambia el tiempo en alto por 2,3ms se coloca en el extremo opuesto. Cualquier señal intermedia gira hasta una posición relativa intermedia.
Bueno, después de aprenderme la teoría llegó la hora de aplicarla a la práctica, para ello he utilizado el PIC16F877 (aunque es muy grande y sobra micro por todas partes) y ensamblador:
LIST P=16F877
__config h'3F39' ;configuración de los fuses del uC
;---------------------------------------------------------------------
;ETIQUETAS
;---------------------------------------------------------------------
PDel0 EQU 0x20 ;registro del retardo
PDel1 EQU 0x21 ;registro del retardo
PDel2 EQU 0x22 ;registro del retardo
Dato EQU 0x23 ;dato del PWM alto
Dato2 EQU 0x24 ;dato del PWM bajo
ESTADO EQU 0x03 ;registro específico
TRISA EQU 0x05 ;registro específico
TRISB EQU 0x06 ;registro específico
TRISC EQU 0x07
;--------------------------------------------------------------------
;PROGRAMA
;--------------------------------------------------------------------
ORG 0 ;PARA COMENZAR EN LA POSICIÓN CERO DE LA MEMORIA
bsf ESTADO,5 ;PASA AL BANCO 1
movlw 0x00 ;LLEVA 'FF' AL ACUMULADOR
movwf TRISB ;PROGRAMA LA PUERTA B EN salida
movwf TRISA ;programa la puerta C en salida
movlw 0xC7 ;LLEVA EL DATO 'C7' AL ACUMULADOR
movwf TRISC ;PROGRAMA LA PUERTA C en entrada
bcf ESTADO,5
clrf TRISB ;BORRA LA PUERTA B
clrf CCP
Leer movf TRISC,0 ;lee el PuertoC
movwf Dato ;guarda el resultado en dato
btfsc Dato,6
bsf Dato,3
btfsc Dato,7
bsf Dato,4
bcf Dato,6
bcf Dato,7
movf Dato,0 ;guarda el contenido de dato en el acumulador
addlw 0x03 ;suma 3, ya que el ángulo 0 tiene un tiempo en alto de 0,3ms
movwf Dato
sublw .200 ;resta a 200 el resultado de la suma anterior
movwf Dato2 ;para calcular el tiempo en bajo
decf Dato2,1 ;porque el primer ciclo de 100us se hace a parte para compensar
PWM bsf TRISB, 3
movf Dato,0
call Ret100
bcf TRISB,3
movf Dato2,0
call Ret100
movlw 0x1B ;retardo para conseguir el periodo de 20ms
movwf PDel0 ;en el bucle infinito "Leer"
ret decfsz PDel0,1
goto ret
movwf PDel0
movwf PDel0
goto Leer
;-------------------------------------------------------------
; Ret 100us
;-------------------------------------------------------------
Ret100 movwf PDel1
movlw 0x1E ; set numero de repeticion
movwf PDel0
PLoop0 decfsz PDel0, 1 ; es el tiempo 0?
goto PLoop0 ; no, loop
decfsz PDel1, 1
goto loop
return
loop movlw 0x20 ; set numero de repetición
movwf PDel0
decfsz PDel0, 1 ; es el tiempo 0?
goto PLoop0 ; no, loop
End
La parte del programa:
movf TRISC,0 ;lee el PuertoC
movwf Dato ;guarda el resultado en dato
btfsc Dato,6
bsf Dato,3
btfsc Dato,7
bsf Dato,4
bcf Dato,6
bcf Dato,7
movf Dato,0 ;guarda el contenido de dato en el acumulador
Se debe a que reutilice una placa y, como podréis ver en el esquema, lleva conmutadores en los terminales RC0, RC1, RC2, RC6 y RC7.
El retardo es bastante fiable, la parte:
loop movlw 0x20 ; set numero de repetición
movwf PDel0
decfsz PDel0, 1 ; es el tiempo 0?
goto PLoop0 ; no, loop
La realicé debido a que al hacer un retardo mayor de 100us, no se lograba con exactitud, por eso, el ciclo de retardo (0x20) es mayor que en el anterior (0x1E).
Por último, aparte del código, adjunto
aqui:- el esquema en pdf
- el esquema en proteus
- una tabla con los ángulos y sus tiempos en alto y en bajo
Espero que os sea de ayuda!!!!
PD: los ángulos que gira el servo con el programa, son los tiempos que no son números periódicos de la tabla. El oscilador es un Xtal de 4MHz
Un saludo