No pude resistir la tentacion de hacer un programa (en realidad solo es la idea) para los 16 servos, hice lo que serian 3 secuencias una
todos a 90º (la que podria ser la posicion de partida) otra moviendolos de 4 en 4 en distintos angulos y otra moviendolos de 2 en 2.
Un par de aclaraciones sobre el programa, en POSICION_1, para moverlos de 4 en 4 lo hago con mascara, haciendo una "and" con un literal sobre el puerto en el que quiero escribir, de este modo los que estan a 0 en el literal quedaran en 0 y los que esten en 1 quedaran con
el valor que tengan, no variaran:
movlw 0XF0 ;para aplicar mascara, pone servos 0,1,2,3 a 0
andwf PORTB ;resto de PORTB queda como estaba
Hago una temporizacion de 1166us que corresponde a 60º, 666 de 60º mas 500us de 0º, esto lo hago porque doy por hecho que nunca va a haber ningun servo que tenga menos de 60º (en cada programa habra que ver cual es este minimo) asi me ahorro de hacer 6 llamadas a demora al principio de cada ciclo.
Cada secuencia se repite 10 veces por 20ms=200ms, despues si en la realidad va lento se disminuye esta numero y si va rapido se aumenta, tambien se podria tener en unas secuencias mas tiempo y en otras menos, si por ejemplo quieres hacerla bailar.
Tambien se puede hacer una temporizacion mas pequeña de 10º y asi se conseguirian movimientos mas reales, esto habra que ver en la practica como se comporta.
Esta hecho para un 16f887 pero se puede cambiar facil para otro 16f, lo depure en el MPLAB para que lo puedas simular y ver como funciona:
;Cuando son muchas salidas o muchas entradas, es mejor definirlos, asi cuando cambiemos algun pin
;no tendremos que modificar el programa, solo cambiar en el #DEFINE cual es su nueva ubicacion, ademas
;hace el programa mas comprensible tanto para el programador, como para algun colaborador que lo revise.
#DEFINE SERVO_0 PORTB,0
#DEFINE SERVO_1 PORTB,1
#DEFINE SERVO_2 PORTB,2
#DEFINE SERVO_3 PORTB,3
#DEFINE SERVO_4 PORTB,4
#DEFINE SERVO_5 PORTB,5
#DEFINE SERVO_6 PORTB,6
#DEFINE SERVO_7 PORTB,7
#DEFINE SERVO_8 PORTC,0
#DEFINE SERVO_9 PORTC,1
#DEFINE SERVO_10 PORTC,2
#DEFINE SERVO_11 PORTC,3
#DEFINE SERVO_12 PORTC,4
#DEFINE SERVO_13 PORTC,5
#DEFINE SERVO_14 PORTC,6
#DEFINE SERVO_15 PORTC,7
list p=16F887
#include P16F887.inc
;__CONFIG _33C4 _3FFF ; creo que asi esta bien para inter_osc 4Mz
ERRORLEVEL -305
ERRORLEVEL -302
CBLOCK 0X20
CONTADOR
PDel0
PDel1
ENDC
CONFIGURACION
banksel ANSEL ;seleccionamos banco 4
clrf ANSEL ;ponemos PORTA digital
clrf ANSELH ;ponemos PORTB digital
bcf STATUS,RP1
bsf STATUS,RP0 ;banco 1 para configurar puertos
clrf TRISB ;todas salidas
clrf TRISC ;todas salidas
movlw 0X06 ;0000 0110
movwf OPTION_REG ;TIMER0, PREESCALER 128
movlw 0X20 ;0010 0000
movwf INTCON ;activar TIMER0 sin interrupcion
bcf STATUS,RP0
clrf CONTADOR
;*************En POSICION_0 TODOS A 90º, para no hacer mas bucles de retardo*************
;*************llamaremos 1 vez bucle de 60º y 3 veces el de 10º**************************
POSICION_0
movlw 0XFF ;para poner a 1 todos los servos
movwf PORTB ;ya estan a 1 los del PORTB
movlw 0XFF ;para poner a 1 todos los servos
movwf PORTC ;ya estan a 1 los del PORTC
movlw .100 ;cargamos TIMER0 para 20ms
movwf TMR0
call DEMORA_60º ;llamamos DEMORA inicial, para servos con DUTTY 60º (minimo posible)
call DEMORA_10º ;llamamos bucle de 10º 3 veces para completar 90º
call DEMORA_10º
call DEMORA_10º
clrf PORTB
clrf PORTC ;ponemos todos lo duttys a 0, todos 90º
;aqui tienes mucho tiempo, minimo 17.5ms, ya que los tiempos en alto de los duttys son
;como maximo 2.5ms y el TIMER desborda a los 20ms, podrias ejecutar 17500 instrucciones
btfss INTCON,T0IF ;aqui esperamos desborde del TIMER0
goto $-1 ;no desbordo, espera
bcf INTCON,T0IF
incf CONTADOR,1 ;desbordo, contaremos los desbordes
movlw .10 ;contando 10 cada movimiento tardara 200ms
subwf CONTADOR,0 ;cuanto menor sea el numero mas rapido ira la araña
btfss STATUS,Z
goto POSICION_0 ;todavia no van 20 veces sigue en esta posicion
clrf CONTADOR ;cuando vayan 20 pasara a siguiente posicion
;*********Aqui vamos a poner servos 0,1,2,3 a 60º, servos 4,5,6,7 a 80º, servos 8,9,10,11 a 100º****
;**********servos 12,13,14,15 a 120º, son posiciones a modo de ejemplo****************************
POSICION_1
movlw 0XFF ;para poner a 1 todos los servos
movwf PORTB ;ya estan a 1 los del PORTB
movlw 0XFF ;para poner a 1 todos los servos
movwf PORTC ;ya estan a 1 los del PORTC
movlw .100 ;cargamos TIMER0 para 20ms
movwf TMR0
call DEMORA_60º ;llamamos DEMORA inicial, para servos con menor DUTTY
movlw 0XF0 ;para aplicar mascara, pone servos 0,1,2,3 a 0, 60º
andwf PORTB ;resto de PORTB queda como estaba
call DEMORA_10º ;llamamos DEMORA_10º equivalente a 10º
call DEMORA_10º ;2 veces para completar 80º, 60+10+10
movlw 0X0F ;mascara igual que antes pero para servos 4,5,6,7
andwf PORTB ;es lo mismo que hacer "bcf SERVO_4-bcf SERVO_5-bcf SERVO_6-bcf SERVO_7"
call DEMORA_10º
call DEMORA_10º ;2 demoras mas para 100º
movlw 0XF0 ;mascara igual que antes pero para servos 8,9,10,11
andwf PORTC ;es lo mismo que hacer "bcf SERVO_8-bcf SERVO_9-bcf SERVO_10-bcf SERVO_11"
call DEMORA_10º
call DEMORA_10º ;2 demoras mas para 120º
movlw 0X0F ;mascara igual que antes pero para servos 12,13,14,15
andwf PORTC ;es lo mismo que hacer "bcf SERVO_12-bcf SERVO_13-bcf SERVO_14-bcf SERVO_15"
;aqui tienes mucho tiempo, minimo 17.5ms, ya que los tiempos en alto de los duttys son
;como maximo 2.5ms y el TIMER desborda a los 20ms, podrias ejecutar 17500 instrucciones
btfss INTCON,T0IF ;aqui esperamos desborde del TIMER0
goto $-1 ;no desbordo, espera
bcf INTCON,T0IF
incf CONTADOR,1 ;desbordo, contaremos los desbordes
movlw .10 ;contando 10 cada movimiento tardara 200ms
subwf CONTADOR,0 ;cuanto menor sea el numero mas rapido ira la araña
btfss STATUS,Z
goto POSICION_1 ;todavia no van 20 veces sigue en esta posicion
clrf CONTADOR ;cuando vayan 20 pasara a siguiente posicion
;***********En esta posicion los pondremos de 2 en 2 en distisntos angulos, servo 0 y 1 en 60º**************
;***********2 y 3 en 70º y asi sucesivamente, al ir de 2 en 2 no lo haremos con mascara sino directamente****
POSICION_2
movlw 0XFF ;para poner a 1 todos los servos
movwf PORTB ;ya estan a 1 los del PORTB
movlw 0XFF ;para poner a 1 todos los servos
movwf PORTC ;ya estan a 1 los del PORTC
movlw .100 ;cargamos TIMER0 para 20ms
movwf TMR0
call DEMORA_60º ;llamamos DEMORA inicial, para servos con menor DUTTY
bcf SERVO_0 ;ponemos a 0 duttys de 60º
bcf SERVO_1 ;ponemos a 0 duttys de 60º
call DEMORA_10º ;llamamos DEMORA_10º equivalente a 10º
bcf SERVO_2 ;ponemos a 0 duttys de 70º
bcf SERVO_3 ;ponemos a 0 duttys de 70º
call DEMORA_10º ;llamamos DEMORA_10º equivalente a 10º
bcf SERVO_4 ;ponemos a 0 duttys de 80º
bcf SERVO_5 ;ponemos a 0 duttys de 80º
call DEMORA_10º ;llamamos DEMORA_10º equivalente a 10º
bcf SERVO_6 ;ponemos a 0 duttys de 90º
bcf SERVO_7 ;ponemos a 0 duttys de 90º
call DEMORA_10º ;llamamos DEMORA_10º equivalente a 10º
bcf SERVO_8 ;ponemos a 0 duttys de 100º
bcf SERVO_9 ;ponemos a 0 duttys de 100º
call DEMORA_10º ;llamamos DEMORA_10º equivalente a 10º
bcf SERVO_10 ;ponemos a 0 duttys de 110º
bcf SERVO_11 ;ponemos a 0 duttys de 110º
call DEMORA_10º ;llamamos DEMORA_10º equivalente a 10º
bcf SERVO_12 ;ponemos a 0 duttys de 120º
bcf SERVO_13 ;ponemos a 0 duttys de 120º
call DEMORA_10º ;llamamos DEMORA_10º equivalente a 10º
bcf SERVO_14 ;ponemos a 0 duttys de 130º
bcf SERVO_15 ;ponemos a 0 duttys de 130º
;aqui tienes mucho tiempo, minimo 17.5ms, ya que los tiempos en alto de los duttys son
;como maximo 2.5ms y el TIMER desborda a los 20ms, podrias ejecutar 17500 instrucciones
btfss INTCON,T0IF ;aqui esperamos desborde del TIMER0
goto $-1 ;no desbordo, espera
bcf INTCON,T0IF
incf CONTADOR,1 ;desbordo, contaremos los desbordes
movlw .10 ;contando 10 cada movimiento tardara 200ms
subwf CONTADOR,0 ;cuanto menor sea el numero mas rapido ira la araña
btfss STATUS,Z
goto POSICION_2 ;todavia no van 20 veces sigue en esta posicion
clrf CONTADOR
DEMORA_60º ; retardo inicial de 1166us, 666us proporcional ya que 2000us son 180º
; mas 500us que son 0º, 666+500=1166us
movlw .232 ; 1 set numero de repeticion
movwf PDel0 ; 1 |
PLoop0 clrwdt ; 1 clear watchdog
clrwdt ; 1 ciclo delay
decfsz PDel0, 1 ; 1 + (1) es el tiempo 0 ?
goto PLoop0 ; 2 no, loop
clrwdt ; 1 ciclo delay
return ; 2+2 Fin.
DEMORA_10º ; retardo de 111us, equivalente a 10º
movlw .26 ; 1 set numero de repeticion
movwf PDel0 ; 1 |
PLoop1 clrwdt ; 1 clear watchdog
decfsz PDel0, 1 ; 1 + (1) es el tiempo 0 ?
goto PLoop1 ; 2 no, loop
PDelL1 goto PDelL2 ; 2 ciclos delay
PDelL2
return ; 2+2 Fin.
END