Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

PWM and Servo, how important is the interval between pulses?

Status
Not open for further replies.

Windmiller

Member level 4
Member level 4
Joined
Mar 30, 2010
Messages
76
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Location
Sweden
Activity points
1,997
Hi!

I'm trying like many others to learn how to control a servo with in my case a PIC12F683 and a Futaba S3110 Servo.

What I've learnt is that a 1 ms long pulse will turn the servo to max ccw and 2 ms will turn it max to the other way, and 1.5 ms will center it.

The interval between the pulses should be between 10-20 ms

Code:
       1.5ms                           1.5ms
       <->                              <->
       ___                              ___
______|   |____________________________|   |__
      <--------------- 10-20ms-------->

I've tried to turn GP1 on in 1.5ms and then turn it off and have it turned off in 10ms which will be a sum of 11.5 ms that is between 10-20ms just like it should? This is working in the simulator of Proteus but not on the real thing, when trying. The servo is just going one way to max in every case, what am I missing?

My latest try in assembler:

Code:
	#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

My delay procedures were generated at this page Microchip PIC, ASM Delay Code, Code Generator

I have been trying several different interval settings, with no go.

Someone who would like to help me in this? Make me understand PWM and Servo.

Regards

/ Morgan
 

Hi


What pin are you using for the servo pulse?

Sorry just read it again and seen it.
 

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
 
Last edited:
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

Hello Stefaan

No I havn't, sadly..

/ Morgan

---------- Post added at 11:50 ---------- Previous post was at 11:44 ----------

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!

But I still don't get it?? What you are saying now is that the entire loop should take 20ms inluding pin low and high, but what about 10-20ms mentioned everywhere on the web?
Soo, I can't use my complete loop of 17.5 ms then? :/

Thanks

/ Morgan

---------- Post added at 11:53 ---------- Previous post was at 11:50 ----------

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

Thank you

What do you mean by "When I compilied for a 4Mhz 16f877 on dev board it worked.
". Did it work all the way? With servo and all?

/ Morgan


Thanks all of you for responding to my thread :)
 

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.
 

Attachments

  • ScreenShot001.jpg
    ScreenShot001.jpg
    29 KB · Views: 188
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.
 
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.

Ok, thank you wp100.. I'll try to use the PICKit2 logic analyzer, didn't know that it existsted.

Is it possible to connect the servos + and - to a completely different power supply than the one the PIC is connected to, with just the signal comming from the pic pulse pin to the Servo or do they have to have common GND with a transistor?

Regards

/ Morgan

---------- Post added at 16:04 ---------- Previous post was at 16:02 ----------

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.

Ok, thanks.. I'll then stick to that loop.

---------- Post added at 16:08 ---------- Previous post was at 16:04 ----------

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.

Ok thanks for taking the time to try it out, very interesting.. I will try the PICkit2 logic analyzer like wp100 wrote, and I will definitely reveal what's unseen. :)

Regards / Morgan
 

You need to have a common GNd between the pic and the servo otherwise the pulse will have no reference point.
 
Last edited:
You need to have a common GNd between the pic and the servo otherwise the pulse will have no reference point.

Thanks, done now!

And I've used the PICKit2 Logic Analyzer now, which gave me the corrrect result. The code and PIC is working like they should, there must be something wrong with my connections and the way I'm connecting it all together with the servo. I believe the problem lies within the voltage dip going on when the servo is taking too much voltage from the power supply.. since I don't have a proper supply, it has a voltage regulator but not power enough i think.

Like I said, it's working according to the logic analyzer software but the servo is going wild. I should double check the servo in the airoplane to see if it's really working :/

Regards

/ Morgan
 

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.
 

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.

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:

vm134.jpg


---------- Post added at 15:20 ---------- Previous post was at 15:19 ----------

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.

Okey, I will have that in mind thanks
 

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.
 
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.

I'll go over to the shop tomorrow on my way home from work and buy me a 7805, I was supposed to do so today but something came up. You are right, it might come in handy one day.. I'll connect it to the wall pack tomorrow and we'll see how it goes from there. Thank you for the guidance :)

Regards
Morgan
 

Aaaah it's done and everything is working I've also applied ADC with a POT as voltage devider controls the Servo.

Here's a video, it's just a quick setup and it's not perfekt.. but I can see it's working :)

Thanks all of you for the support you all have been giving me!

[video=facebook;1487055108749]http://www.facebook.com/video/video.php?v=1487055108749[/video]

Regards

/ Morgan
 

Glad to be of assistance :smile:
 

Now I have a very strange problem with the PWM and ADC..

I have a 10k potentiometer connected as a voltage divider to AN0 for ADC conversion, which is working like a charm exept in one single case and that's when the input voltage is round 0.95V. At this point the servo is going completely insane to the point where it should be and to the ccw max and back and fourth, but like I said only on input AN0 +0.95V that I've measured in the live going cirquit all other values is working fine with the servo.

Here's my code:

Code:
	#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

I just can't figure it out, what it could be? I've tried different servos and different POTs without any success.. it's driving me nuts here. Anyone who knows anything about this strange behaviour?

By the way.. I don't know if I'm exadurating with all of my BANKSEL in my code, but well..

Regards

/ Morgan
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top