| View previous topic :: View next topic |
| Author |
Message |
MichaelM
Joined: 13 May 2007 Posts: 57 Location: Michigan, USA
|
Posted: Sun Feb 10, 2008 3:04 am Post subject: |
|
|
Ok, sorry. I just didn't see where you setup the servo() array in that code and make the servos move back and forth.
I must say that "special event trigger" mode has some nice advantages (I've never used it before).
Your code looks nice and should work fine as long you prevent your servo() array values from approaching 2500 or whatever value you eventually use for the special event trigger. Not sure it's any easier or more intuitive though and using "special event trigger" and "compare" CCP modules will make it difficult setting up an odd number of servo outputs (1, 3, 5, etc). I think my code is simpler and a bit more flexible though I would change it to use "special event trigger" mode using a CCPR1 = Servo(n) assignment in the ISR.
I'm glad Phil was able to work through his problems. Way to go Phil... |
|
| Back to top |
|
 |
xor
Joined: 05 Nov 2006 Posts: 286 Location: NYC
|
Posted: Sun Feb 10, 2008 3:18 am Post subject: |
|
|
Mike,
I understand your approach, there is nothing wrong with it. My angle on it was to simply avoid the adding and subtracting to get to the end. In the overall progress of the thread I determined that this might be a viable alternative, and it worked for the application.
WS _________________ xor
CircuitED - US Distributor of the Swordfish Compiler |
|
| Back to top |
|
 |
MichaelM
Joined: 13 May 2007 Posts: 57 Location: Michigan, USA
|
Posted: Sun Feb 10, 2008 4:33 am Post subject: |
|
|
It is a viable alternative and should provide a perfect 20 msec servo period when used for 1, 2, 4, or 8 servos. There would be a problem with a servo() array value equal to 2500 but you can easily enforce an upper limit for the array values. It also uses twice as many interrupts per 20 msec servo period but that shouldn't be a problem unless you allow lower and upper array limit values approaching 0 and 2500 usecs, respectively.
We just have different considerations and approaches to solutions, that's all. I prefer 'simple' and 'low overhead' and feel your approach using 2 CCP modules is more complicated than need be (but magnitudes better than all of your old 256 step examples).
I would however modify my code to use the "special event trigger" (CCP1CON = %00001011) which really does fit this application better;
| Code: | ****************************************************************
* K8LH Hi-Rez Soft 8-chan PORTB 'special event trigger' mode *
****************************************************************
}
Interrupt Soft_Servo()
LATB = Servx ' output new Servo pulse
CCPR1 = Servo(n) ' setup next compare interrupt
Servo(8) = Servo(8)-Servo(n) ' adjust end-of-cycle off time
CCP1IF = 0 ' clear CCP1 interrupt flag
Servx = Servx << 1 ' move servo bit to the left
Inc(n) ' increment servo array index
If n = 9 Then ' if end of 20 msec period
n = 0 ' reset array index
Servo(8) = 20000 ' reset 20 msec servo period
Servx = 1 ' for Servo(0) -> '00000001'
EndIf '
End Interrupt
|
I suspect this code could be modified easily enough for conversion into a 'module' to support 1 to 8 servos on Port B. |
|
| Back to top |
|
 |
Philtkp
Joined: 18 Oct 2007 Posts: 90 Location: Tucson AZ
|
Posted: Sun Feb 10, 2008 3:04 pm Post subject: |
|
|
Michael,
I might have been doing something wrong when trying the code you posted. But I was having a problem gettng the servo to rotate in the opposite direction. For me this has been a great learning experience on the use of interrupts not to mention SF itself.
Thank you both |
|
| Back to top |
|
 |
MichaelM
Joined: 13 May 2007 Posts: 57 Location: Michigan, USA
|
Posted: Sun Feb 10, 2008 3:13 pm Post subject: |
|
|
Phil,
We're happy you're making progress and having fun at the same time.
If you find yourself short of I/O on a future project you might consider a 2 pin eight or nine Servo hardware method that uses a relatively inexpensive 74HC4017 'Johnson ring counter' IC. The drawing shows a 16F' device but you should be able to see how it would be connected to an 18F' device.
This method uses the CCP module "compare" mode to set the CCP1 pin on a 'match' which provides the rising edge on the '4017 'CLK' line that is used to shift or 'bump' the '4017 'Qn' output. We use eight or nine of the Qn outputs to drive Servos and the remaining unconnected Q0 output for the 'off time' to fill a 20 msec Servo period.
Define your CLK_pin (CCP1), CLR_pin, and other variables, dimension your arrays, then initialize the CCP module in "compare" mode and "set CCP1 on match". Here's an 'untested' driver example;
| Code: | {
****************************************************************
* K8LH Hi-Rez 8-channel 74HC4017 Servo Controller Algorithm *
****************************************************************
}
Interrupt Servo_8()
Pulse = CCPR1 + Servo(n) ' next 'compare' value
CCPR1H = Pulse.Byte1 '
CCPR1L = Pulse.Byte0 '
CLK_pin = 0 ' reset 74HC4017 <CLK> line
CCP1IF = 0 ' clear CCP1 interrupt flag
Servo(8) = Servo(8)-Servo(n) ' adjust end-of-cycle off time
Inc(n) '
If n = 9 Then ' if end of 20 msec period
n = 0 ' reset array index
Servo(8) = 20000 ' reset 20 msec servo period
CLR_pin = 1 ' toggle 74HC4017 <CLR> line
CLR_pin = 0 ' to force output Q0 re-sync'
EndIf '
End Interrupt
|
One not-so-obvious advantage of this and other 'hardware' methods over our 'software' methods is that you can take your sweet time servicing the interrupt because the CCP module provides the CLK signal no matter what the processor is doing and we have several hundred microseconds minimum to service that interrupt. This means you can disable interrupts in Main for several hundred milliseconds for time critical stuff, if needed, or service other time critical interrupts at the high priority vector and our Servo outputs will remain 'jitter' free.
BTW, a 4 pin sixteen or eighteen channel Servo solution can be done using a pair of 74HC4017 ICs and both CCP modules.
Regards, Mike
Last edited by MichaelM on Tue Feb 12, 2008 11:43 am; edited 3 times in total |
|
| Back to top |
|
 |
xor
Joined: 05 Nov 2006 Posts: 286 Location: NYC
|
Posted: Mon Feb 11, 2008 3:24 am Post subject: |
|
|
| MichaelM wrote: | | It is a viable alternative and should provide a perfect 20 msec servo period when used for 1, 2, 4, or 8 servos. |
Perfect is not a necessary criteria, and something that can't be rectified by using no prescaler, which raises the ante to 1/2 us resolution ( in our examples). Can't think of a servo responsive enough to a timing resolution that fine. Although setup in my example should not be a problem for any quantity up to 8 servos with max 2500us.
1 servo = 20000us period
2 servos = 10000us period
3 servos = 6666us period
4 servos = 5000us period
5 servos = 4000us period
6 servos = 3333us period
7 servos = 2857us period
| Quote: | | There would be a problem with a servo() array value equal to 2500 but you can easily enforce an upper limit for the array values. |
| Quote: | | It also uses twice as many interrupts per 20 msec servo period but that shouldn't be a problem unless you allow lower and upper array limit values approaching 0 and 2500 usecs, respectively. |
I don't see twice as many... please explain? Also, code overhead is pretty low in my ISR and elsewhere. Also, 0 "hold" position for most hobby servos is 300us and more. There should never be a real setting of 0us, otherwise the servo will not refesh and hold. The user should be aware of some limits in the software.
I suppose I don't understand the point of this. Is there a potential problem I am missing here? _________________ xor
CircuitED - US Distributor of the Swordfish Compiler |
|
| Back to top |
|
 |
dman776
Joined: 28 May 2007 Posts: 110 Location: Texas
|
Posted: Wed Jul 02, 2008 7:57 pm Post subject: |
|
|
| Michael, did you ever get this method (compare mode) working? |
|
| Back to top |
|
 |
MichaelM
Joined: 13 May 2007 Posts: 57 Location: Michigan, USA
|
Posted: Wed Jul 02, 2008 8:08 pm Post subject: |
|
|
| dman776 wrote: | | Michael, did you ever get this method (compare mode) working? |
It simulates ok but truthfully, I've never had a Servo to try it on...
Mike |
|
| Back to top |
|
 |
dman776
Joined: 28 May 2007 Posts: 110 Location: Texas
|
Posted: Wed Jul 02, 2008 9:40 pm Post subject: |
|
|
I have:
18F2420 @ 10Mhz (no PLL)
CCP1 (PORTC.2) connected to the 4017 CP1 (CLK) pin
PORTA.5 connected to the 4017 RES (reset/clr) pin
Code summary...
| Code: |
// Pin aliases
Dim LED As PORTC.0
Dim CLR_pin As PORTA.5
Dim CLK_pin As PORTC.2
dim i,x, n as byte
dim Pulse as Word
dim Servo(9) as Word
|
| Code: |
Utils.SetAllDigital()
TRISA = 0
TRISB = 0
TRISC = 0
T1CON = %10000000
CCP1CON = %00001000 ' compare mode
PEIE = 1
PIE1 = 0
PIE2 = 0
TMR1IE = 0
CCP1IE = 1
for x=0 to 7
Servo(x)= 1500
next
n =1
while true
toggle(LED)
delayms(500)
wend
|
And the ISR looks like:
| Code: |
Interrupt ISR()
if CCP1IF=1 then
Pulse = CCPR1 + Servo(n) ' next 'compare' value
CCPR1H = Pulse.Byte1 '
CCPR1L = Pulse.Byte0 '
CLK_pin = 0 ' reset 74HC4017 <CLK> line
CCP1IF = 0 ' clear CCP1 interrupt flag
Servo(8) = Servo(8)-Servo(n) ' adjust end-of-cycle off time
Inc(n) '
If n = 9 Then ' if end of 20 msec period
n = 0 ' reset array index
Servo(8) = 50000 ' reset 20 msec servo period
CLR_pin = 1 ' toggle 74HC4017 <CLR> line
CLR_pin = 0 ' to force output Q0 re-sync'
EndIf '
endif
end interrupt
|
I don't get any servo movement at all. Any ideas?[/code] |
|
| Back to top |
|
 |
MichaelM
Joined: 13 May 2007 Posts: 57 Location: Michigan, USA
|
Posted: Thu Jul 03, 2008 12:53 am Post subject: |
|
|
Do you have an Enable(ISR) statement in there somewhere?
Did you dimension CCP1IE and CCP1IF somewhere?
| Code: | Dim CCP1IF As PIR1.2 ' the CCP1 interrupt flag bit
Dim CCP1IE as PIE1.2 ' the CCP1 interrupt enable flag
|
Did you turn on Timer 1?
| Code: | // setup CCP1
T1CON = 0b10000001 // 1-------, RD16, enable 16 bit rd/wr
// -0------, T1RUN, 'other' source
// --00----, T1CKPS1:0, prescale 1:1
// ----0---, T1OSCEN, oscillator off
// -----0--, T1SYNC, n/a
// ------0-, TMR1CS, int Fosc/4 source
// -------1, TMR1ON, timer 'on'
|
Are you using a 4 MHz clock? Never mind, I see you're using 10 MHz. That's kind of a yucky frequency when using Timer 1 and it's limited prescaler settings.
Can you try using INTOSC at 4 MHz and fix your initialization code and let me (us) know if it works?
I'd still like to get a Servo to play with one of these days, when finances permit...
Mike |
|
| Back to top |
|
 |
bunny-rabbit
Joined: 18 Jan 2008 Posts: 42 Location: Emmen/ Netherlands
|
Posted: Thu Jan 22, 2009 2:01 pm Post subject: |
|
|
Hey!
I want to use 3 servo`s in a project, how do i connect the servo`s to the PIC?
And is the software easily converted to be used on 3 servo`s?
Greetz,
Gert |
|
| Back to top |
|
 |
Philtkp
Joined: 18 Oct 2007 Posts: 90 Location: Tucson AZ
|
Posted: Thu Jan 22, 2009 2:56 pm Post subject: |
|
|
You just need to connect the servos signal pin (normally white or yellow) to the pic. Here's a link to a sample schematic
Hope this helps
Heres a proteus screen capture using two servos. I was testing two seperate projects here  |
|
| Back to top |
|
 |
bunny-rabbit
Joined: 18 Jan 2008 Posts: 42 Location: Emmen/ Netherlands
|
Posted: Fri Jan 23, 2009 9:16 pm Post subject: |
|
|
This definitely helps!
Thanks! |
|
| Back to top |
|
 |
bunny-rabbit
Joined: 18 Jan 2008 Posts: 42 Location: Emmen/ Netherlands
|
Posted: Wed Feb 18, 2009 6:27 pm Post subject: |
|
|
I`m experimenting with xor`s code but i`m still not succesfull..
I am using a 20 mhz crystal is that the problem?
Gert |
|
| Back to top |
|
 |
Philtkp
Joined: 18 Oct 2007 Posts: 90 Location: Tucson AZ
|
Posted: Wed Feb 18, 2009 7:50 pm Post subject: |
|
|
Hi,
XOR wrote this for
device = 18F452
Clock = 8
The diagram posted also used a 8MHz crystal |
|
| Back to top |
|
 |
|