Putting robotics at your service™

Free shipping on orders over $200

Using a timer so se how fast (?) my code runs

Print view Share :
Previous topicNext topic

Page 1 of 1 [ 5 posts ]

User avatar
Veteran ( offline )
Posts: 158
Posted: 2011-01-31 14:51 
it this possible on the ARC32 ?

Ive been cutting out bits and pices from the Phonex code, but it dosnt make much sens to me, and (maby) therefor i havnt got it to work. It is really not nesessery if it is something "usual", like milliseconds, it can just as well be clockcykels or whatever... as long at it reprecent time in some manner
I was thinking something like
Code:
Init Timerfunction
......
Start timer
...
test this code
...
Stop timer
Pressent the result

Can anyone help me with some code ?

_________________
PS
As i am Swedish, you may laugh at my spelling and grammar, but please please don’t comment it if you understand what i mean
DS


User avatar
Guru ( offline )
Posts: 4913
Posted: 2011-01-31 20:53 
It is all in the phoenix code... Depending on which version and processors it uses different timers... From the version I uploaded today for serial communications...

some defines to use...
Code:
;[TIMING]
lTimerCnt         var   LONG   ; used now also in timing of how long since we received a message
lCurrentTime      var long   
lTimerStart         var long   ;Start time of the calculation cycles
lTimerEnd         var long    ;End time of the calculation cycles
CycleTime         var byte   ;Total Cycle time


You need to define the interrupts you are using...
Code:
;[TIMER INTERRUPT INIT]
#ifdef BASICATOMPRO28

TIMERINT   con   TIMERAINT
ONASMINTERRUPT TIMERAINT, HANDLE_TIMERA_ASM
#else
TIMERINT   con   TIMERB1INT
ONASMINTERRUPT TIMERB1INT, HANDLE_TIMERB1_ASM
#endif


You need to initialize the timer code...
Code:
;Timer

Then define the timer interrupt code as well as a helper function to get the time...
[code];==============================================================================
;[Handle_Timer_asm] - Handle timer A overflow in assembly language.  Currently only
;used for timings for debugging the speed of the code
;Now used to time how long since we received a message from the remote.
;this is important when we are in the NEW message mode, as we could be hung
;out with the robot walking and no new commands coming in.
;==============================================================================
#ifdef BASICATOMPRO28
   BEGINASMSUB
HANDLE_TIMERA_ASM
   push.l    er1                  ; first save away ER1 as we will mess with it.
   bclr    #6,@IRR1:8               ; clear the corresponding bit in the interrupt pending mask
   mov.l    @LTIMERCNT:16,er1      ; Add 256 to our counter
   add.l   #256,er1
   mov.l    er1, @LTIMERCNT:16
   pop.l    er1
   rte
   ENDASMSUB
#else
   BEGINASMSUB
HANDLE_TIMERB1_ASM
   push.l    er1                  ; first save away ER1 as we will mess with it.
   bclr    #5,@IRR2:8               ; clear the corresponding bit in the interrupt pending mask
   mov.l    @LTIMERCNT:16,er1      ; Add 256 to our counter
   add.l   #256,er1
   mov.l    er1, @LTIMERCNT:16
   pop.l    er1
   rte
   ENDASMSUB
#endif
   return      ; Put a basic statement before...

;==============================================================================
;[GetCurrentTime] - Gets the Timer value from our overflow counter as well as the TCA counter.  It
;                makes sure of consistency. That is it is very possible that
;                after we grabbed the timers value it overflows, before we grab the other part
;                so we check to make sure it is correct and if necessary regrab things.
;==============================================================================
GetCurrentTime:
#ifdef BASICATOMPRO28
   lCurrentTime = lTimerCnt + TCA
#else   
   lCurrentTime = lTimerCnt + TCB1
#endif   
   ; handle wrap
   if lTimerCnt <> (lCurrentTime & 0xffffff00) then
#ifdef BASICATOMPRO28   
      lCurrentTime = lTimerCnt + TCA
#else
   lCurrentTime = lTimerCnt + TCB1
#endif
   endif

   return lCurrentTime
[/code]
lTimerCnt = 0
#ifdef BASICATOMPRO28
WTIMERTICSPERMSMUL con 64   ; BAP28 is 16mhz need a multiplier and divider to make the conversion with /8192
WTIMERTICSPERMSDIV con 125  ;
TMA = 0   ; clock / 8192               ; Low resolution clock - used for timeouts...
#else
WTIMERTICSPERMSMUL con 256   ; Arc32 is 20mhz need a multiplier and divider to make the conversion with /8192
WTIMERTICSPERMSDIV con 625  ;
TMB1 = 0   ; clock / 8192               ; Low resolution clock - used for timeouts...
#endif

ENABLE TIMERINT
ENABLE


How to time something...
Code:
; get the start time...
  'Start time
  GOSUB GetCurrentTime[], lTimerStart
... do whatever you wish to time...
; Get the end time
  Gosub GetCurrentTime[], lTimerEnd
; compute Delta time in Miliseconds...
  CycleTime = ((lTimerEnd-lTimerStart) * WTIMERTICSPERMSMUL) / WTIMERTICSPERMSDIV

This is setup to use TimerA on Bap28 and timerB1 on Bap40 and Arc32. It initializes the timer to say only increment every 8192 clocks, size these timers are 8 bit timers that will overflow every 8192*256=2,097,152 clocks. So on Arc32 you will get 20000000/2,097,152 or about 9.5 times per second...

=======================================================================================================
Option 2:

So if all you wish to do is time a specific thing and it will complete in under 1/9.5 seconds and this resolution is sufficient for you than all of this could be overkill. That is you don't need the interrupt... You could get away with simply using the timer without an interrupt. That is for Arc32, you could simply initialize the timer somewhere at the start...

TMB1 = 0 ; clock / 8192

Then at the start of the code you wish to time simply set the counter associated with the timer to zero
TCB1 = 0

Do your stuff and then at the end save away the timer and convert to ms...
CycleTime = (TCB1 * WTIMERTICSPERMSMUL) / WTIMERTICSPERMSDIV

==========================================================================
Option 3:

Personally if I need this for timings that are not needed for the program itself (like timings for the servos or error out if I don't see anything on an XBee for a timeout period...) I cheat.

I find an unused IO pin on my board (example P4). At the start of the code I wish to time, I do a: high P4 and the end of the code I wish to time I do a low P4. I then hook up my logic analyzer and record the time. When I move the mouse inside the pulse shown in the analyzer software it will give me the time... But that is cheating!

Sorry for the long winded three different ways answer.
Kurt


User avatar
Guru ( offline )
Posts: 2120
Posted: 2011-02-01 03:56 
Very thorough explanation Kurt! And very useful information. :D

I've used option #3 several times, its definitely the easiest way to do it in code though. And also very accurate.

_________________
Kåre Halvorsen, Zenta
-----------------------------------------
Zenta's blog
http://zentasrobots.com/
Zenta's YouTube channel
http://www.youtube.com/ZentaOlbaid
-----------------------------------------


User avatar
Veteran ( offline )
Posts: 158
Posted: 2011-02-01 08:25 
Thanks, this was _exactly_ what i wanted

*i bow deeply*

Ill try it when i get home from work

_________________
PS
As i am Swedish, you may laugh at my spelling and grammar, but please please don’t comment it if you understand what i mean
DS


User avatar
Veteran ( offline )
Posts: 158
Posted: 2011-02-01 17:14 
It works like a charm !!

There semes to be an Option 4 if you have an ARC32:

Init Timerfunction:
Code:
starttime var long
stoptime var long

Start timer
Code:
starttime = hservotime 0

test this code, for example
Code:
GOSUB GetIRDistance[cIRRanger], Result

Stop timer
Code:
stoptime = hservotime 0

Pressent the result
Code:
hserout ["Time (usec) = ", dec (stoptime-starttime)/20, 13]

By doing this timing i found out that the penalty for doing /4.35 instead of the recommended * 100 / 435 is about 5 us
Not much but intresting !

_________________
PS
As i am Swedish, you may laugh at my spelling and grammar, but please please don’t comment it if you understand what i mean
DS


 

All times are UTC - 5 hours [ DST ]. It is currently 2014-10-22 21:36
Feedback Form
Feedback Form