Hi Guys, another quick question I have a scene that has multiple triggers and props. I have more than ample inputs and outputs using one HC-8+. I could write the code in a linear fashion however this does not work all the time, if someone backs out of the scene the program never finishes and never resets. No fun. So below I have laid out a simplified version of what I would like to do.
Thanks
Keith
Code
Scan all inputs
Scare 1
if (ttl_pin == 0)
outs.high(0) ' prop moves
outs.high(1) ' strobe on
time.pause(5000) ' wait 5s
outs.low(1) ' strobe off
outs.low(0) ' prop moves
time.pause(3000) ' wait 3s
Scare 2
if (ttl_pin == 1)
outs.high(2) ' prop moves
outs.high(3) ' strobe on
time.pause(5000) ' wait 5s
outs.low(3) ' strobe off
outs.low(2) ' prop moves
time.pause(3000) ' wait 3s
Scare 3
if (ttl_pin == 2)
outs.high(4) ' prop moves
outs.high(5) ' strobe on
time.pause(5000) ' wait 5s
outs.low(5) ' strobe off
outs.low(4) ' prop moves
time.pause(3000) ' wait 3s
You could use separate cogs, but that would be a waste of resources and limit the number of "scares" you could handle. Let me introduce you to a concept called a finite state machine. I will code Scare1 for you, then let you use the same strategy to work out the code for Scare2 and Scare3.
Scare1 has three states: 0) wait for trigger; 1) outputs on, hold 5s, 2) outputs off, retrigger delay of 3s
The jm_time object that I use has a running milliseconds timer. We can grab this from the start of a timed state and then repeatedly check until the state time has elapsed. It's a little easier to see in code than to explain. Have a look:
var
long scare1state
long scare1ms
long scare2state
long scare2ms
long scare3state
long scare3ms
pub main
setup
repeat
run_scare1
run_scare2
run_scare3
pub run_scare1
case scare1state
0 : ' wait for trigger
if (ttl_pin == 0) ' if trigger
scare1ms := time.millis ' mark start of event
outs.high(0) ' outputs on
outs.high(1)
scare1state := 1 ' change state
1 : ' outputs on
if ((time.millis - scare1ms) => 5000) ' have at least 5000ms elapsed?
scare1ms := time.millis ' yes, mark event
outs.low(0) ' outputs off
outs.low(1)
scare1state := 2 ' next state
2 : ' outputs off / trigger delay
if ((time.millis - scare1ms) => 3000) ' have at least 3000ms elapsed?
scare1state := 0 ' yes, back to 0 (look for trigger)
pub run_scare2
pub run_scare3
Note that the state values and timers must be global so they are maintained when the code jumps back to main(). In this short sample main is just cycling through the scares, but it could be maintaining global processes, too. What's critical for this kind of coding to work is to stop using time.pause() which is a blocking method. In this code nothing is blocked and each little section runs very quickly.
That is very cool, I can't wait to try it out latter today, thanks for your help.
Keith