1. ## 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. ## 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

3. ## 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. ## Re: Linear acceleration ramp

Originally Posted by Charlie
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!

5. ## 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. ## 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. ## Re: Linear acceleration ramp

Originally Posted by SteveB
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. ## 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)

9. ## Re: Linear acceleration ramp

Originally Posted by pxidr84
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. ## 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```

11. ## Re: Linear acceleration ramp

Originally Posted by SteveB
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```
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. ## Re: Linear acceleration ramp

PBP 2.6 suppoerts LONGS with 18F devices. You just need to select "Use PBPL" for the compiler.

13. ## Re: Linear acceleration ramp

Originally Posted by pxidr84
-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. ## Re: Linear acceleration ramp

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