Author Topic: Accurate Subsecond Timing  (Read 391 times)

0 Members and 1 Guest are viewing this topic.

Offline newsboys6

  • LV0 Newcomer (Next: 5)
  • Posts: 4
  • Rating: +0/-0
    • View Profile
Accurate Subsecond Timing
« on: March 05, 2024, 09:13:44 pm »
Hey Everyone,

I'm new to a lot of things this forum being one of them.  First and foremost I am a high school science teacher seeking to make science more fun for my students.  When I started, all the classroom I started in was hot wheels cars and track with handheld stopwatches for timing.  Well, I didn't like that.  So I bought some more expensive carts and the track they roll on.  With the new sets, I never saw a more bored group of kids and they always seemed to be engaged when using hotwheels.  So I set out to build a way for them to use hotwheels with precision.  I discovered Anders Dnar's stopwatch program on ticalc that seemed to be exactly what I needed, a timer that could time events using changes in state of the linkport.  Performance wise the interface is a little clunky for high school level and I found myself having to set up all the stations before student use.  (my setup is in the attached photo)

I kind of lost hope and eventually stumbled upon a youtube video showing how to hex code directly into the calculator a little "driver" that could give ti basic access to the link port (linked below if you have never seen it) and with that I felt I could use ti basic to make a simpler interface program for students to use.

&index=3

I was very naive as looking through the ti manual I thought i could simply use startTmr and checkTmr.  Well the first time it ran it threw a little zero on the screen as the car passed both sensors in less than a second.  Haha, what a great timer able to do high precision timings at the second level.

Thats what I am looking for.  Thats the idea.  A way better startTmr and checkTmr command that uses Asm(prgm.  They would need to be separate like that if possible.  One to start the timer and one to display the time to the screen and stop the timer.  I can more easily impliment them in pendulum period timing if they are separate.  There is a program for the CE that does that but not the 84+ from my searching of the web.  I use TI-84+'s in my classroom.

Here is my beginner level ti basic program (I have done no improvements to the way text is displayed and will work on that once i nail down the timer)  I will also fill in all the place holders.

Code: [Select]
Lbl 0
ClrHome
Menu("Physics Tools","Car Timer",1,"Pendulum Timer",2,"Drop Timer",3,"Kinetic Energy",4,"Quit",5)
Lbl 1
ClrHome
Pause "Press Enter to Begin"
Asm(prgmIN
While Ans=3
Asm(prgmIN
End
startTmr
Asm(prgmIN
While Ans=1
Asm(prgmIN
End
While Ans=3
Asm(prgmIN
End
chckTmr
Disp "Press 1 to Time Again"
Disp "Or press 2 to Return to Menu"
Prompt K
If K=1
Goto 1
Goto 0
Lbl 2
ClrHome
Disp "Pendulum Stuff!"
Pause "Press Enter"
Goto 0
Lbl 3
ClrHome
Disp "Drop It!"
Pause "Press Enter"
Goto 0
Lbl 4
ClrHome
Disp "Kinetic Energy!"
Pause "Press Enter"
Goto 0
Lbl 5

Thanks everyone for taking the time to read this.

Offline Eeems

  • Mr. Dictator
  • Administrator
  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 6265
  • Rating: +318/-36
  • little oof
    • View Profile
    • Eeems
Re: Accurate Subsecond Timing
« Reply #1 on: March 05, 2024, 09:45:27 pm »
It appears that the clock on the 84+/84+SE is only accurate to the nearest second: https://wikiti.brandonw.net/index.php?title=83Plus:Ports:45

To do subsecond timing, you'd probably need to use assembler and count the cycles for every command in the loop used to wait, and then use the current CPU clock speed (https://wikiti.brandonw.net/index.php?title=83Plus:Ports:20) to determine a close estimate.
/e

Offline newsboys6

  • LV0 Newcomer (Next: 5)
  • Posts: 4
  • Rating: +0/-0
    • View Profile
Re: Accurate Subsecond Timing
« Reply #2 on: March 06, 2024, 09:33:46 am »
Ok, so am I to assume that I am being a little naive again and that this cannot be simply solve with a little asm program that starts and then another that just gets a time and stops the timer?

I hate to bother but I know next to nothing about asm and have messaged thepenguin77 about this as he wrote a nifty little timer that responds to the linkport actions shown here: 

https://www.omnimaga.org/ti-z80-calculator-projects/thepenguin77's-utilities/msg350488/#msg350488

He has responded but is currently on vacation and I do not wish to interrupt the vacation any further.  He linked me to the page below:

https://wikiti.brandonw.net/index.php?title=83Plus:Ports:30

If I am understanding the asm from that page using what limited knowledge I have.

Code: [Select]
;Setup up a timer that waits 2 seconds
   di
   ld a,$47      ;8 hz
   out ($30),a
   ld a,0        ; no loop, no interrupt
   out ($31),a
   ld a,16       ;16 ticks / 8 hz equals 2 seconds
   out ($32),a
wait:
   in a,(4)
   bit 5,a       ;bit 5 tells if timer 1
   jr z,wait     ;is done
   xor a
   out ($30),a   ;Turn off the timer.
   out ($31),a

We are loading an 8hz clock into a ($47).  The 8hz clock is turned on ($30).  We load a with 0.  Now loop control is started ($31) (This is where we are running processes to count ticks?).  Below that we keep rolling until a is equal to 16 (counting 16 ticks at 8 hz equals 2 seconds).  I am not sure what all the wait part is doing other than hitting the $30 which is the on/off switch.

So as I understand using 8hz only gives an accuracy of 1/8th seconds but there are higher hz clocks available.  Ticks will have to be counted and stored somewhere which may be able to be retrieved by the same or another program to then use some math and figure out the time based on the ticks that have passed.

So all this is running while the ti-basic processes are also running which I think would also use the CPU which could affect the accuracy of the calculated time?

I feel like I am getting somewhere and I feel like I am not.  Am I making any sense at all here?

Offline Eeems

  • Mr. Dictator
  • Administrator
  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 6265
  • Rating: +318/-36
  • little oof
    • View Profile
    • Eeems
Re: Accurate Subsecond Timing
« Reply #3 on: March 06, 2024, 10:57:53 pm »
Ok, so am I to assume that I am being a little naive again and that this cannot be simply solve with a little asm program that starts and then another that just gets a time and stops the timer?
Correct, as you wouldn't know how long the TI-Basic code took to hand off to assembler etc.


I hate to bother but I know next to nothing about asm and have messaged thepenguin77 about this as he wrote a nifty little timer that responds to the linkport actions shown here: 

https://www.omnimaga.org/ti-z80-calculator-projects/thepenguin77's-utilities/msg350488/#msg350488

He has responded but is currently on vacation and I do not wish to interrupt the vacation any further.  He linked me to the page below:
This is a forum which, similar to email, can have several weeks between replies, so it's totally fair to ping @thepenguin77 to ask for an explanation, it just may take a little while to get a response.

https://wikiti.brandonw.net/index.php?title=83Plus:Ports:30

If I am understanding the asm from that page using what limited knowledge I have.

Code: [Select]
;Setup up a timer that waits 2 seconds
   di
   ld a,$47      ;8 hz
   out ($30),a
   ld a,0        ; no loop, no interrupt
   out ($31),a
   ld a,16       ;16 ticks / 8 hz equals 2 seconds
   out ($32),a
wait:
   in a,(4)
   bit 5,a       ;bit 5 tells if timer 1
   jr z,wait     ;is done
   xor a
   out ($30),a   ;Turn off the timer.
   out ($31),a

We are loading an 8hz clock into a ($47).  The 8hz clock is turned on ($30).  We load a with 0.  Now loop control is started ($31) (This is where we are running processes to count ticks?).  Below that we keep rolling until a is equal to 16 (counting 16 ticks at 8 hz equals 2 seconds).  I am not sure what all the wait part is doing other than hitting the $30 which is the on/off switch.

So as I understand using 8hz only gives an accuracy of 1/8th seconds but there are higher hz clocks available.  Ticks will have to be counted and stored somewhere which may be able to be retrieved by the same or another program to then use some math and figure out the time based on the ticks that have passed.
I'll have to defer to someone with more experience here on if there is anything in the code itself that's an issue. But yes, you'd need to store the count somewhere by calculating how many ticks it would take based on the opcodes you are using, and then incrementing a counter on each iteration.

So all this is running while the ti-basic processes are also running which I think would also use the CPU which could affect the accuracy of the calculated time?
TI-OS is not multithreaded with processes. It's running on a z80 with very limited RAM. It only affects timing to switch contexts, so switching from TI-Basic to assembler, or switching to an interrupt if they are enabled. You would need to write assembler code that both waits for the link port to be in the state you want it to be, as well as handles the timing, and then returns the result to TI-Basic.

I feel like I am getting somewhere and I feel like I am not.  Am I making any sense at all here?
/e

Offline thepenguin77

  • z80 Assembly Master
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1594
  • Rating: +823/-5
  • The game in my avatar is bit.ly/p0zPWu
    • View Profile
Re: Accurate Subsecond Timing
« Reply #4 on: March 07, 2024, 11:48:58 am »
A mention after like 10 years :3? I'm honored. Ski vacations have lots of downtime, you might be surprised how excited I am to actually have a real need to make a Ti84 program again.

Here was my solution to this program, idk if it actually works since I haven't messed with the timers in years. The idea is set up 3 timers. Timer2 runs as 128Hz for the actual timing, but this loops every 2 seconds. Timer3 runs at 8Hz to keep track of Timer2. The TI84 clock runs at 1Hz to keep track of Timer2.

Program 1:
Code: [Select]
46h -> (33h) ; 128 Hz on timer2
1   -> (34h) ; no interrupts but loop; does this work?
47h -> (36h) ; 8 Hz on timer3
1   -> (37h) ; no interrupts but loop

Store ports 45h-48h to somewhere secret in ram. MD5Buffer?

0 ->(35h); start timer2 in an infinite loop
0 ->(38h); start timer3 in an infinite loop (does this work?)

Timer2 overflows every 2 seconds. Timer3 overflows every 32 seconds. (Edit, checked in Calcsys, this totally works)


Program 2: (this is in python because the asm code to do this will be hard to read)
Code: [Select]
timer2 = (35h) - 1 # subtract 1 so that 255 is the highest value
timer3 = (38h) - 1
simple_elapsed = Compare 45h-48h with stored time to get seconds

# ok, the hard part is that the ti84 clock only has a resolution of 1 second
#   we need to be careful if we're really close to 32 seconds
timer3_full_cycles = int( (simple_elapsed - 3) / 32 ) # 3 seconds is overkill
seconds_into_current_cycle_safe = (simple_elapsed - 3) % 32 ; if this is -3 it underflows to 29
if seconds_into_current_cycle_safe > 32 - 6:
    if timer3 > 128:
        timer3_full_cycles += 1

# timer2 does a full cycle every 16 ticks of timer3
timer3_elapsed = 255 - timer3
timer2_full_cycles = int( (timer3_elapsed - 2) / 16 ) # 2 ticks of safety
ticks_into_current_cycle_safe = (timer3_elapsed - 2) % 16
if ticks_into_current_cycle_safe > 16 - 4:
    if timer2 > 128:
        timer2_full_cycles += 1

timer2_elapsed = 255 - timer2

final_time = timer3_full_cycles * 32 + timer2_full_cycles * 2 + timer2_elapsed / 128

final_time -> ANS # how do you do this?

I think this code is buggy if you manage to call program 2 within 1/128 of a second of program 1. Should work otherwise unless I'm missing something.



Things I vaguely remember and it would be cool if someone could verify them:
A. One of the timers messes up TI-OS right? Is that timer1?
B. How does one return a list in ANS (or even a simple number like above)?
« Last Edit: March 17, 2024, 05:58:23 pm by thepenguin77 »
zStart v1.3.013 9-20-2013 
All of my utilities
TI-Connect Help
You can build a statue out of either 1'x1' blocks or 12'x12' blocks. The 1'x1' blocks will take a lot longer, but the final product is worth it.
       -Runer112

Offline E37

  • LV6 Super Member (Next: 500)
  • ******
  • Posts: 358
  • Rating: +23/-0
  • Trial and error is the best teacher
    • View Profile
Re: Accurate Subsecond Timing
« Reply #5 on: March 09, 2024, 05:18:07 pm »
According to wikiti, TI-OS uses all but 1 timer for its own purposes.

This is the code that Axe uses to input and output to Ans:
Code: [Select]
p_StoreAns: ;sets ans to hl
B_CALL(_SetXXXXOP2)
B_CALL(_OP2toOP1)
B_CALL(_StoAns)
ret

p_RecalAns: ;reads ans into hl
B_CALL(_RclAns)
B_CALL(_ConvOP1)
ex de,hl
ret
I'm still around... kind of.

Offline thepenguin77

  • z80 Assembly Master
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1594
  • Rating: +823/-5
  • The game in my avatar is bit.ly/p0zPWu
    • View Profile
Re: Accurate Subsecond Timing
« Reply #6 on: March 17, 2024, 06:23:42 pm »
I do miss figuring out how the hardware works and reverse engineering the OS. I don't miss debugging asm code...

Here's how to use the program that does accurate timing on the TI-84+ like startTmr:
Code: [Select]
# Start the timers
Asm(prgmTIMESTRT)

# Store the elapsed time (at 1/128s resolution) into Ans
#   -1 if an error is detected (timers disabled or system clock went backwards)
Asm(prgmTIMEIT)

Someone should do a whole bunch of testing on this to make sure it's accurate. I've tested all the special cases like 0 and 2^21 (where the final result requires 17 bits to be stored), and they work. But I can't guarantee this works always and forever. I'd probably recommend a basic program that asserts that the outputs from this program are consistently increasing at the same rate and then let that run overnight or something.

Caveats:
  • If you change your system clock, this will be inaccurate
  • If you let your calculator turn off, the timers are disabled.
  • Running other programs that mess with the timers will break this.



The details:

After playing around with the timers, I can see that timer2 get disabled the very first time it overflows which makes it totally useless. This check happens in the interrupt routine and there's no way to stop it.

Timer1 and Timer3 don't get disabled as long as their control port has bit 1 set to 0 (they aren't triggering interrupts), so these are both safe to use as far as I can tell. Presumably they get used somewhere but I'm not sure where.


The program works exactly as depicted in the python code above. There was a mistake in the original post but I've edited it to fix it. Nothing is too complicated, but coding this up in assembly is rough. I kept the full-precision of the internal clock, so in theory, this program can keep track of time for like 2^32 seconds.

The program seems to take 0.0195 seconds to run from within TI-BASIC (just call TIMESTRT then call TIMEIT 10 times and divide ANS by 10). The program stores the timer values as soon as it starts, but whether the slowness is TI-BASIC starting the program or the floating point operations while returning the result I'm not sure.


Code and programs attached. It ended up being around 300 lines and 400 bytes.
« Last Edit: March 17, 2024, 06:31:41 pm by thepenguin77 »
zStart v1.3.013 9-20-2013 
All of my utilities
TI-Connect Help
You can build a statue out of either 1'x1' blocks or 12'x12' blocks. The 1'x1' blocks will take a lot longer, but the final product is worth it.
       -Runer112

Offline newsboys6

  • LV0 Newcomer (Next: 5)
  • Posts: 4
  • Rating: +0/-0
    • View Profile
Re: Accurate Subsecond Timing
« Reply #7 on: March 17, 2024, 07:11:32 pm »
Oh wow Oh wow.

So time start starts the timer once called and then does timeit return the total time elapsed once it is triggered?

I do believe that these are what I need and when I get to work tomorrow morning I will hook everything up and let everyone know how it goes.

Cheap precision is something I have been chasing for a while and the hardware to hook up only requires a few leds, photoresisors, a transistor and a resistor.  Far cheaper than $50 for a single photogate from Vernier (you need two to time something).  I think something like this can benefit elementary schools, middle schools, and high schools.  Especially ones that are underfunded.

So, from the bottom of my heart, thank you.



Ok, don't know if i am using it wrong or not.  It could be a problem that the program I am using to listen to the link port is also storing values in Ans.  When I first ran it I was getting syntax errors when I was calling TIMESTRT after IN took the trigger from the linkport.

I switched things around to start the timer before everything else but being that I have to also call IN to listen to the state of the port may be causing problems.  My posted TI basic code below returns two 3's which is the default state of the linkport.

Not that a beggar can be a chooser but doing your emailed suggestion on having a program that listens and triggers and stores a set number of times in a list in Ans and is triggered by tip tip or ring ring might be the better way to go if possible.

Code and result attached below.

Code: [Select]
Lbl 0
ClrHome
Menu("Physics Tools","Car Timer",1,"Pendulum Timer",2,"Drop Timer",3,"Kinetic Energy",4,"Quit",5)
Lbl 1
ClrHome
Pause "Press Enter to Begin"
Asm(prgmTIMESTRT
Asm(prgmIN
While Ans=3
Asm(prgmIN
End
Asm(prgmTIMEIT
Disp Ans
Asm(prgmIN
While Ans=1
Asm(prgmIN
End
While Ans=3
Asm(prgmIN
End
Asm(prgmTIMEIT
Disp Ans
Disp "Press 1 to Time Again"
Disp "Or press 2 to Return to Menu"
Prompt K
If K=1
Goto 1
Goto 0

Ill attach an image later, it returns to 3's.


Edit (Eeems): Merged double post
« Last Edit: March 18, 2024, 01:40:16 pm by Eeems »

Offline thepenguin77

  • z80 Assembly Master
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1594
  • Rating: +823/-5
  • The game in my avatar is bit.ly/p0zPWu
    • View Profile
Re: Accurate Subsecond Timing
« Reply #8 on: March 18, 2024, 12:30:26 pm »
I think we're going to need the code of the IN program.

Do my programs at least work in isolation for you?
zStart v1.3.013 9-20-2013 
All of my utilities
TI-Connect Help
You can build a statue out of either 1'x1' blocks or 12'x12' blocks. The 1'x1' blocks will take a lot longer, but the final product is worth it.
       -Runer112

Offline newsboys6

  • LV0 Newcomer (Next: 5)
  • Posts: 4
  • Rating: +0/-0
    • View Profile
Re: Accurate Subsecond Timing
« Reply #9 on: March 18, 2024, 12:44:39 pm »
IN is a program written entirely in hex provided by the youtube video linked up top.  It can be typed directly into the calculator and compiled by the calculator itself the code is as follows:

Code: [Select]
PROGRAM:0IN
:AsmPrgm
:DB00
:26006F
:EF9247
:EF5641
:EFBF4A
:C9

You type that into your calculator and save it.  Then you run: AsmComp(prgm0IN, prgmIN)

And there you go, you have IN which returns a 3 by default when both he tip and the ring are high.

These are the states returned to Ans by IN:

Value     Tip      Ring

0           Low     Low
1           High    Low
2           Low     High
3           High    High

They go low when they are connected to ground.  My little circuit connects the ring to the ground when a car rolls over either of the photoresistors thus triggering the start or end of something when Ans is not equal to 3 (equal to 1).

Thank you again, I can't say that enough.