State machines for interactive Arduino projects
Make games and controls predictable by separating modes, events and timeouts.
A state machine describes the mode a project is currently in and the events allowed to change that mode. It is useful when the same button must behave differently at different times. Start with a small table on paper: state, accepted event, next state and action. Every rule should have an observable result.
For the Reaction-Time Game, RELEASE waits for a clean release, READY accepts a start press, WAIT rejects an early second press, and GO accepts the measured response. A missed response eventually returns to RELEASE. This makes the false-start rule explicit instead of hiding it among unrelated button conditions.
Keep an enum for the states and one timestamp for each timed phase. When entering WAIT, save startedAt. While waiting, compare uint32_t(now - startedAt) with the selected wait duration. When the LED turns on, save goAt immediately. The response result is the interval from that cue to the accepted response edge.
Decide which event wins when two conditions appear in the same loop. In the provided game, a confirmed false start is handled before producing the cue; the cue is also withheld while the raw button is held. Document these choices. Otherwise a player near the time boundary can get inconsistent behavior.
Avoid a multi-second delay for the waiting phase because it prevents the main loop from noticing an early press. Nonblocking timestamp comparisons keep inputs readable. This does not make every operation asynchronous: a Serial print or a pulseIn call elsewhere can still take time. Budget those operations separately.
Write recovery behavior for each state. Ask what happens after a held button, a reset, a sensor failure or a missing response. Begin in a known output condition and require deliberate input before starting. For a moving mechanism, recovery must also consider the physical position and power state.
Verify the transitions one at a time using short Serial messages, not a flood of output on every loop. Log only state changes at first. This approach scales to menu navigation, timed LED sequences and low-voltage demonstrators. Reference: Arduino Blink Without Delay: https://docs.arduino.cc/built-in-examples/digital/BlinkWithoutDelay/

