Manejo de un servomotor con PIC 16F887

Hola! Soy nuevo en esto, busque informacion sobre el tema sin demasiado exito. Tengo problemas para manejar un servomotor con el modulo CCP2 del microcontrolador (PIC 16F887). Voy a utilizar un cristal de 20MHz. El lenguaje que debo utilizar es Assembler. Hasta ahora configure e inicie el modulo de la siguiente forma:

BANKSEL TRISA
MOVLW b´X1XXXXXX´ ; CONF. ENTRADA PIN MOD. CCP2
MOVWF TRISC
MOVLW 0 x XX ; 1° DUDA: QUE VALOR PONER?
MOVWF PR2
MOVLW b´--XX1111´
MOVWF CCP2CON ; ELIJO MODO PWM
BANKSEL PIR1
BCF PIR1,1
BSF T2CON,1 ; 2° DUDA: QUE Ps USAR? COMO LO DETERMINO?
BSF T2CON,2 ; INICIO TEMPORIZADOR
AQUI
BTFSS PIR2,TMR2IF
GOTO AQUI; DESB. TIMER
MOVLW b´XXXXXX0X´
MOVWF TRISC


Lei en el foro que los servomotores funcionan a 50 Hz.

Utilizando la ecuación:

periodoPWM=(PR2+1) x 4Tosc x Ps TMR2

y sabiendo que la frecuencia es igual a:

Frec= 1 / periodoPWM

Es imposible lograr 50 Hz, como manejo el servomotor?

Tampoco se como mover (en asm) el servomotor.

Desde ya muchas gracias!

Saludos!
 
hola!!! yo hace poco hice un pequeño proyecto dond emanejaba un servo, pero tuve que reducir la frecuencia de oscilacion bastante, o otra opción es hacer el pwm con temporizadores. De todas formas los pics de ahora pueden sintetizar diferentes frecuencias de reloj a partir de una sola, lee el datasheet que ahi te viene los registros que tienes que modificar para bajar la frecuencia de oscilación hasta 1MHz o incluso 32KHz.

Un saludo
 
El alcance que puedo darte es que te sera imposible maniobrar bien tu servomotor si utilizas
el modulo PWM del pic16f877, puesto que para que tu servo funcione bien debe tener un periodo
como minimo de 10 ms, y con el moludo PWM del pic solo puedes tener un periodo como
maximo de 4.096 ms (PR2=11111111) max valor.

Lo que sucede cuando tienes un periodo de 4.096 ms, es que si bien tu servo busca la posicion correcta de acuerdo al duty cycle, lo que obtendras seran vibraciones aun cuando el servo haya
alcanzado la posicion deseada. Lo que te recomiendo es que hagas tu propio PWM, osea setea un bit por un tiempo determinado, puede ser entre (1 a 2 ms, estos tiempos son de acuedo al servo que tengas, algunos varian) y limpias el mismo bit por 8 o 9 ms, recuerda que la suma de los tiempos en prendido y apagado de tu bit deben sumar como minimo 10 ms.

aqui te paso un programa mio hecho en assembler, espero te sirva, pues a mi me funciono.

list p=16f877
__CONFIG _BODEN_OFF & _WDT_OFF & _PWRTE_ON & _LVP_OFF & _XT_OSC
include <p16f877.inc>

org 0x00

El alcance que puedo darte es que te sera imposible maniobrar bien tu servomotor si utilizas
el modulo PWM del pic16f877, puesto que para que tu servo funcione bien debe tener un periodo
como minimo de 10 ms, y con el moludo PWM del pic solo puedes tener un periodo como
maximo de 4.096 ms (PR2=11111111) max valor.

Lo que sucede cuando tienes un periodo de 4.096 ms, es que si bien tu servo busca la posicion correcta de acuerdo al duty cycle, lo que obtendras seran vibraciones aun cuando el servo haya
alcanzado la posicion deseada. Lo que te recomiendo es que hagas tu propio PWM, osea setea un bit por un tiempo determinado, puede ser entre (1 a 2 ms, estos tiempos son de acuedo al servo que tengas, algunos varian) y limpias el mismo bit por 8 o 9 ms, recuerda que la suma de los tiempos en prendido y apagado de tu bit deben sumar como minimo 10 ms.

aqui te paso un programa mio hecho en assembler, espero te sirva, pues a mi me funciono.

list p=16f877
__CONFIG _BODEN_OFF & _WDT_OFF & _PWRTE_ON & _LVP_OFF & _XT_OSC
include <p16f877.inc>

PDel0 equ 0x20
PDel1 equ 0x21 ;declaracion de variables empleadas en PicDel

org 0x00

bcf status,7 ;me mantiene entre los banco 0 y 1
bcf status,6
bsf status,5 ;banco 1
movlw b'11111110'
movwf trisc ;configuro al bit 0 del puerto c como salida
bcf status,5 ;banco 0

;*****rutina de PWM*****

rutpwm bsf portc,0 ;seteo el bit 0 del puerto c
call retardo ;llamo a la subrutina de retardo, dura 1 ms
bcf portc,0 ;limpio el bit 0 del puerto c
call retardo ;llamo a la subrutina de retardo, dura 1 ms
.
.
.
;llamar 9 veces a la subrutina "retardo" despues de limpiar el bit 0 del puerto c
.
goto rutpwm

la rutina de "retardo" te recomiendo que la obtengas por medio del programa PicDel, es pequeño y puedes descargarlo gratis y facilmente de google, aqui te paso el link http://www.ziddu.com/download/5654504/PICDEL.EXE.html/eng es facil de utilizar y los retardos que obtienes son precisos, no te olvides de declarar las variables que te manda. no olvides de colocar END depues del RETURN de la subrutina retardo. el programa empleado es el
MPLAB.IDE v7.20, la señal de control de tu servo la conectas al pin 0 del puerto c del pic.

Espero mi aporte te haya sido de ayuda. Saludos
 
Última edición:
Hola buenas noches, recientemente he estado aprendiendo a programar PIC´s en ensamblador, tengo un problema en un programa que hice para controlar un servo, el hardware consta solo de un pulsador de entrada y la salida con el PWM conectada al servo, al presionar el botón la posición del servo debe de incrementarse desde su posición cero hasta sus 180° y si se sigue presionando va de regreso de 180° hasta su posición cero.
Hasta el momento tengo el siguiente programa, lo he simulado en MPLAB y por lo que puedo ver ya funciona como debería, al simular en proteus no funciona del todo bien, pues me aparecen pequeños pulsos cuando presiono el pulsador, ahora cuando lo arme en físico no funciona nada bien solo mueve el servo desde cero a 90° y se estanca en esa posición.

El tiempo de la señal es de 20ms, para el servo tiempo en alto: 600us ---> 0°, 1500us ---> 90°, 2400us--->180°

También cabe destacar que es la primera vez que trabajo con un servomotor y no se si sea de importancia pero los retardos los hice con picloops.

Disculpen si no lo hice de una forma más sencilla o con otras instrucciones, pero como dije anteriormente apenas estoy aprendiendo ensamblador y realicé el programa con lo poco que he aprendido.

Espero que alguien pueda ayudarme y gracias de antemano.

Código:
INCLUDE <P16F887.INC>
 LIST P=16F887
 __CONFIG _CONFIG1 , _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _PWRTE_OFF & _CP_OFF & _CPD_OFF & _BOREN_OFF
 CBLOCK  0X21
		CA,CB,CA1,CB1,CA2,CB2,SENTIDO,INDICE
		ENDC
			ORG 0X00
			CLRF SENTIDO
			CLRF INDICE
			BANKSEL TRISA
			MOVLW 0XF0
			MOVWF TRISD
			MOVLW 0X0F	
			MOVWF TRISB
			BANKSEL PORTD
			MOVLW 0X00
			MOVWF PORTD
			;MOVWF PORTB

MAIN		BSF PORTD,0
			MOVF CA1,W
			MOVWF CA
			MOVF CB1,W
			MOVWF CB
			CALL DELAY
			BCF PORTD,0
			MOVF CB2,W
			MOVWF CB
			MOVF CA2,W
			MOVWF CA
			CALL DELAY
			GOTO MAIN

DELAY		NOP
LOOP		BTFSC PORTD,7
			GOTO SIGUE
			DECFSZ CA
			GOTO LOOP
			DECFSZ CB
			GOTO LOOP
			RETURN



SIGUE 		MOVLW 0X09
			SUBWF INDICE,W
			BTFSS STATUS,Z
			GOTO SIGUE2
			MOVLW 0X01
			MOVWF SENTIDO
SIGUE2		MOVLW 0X00
			SUBWF SENTIDO,W
			BTFSS STATUS,Z  
			GOTO SIGUE3
			INCF INDICE
			GOTO SIGUE4
SIGUE3		;MOVLW 0X01
			;DECF INDICE
			MOVLW 0X00
			SUBWF INDICE,W
			BTFSS STATUS,Z
			GOTO DECRM   ;DECF INDICE
			CLRF SENTIDO
			RETURN
						
DECRM		DECF INDICE		

SIGUE4		CALL T1
			MOVWF CB1
			CALL T2
			MOVWF CA1
			CALL T3
			MOVWF CB2
			CALL T4
			MOVWF CA2
			RETURN
			
T1			MOVF INDICE,W
			ADDWF PCL
			RETLW D'2'
			RETLW D'3'
			RETLW D'3'
			RETLW D'4'
			RETLW D'4'
			RETLW D'5'
			RETLW D'5'
			RETLW D'6'
			RETLW D'6'
			RETLW D'7'

T2			MOVF INDICE,W
			ADDWF PCL
			RETLW D'141'
			RETLW D'17'
			RETLW D'151'
			RETLW D'27'
			RETLW D'161'
			RETLW D'37'
			RETLW D'171'
			RETLW D'47'
			RETLW D'181'
			RETLW D'57'

T3			MOVF INDICE,W
			ADDWF PCL
			RETLW D'51'
			RETLW D'50'
			RETLW D'50'
			RETLW D'49'
			RETLW D'49'
			RETLW D'48'
			RETLW D'48'
			RETLW D'47'
			RETLW D'47'
			RETLW D'46'

T4			MOVF INDICE,W
			ADDWF PCL
			RETLW D'98'
			RETLW D'221'
			RETLW D'87'
			RETLW D'211'
			RETLW D'77'
			RETLW D'201'
			RETLW D'68'
			RETLW D'191'
			RETLW D'57'
			RETLW D'181'
			END
 
Hola. Perdón si me equivoco, pero no es poco 50Hz para un motor? Una frecuencia más alta, como de 300Hz te iría bien, así el movimiento sería más fluido.

Con un pulso largo es poco preciso mover un motor; si cambia la temperatura o algo, se puede mover más o menos. Te recomiendo usar PWM a un duty alto al principio, y uno bajo al final, así el motor se mueve más despacio al final, y cuando frena casi no tiene inercia. Resulta en mejor precisión.

Respecto a ASM no sé nada, en eso no te puedo ayudar. Saludos.
 
Atrás
Arriba