1.5ms 1.5ms
<-> <->
___ ___
______| |____________________________| |__
<--------------- 10-20ms-------->
#include "p12f683.inc"
LIST P=PIC12F683
__CONFIG _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _WDT_OFF & _PWRTE_OFF
; Define variables used
CBLOCK 0x20
d10ms1 ; 10 ms delay part 1
d10ms2 ; 10 ms delay part 2
d1
d2
ENDC
ORG 0x00
init:
BANKSEL TRISIO ;
MOVLW b'00000000' ; Set GPIO to output
MOVWF TRISIO
BANKSEL GPIO
CLRF GPIO
BANKSEL ANSEL ;
CLRF ANSEL ; digital I/O
BANKSEL CMCON0
MOVLW 0x07 ; Turn comparator off
MOVWF CMCON0
BANKSEL GPIO
loop:
MOVLW b'11111110' ; Turn them all on, pulse on
MOVWF GPIO ;
CALL Delay1_5ms ; Servo delay 1.5 ms pulse
CLRF GPIO ; Turn them off, no more pulse
CALL Delay10ms ; Run 10 ms delay
GOTO loop ; Start over
Delay10ms:
MOVLW 0xCF
MOVWF d10ms1
MOVLW 0x08
MOVWF d10ms2
Delay10ms_0
DECFSZ d10ms1, f
GOTO $+2
DECFSZ d10ms2, f
GOTO Delay10ms_0
GOTO $+1
RETURN
Delay1_5ms
movlw 0x2B
movwf d1
movlw 0x02
movwf d2
Delay_0
decfsz d1, f
goto $+2
decfsz d2, f
goto Delay_0
goto $+1
return
END
init:
BANKSEL GPIO
CLRF GPIO
BANKSEL CMCON
MOVLW 0x07 ; Turn comparators off
MOVWF CMCON ; ANSEL is not needed because
BANKSEL TRISIO ; your code is outputting on the
CLRF TRISIO ; pin and not acting as an input
BANKSEL GPIO
loop:
BSF GPIO,1 ; Set pin GPIO,1 high
CALL Delay1_5ms ; Servo delay 1.5 ms pulse
BCF GPIO,1 ; Turn them off, no more pulse
CALL Delay10ms ; Run 10 ms delay
GOTO loop ; Start over
Do you have access to an oscilloscope? Can you verify in some way that the pulsed output is correct? This should be the fastest way to see if the problem is related to the servo or the code you have written.
Stefaan
Controlling a servo is a little more involved than this code. See if the information from this link Controlling a Servo helps you to understand how to control the servo from a PIC.
"Servos are controlled with a 5vdc positive-going variable pulse width that repeats every 20mS. The pulse length determines the servo output shaft position but the 20mS frame rate is not position critical. The frame rate does need to repeat at least every 20mS or it will lose power or even stutter. The servo was designed for pulse widths that vary from 1.0mS to 2.0mS, where 1.5mS is centered. In the normal range the servo will move +/- 45 degrees from the centered (neutral) position.
Most servos can be positioned to around +/- 90 degrees from neutral by expanding the range to 0.75mS to 2.25mS. However, care must be taken to avoid commanding a servo beyond its capabilities. Personal experience with Hitec servos reveals all of the standard size servos can achieve a full 180 degree range. Micro and special purpose servos are often limited to less than 180 degrees."
So your entire loop should take 20ms including both when the pin is low and high; The amount of time the PIC pin is high will range from .75ms to 2.25ms in most cases.
Hi
I have played with your code on 12f675 and my scope the pulses are there but the timing needs to be set. It code be the int oscillator was off.
I have made your code a bit more readable in one section
Code:init: BANKSEL GPIO CLRF GPIO BANKSEL CMCON MOVLW 0x07 ; Turn comparators off MOVWF CMCON ; ANSEL is not needed because BANKSEL TRISIO ; your code is outputting on the CLRF TRISIO ; pin and not acting as an input BANKSEL GPIO loop: BSF GPIO,1 ; Set pin GPIO,1 high CALL Delay1_5ms ; Servo delay 1.5 ms pulse BCF GPIO,1 ; Turn them off, no more pulse CALL Delay10ms ; Run 10 ms delay GOTO loop ; Start over
I think you may need to resolve your timings, When I compilied for a 4Mhz 16f877 on dev board it worked.
HTH
Hi,
Well have just got a servo motor and was wanting to test it, so used your code and it works fine, although as the required pulse is 10-20ms I think I would aim for around 15ms rather than your 10ms pulse.
You can check your timings with MPlab Sim Stopwatch or check the pulses on a Pickit2 logic analyzer function if you have one, or the software oscilloscope of a full Simulator.
The specifications for servo control state that a pulse should be sent every 20ms. However, depending on the servo, this frame rate is flexible. Your loop of 17.5 ms is probably close enough to work for most servos.
Hi
I took your code for the delays etc and modified the port to use a port on 16f877. The pic is running at 4Mhz and the servo moved to the required position.
You need to have a common GNd between the pic and the servo otherwise the pulse will have no reference point.
Hi,
Well I have a little Hitec HS311 and it takes about 7ma stationary and around 170ma when moving.
You don't say what your motor is like or what psu you have ..? - if its a 5v 100ma regulator probably too small.
Hi,
Well I have a little Hitec HS311 and it takes about 7ma stationary and around 170ma when moving.
You don't say what your motor is like or what psu you have ..? - if its a 5v 100ma regulator probably too small.
Also be aware of what you are controlling, if the servo stalls the current drain will increase. Digital servos also draw more current that standard ones.
Ok, I'm using a Futaba S3110 and as PSU I'm using the +5V and GND from the ISCP on my old velleman vm134 programmer. On the vm134 cirquit there's a 7812CV voltage regulator (out 12V 1A, but still +5V from the ISCP bus, can't be much current going out here though it is only made for programming). Here is an image:
Hi
Well without seen a circuit diagram its hard to say how much current is available from that 5v point - I would assume not a lot if your motor does not work properly.
Would avoid connecting like that incase you destroy something on the programmer board - it might still prove useful.
Probably be better using a 7805 1Amp regulator to run off your wall pack or a 4.5v battery pack.
#include "p12f683.inc"
LIST P=PIC12F683
__CONFIG _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _WDT_OFF & _PWRTE_OFF
; Define variables used
CBLOCK 0x20
d16ms1 ; 16 ms delay part 1
d16ms2 ; 16 ms delay part 2
pwm1 ; PWM Delay part low part
pwm2 ; PWM Delay part high part
ENDC
ORG 0x00
init:
BANKSEL TRISIO ;
MOVLW b'00000001' ; Set GP0 to input
MOVWF TRISIO
BANKSEL ANSEL ;
MOVLW B'01110001' ; ADC Frc clock,
IORWF ANSEL ; and GP0 as analog
BANKSEL ADCON0 ;
MOVLW B'10000001' ; Right justify,
MOVWF ADCON0 ; Vdd Vref, AN0, On
CALL Delay16ms ;
BANKSEL 0
CLRF GPIO
BANKSEL ANSEL ;
CLRF ANSEL ; digital I/O
BSF ANSEL, 0 ; Set GP0 as analog
BANKSEL CMCON0
MOVLW 0x07 ; Turn comparator off
MOVWF CMCON0
loop:
BANKSEL ADCON0 ;
BSF ADCON0, GO ; Start conversion
BTFSC ADCON0, GO ; Is conversion done?
GOTO $-1 ; No, test again
BANKSEL ADRESL ;
MOVF ADRESL, W ; Read lower 8 bits
BANKSEL pwm1 ;
MOVWF pwm1 ; Store in pwm1
BANKSEL ADRESH ;
MOVF ADRESH, W ; Read high 8(2) bits
BANKSEL pwm2 ;
MOVWF pwm2 ; Store in pwm2
INCF pwm2, f ; Add one for the Servo Delay
BSF GPIO, 1 ; Turn pulse on
CALL DelayPWM ; Servo delay based on pwm_m1 and 2
BCF GPIO, 1 ; Turn pulse off
CALL Delay16ms ; Run 16 ms delay
GOTO loop ; Start over
Delay16ms:
MOVLW 0xEF
MOVWF d16ms1
MOVLW 0x0B
MOVWF d16ms2
Delay16ms_0
DECFSZ d16ms1, f
GOTO $+2
DECFSZ d16ms2, f
GOTO Delay16ms_0
GOTO $+1
RETURN
DelayPWM
DECFSZ pwm1, f
GOTO $+2
DECFSZ pwm2, f
GOTO DelayPWM
GOTO $+1
RETURN
END
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?