Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Software PWM for 2 servos

Status
Not open for further replies.

garmcqui

New Member
Hi all,

I'm new to PIC programming, but I want to create a very simple software PWM which will controll 2 servos according to the data received via RS232. I am using the PIC16F628.

The data will arrive at the USART in the following format:

**broken link removed**

Obviously the first byte can be discarded once received. The second byte determines which pin of Port B to use. The third byte determines the position of the servo addressed in byte 2.

The value of byte 3 can range from 0 to 255 (with only odd numbers being used to simplify it) so that 0 = 1ms pulse, 255 = 2ms pulse. I

Is a lookup table with 128 lines needed or is there a simpler way of doing it?

Also, can the timer value be adjusted with such accuracy, as the difference between pulses is around 0.0078125ms?

Any help is greatly appreciated, as this is getting over my head[:(][:(]


The PCB is built and simplified schematic can be seen by clicking on the following thumbnail:

**broken link removed**



Thanks,

Gareth
 
garmcqui said:
I'm new to PIC programming, but I want to create a very simple software PWM which will controll 2 servos according to the data received via RS232. I am using the PIC16F628.

Obviously the first byte can be discarded once received. The second byte determines which pin of Port B to use. The third byte determines the position of the servo addressed in byte 2.

The value of byte 3 can range from 0 to 255 (with only odd numbers being used to simplify it) so that 0 = 1ms pulse, 255 = 2ms pulse. I

Is a lookup table with 128 lines needed or is there a simpler way of doing it?

For a start make it simpler!, there's no need to have full 8 bit resolution for the servo pulses, the servo itself doesn't give that degree of precision, so it's just a waste.

However, for now I'll assume the MAXIMUM value is 250 (rather than 255), as it makes life much easier. Simply use the received value (from 0 to 250) as the counter in a loop - the inner part of the loop should be a simple delay of 4uS (you should also account for the loop time in the 4uS). You need two actual loops, the first (which is always 250) delays the fixed 1mS, the second (which uses the variable) delays between 0mS and 1mS - giving the required 1mS-2mS pulse width.

So simply set the output pin HIGH, called the fixed delay, call the variable delay, then set the pin LOW again.

You can then repeat the procedure for the second servo pulse.

Bear in mind the pulse repetition frequency of servo pulses is 20mS, however this isn't at all critical, only the width of the pulses is.

Depending on the actual RS232 control data you may have to use interrupts to receive the data, triggered by the hardware USART. It really depends on what is generating the data - if you send updated values every 20mS, that would automatically give you the required repetition timing, and you could use software polling to receive the RS232.
 
cheers nigel.

The software delays I have been working with are in the format shown below (for 50ms delay using a 4MHz clock):

Code:
delay	movlw		 .65		   ; 1 Cycle(1)
	     movwf		 value1		; 1 Cycle(1)
outer	movlw		 .255		  ; 1 Cycle Repeated 65 Times(65)
	     movwf		 value2		; 1 Cycle Repeated 65 Times(65)
inner	decfsz		value2		; 256 Cycles  Repeated 65 Times (16640)
	     goto		  inner		 ; (2x254) Cycles Repeated 65 Times(33020)
	     decfsz		value1		; 1 Cycle Repeated 64 Times (+2)		(66)
	     goto		  outer		 ; 2 Cycles Repeated 64 Times(128)

        return

Could this code be modified to produce the 0-1ms delay required?
 
I have since devised the following simple delay:


Code:
delay   movlw  	.250        ; 1 cycle 
        movwf     value1      ; 1 cycle 

        inner     nop
	     decfsz    value1      ; 249 + 2 = 251
        goto      inner       ; 2 x 249 = 498     

	     return


RESULTS:

At .250 delay = 1.001ms (1001 cycles)

At .125 delay = 0.501ms (501 cycles)

At .1 delay = 0.005ms (5 cycles)

I think your idea has worked!!!

Thanks, gareth
 
Yes thanks Nigel, works a treat! :D :D :D

The way the program works now is that each of the 2 servos is sent a pulse one after another, then there is a delay (which varies between 19.5 & 20.5ms) before the next pulses.

This is a conatant loop of sending pulses, so how do I break this loop to update the positions with newly received data from the USART. All that needs to happen is:

1. Discard Synchronisation Byte

2. Read byte 2

3. Depending on what byte 2 is, store received byte 3 in one of 2 memory locations (position1 and position2).

Could this be done in the main code without affecting the delays too much, or can it be done by interrupt etc?

I was thinking of shortening the 20ms delay and adding the code in after this, but keeping the overall processing time close to 20ms?

Thanks for all the help so far,

Gareth
 
garmcqui said:
Yes thanks Nigel, works a treat! :D :D :D

Could this be done in the main code without affecting the delays too much, or can it be done by interrupt etc?

I was thinking of shortening the 20ms delay and adding the code in after this, but keeping the overall processing time close to 20ms?

As I mentioned originally, you could either do it with interrupts, or during the 20mS 'dead' time. As I also mentioned, there's no need to keep the overall time close to 20mS - it doesn't have any effect on servo positioning - 10mS would be fine, as would 40mS (or longer). The only problem with making it too long is that is slows down servo updating. With 20mS the servos can change position 50 times a second, with 40mS it's down to 25 times a second.
 
cheers mate,

I'll have a go fiddling about with the USART and getting the data to store in registers, ready to work with the software PWM.

I'd love to say I won't need help but in al probability I will, hehe.

cheers,

gareth
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top