Make an acceleration/deceleration ramp : any ideas?


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

    Question Make an acceleration/deceleration ramp : any ideas?

    Hi,

    I'm currently making a 3-phase VFD for an AC motor.
    The program is 70-80% done, but I've to make an acceleration/deceleration ramp.

    In other words, I start with a minimum value defined by the user (for exemple : 10), and I reach the maximum value defined by the user (for exemple 1200) linearly in x seconds (again defined by the user).

    Here an exemple :


    So any ideas how I can do that simply?
    -With a low-priority interrupt?
    -With a for...next loop?
    -etc.

    Thanks for your future help.
    Last edited by pxidr84; - 31st March 2011 at 18:38.

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


    Did you find this post helpful? Yes | No

    Default Re: Make an acceleration/deceleration ramp : any ideas?

    If you do not intend running any tasks in the background while doing the acc/deceleration, the following idea may work

    Code:
    Rate = ((Max-Min) *1000)/ Time   ' the 1000 is since I assume a mS time base
    Here the Time variable is specified in seconds.

    Now, using a 1mS time base, you can do this

    Code:
    for x = 0 to rate
       Output = Output + Rate  ' increase the output by a fraction we calculated
       pause 1           ' this is the 1mS time base I talked of
    next
    Rate could be -ve to decelerate.

  3. #3


    Did you find this post helpful? Yes | No

    Default Re: Make an acceleration/deceleration ramp : any ideas?

    Quote Originally Posted by Jerson View Post
    If you do not intend running any tasks in the background while doing the acc/deceleration, the following idea may work

    Code:
    Rate = ((Max-Min) *1000)/ Time   ' the 1000 is since I assume a mS time base
    Here the Time variable is specified in seconds.

    Now, using a 1mS time base, you can do this

    Code:
    for x = 0 to rate
       Output = Output + Rate  ' increase the output by a fraction we calculated
       pause 1           ' this is the 1mS time base I talked of
    next
    Rate could be -ve to decelerate.
    Hello,

    Thanks for your idea, I will try this into my program, but unfortunately I think that the "pause" command will make problems, because a lot of things are running in the background during this acc/deceleration (like the sine PWM generation high priority interrupt, using timer 1).

    I think use this in a low frequency and low priority interrupt (with timer 0), maybe the "pause" command will be useless?

    Note I'm using Darrel Taylor's interrupts.

  4. #4
    Join Date
    Oct 2005
    Location
    Pinckney, Michigan
    Posts
    91


    Did you find this post helpful? Yes | No

    Default Re: Make an acceleration/deceleration ramp : any ideas?

    My approach would be to generate the "points" you need for the line equation, given your slope and time parameters, in Excel. Then print a CSV file of the results, then copy the CSV file into your program as a table. It'll take some minor editing to generate your table but no big deal, and get the values from the table with Lookup or Lookup2. You can even change the slope of your ramp easily by adjusting the dwell time at each point, etc.

    I do this sort of thing a lot for thermistor temperature tables, etc. Saves the time of executing the extensive formula for thermistor values.

  5. #5


    Did you find this post helpful? Yes | No

    Default Re: Make an acceleration/deceleration ramp : any ideas?

    Can you give more info?

    What is the motor being used for?

    How does the user change the speed?

    Typical servo systems use a PID routine.

    Henrik Olsson posted a great PID program example on the forum. As I recall the thread mentioned motors and DT interupts.

  6. #6


    Did you find this post helpful? Yes | No

    Default Re: Make an acceleration/deceleration ramp : any ideas?

    I don't want to use a PID routine or a lookup table (because a lookup table is hungry of program memory space). It's a open-loop inverter.

    The user changes the frequency reference by turning a potentiometer connected to a ADCIN port.

    Exemple :

    Note the acceleration and deceleration ramp of the output frequency, that changes the speed of the AC motor.

    I like to have a routine (in a low-priority interrupt for exemple, to have the most accurate timings) that increments a value from the actual output frequency (for exemple 20Hz) to the frequency reference (for exemple 60Hz, defined by the user) in x seconds (for exemple 10 seconds, can be modified in real-time), and that without using any "pause" command (because my PIC has a lot things to do during this time).
    Last edited by pxidr84; - 1st April 2011 at 17:17.

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


    Did you find this post helpful? Yes | No

    Default Re: Make an acceleration/deceleration ramp : any ideas?

    You can delegate the timekeeping and ramping to the ISR. What you need to pass to it is the 'target' value and 'step size' Step Size could be +ve or -ve depending on which way you want it to move.

    the ISR could tick every millisec or maybe more depending on how fast you want to change the output.

  8. #8
    Join Date
    Sep 2005
    Location
    Campbell, CA
    Posts
    1,107


    Did you find this post helpful? Yes | No

    Default Re: Make an acceleration/deceleration ramp : any ideas?

    I don't know how fast your ramp needs to be - but..

    I would use a timer interrupt - say 1 millisecond

    Multiply ramp time (in seconds) X 1000 to get the number of steps
    Take

    (endvalue - startvalue)/numberofsteps to get step size
    Initialize a counter with the start value and increment the step size in each interrupt.

    Depending on your needs, you may have to add some extra increments, because the step size will be an integer, and when multiplied by the number of steps may not exactly equal the
    end value.
    Charles Linquist

  9. #9


    Did you find this post helpful? Yes | No

    Default Re: Make an acceleration/deceleration ramp : any ideas?

    Quote Originally Posted by Charles Linquis View Post
    I don't know how fast your ramp needs to be - but..

    I would use a timer interrupt - say 1 millisecond

    Multiply ramp time (in seconds) X 1000 to get the number of steps
    Take

    (endvalue - startvalue)/numberofsteps to get step size
    Initialize a counter with the start value and increment the step size in each interrupt.

    Depending on your needs, you may have to add some extra increments, because the step size will be an integer, and when multiplied by the number of steps may not exactly equal the
    end value.
    My maximum acceleration slope is incrementing a variable from 0 to 1200 in one second with a resolution of 1 (steps of 1).

    I've tried to "translate" your algorithm into this :


    'Variable init
    freq var word
    maxfreq var word
    minfreq var word
    stepnum var word
    stepsize var word
    time var word

    'Variables def
    minfreq=10
    maxfreq=1200
    time=10

    'Calculate steps
    stepnum=time*1000
    stepsize=(maxfreq-minfreq)/stepnum

    'Init counter
    freq=minfreq

    main:

    ' Counter
    freq=freq+stepsize

    'Update LCD
    lcdout $fe,$2,"Frequency: ",dec5 freq

    ' 1ms time base (simulates an interrupt)
    pause 1

    goto main


    It is correct? Because the result of "stepsize" is a float in this case (0.119)...
    Last edited by pxidr84; - 2nd April 2011 at 14:30.

  10. #10
    Join Date
    Sep 2005
    Location
    Campbell, CA
    Posts
    1,107


    Did you find this post helpful? Yes | No

    Default Re: Make an acceleration/deceleration ramp : any ideas?

    According to my calculations -

    endval = 1200
    startval = 20


    endval - startval = 1180
    ramp time in milliseconds = 1000

    1180/1000 = 1.18 (so 1180/1000 = 1 = increment)
    1180//1000 = 180 (=remainder = fractional)



    fractional = 0
    oldfractional = 0

    frequency = 20 ; start value

    ISR:

    Frequency = frequency + increment ; increment the main part

    fractional = fractional + remainder ; Deal with the fractional part
    If fractional dig3 != oldfractional ; keep adding up the partial until we reach 1000
    oldfractional = fractional ; update so we can see the next change
    frequency = frequency + 1 ; add a count - since we broke 1000
    Endif


    This will increment by one every program loop and then add an extra count every 5 (or so) loops. I haven't tested the algorithm, but I believe it should deal properly with the 'wrap' when "fractional" overflows.
    Charles Linquist

  11. #11


    Did you find this post helpful? Yes | No

    Default Re: Make an acceleration/deceleration ramp : any ideas?

    Quote Originally Posted by Charles Linquis View Post
    According to my calculations -

    endval = 1200
    startval = 20


    endval - startval = 1180
    ramp time in milliseconds = 1000

    1180/1000 = 1.18 (so 1180/1000 = 1 = increment)
    1180//1000 = 180 (=remainder = fractional)



    fractional = 0
    oldfractional = 0

    frequency = 20 ; start value

    ISR:

    Frequency = frequency + increment ; increment the main part

    fractional = fractional + remainder ; Deal with the fractional part
    If fractional dig3 != oldfractional ; keep adding up the partial until we reach 1000
    oldfractional = fractional ; update so we can see the next change
    frequency = frequency + 1 ; add a count - since we broke 1000
    Endif


    This will increment by one every program loop and then add an extra count every 5 (or so) loops. I haven't tested the algorithm, but I believe it should deal properly with the 'wrap' when "fractional" overflows.
    I've tested this :
    Code:
    DEFINE OSC 32      
    DEFINE LCD_DREG PORTC
    DEFINE LCD_EREG PORTD
    DEFINE LCD_RSREG PORTD
    DEFINE LCD_EBIT 0
    DEFINE LCD_RSBIT 1
    DEFINE ADC_BITS 10
    DEFINE LCD_COMMANDUS 10000
    DEFINE LCD_DATAUS 2000
    
    'Variable init
    freq var word
    maxfreq var word
    minfreq var word
    remain var word
    increm var word
    time var word
    potsense var word
    frac var word
    oldfrac var word
    delta var word
    
    'Variables def
    minfreq=10
    maxfreq=1200
    
    
    'Calculate steps
    delta=maxfreq-minfreq
    time=1000
    
    increm=delta/time
    remain=delta//time
    
    frac=0
    oldfrac=0
    freq=10
    
    main:
    
    ' Counter
    freq=freq+increm
    frac=frac+remain
    if frac dig 3 != oldfrac then
    oldfrac=frac
    freq=freq+1
    endif
    
    ' 1ms time base (simulates an interrupt)
    pause 1
    
    lcdout $fe,$2,"Frequency: ",dec5 freq
    
    goto main
    And it seems to work well, the "freq" value get incremented, and if I change the "time" variable, the "freq" value increments more or less quickly.

    But the "freq" increments without stopping, and this over 1200!

  12. #12
    Join Date
    Sep 2005
    Location
    Campbell, CA
    Posts
    1,107


    Did you find this post helpful? Yes | No

    Default Re: Make an acceleration/deceleration ramp : any ideas?

    stop the incrementing or stop the interrupt when freq >= maxfreq
    Charles Linquist

  13. #13


    Did you find this post helpful? Yes | No

    Default Re: Make an acceleration/deceleration ramp : any ideas?

    Quote Originally Posted by Charles Linquis View Post
    stop the incrementing or stop the interrupt when freq >= maxfreq
    I've tried this on my real PIC with a potentiometer :

    Code:
    DEFINE OSC 32      
    DEFINE LCD_DREG PORTC
    DEFINE LCD_EREG PORTD
    DEFINE LCD_RSREG PORTD
    DEFINE LCD_EBIT 0
    DEFINE LCD_RSBIT 1
    DEFINE ADC_BITS 10
    
    ' ADC registers configuration
    ADCON0=%11101
    ADCON1=%10000    
    ADCON2=%10000110  
    ADCHS=%1010101  
    ANSEL0=%11110000 
    
    ' Variable init
    freq var word
    rfreq var word
    maxfreq var word
    minfreq var word
    dum6 var word
    dum7 var word
    accel var word
    decel var word
    frac var word
    oldfrac var word
    potsense var word
    
    ' Variables def
    maxfreq=1200
    minfreq=10
    accel=1000
    decel=1000
    
    ' Start freq
    freq=minfreq
     
    main:
    
    ' Start ADC conversion
    ADCON0.1=1       
    WHILE ADCON0.1=1:WEND
    
    ' Store ADC results   
    potsense.HighByte=ADRESH 
    potsense.LowByte=ADRESL 
    
    ' Convert pot result
    rfreq=(potsense<<6)**maxfreq
    
    ' Acceleration ramp
    if freq<rfreq then
    dum6=(rfreq-minfreq)/accel
    dum7=(rfreq-minfreq)//accel
    freq=freq+dum6
    frac=frac+dum7
    if frac dig 3<>oldfrac then oldfrac=frac:freq=freq+1
    endif 
    
    ' Deceleration ramp
    if freq>rfreq then
    dum6=(maxfreq-rfreq)/decel
    dum7=(maxfreq-rfreq)//decel
    freq=freq-dum6
    frac=frac-dum7
    if frac dig 3<>oldfrac then oldfrac=frac:freq=freq-1
    endif 
    
    ' Display results
    lcdout $fe,$2,"Frequency: ",dec5 freq
    lcdout $fe,$c0,"Ref: ",dec5 rfreq
    
    pause 1
    
    goto main
    And unfortunately the timing is not very accurate, it depends of the "maxfreq" variable defined. I can have a 1 or 2 seconds gap.
    And above 1000, the "accel"/"decel" values doesn't increase the time of the ramp.

  14. #14
    Join Date
    Sep 2005
    Location
    Campbell, CA
    Posts
    1,107


    Did you find this post helpful? Yes | No

    Default Re: Make an acceleration/deceleration ramp : any ideas?

    If you use an interrupt, the timing is guaranteed.

    Your LCD can't possibly update every millisecond.
    Charles Linquist

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