DT-Ints latency and other interrupt conciderations


Closed Thread
Results 1 to 40 of 59

Hybrid View

  1. #1
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    Did you find this post helpful? Yes | No

    Default

    Hi,
    I agree, generally. BUT the "few uS" quickly add up... The servo code, including the PID, is supposed to run at 1220Hz and currently takes up to 400uS from "input to output". Let's say we're stepping at 50kHz and each interrupt takes 20uS. This means that during the 400uS it takes the servo code to execute there will be 20 interrupts, each taking 18uS for a total of another 360uS - the servo code now takes 760uS from "input to output".

    However, the numbers will be the same no matter "where" the servo code is run - it's just a matter of finding which works the best. One benefit of moving it to the main routine is that it makes it at least possible for me to have the ISRs in "real" ASM which will help bring the latency down further. Don't know how I'll handle the USART though.... I love DT-Ints.... :-/

    Thanks!
    /Henrik.

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


    Did you find this post helpful? Yes | No

    Default

    Hi,
    Still messing around with this.... I changed the TMR2 interrupt to high priority and its type (as "declared" in the INT-List) to ASM but kept the code in PBP and moved the PID and PWM code to the main routine. The INT2 ISR now executes in 14uS. A semaphore signals the main routine to run the PID etc.

    It works but there's no noticable increase in performance. At 10kHz the motor moves smoothly and silently, at 22.5kHz it's a lot more nervous and you can hear it kind of "ticking".

    So I stopped playing with that for a while and instead tried to find what it is that eats up the CPU cycles in the servo-code and not surprisingly the PID-code is the biggest hog. What I find strange though is that when it's compiled with PBP 2.6 it runs in 40-125uS but when compiled with PBPL it takes 80-325uS to execute - quite a difference.

    Why does it take more than twice the number of cycles to execute when compiled with PBPL? The PID code itself doesn't even use any longs.

    Thanks!
    /Henrik.

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


    Did you find this post helpful? Yes | No

    Default

    With PBPL, all internal System and T? variables are LONGs.

    All multiplications and divisions are done as Longs, even if they are byte vars.
    Most things that get put in a System var with a CALL to the library are done as a Long.

    Code:
    IF ByteVar1 >= ByteVar2 THEN             ; <-- Long 
    IF ByteVar1 = ByteVar2 THEN              ; <-- Byte
    WordVar = WordVar /* Const               ; <-- Long
    ByteVar1 = ByteVar1 + Const              ; <-- Byte
    ByteVar1 = ByteVar1 + (ByteVar2 >> 2)    ; <-- Long
    ByteVar1 = ByteVar1 + (ByteVar2 >> 1)    ; <-- Byte
    Having 32-bit vars is nice, ... unless you need speed.

    Is there a particular reason you need PBPL?
    Maybe we can cut that down to word sized math so you can go back to PBPW.
    <br>
    Last edited by Darrel Taylor; - 1st January 2010 at 21:26. Reason: added
    DT

  4. #4
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    Did you find this post helpful? Yes | No

    Default

    Thanks Darrel,
    That explains it for sure - but it kind of sucks.... :-/

    Basically, the Position and the Setpoint variables are the only longs and the reason for PBPL.

    The setpoint is calculated by adding or subtracting the number of steps that has arrived since the last servoloop. For the position I get the lower 16bits from the hardware QEI counter and the upper 16bits by keeping track of the number of over/underflows with the RollOver ISR.

    Man, I'm painting myself into a corner here....

    BTW, how come these two...
    Code:
    ByteVar1 = ByteVar1 + (ByteVar2 >> 2)    ; <-- Long
    ByteVar1 = ByteVar1 + (ByteVar2 >> 1)    ; <-- Byte
    ...are treated different?

    Thanks for all the help, I appreciate it!

    /Henrik.

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


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by HenrikOlsson View Post
    Basically, the Position and the Setpoint variables are the only longs and the reason for PBPL.

    The setpoint is calculated by adding or subtracting the number of steps that has arrived since the last servoloop. For the position I get the lower 16bits from the hardware QEI counter and the upper 16bits by keeping track of the number of over/underflows with the RollOver ISR.
    If that's all there is ... it's a piece of cake for PBPW.

    Man, I'm painting myself into a corner here....
    I think not.

    BTW, how come these two...
    Code:
    ByteVar1 = ByteVar1 + (ByteVar2 >> 2)    ; <-- Long
    ByteVar1 = ByteVar1 + (ByteVar2 >> 1)    ; <-- Byte
    ...are treated different?
    A single shift right compiles to a
    Code:
        BCF STATUS,C
        RRF _ByteVar2,F
    or, RRNCF for an 18F.

    But for 2 or more shifts, it puts the value in a system reg, saves the number of bits to shift, then calls a library routine to actually do the shift. Therefore ... LONG.

    Let me try to figure out the PBPW way. (should be easy)
    I think all the info is already in this thread.
    Anything missing that might help?
    <br>
    DT

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


    Did you find this post helpful? Yes | No

    Default

    Thanks Darrel,

    At the Piclist I found some signed 32bit math routines. I copied the add, subtract and the needed support routines (addba and negateb) as add and subtract is the only 32bit ops I need (at the moment at least).

    After some trial and error I managed to get these working on the 18F2431 by replacing the skpnc with btfsc, STATUS, C and clrc with bcf STATUS, C. I also made it so that the REGA, REGB and MTEMP variables are declared as PBP variables and then preceeded by an underscore in the actual ASM code. I saved it as a separate file and INCLUDE it in the program together with DT-Ints and inc_PID.

    I've replaced my LONG-ops in the DoServo code with calls to these routines, it compiles with PBPW and as far as I can currently see it runs correctly. I haven't tried to apply any step-pulses to see what it does "in real life" but I used TMR1 to time the DoServo routine (including the PID) and worst case I've seen so far is 207uS. ~100% increase in performance compared to when compiled with PBPL.

    I've also sent various variables (like the 4 bytes 'building' the 32bit position variable and the pid_Error variable) to the PC and it all looks to be correct. I need to test this much much more but what I'm currently worried about is if there are some bank-switching or RAM issues that I need to take into consideration with these math routines.

    I consider it pure luck that I've got it working this far and I'm afraid once I'll start to add more variables and code I'll break it - and I'll have no clue why.

    /Henrik.
    Last edited by HenrikOlsson; - 3rd January 2010 at 00:17.

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


    Did you find this post helpful? Yes | No

    Default

    Great minds think alike ....
    I had a similar idea, although started with different code from the net.

    I guess it's good you got yours working, because I'm still struggling to convert it to 18F's.

    I will continue anyway, because it's really cool.
    It will be extremely useful for everyone else too.

    And if you have problems with yours, it might fill the gap.

    Best regards,
    DT

Members who have read this thread : 2

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