DT-Ints latency and other interrupt conciderations


Closed Thread
Results 1 to 40 of 59

Hybrid View

  1. #1
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    I think that both INT2 and TMR2 interrupts should be HIGH priority.
    The USART can be LOW priority, since servicing it is not really time critical.
    But no, you won't be able to use DT_INTS for just the Low Priority.

    Sougata is correct about the shadow registers...
    They are only good for High Priority interrupts.
    For Low priority ints you have to save W, STATUS and BSR in the ISR.

    What are you doing with the USART handler?
    Stuffing the bytes in a buffer?
    <br>
    DT

  2. #2
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,623


    Did you find this post helpful? Yes | No

    Default

    Hi,
    At the moment I'm not doing anything with the USART interrupt - it's never been fired during these tests. But I'll need to use it for the "front end" later on - if I get there - and the is to stuff data into a buffer and signal the main program when a LF or CR arrives.

    Just so we're all on the same page, here are the current interupts:
    INT2_INT - High priority ISR in ASM
    IC2QEIF_INT - High priority ISR in PBP but "declared" as ASM in the INT_LIST macro
    TMR2_INT - Low priroity ISR in PBP
    RX_INT - Low priotity ISR in PBP


    I originally had the TMR2 interrupt as high priority but then I didn't get more than a few kHz before it started to miss pulses. The DoServo routine that is run as the TMR2 ISR is quite "heavy" since it does all the math including the PID routine:
    Code:
    DoServo:                                    'Interrupt handler starts here.
    PortB.5 = 1                                 'Used for timing purposes
    GetPosition:
    'Since the position counter isn't double buffered we can get to situations
    'where the lowbyte overflows between readings of the high and low byte. This
    'is prevented by reading the high byte two times and compare the two readings.
    'If they are the same then we're fine, if not re-read the registers.
      
        PosHigh = POSCNTH                       'Get high byte of counter
        PosLow = POSCNTL                        'Get low byte of counter
        PosTemp = POSCNTH                       'Get high byte again
        
        If PosHigh - PosTemp = 0 then Goto Done 'Compare, if equal we're done.
        
        PosHigh = POSCNTH                       'If not, get values again.
        PosLow = POSCNTL
    
    Done:  
    'The high word of the Position variable is handled by the RollOver ISR that gets
    'tripped by IC2QEIF when POSCNT = MAXCNT.
        
        Position.Word0 = POSHIGH * 256 + PosLow 'Put high and lowbyte together.
        Speed = Position - oldPosition          'Calculate current motor speed.
    
        INTCON3.4 = 0                           'Temporarily disable INT2 interrupt
        TempStepBuffer = StepBuffer
        StepBuffer = 0
        INTCON3.4 = 1                           'Re-enable INT2 interrupt.
    
        If TempStepBuffer.7 = 1 then            'Step buffer is negative
         Setpoint = Setpoint - ABS (TempStepBuffer)
        Else
         SetPoint = Setpoint + TempStepBuffer
        Endif
        pid_Error = Setpoint - Position          'Calculate error....
        
    'Now we have our error-signal in the variable that the PID-routine expects
    'so we call the PID-filter with a GOSUB. The filter will respond with the
    'output in variable pid_out.
    
        Gosub PID                               'and send to PID filter
    ' (PID filter execution time measured to ~190uS worst case @20Mhz)
     
        If pid_out.15 = 0 then                  'If the output from the pid-filter
           Direction = 1                        'is positive we want to drive the
           Duty = pid_Out                       'motor forward.
        Else
           Direction = 0                        'If it's negative we want to drive
           Duty = ABS (pid_Out)                 'it backwards.
        Endif
    
        CCP1CON.5 = Duty.1                      'Set the two LSB's of the dutycycle-
        CCP1CON.4 = Duty.0                      'register. Then shift them out and
        CCPR1L = Duty >> 2                      'set the remainig 8 bits.
        
        oldPosition = Position                  'Store position for next interrupt.
    
    ISRCount = ISRCount + 1
    PortB.5 = 0
    
    @  INT_RETURN                               ;ISR is complete, return from here.
    The actual PID code isn't shown here, I've measured the execution time of the complete DoServo ISR and it seems to vary alot, from 160uS all the way up to 400uS.

    So, I guess I'll need to stick with DT-Ints since re-writing the DoServo routine including the PID code in ASM would take me years. Question is what else, if anything, can be improved to increase the speed. The thing is that I was hoping to add more code to the DoServo routine but I guess that may not be a good idea.

    Thanks alot guys!

    /Henrik.

  3. #3
    Join Date
    Feb 2005
    Location
    Kolkata-India
    Posts
    563


    Did you find this post helpful? Yes | No

    Default Any possibilities of checking INTs within INTs

    Henrik,

    I wonder if there could be any hardware optimizations however I would just like to remind you:

    Even if an Interrupt is Enabled (IE bit), the Flag (IF bit) always gets set. So it might just be possible to check within an interrupt that if other sources triggered. This enables you to pre-service that interrupt without a return then re-entry. This can save a lot of cycles with the penalty of a bit more code space.
    Regards

    Sougata

  4. #4
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    I may be continuing to miss the point, but ...

    I still think TMR2 should be a high priority interrupt.
    Except, it should be ASM, and ONLY collect the data required to calculate the error.

    The PID and motor control should be running in the main loop, using the error info from the interrupt.

    If the PID happens to miss an update, it won't matter that much because the error will still be updated the next time. And it's not like the PID loop can cancel the error on each update. It takes time. But at least the actual error measurements will be consistent at much higher frequencies.

    Obviously, the "I" time period won't be constant, but I think they'll be close enough that you won't notice a difference. IMHO
    Then the PID loop can run at it's maximum rate, while the interrupts run at their maximum rate, without interfering with each other.
    <br>
    DT

  5. #5
    Join Date
    Feb 2005
    Location
    Kolkata-India
    Posts
    563


    Did you find this post helpful? Yes | No

    Default Agree to that

    Quote Originally Posted by Darrel Taylor View Post
    I may be continuing to miss the point, but ...

    I still think TMR2 should be a high priority interrupt.
    Except, it should be ASM, and ONLY collect the data required to calculate the error.

    The PID and motor control should be running in the main loop, using the error info from the interrupt.

    <br>
    I did not realize that the PID routine was running within the ISR. Henrik is it necessary ?? A better way could be accumulating error in the back (ISR) while processing error in main loop. I did tried your PID loop once but never closely worked on it. So excuse my ignorance if I am talking something analogue (illogical!!)
    Regards

    Sougata

  6. #6
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,623


    Did you find this post helpful? Yes | No

    Default

    Hi,
    Yes the PID is currently run as part of the 1220Hz TMR2 ISR because I've always been taught that digital PID systems needs to be run at constant intervals and I can definetly see why that is neccessary.

    You are correct that the important thing is to sample the data at precise intervals - if that's not done the effect will be the same as constantly changing the gains up and down. Or it will "look like" the speed of the motor isn't constant even though it actually is because the number of encoder counts per update is changing.

    On the other hand, if the output of the filter isn't updated at constant intervals the motor doesn't have the same time to respond to input which is also the same as changing the gains but it might not be as bad as not sampling regularly. So, this is essentially why the PID routine is run inside the TMR2 ISR.

    However, it's definitely worth a try to move it to the main routine and then have the TMR2 ISR signaling the main routine that new data is available, I'll try that! That would mean that the TMR2 ISR wouldn't (hopefully) contain any code that requires the PBP system variables so I'll be able to change its type to ASM although it's coded in PBP.


    As a side note, I'm wondering what in the DoServo code it is that takes so much time. The PID code alone was measured to 190uS worsy case and it contains far more math than the rest of the DoServo code. Yet the complete DoServo routine sometimes takes 400uS, without it being interrupted. The 190uS was measured when compiled with PBP though, not PBPL but the PID code doesn't contain ANY operations on LONGS, does it matter?

    Sorry, now I'm asking queastion that my scope can answer.... Thank you both!

    /Henrik.

  7. #7
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    4,170


    Did you find this post helpful? Yes | No

    Default

    I believe that motor will not feel the difference ifthe PID routine is interrupted for a small fraction of time (in the order of microseconds).

    The inertia is large enough even for small motors.

    As Darrel always says, keep the ISR as fast as possible and return to your main routine for the processing. That way your PID will still run fast.

    Ioannis

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