+ Reply to Thread
Results 1 to 14 of 14
  1. #1
    Join Date
    Jan 2011
    Posts
    113

    Question Linear acceleration ramp

    Hi everyone,

    I would like to make a simple, linear acceleration ramp.
    I think that low priority DT interrupts can serve as a timebase.

    The thing I want is like that: increase linearly the value "x" to value "y" in "n" seconds.

    For example, ramp from 10 (x) to 560 (y) in 42 seconds (n).

    Time (n) is between 0 and 255 seconds.
    Values to increment (x and y) are between 10 and 1200.

    Thanks

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

    Default Re: Linear acceleration ramp

    I don't know if it will execute quickly enough but you could use a lookup table in a for next loop where the counter VAR is the lookup VAR.
    example:
    for i = 0 to 10
    lookup i,[10,25,50, . . . . ] pulsevar
    next i
    Prepare as a nonbeliever. If your belief fails you will be prepared, and if your belief comes to fruition, you have prepared a nonbeliever,
    to survive tribulation.



  3. #3
    Join Date
    Dec 2010
    Posts
    276

    Default Re: Linear acceleration ramp

    Although you said linear, I assume you really can live with a staircase.
    If that's the case, and I understand the question correctly, then it's just simple math.

    Your example: ramp from 10 (x) to 560 (y) in 42 seconds (n).
    Suppose you want 1 step per second. In that case:
    stepsize = (y-x)/n
    output = x
    FOR QQ = 1 to n
    PAUSE 1000
    output = x + stepsize
    next QQ
    Replace the pause with a 1 second interrupt if you need to do other things.
    "output" feeds yout DAC

  4. #4
    Join Date
    Jan 2011
    Posts
    113

    Default Re: Linear acceleration ramp

    Quote Originally Posted by Charlie View Post
    Although you said linear, I assume you really can live with a staircase.
    If that's the case, and I understand the question correctly, then it's just simple math.

    Your example: ramp from 10 (x) to 560 (y) in 42 seconds (n).
    Suppose you want 1 step per second. In that case:
    stepsize = (y-x)/n
    output = x
    FOR QQ = 1 to n
    PAUSE 1000
    output = x + stepsize
    next QQ
    Replace the pause with a 1 second interrupt if you need to do other things.
    "output" feeds yout DAC
    I will try that, thanks!


    Hi, we are pleased to see that you are using our forum.

    We'd like you to become a member of our community. Membership is FREE, please REGISTER and view our forums without these annoying reminders!

    Once registered you may post on the forums, download from the file areas and use the WIKI without interruption.





  5. #5
    Join Date
    May 2006
    Location
    Del Rio, TX, USA
    Posts
    345

    Default Re: Linear acceleration ramp

    On problem is the rounding error you will get with (y-x)/n

    In your example: (560-10)/42 = 13.09524
    But, PBP will only see 13. So, at the end of your routine, you will end up with 10 + (42*13) = 556

    You will need to put in one line at after Next QQ:

    Output = y

  6. #6
    Join Date
    May 2006
    Location
    Del Rio, TX, USA
    Posts
    345

    Default Re: Linear acceleration ramp

    Here is another alternative: Vary the period you increment your speed.
    This examply uses PAUSE.
    Code:
    Incr_Time_ms = (1000 * Duration) / (End_Val - Start_Val)
    Current_Val = Start_Val
    Do Until Current_Val = End_Val
       PAUSE Incr_Time_ms 
       Current_Val = Current_Val + 1
    Loop
    What would be ideal is set up a timer and add a value so that it overflows after "Incr_Time_ms". You can then use interrupts, or just poll the flag bit. increment your "Current_Val", clear the flag bit, and then add the value to set up the overflow after "Incr_Time_ms". Wash-Rinse-Repeat until "Current_Val = End_Val"

  7. #7
    Join Date
    Jan 2011
    Posts
    113

    Default Re: Linear acceleration ramp

    Quote Originally Posted by SteveB View Post
    Here is another alternative: Vary the period you increment your speed.
    This examply uses PAUSE.
    Code:
    Incr_Time_ms = (1000 * Duration) / (End_Val - Start_Val)
    Current_Val = Start_Val
    Do Until Current_Val = End_Val
       PAUSE Incr_Time_ms 
       Current_Val = Current_Val + 1
    Loop
    What would be ideal is set up a timer and add a value so that it overflows after "Incr_Time_ms". You can then use interrupts, or just poll the flag bit. increment your "Current_Val", clear the flag bit, and then add the value to set up the overflow after "Incr_Time_ms". Wash-Rinse-Repeat until "Current_Val = End_Val"
    Hi Steve,

    I've used what you said, and I've also included a deceleration ramp:
    (sorry for renaming the values, it's for a easier integration in my main program).

    Code:
    ' PIC18F4431 initialization
    DEFINE OSC 40      
    DEFINE LCD_DREG PORTD
    DEFINE LCD_EREG PORTB
    DEFINE LCD_RSREG PORTB
    DEFINE LCD_EBIT 6
    DEFINE LCD_RSBIT 7
    
    
    tacc var BYTE
    tdec var BYTE
    cacc var word
    cdec var word  
    ref var word
    fmin var word
    freq var WORD
    
    
    tacc=1
    tdec=10
    fmin=10
    ref=1200
    
    
    PAUSE 4000
    LCDOUT $fe,$1
    
    
    cacc = (1000 * tacc) / (ref - fmin)
    cdec = (1000 * tdec) / (ref - fmin)
    
    
    lp:
       if freq<ref then PAUSE cacc
       if freq>ref then PAUSE cdec
       
       if freq<ref then freq = freq + 1
       if freq>ref then freq = freq - 1
       
       LCDOUT $fe,$2,DEC5 freq          
       if PORTC.0=%1 then ref=500
    goto lp
    It works quite good, but I cannot exeed 65 seconds (because 66*1000=66000, 16-bit integer is overflowed).
    But, more importantly, I want to integrate the loop in a low priority DT interrupt. I really don't understand how you're using flags, etc. (I'm a beginner lol).

    Thanks

  8. #8
    Join Date
    May 2006
    Location
    Del Rio, TX, USA
    Posts
    345

    Default Re: Linear acceleration ramp

    Here is a start (not tested!). But it should get you going in the right direction. I only included the acceleration stuff to keep the logic simpler.
    You will need the include files (Get Darrel's from http://darreltaylor.com/DT_INTS-18/downloads.html), and make sure the file names match.
    Code:
    ' PIC18F4431 initializationDEFINE OSC 40      
    DEFINE LCD_DREG PORTD
    DEFINE LCD_EREG PORTB
    DEFINE LCD_RSREG PORTB
    DEFINE LCD_EBIT 6
    DEFINE LCD_RSBIT 7
    
    tacc var BYTE
    tdec var BYTE
    cacc var word
    cdec var word  
    ref var word
    fmin var word
    freq var WORD
    
    cacc_div VAR BYTE
    cdec_div VAR BYTE
    
    tacc=1
    tdec=10
    fmin=10
    ref=1200
    
    PAUSE 4000
    LCDOUT $fe,$1
    
    INCLUDE "DT_INTS-18.bas"
    INCLUDE "ReEnterPBP-18.bas"
    INCLUDE "TimerControl.pbp"  ; Timer Control Routines
    
    ASM
    INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag?
            INT_Handler   TMR1_INT,  _UpdateTickCount,   PBP,  yes
        endm
        INT_CREATE            ; Creates the interrupt processor
    ENDASM
    
    @   INT_ENABLE  TMR1_INT  ; Enable Timer 1 Interrupts  
    
    GOSUB ResetTime           ' Reset Timer and mSec_Ticks = 0
    
    IF tacc > 65 THEN
       cacc_div = 10
    ELSE 
       cacc_div = 1     
    ENDIF 
    
    cacc = ((1000/cacc_div) * tacc) / (ref - fmin)
    GOSUB StartTimer          ' Start Counting mSec_Ticks
    
    
    Main:
    
    
         IF mSec_Ticks > (cacc * cacc_div) THEN
            IF freq < ref THEN freq = freq + 1
            mSec_Ticks = mSec_Ticks - (cacc * cacc_div)
            IF freq >= ref THEN
               GOSUB StopTimer
               GOSUB ResetTime
         ENDIF
         
       LCDOUT $fe,$2,DEC5 freq          
       IF PORTC.0=%1 THEN ref=500
    
    
    GOTO Main
    I may not be much use the next couple of days, but the building blocks are here (hopefully without too many errors/typos)
    Attached Files Attached Files

  9. #9
    Join Date
    Dec 2010
    Posts
    276

    Default Re: Linear acceleration ramp

    Quote Originally Posted by pxidr84 View Post
    Hi Steve,

    It works quite good, but I cannot exeed 65 seconds (because 66*1000=66000, 16-bit integer is overflowed).
    But, more importantly, I want to integrate the loop in a low priority DT interrupt. I really don't understand how you're using flags, etc. (I'm a beginner lol).

    Thanks
    Use a long for your variable - you'll have to work hard to overflow 32 bits.

  10. #10
    Join Date
    May 2006
    Location
    Del Rio, TX, USA
    Posts
    345

    Default Re: Linear acceleration ramp

    Thanks for mentioning that Charlie! (I forgot too)

    It would certainly simplify the code. I went with the non-LONG method in the case that Pxidr84 might not have PBP3, and so no LONG variables. But yes, I would definitely use them if available. Either way, hopefully the methodology of the example is instructive in learning to scale integers to fit into the given variable space.

    Also, there is a correction I need to make to the code. I forgot an ENDIF:

    Code:
         IF mSec_Ticks > (cacc * cacc_div) THEN
            IF freq < ref THEN freq = freq + 1
            mSec_Ticks = mSec_Ticks - (cacc * cacc_div)
            IF freq >= ref THEN
               GOSUB StopTimer
               GOSUB ResetTime
            ENDIF
         ENDIF
    Sorry about that.

  11. #11
    Join Date
    Jan 2011
    Posts
    113

    Default Re: Linear acceleration ramp

    Quote Originally Posted by SteveB View Post
    Thanks for mentioning that Charlie! (I forgot too)

    It would certainly simplify the code. I went with the non-LONG method in the case that Pxidr84 might not have PBP3, and so no LONG variables. But yes, I would definitely use them if available. Either way, hopefully the methodology of the example is instructive in learning to scale integers to fit into the given variable space.

    Also, there is a correction I need to make to the code. I forgot an ENDIF:

    Code:
         IF mSec_Ticks > (cacc * cacc_div) THEN
            IF freq < ref THEN freq = freq + 1
            mSec_Ticks = mSec_Ticks - (cacc * cacc_div)
            IF freq >= ref THEN
               GOSUB StopTimer
               GOSUB ResetTime
            ENDIF
         ENDIF
    Sorry about that.
    I think that my PBP 2.6 support LONGs... I can't exceed 65s, but right now it's not important.

    I've maybe find an another way (only for make a timer without PAUSE):

    -Use a "fixed" frequency low priority interrupt
    -Increment a value at each interrupt execution (for exemple, incr=incr+1)
    -And execute the ramp code if "incr" as reached a certain calculated value (actually it's "cacc" and "cdec"), and then reset "incr" to zero.

    Really, I don't need a nanosec precision for this ramp.

  12. #12
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,844

    Default Re: Linear acceleration ramp

    PBP 2.6 suppoerts LONGS with 18F devices. You just need to select "Use PBPL" for the compiler.
    Dave
    Always wear safety glasses while programming.

  13. #13
    Join Date
    May 2006
    Location
    Del Rio, TX, USA
    Posts
    345

    Default Re: Linear acceleration ramp

    Quote Originally Posted by pxidr84 View Post
    -Use a "fixed" frequency low priority interrupt
    -Increment a value at each interrupt execution (for exemple, incr=incr+1)
    -And execute the ramp code if "incr" as reached a certain calculated value (actually it's "cacc" and "cdec"), and then reset "incr" to zero.
    Did you see post # 8?

  14. #14
    Join Date
    Jan 2011
    Posts
    113

    Default Re: Linear acceleration ramp

    Quote Originally Posted by SteveB View Post
    Did you see post # 8?
    Yes I've see your post, but I've not tried it yet, I will do that today.

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