Servo Jumpy with DT Interrupt


Closed Thread
Results 1 to 10 of 10
  1. #1

    Default Servo Jumpy with DT Interrupt

    I'm running a servo with a PBP routine which use the pulseout funtion to generate the required servo pulse width, followed by a pause to fill out the normal 20 ms servo time frame. A loop keeps the servo running continuously. I keep track of time by counting the number of 50 hz frames. The servo is quiet and moves smoothly in response to changes in pulse width.

    In an effort to increase the accuracy of timekeeping, I recently added an Elapsed Timer using DT interrupts. It's a 100 hz timer set up to accumulate seconds and tenths of seconds. It works well. However, the servo is now twitching while the the interrupt routine is running. Why is this? Does PBP use the same Timer1 that the interrupt counter is using? Is there a possible interaction that accounts for the servo's jumpiness? Is there a fix?

    BTW, pic is 16F690.
    Last edited by Dick Ivers; - 29th November 2010 at 01:08. Reason: Add info

  2. #2
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    966


    Did you find this post helpful? Yes | No

    Default

    The reason for the twitching is simply the way interrupts work. When an int occurs, it 'bites' away time from the main code which is executing. In your case, this main code happens to be doing the pulsout function. The int could be disturbing this by an amount equal to the executing time of the interrupt routine.

    The way around it - have a variable that tells the int how much pulsewidth you need to be sent to the servo. then in the int, which is always running, you send this pulsewidth to the servo. This way you will avoid the pulsout. Now, there will be no twitching

    Hope this helps

  3. #3
    Join Date
    Aug 2006
    Location
    Look, behind you.
    Posts
    2,818


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by Dick Ivers View Post
    I'm running a servo with a PBP routine which use the pulseout funtion to generate the required servo pulse width, followed by a pause to fill out the normal 20 ms servo time frame. A loop keeps the servo running continuously. I keep track of time by counting the number of 50 hz frames. The servo is quiet and moves smoothly in response to changes in pulse width.

    In an effort to increase the accuracy of timekeeping, I recently added an Elapsed Timer using DT interrupts. It's a 100 hz timer set up to accumulate seconds and tenths of seconds. It works well. However, the servo is now twitching while the the interrupt routine is running. Why is this? Does PBP use the same Timer1 that the interrupt counter is using? Is there a possible interaction that accounts for the servo's jumpiness? Is there a fix?

    BTW, pic is 16F690.
    Hi Dick,
    _With no disrespect to Jerson, as what he said is likely 100 percent right . . .
    and keeping in mind, I who am NO expert, have not played with a servo in a very long time . . .

    I seem to remember the servos jerking, each time the loop ran using software PWM or pulseout, as I remember it ran fine using HPWM.
    Last edited by Archangel; - 29th November 2010 at 03:03.
    If you do not believe in MAGIC, Consider how currency has value simply by printing it, and is then traded for real assets.
    .
    Gold is the money of kings, silver is the money of gentlemen, barter is the money of peasants - but debt is the money of slaves
    .
    There simply is no "Happy Spam" If you do it you will disappear from this forum.

  4. #4
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    966


    Did you find this post helpful? Yes | No

    Default

    Hi Joe

    Your observation seems to confirm what I'm saying. All software timed processes like Serout or Pulsout are affected by interrupts biting into their timing. I have had this experience before with regards to Serin and Serout. HPWM is a hardware timed process as is HSERIN or HSEROUT which work with devices that have the relevant hardware built in. Unfortunately, there is no HPULSIN or HPULSOUT in PbP.

    I haven't used servos at all

  5. #5
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,648


    Did you find this post helpful? Yes | No

    Default

    Hi, Dick

    In an effort to increase the accuracy of timekeeping
    Could you just explain what you want to do ???

    if you want your servo to work properly ...

    OR you disable interrupts while the PULSOUT Command ...

    OR you place the PULSOUT Command into the interrupt stubb ...

    BUT you must not interrupt the Pulsout command.

    So, I do not think you can reach your goal, if you keep a RTC timer interrupt period that is lower than the PULSOUT max duration ...

    Now ... I do not see any other way using pure PBP and Elapsed Timer with a 16F690 ... as it needs Timer 1.

    Alain
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  6. #6
    Join Date
    Aug 2005
    Location
    Michigan, USA
    Posts
    224


    Did you find this post helpful? Yes | No

    Default

    Have you considered using the PWM module? Many people don't realize you can run the PWM module at very low frequencies by using a software "helper" ISR (interrupt service routine) to link together several much smaller/faster PWM period "frames" to form a much longer/slower overall period.

    This method provides many of the advantages of the PWM module (zero jitter, interrupt tolerant, very high resolution pulse width, etc.) at the cost of using a small low overhead ISR software "helper". You can also use the 1-msec interrupt interval as a basis for timer operations.

    Perhaps one of the PBP gurus can convert, test, and qualify this code for you?

    Happy Holidays!

    Mike, K8LH

    Code:
      //  setup a 1000 usec PWM period with PR2 = 249 and prescaler
      //  16:1 (16 MHz clock) or 4:1 (4 MHz clock) and then link 20
      //  of these 1000 usec PWM "frames" together to form the much
      //  longer 20-ms servo period (1-usec pulse width resolution)
    
      int servo = 1500;            // 0..20000 in 1 usec steps
      int frame = 1;               // frame number 1..20
    
      void interrupt()             //
      { int width;                 // work variable
        pir1.TMR2IF = 0;           // clear Timer 2 interrupt flag
        frame--;                   //
        if (frame == 0)            // if end of the 20 msec period
        { frame = 20;              // reset for new 20 msec period
          width = servo;           // reset 'width' work variable
        }
        if ((width > 1000)         // if width > 1000 usecs
        { ccpr1l = 250;            // do a 100% duty cycle frame
          ccp1con.CCP1Y = 0;       //
          ccp1con.CCP1X = 0;       //
          width -= 1000;           // subtract 1000 usecs
        }
        else                       // else do a 0..1000 usec frame
        { ccpr1l = (width >> 2);   // 0..250 (0..1000 usecs)
          ccp1con.CCP1Y = (width & 1);
          ccp1con.CCP1X = (width & 2);
          width = 0;               // force remaining frames to 0%
        }
      }
    Last edited by Mike, K8LH; - 1st December 2010 at 02:15.

  7. #7
    Join Date
    Feb 2006
    Location
    Gilroy, CA
    Posts
    1,530


    Did you find this post helpful? Yes | No

    Default

    That is interesting Mike. I had not seen that before. (ccp1x, ccp1y, and the register for ccpr1l are different on the 16f690, so some tinkering required).

    You could also use Darrel's 18F servo code: http://www.picbasic.co.uk/forum/cont...e-Servo-Driver

    If you are not tied to hardware, you could do it (almost) exclusively in hardware with a 18f2431 or a 18f4431 chip. These allow PWM down to 19 hertz on their power control pwm port pins. They have a "single shot mode" which gives the servo a single shot pulse. An interrupt would run at 20 ms to tell the single shot pulse widths when to fire. See the bottom of this wiki for more info: http://www.picbasic.co.uk/forum/cont...-encode-decode
    Last edited by ScaleRobotics; - 1st December 2010 at 16:16.
    http://www.scalerobotics.com

  8. #8


    Did you find this post helpful? Yes | No

    Default

    Guys,

    Thanks for the suggestions. I'll follow your tips and see where they lead. It the meantime, here is a sample of the code that causes the servo to twitch.

    I've observed that the jumps occur about 2 times per second, and are in a direction that a longer pulse width would cause. This supports Jerson's idea that the interrupt service is periodically adding to the pulse width. Maybe it would help if the ISR were written is assembly and therefore be faster?

    Code:
    '****************************************************************
    '*  Name    : servo_demo.pbp                                     *
    '*  Author  : Dick Ivers                                         *
    '*  Date    : Nov 30, 2010                                       *
    '*  Notes   : This is a simplistic demo of servo w/Elapsed Timer *
    '****************************************************************
    '435 program words
    'device is PIC 16F690
     '****************************************************************
    'set device configuration
    @ __config _HS_OSC & _WDT_ON & _MCLRE_ON & _CP_OFF
    
    'set registers
            CM1CON0.7 = 0        'comparator1 off
            CM2CON0.7 = 0        'comparator2 off
            ANSEL = 0            'porta pins all digital 
            ANSELH = 0           'all porta pins digital
    
            DEFINE OSC 16          '16 Mhz oscillator
     
    'declare variables
            led       var portc.5      'led output on portc.5
            servopos  var word
            runtime   var word         'motor runtime in tenths of seconds
    
    start: 
            low led      'flash red LED for 0.5 sec to show circuit is functioning
            pause 500
            high led     'turn off led
    
    
    INCLUDE "DT_INTS-14.bas"      'Base interrupt system
    INCLUDE "ReEnterPBP.bas"      'Using PBP interrupts
    INCLUDE "Elapsed_INT_RI2.bas" 'Elasped timer counting seconds and tenths seconds
    
    ASM
    INT_LIST  macro     ; IntSource,        Label,  Type, ResetFlag?
             INT_Handler   TMR1_INT,  _ClockCount,   PBP,  yes
        endm
        INT_CREATE            ; Creates the interrupt processor
    ENDASM
    
    @    INT_ENABLE  TMR1_INT         ; Enable Timer 1 Interrupts  
    
            runtime = 100             ' run servo for 10.0 seconds
            servopos = 600            ' hold at mid servo range (4*150)
            gosub ResetTime           ' Reset Time to  0d-00:00:00.00
            gosub StartTimer          ' Start the Elapsed Timer
            low Led                   'turn on led
            low portc.4               'turn on servo 
    main:  
            pulsout portc.0,servopos
            pause 18
             if time => runtime then     'stop servo when target time is reached
             high led                    'turn off led
             goto hold
            endif
            goto main                   'loop until endtime is reached
            
    hold:   
    @    INT_DISABLE  TMR1_INT          ; Disable Timer 1 Interrupts  
            high portc.4                'turn off servo
            end
    Attached Files Attached Files

  9. #9
    Join Date
    Aug 2005
    Location
    Michigan, USA
    Posts
    224


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by scalerobotics View Post
    That is interesting Mike. I had not seen that before. (ccp1x, ccp1y, and the register for ccpr1l are different on the 16f690, so some tinkering required).
    Yes, you would need to change bit labels to match the device you're using. Sorry!

    You could also use Darrel's 18F servo code: http://www.picbasic.co.uk/forum/cont...e-Servo-Driver
    I didn't care for that method (it's not entirely interrupt tolerant) but it probably would work fine for the OP. The odd interrupt interval timing (26.2144-msecs) would make it difficult to use for for general purpose interval timers.

    If you are not tied to hardware, you could do it (almost) exclusively in hardware with a 18f2431 or a 18f4431 chip. These allow PWM down to 19 hertz on their power control pwm port pins. They have a "single shot mode" which gives the servo a single shot pulse. An interrupt would run at 20 ms to tell the single shot pulse widths when to fire. See the bottom of this wiki for more info: http://www.picbasic.co.uk/forum/cont...-encode-decode
    That's an excellent example. Thank you.

    If anyone is interested, here's the link to another example of the PWM "frame" method for 8 or 16 "zero jitter" Servos with 250-nsec pulse width resolution (4000 steps between 1.0-2.0 msecs); 8 or 16 Servos using the PWM module

    Happy Holidays everyone!

    Cheerful regards, Mike
    Last edited by Mike, K8LH; - 2nd December 2010 at 13:57.

  10. #10


    Did you find this post helpful? Yes | No

    Default

    This message is just to close out this discussion in case someone is searching in the future.

    I was not able to implement any of the proposed ideas using the CCP module. The project hardware is stuck with the 16F690. The CCP1 and CCP2 pins are already committed to other functions. The proposed ideas sound good, so I'll try them in the future upon redesign.

    I measured the interrupt service routine of the present elapsed timer using the stopwatch function in MPASM. With a 16 mhz osc the ISR is only 2.5 usec. I don't think this is enough to account for the servo jitter, so the jitter must be coming from somewhere else.

    I've ditched the elapsed timer and gone to servo frame cycle counting to keep track of time. That's working okay.

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts