Ok, did some thinking, even easier plan to work with...
Set up an interrupt routine to trigger a TRM1 overflow. PIC16F628A (or whatever), TMR1 prescale 1:2, you get an overflow interrupt 38.14 times per second, giving you about 26.21ms between interrupts. A servo needs at most a 2.5ms pulse to work right, and as you've figured out, 38 times per second should be good enough to hold position.
So, you've got 26.21ms to work with, and 2.5ms for each servo. Should be able to handle 10 servo's here.
So here's what some code might look like:
Code:
....set up....
....Clear the pins, set up the variables, set up TMR1, set up the serial port, turn on TMR1 interrupts, turn on serial port receive interrupts
inthandler: 'each time TMR1 overflows
If TMR1 overflow interrupt
...clear the overflow flag
...put all servo pins low (even though they should be already)
...send out the pulse for servo 1 (all 2.5ms of it, high and low chunks included)
...send out the pulse for servo 2 thru 10 each in turn...
...check the RXIF flag in between each servo pulse, if there is one there, handle it in the main loop in the spare time after sending out all those pulses which probably won't total up to the total time between TMR1 interrupts...
...if the byte received by the serial port is an $FF, it'll mean that the next byte received is for servo 1, after that servo 2, after that servo 3, and so on... This will also mean that a servo cannot have a position of $FF, which is okay, you're only losing one position.
...if it's not an $FF, it's for the next servo position in turn...
RESUME
mainloop: 'handle the received serial bytes and save them in the respective servo position variables...
You get good enough framing for the individual servo pulses (about 38 per second), each servo gets the required 'high' time depending on the desired position, the rest of the time the pin is low (until the next TMR1 interrupt), and if you take care of the high and low time for each servo, in other words allotting 2.5ms per servo, each servo will get the right pulses at the same time in the TMR1 interrupt 'frame'...
Of course, you'll have to 'convert' your received byte value to a value that'll fit inside that 2.5ms window, not really that hard, just multiply it by 10 will get you the full window plus a bit, but that might be too much for the servo's themselves.
And if you're not using all 10 servo's, you could reload TMR1 with a 'correction value' and bring the refresh time for all the servo's up to 50hz. Theoretically, you should be able to drive 8 servo's at 50hz, but in a real world, probably only 7 because you'll have to have a bit of time left over for 'housekeeping' chores.
If I get ambitious, I'll write up some actual code...if I get ambitious
Bookmarks