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
Here is another alternative: Vary the period you increment your speed.
This examply uses PAUSE.
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"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
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).
It works quite good, but I cannot exeed 65 seconds (because 66*1000=66000, 16-bit integer is overflowed).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
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
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.
I may not be much use the next couple of days, but the building blocks are here (hopefully without too many errors/typos)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
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:
Sorry about that.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.
Bookmarks