• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Simplistic reaction timer

MrDEB

Well-Known Member
Thread starter #1
My neighbor is constructing a "man cave" with a hot rod, fast car theme (old gas pump front panel, drag slick, stop light etc.
I got crazy idea to build a Chrondike Christmas Tree (a "tree" used in drag racing indicating when to leave the starting line. The starting line utilizes clocks to measure drivers reaction time)
Reaction time is measured how fast a driver gets their car moving after the green light on the tree comes on.
So I wrote a short code to begin a reaction time that is displayed on an LCD. This is a crude start and for a better clock to use TMR1 and interrupts.
So a work in progress. End project to utilize 12v Leds using mosfets.
DEVICE = 18F4321
CLOCK = 8
CONFIG MCLRE = off
// some LCD options...
#option LCD_DATA = PORTD.4
#option LCD_RS = PORTd.0
#option LCD_EN = PORTd.1
// import LCD library...
INCLUDE "SetDigitalIO.bas"
INCLUDE "IntOSC8.bas"
INCLUDE "LCD.bas"
INCLUDE "utils.bas"
'INCLUDE "Keypad16pullup.bas"
INCLUDE "Convert.bas"
DIM blue AS portB.7
DIM green AS portb.5
DIM button AS portb.4
DIM time AS WORD
DIM start AS portb.0
time = 0
setalldigital
OUTPUT (blue)
OUTPUT (green)
INPUT(start)
cls
DELAYMS(50)
blue =1
green = 1
start = 1
WHILE true
blue = 0
DELAYMS(3000)
blue = 1
green = 0 //go
REPEAT
INC (time)
UNTIL button = 0
green = 1
WriteAt(1,1,"reaction=",DecToStr(time),"ms",2)
DELAYMS(3000)
time = 0 //reset to zero
WEND
 
#2
If you want to count msecs your loop should look more like this:
Code:
time = 0
REPEAT
    DELAYMS(1)
    INC (time)
UNTIL button = 0
Otherwise you'll increment the 'time' variable as fast as the loop runs
 

MrDEB

Well-Known Member
Thread starter #4
After using tumbleweeds suggestion it looks like it works but being really bad at math, how to display time in one thousands of a second?
.0075 as an example
1ms is 1000 of a second and um is 10000 of a second so how to display correctly.
I tried dividing by 1000 but that isn't right either
Pretty sure the indents are correct??
DEVICE = 18F4321
CLOCK = 8
CONFIG MCLRE = off
// some LCD options...
#option LCD_DATA = PORTD.4
#option LCD_RS = PORTd.0
#option LCD_EN = PORTd.1
// import LCD library...
INCLUDE "SetDigitalIO.bas"
INCLUDE "IntOSC8.bas"
INCLUDE "LCD.bas"
INCLUDE "utils.bas"
INCLUDE "Convert.bas"
DIM blue AS portB.7
DIM green AS portb.5
DIM button AS portb.4
DIM time AS WORD
DIM start AS portb.0
time = 0
setalldigital
OUTPUT (blue)
OUTPUT (green)
INPUT(start)
cls
DELAYMS(50)
blue =1
green = 1
start = 1
WHILE true
blue = 0
DELAYMS(3000)
blue = 1
green = 0 //go
REPEAT
DELAYuS(time)
INC (time)
UNTIL button = 0
green = 1
'time = time /1000
WriteAt(1,1,"reaction=",DecToStr(time),"ms",4)
DELAYMS(3000)
time = 0 //reset to zero
WriteAt(1,1,"try again=",DecToStr(time),"ms",4)
WEND
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
#5
Pretty sure the indents are correct??
You are desperately trying to show code... Here is your code in code tags..
Code:
DEVICE = 18F4321
CLOCK = 8
CONFIG MCLRE = off
// some LCD options...
#option LCD_DATA = PORTD.4
#option LCD_RS = PORTd.0
#option LCD_EN = PORTd.1
// import LCD library...
INCLUDE "SetDigitalIO.bas"
INCLUDE "IntOSC8.bas"
INCLUDE "LCD.bas"
INCLUDE "utils.bas"
INCLUDE "Convert.bas"
DIM blue AS portB.7
DIM green AS portb.5
DIM button AS portb.4
DIM time AS WORD
DIM start AS portb.0
time = 0
setalldigital
OUTPUT (blue)
OUTPUT (green)
INPUT(start)
cls
DELAYMS(50)
blue =1
green = 1
start = 1
WHILE true
   blue = 0
   DELAYMS(3000)
   blue = 1
   green = 0      //go
   REPEAT
      DELAYuS(time)
      INC (time)
   UNTIL button = 0
   green = 1
   'time = time /1000
   WriteAt(1,1,"reaction=",DecToStr(time),"ms",4)
   DELAYMS(3000)
   time = 0 //reset to zero
   WriteAt(1,1,"try again=",DecToStr(time),"ms",4)
WEND
Type "["code=basic"]"
at the end "["/code"]" All except the inverted commas These are so you can see
 
#6
Do you really have a need to show more than 1/1000 of a second?
One msec resolution seems like it would be more than acceptable unless you've got a bunch of Olympic neighbors.

In any event, there are now at least two things wrong.
Code:
dim time as word

   REPEAT
      DELAYuS(time)
      INC (time)
   UNTIL button = 0
First, 'time' is a word. That's 16 bits. The max value it can hold is (2^16)-1 = 65535.
If 'time' is counting usecs then that's 65,535 usecs = 65.535 msecs, which is far too short.
If 'time' counts msecs then it's 65535 msecs = 65.535 secs which sounds just fine for what you're doing.

Secondly, 'DELAYUS(time)' delays more and more time each iteration through the loop as 'time' gets incremented.

Put 'DELAYUS(time)' back to 'DELAYMS(1)'.

I'll leave the printing part to others. Wouldn't want this to end prematurely.
 

large_ghostman

Well-Known Member
Most Helpful Member
#8
Whats a 12V led? serious question...

I got some 10W ones that i rarely use(way too bright) and some 1 W ones I normally use. I run then off a 5V rail, why use 12V out of interest.
For what your doing i would get a busted bulls eye bulb (old style non led), take apart and stick a led in it. it should give ample reflection for a traffic light with one led per colour. And why use a LCD?? for that kind of thing a read out in leds above the traffic lights seems more authentic and a better option

 
#9
whatever code you post will be randomly changed until it doesn't work
Mike, that's a given.

I now take bets with myself as to what portion of the code will get screwed up first.
I know there's no real point in answering, it's just for my own amusement.
 

large_ghostman

Well-Known Member
Most Helpful Member
#10
Mike, that's a given.

I now take bets with myself as to what portion of the code will get screwed up first.
I know there's no real point in answering, it's just for my own amusement.
DIM will be first

All old hands know that Dim is always the major issue in these posts ;)
 

MrDEB

Well-Known Member
Thread starter #12
this looks more accurate and runs better. Still need to figure out how to display (example 1ms = .001)


[code = basic]
DEVICE = 18F4321
CLOCK = 8
CONFIG MCLRE = off
// some LCD options...
'#option KEYPAD_PORT = PORTc
#option LCD_DATA = PORTD.4
#option LCD_RS = PORTd.0
#option LCD_EN = PORTd.1
// import LCD library...
INCLUDE "SetDigitalIO.bas"
INCLUDE "IntOSC8.bas"
INCLUDE "LCD.bas"
INCLUDE "utils.bas"
'INCLUDE "Keypad16pullup.bas"
INCLUDE "Convert.bas"
// include ISR timer module
INCLUDE "ISRTimer.bas"
DIM mS AS WORD
DIM blue AS portb.7
DIM button AS portb.4
DIM green AS portb.5
dim red as portb.6
// OnTimer event, flash LED...
SUB OnTimer()
INC(mS)
END SUB
// initialise the timer module...
Timer.Initialize(1)
// initialise timer.items(0)
Timer.Items(0).Interval = 1 // 1mS
Timer.Items(0).OnTimer = @OnTimer // timer event handler
// enable the timers...
Timer.Items(0).Enabled = true
INPUT (button)
OUTPUT (blue)
output (green)
output (red)
setalldigital
green = 1
blue = 1
button = 1
red = 1
WHILE True
mS = 0
green = 0 //turn on green until button is pressed

Timer.Start //start timing reaction time

REPEAT
UNTIL
button = 0 // button pressed then turn off green, turn on blue
green = 1 //off
blue = 0 //on
Timer.Stop //stop timer
WriteAt(1,1,"reaction=",DecToStr(mS),"ms",2)
DELAYMS(3000)
blue = 1 //led is off
DELAYMS(1000)

WEND
[/code]
 

large_ghostman

Well-Known Member
Most Helpful Member
#13
try displaying 001
lets face it anything over 999 and you might as well use a candle and bands marked on it.
Also stop the timer as soon as something is pressed, dont leave it until last ;)
 

large_ghostman

Well-Known Member
Most Helpful Member
#14
Code:
[code = basic]
DEVICE = 18F4321
CLOCK = 8
CONFIG MCLRE = off
// some LCD options...
'#option KEYPAD_PORT = PORTc
#option LCD_DATA = PORTD.4
#option LCD_RS = PORTd.0
#option LCD_EN = PORTd.1
// import LCD library...
INCLUDE "SetDigitalIO.bas"
INCLUDE "IntOSC8.bas"
INCLUDE "LCD.bas"
INCLUDE "utils.bas"
'INCLUDE "Keypad16pullup.bas"
INCLUDE "Convert.bas"
// include ISR timer module
INCLUDE "ISRTimer.bas"
DIM mS AS WORD
DIM blue AS portb.7
DIM button AS portb.4
DIM green AS portb.5
dim red as portb.6
// OnTimer event, flash LED...
SUB OnTimer()
INC(mS)
END SUB
// initialise the timer module...
Timer.Initialize(1)
// initialise timer.items(0)
Timer.Items(0).Interval = 1 // 1mS
Timer.Items(0).OnTimer = @OnTimer // timer event handler
// enable the timers...
Timer.Items(0).Enabled = true
INPUT (button)
OUTPUT (blue)
output (green)
output (red)
setalldigital
green = 1
blue = 1
button = 1
red = 1
WHILE True
mS = 0
green = 0 //turn on green until button is pressed

Timer.Start //start timing reaction time

REPEAT
UNTIL
button = 0 // button pressed then turn off green, turn on blue
green = 1 //off
blue = 0 //on
Timer.Stop //stop timer
WriteAt(1,1,"reaction=",DecToStr(mS),"ms",2)
DELAYMS(3000)
blue = 1 //led is off
DELAYMS(1000)

WEND
The above is your code, i was trying to work out how you messed up code tags! I think in the top code tag you got a space, no spaces

How the feck can you mess that up??finally worked it out.............

you put a space both sides of = there is no space its code=basic but with square brackets around it and no spaces
 
Last edited:
#15
Here's how you would convert ms to a secs string, broken up into its steps
Code:
include "convert.bas"
dim ms as word
dim s as string

// convert word ms to secs string (ie "D.DDD")
s = DecToStr(ms/1000)               ' print whole portion (number before decpt)
s = s + "."                         ' add decpt
s = s + DecToStr((ms MOD 1000), 3)  ' add three digits fractional part
s = s + "secs"

// or all in one shot
s = DecToStr(ms/1000) + "." + DecToStr((ms MOD 1000), 3) + "secs"
To write it to the LCD you could just use
Code:
// write string to LCD
s = DecToStr(ms/1000) + "." + DecToStr((ms MOD 1000), 3) + "secs"
WriteAt(1,1,"reaction=",s,2)
or put it all into the WriteAt statement
 

large_ghostman

Well-Known Member
Most Helpful Member
#16
Seriously it takes you guys a second to notice a color change and press a button?? I am not looking forward to getting over 30! :D
 

MrDEB

Well-Known Member
Thread starter #17
Thanks tumbleweed. I will try your suggestion out.
I tried ms/1000 but it didn't work as I wanted it to.
Your suggestion is very imaganitive. I was even thinking a CONST ARRAY but then what do I know. Would screw up the indenting--lol
 

large_ghostman

Well-Known Member
Most Helpful Member
#18
You need a random seed value, muscle memory will quickly sync with a set speed of light change. Try it with a stop watch and try and hit exactly one second. I bet 15 mins your within a few ms
 

MrDEB

Well-Known Member
Thread starter #19
the addition of tumbleweeds suggestion worked like a charm. My best reaction was .042 but mostly .160 or so. I kinda jumped the gun in anticipation.
What I want to add now is a Red led to indicate if the player jumped the gun before the green led sand display how bad the reaction was before the green.
LG is correct that I need a random # before the green led. Will add AFTER I get the basic code working then add the random #
 

MrDEB

Well-Known Member
Thread starter #20
For the fun of the game, as a suggestion only, is to build the circuit and have fun with playing with friends, add a second player option, random # and the red led.
I did have a reaction of .001 but am sure that was a fluke
 

Latest threads

EE World Online Articles

Loading

 
Top