Swordfish Forum Index Swordfish
Structured BASIC for PICŪ Microcontrollers
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
  
modules, sample code and more...

RC servo control
Goto page Previous  1, 2, 3, 4, 5, 6  Next
 
Post new topic   Reply to topic    Swordfish Forum Index -> Compiler
View previous topic :: View next topic  
Author Message
MichaelM



Joined: 13 May 2007
Posts: 57
Location: Michigan, USA

PostPosted: Sun Feb 10, 2008 3:04 am    Post subject: Reply with quote

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
View user's profile Send private message
xor



Joined: 05 Nov 2006
Posts: 286
Location: NYC

PostPosted: Sun Feb 10, 2008 3:18 am    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
MichaelM



Joined: 13 May 2007
Posts: 57
Location: Michigan, USA

PostPosted: Sun Feb 10, 2008 4:33 am    Post subject: Reply with quote

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
View user's profile Send private message
Philtkp



Joined: 18 Oct 2007
Posts: 90
Location: Tucson AZ

PostPosted: Sun Feb 10, 2008 3:04 pm    Post subject: Reply with quote

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
View user's profile Send private message
MichaelM



Joined: 13 May 2007
Posts: 57
Location: Michigan, USA

PostPosted: Sun Feb 10, 2008 3:13 pm    Post subject: Reply with quote

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
View user's profile Send private message
xor



Joined: 05 Nov 2006
Posts: 286
Location: NYC

PostPosted: Mon Feb 11, 2008 3:24 am    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
dman776



Joined: 28 May 2007
Posts: 110
Location: Texas

PostPosted: Wed Jul 02, 2008 7:57 pm    Post subject: Reply with quote

Michael, did you ever get this method (compare mode) working?
Back to top
View user's profile Send private message
MichaelM



Joined: 13 May 2007
Posts: 57
Location: Michigan, USA

PostPosted: Wed Jul 02, 2008 8:08 pm    Post subject: Reply with quote

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
View user's profile Send private message
dman776



Joined: 28 May 2007
Posts: 110
Location: Texas

PostPosted: Wed Jul 02, 2008 9:40 pm    Post subject: Reply with quote

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
View user's profile Send private message
MichaelM



Joined: 13 May 2007
Posts: 57
Location: Michigan, USA

PostPosted: Thu Jul 03, 2008 12:53 am    Post subject: Reply with quote

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
View user's profile Send private message
bunny-rabbit



Joined: 18 Jan 2008
Posts: 42
Location: Emmen/ Netherlands

PostPosted: Thu Jan 22, 2009 2:01 pm    Post subject: Reply with quote

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
View user's profile Send private message
Philtkp



Joined: 18 Oct 2007
Posts: 90
Location: Tucson AZ

PostPosted: Thu Jan 22, 2009 2:56 pm    Post subject: Reply with quote

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
View user's profile Send private message
bunny-rabbit



Joined: 18 Jan 2008
Posts: 42
Location: Emmen/ Netherlands

PostPosted: Fri Jan 23, 2009 9:16 pm    Post subject: Reply with quote

This definitely helps!

Thanks!
Back to top
View user's profile Send private message
bunny-rabbit



Joined: 18 Jan 2008
Posts: 42
Location: Emmen/ Netherlands

PostPosted: Wed Feb 18, 2009 6:27 pm    Post subject: Reply with quote

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
View user's profile Send private message
Philtkp



Joined: 18 Oct 2007
Posts: 90
Location: Tucson AZ

PostPosted: Wed Feb 18, 2009 7:50 pm    Post subject: Reply with quote

Hi,

XOR wrote this for

device = 18F452
Clock = 8

The diagram posted also used a 8MHz crystal
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Swordfish Forum Index -> Compiler All times are GMT
Goto page Previous  1, 2, 3, 4, 5, 6  Next
Page 5 of 6

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group