Calculator Community > TI Z80

Accurate Subsecond Timing

(1/2) > >>

newsboys6:
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: ---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
--- End code ---

Thanks everyone for taking the time to read this.

Eeems:
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.

newsboys6:
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: --- ;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
--- End code ---

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?

Eeems:

--- Quote from: newsboys6 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?

--- End quote ---
Correct, as you wouldn't know how long the TI-Basic code took to hand off to assembler etc.



--- Quote from: newsboys6 on March 06, 2024, 09:33:46 am ---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:

--- End quote ---
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.


--- Quote from: newsboys6 on March 06, 2024, 09:33:46 am ---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: --- ;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
--- End code ---

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.

--- End quote ---
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.


--- Quote from: newsboys6 on March 06, 2024, 09:33:46 am ---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?

--- End quote ---
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.


--- Quote from: newsboys6 on March 06, 2024, 09:33:46 am ---I feel like I am getting somewhere and I feel like I am not.  Am I making any sense at all here?

--- End quote ---

thepenguin77:
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: ---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?)

--- End code ---

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: ---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?

--- End code ---

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)?

Navigation

[0] Message Index

[#] Next page

Go to full version