Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:
Hola, tengo un problemilla con un servo. Utilizo un pic (12f683 o 16f84a) conectado a un servo. Con ambos pics obtengo la misma respuesta. El programa intenta realizar un movimiento del servo de 0 a 180 y que vuelva seguidamente, pero el resultado esque el servo vibra como si quisiese ir para ambos lados a la vez. Por más que leo por numerosos foros no encuentro solución al problema ya que parece ser a a nadie le a surgido.
Incluso poniendo un delay (5s) entre ambos movimientos para que diese tiempo a moverse sigue sin solucionarse.
¿a alguien le ha surgido este problema?
¿alguna solucion?
Dejo el codigo.
Gracias.
list p=12F683 ; list directive to define processor
#include <p12F683> ; processor specific variable definitions
errorlevel -302 ; suppress message 302 from list file
__CONFIG _FCMEN_ON & _IESO_OFF & _CP_OFF & _CPD_OFF & _BOD_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT
ORG 0X00
BANCO1
MOVLW b'01100001' ; Carga el acumulador, Ponemos el oscilador a 4Mhz
MOVWF OSCCON ; Copia de acumulador a OSCCON
GOTO INICIO
;-------------------------------- programa principal------------------------------------------
INICIO:
START BANCO0
MOVLW 07H
MOVWF CMCON0
CLRF GPIO ; Inicializamos GPIO (el registro gp3 es solo de entrada)
BANCO1
BCF TRISIO,5 ;Ponemos GP5 como salida
BANCO0
BCF GPIO,5
BANCO0
BANCO1
MOVLW B'01110000' ;Ponemos AN3, AN2, AN1 Y AN0 como salida digital
MOVWF ANSEL
BANCO0
LeerEntrada CALL Servo_pos_1
CALL Servo_pos_2
GOTO Fin
;--------------------------------------------------------------------
Servo_pos_1 BSF GPIO,5
movlw .248 ; 1 set number of repetitions
movwf PDel0 ; 1 |
PLoop01 clrwdt ; 1 clear watchdog
decfsz PDel0, 1 ; 1 + (1) is the time over?
goto PLoop01 ; 2 no, loop
PDelL11 goto PDelL21 ; 2 cycles delay
PDelL21 clrwdt ; 1 cycle delay
BCF GPIO,5
PDelay19 movlw .29 ; 1 set number of repetitions (B)
movwf PDel0 ; 1 |
PLoop119 movlw .93 ; 1 set number of repetitions (A)
movwf PDel1 ; 1 |
PLoop219 clrwdt ; 1 clear watchdog
PDelL119 goto PDelL219 ; 2 cycles delay
PDelL219 clrwdt ; 1 cycle delay
decfsz PDel1, 1 ; 1 + (1) is the time over? (A)
goto PLoop219 ; 2 no, loop
decfsz PDel0, 1 ; 1 + (1) is the time over? (B)
goto PLoop119 ; 2 no, loop
return
;------------------------------------------------------------------
;------------------------------------------------------------------
Servo_pos_2 BSF GPIO,5
movlw .249 ; 1 set number of repetitions
movwf PDel0 ; 1 |
PLoop02 clrwdt ; 1 clear watchdog
PDelL12 goto PDelL22 ; 2 cycles delay
PDelL22 goto PDelL32 ; 2 cycles delay
PDelL32
decfsz PDel0, 1 ; 1 + (1) is the time over?
goto PLoop02 ; 2 no, loop
PDelL42 goto PDelL52 ; 2 cycles delay
PDelL52 clrwdt ; 1 cycle delay
BCF GPIO,5
PDelay18 movlw .26 ; 1 set number of repetitions (B)
movwf PDel0 ; 1 |
PLoop118 movlw .172 ; 1 set number of repetitions (A)
movwf PDel1 ; 1 |
PLoop218 clrwdt ; 1 clear watchdog
decfsz PDel1, 1 ; 1 + (1) is the time over? (A);
goto PLoop218 ; 2 no, loop
decfsz PDel0, 1 ; 1 + (1) is the time over? (B)
goto PLoop118 ; 2 no, loop
PDelL118 goto PDelL218 ; 2 cycles delay
PDelL218 clrwdt ; 1 cycle delay
return
;------------------------------------------------------------------
Fin END
Proyectista, prueba a realizar uno solo de los movimientos a ver si te hace lo mismo. Luego hazlo con pulsadores, si pulsas el botón 1 haces el primer movimiento y si pulsas el botón 2 haces el segundo. Si todo esto te funciona pasa a hacerlo todo junto.
Usando los timers podrías hacer el posicionamiento del motor y controlar el tiempo de disparo con el mismo timer (se necesitan un par de variables).
Sería mas o menos así:
interrupcion Timer1()
{
si estamos en pulsoAlto
pulsoAlto --
si pulsoAlto == 0
pulsoBajo = 20ms
return
si estamos en pulsoBajo
pulsoBajo --
si pulsoBajo == 0
Delay = 5s
return
si estamos en Delay
Delay --
si Delay == 0
PulsoAlto = 1.5ms
return
}
main
{
PulsoAlto = 2.5ms
TimerOn()
while(1)
}
S2
Ranganok Schahzaman
en el libro "MICROCONTROLADOR PIC16F84. DESARROLLO DE PROYECTOS", E. Palacios, F. Remiro y L. López., Editorial Ra-Ma
aparece justamente un ejemplo para el control de servo que coincide con el movimiento de 0 a 180º.
te paso el código en privado porque creo que no se debe publicar.
salu2.
Ranganok esas pruebas las hice, y me funciona correctamente. Es decir, si pruebo un movimiento independiente lo hace correctamente. Si pruebo con un interruptor con el ejemplo de Chris también funciona correctamente. El problema viene cuando quiero enlazar dos movimientos seguidos y empieza a vibrar aunque ponga los delays. Estos dias probare algo similar a lo que me as comentado con las interrupciones, pero esque no entiendo muy bien lo que haces en ese esquema.
¿Me puedes explicar un poco lo que haces?
¿a cuanto inicializas el timer?
¿si quiero programar 3 interrupciones (una para verificar cada cuanto tiempo quiero realizar el movimiento, otra para mantener un pulso alto y otra para manterer un pulso bajo) como debo realizarlo?
Muchas gracias.
Proyectista, el timer lo inicializas a la frecuencia que sea común divisor entre el tiempo de repetición de pulsos, el ciclo de trabajo (tiempo de pulso en estado Alto) y el tiempo de delay (ms o decimas de ms tendrás sufiente)..
Lo que haces es utilizar variables para con un mismo timer decidir entre 3 estados. Pulso Alto, pulso Bajo y Delay. Durante Pulso Alto la salida del servo tiene que estar a 1 (lógicamente), durante Pulso Bajo la salida estara a 0, y durante el tiempo de Delay la salida debe estar como alta impedancia (como entrada vaya).
Dentro de la función de interrupción sólo se controlan los cambio de estado de las variables, y en programa principal se hacen las inicializaciones (antes del bucle principal) y el cambio de estado del puerto (dentro del bucle).
S2
Ranganok Schahzaman
Muchas gracias Ranganok. Tus respuestas me sirven de gran ayuda. Lo que pasa esque según voy programando en función de tus respuestas me surge alguna dudilla.
¿ dentro del bucle del programa principal, es donde se cambia de estado el puerto tanto para entrada-salida (alta impedancia en caso de ser entrada) como para modificar el dato de salida del puerto (0 o 1)? ¿o solo es para el cambio de entrada salida?
Saludos.