Dart trainer · operator guide · v0.9.59

Between darts

The board is not merely waiting. It is deciding whether motion was a dart, protecting its empty-board reference from changing light, or handing the turn to the next player. This page shows every player-visible timing control on an honest clock.

00 / LEGEND

Four states, one ruler

Every timeline starts at the event named in its title. Vertical grid lines are real seconds. A bar's width therefore means the same thing everywhere on the page.

Waiting for evidenceThe board is still deciding what happened.
Ignoring motionStriped red means a dart cannot register in that lane.
Changing lightThe LEDs are active; references need protection.
ReadyThe relevant guard has ended. This does not override another active lane.
Important: overlapping bars are independent protections. The board is fully ready only when every blocking lane that applies has ended.

Dart lands

1.0 s

Minimum detection gap before another dart can register.

Darts pulled

≈2 s

One breath lets the arm and new player lighting settle.

Leg won

3.5 s

Rainbow plus its one-second vision guard.

New game

0–3 s

Up to four clean-board photographs, one second apart.

01 / THROW

After a dart lands

The white score flash and the detection cooldown begin together, but they protect different things. The flash does not itself block throws; the cooldown does.

Dart landed = 0 s

scale 0–4 seconds
01234 s
score flash
empty-photo guard
next-dart cooldown
The empty-photo guard is flash + 0.3 s. It prevents the lit board becoming the remembered “empty” board. The separate 1 s cooldown prevents one wobbling dart from being counted twice.
DT_LED_FLASH_S
1.5 s

What you feel

Shorter is a quicker blink; longer gives the score more stage time.

DT_ANCHOR_FLASH_GUARD_S
flash + 0.3

Safety rule

Leave this derived. Setting it below the flash lets lit frames poison the empty reference.

DT_COOLDOWN_S
1.0 s

What you trade

Shorter accepts rapid throws sooner but increases double-count risk. Longer can swallow a genuinely fast next dart.

DT_IGNORE_COOLDOWN_S
0.0 s

Do not raise casually

After a “nothing landed” result, zero returns the unused cooldown immediately. At ≥0.24 s the field regression reappears.

Why “nothing landed” must release the cooldown

Before v0.9.58, a harmless motion blip could reserve the full second even though no dart landed. A normal dart arriving 0.24 s later was then dropped until the player pressed Detect now. Only a real landed dart now earns the full cooldown.

02 / TAKEOUT

After you pull the darts

This is two clocks, not one. First the board confirms that the pull is real. Only after the visit is booked do the suppression, player-colour change, and bounce lockout begin.

A · tentative pull detected = 0 s

confirmation clock · outcome varies
0123 s
continuous quiet needed
confirmation ceiling
A clean, quiet board can book the visit after 0.35 s of continuous stillness. A restless or partial pull may wait up to 3 s. The ceiling prevents noise from wedging play forever; it is not a typical delay.

B · visit booked = 0 s

protection clock · one square = one second
01234 s
clean pull: motion ignored
messy pull: motion ignored
player colour
refresh reference
bounce lockout
The colour flip deliberately happens inside the motion-suppression window. Once motion and LED flashes are quiet, the board photographs the empty scene under the new player's final lighting. The first eligible recheck is at 0.7 s; a recent score flash can delay it.
DT_TURN_FLIP_DELAY_S
0.4 s
< DT_POST_PULL_SUPPRESS_S
1.0 s

Hard constraint: the colour flip must remain inside the clean-pull suppression window. A delay at or beyond 1.0 s moves the lighting transition back into live detection and recreates the phantom-dart failure.

DT_TAKEOUT_CONFIRM_MIN_QUIET_S
0.35 s

Less feels faster but can book while the hand is still present. More is calmer but adds delay to every confirmed pull.

DT_TAKEOUT_CONFIRM_MAX_S
3.0 s

The fail-open ceiling for a noisy or partial pull. Raising it adds patience; lowering it accepts a less-settled scene.

DT_POST_PULL_SUPPRESS_S
1.0 s

Protection after a clean pull. Shortening it lets the next dart count sooner, but also the retreating arm and LED transition.

DT_POST_PULL_SUPPRESS_DIRTY_S
1.8 s

The longer version used after a dirty or ceiling-booked pull, when the scene is less trustworthy.

DT_BOUNCE_TAKEOUT_LOCKOUT_S
2.5 s

No bounce is recorded or hinted here: the impact signature is assumed to be the pull tail, not a new throw.

DT_REF_ADOPT_MAX
150 px

A vision threshold, not a delay. Drift from 30–149 px with no darts down is treated as lighting and becomes the new visit reference.

Why the player colour waits 0.4 seconds

The previous design photographed the new visit under the old player's light and changed colour immediately afterwards. Camera exposure and reflection drift crossed the throw trigger at a repeatable 2.1 s, creating four phantom first darts in one field session. The delayed flip plus the refreshed reference remove both halves of that failure.

Why the bounce lockout is longer than motion suppression

Six false “BOUNCE” events arrived 2.05–2.13 s after a takeout. Real first darts measured much later (5th percentile 3.5 s, n=271), so the 2.5 s window removes the pull-tail signature without taxing normal play.

03 / LEG END

After a winning dart

The rainbow is visible celebration. The extra second after it is invisible protection: the strip's return to normal lighting must not look like a bounce-out.

Winning dart = 0 s

scale 0–5 seconds
012345 s
rainbow
vision guard
DT_CELEBRATE_GUARD_S derives as DT_LED_CELEBRATE_S + 1.0 s. If the rainbow changes, the safe default follows it.
DT_LED_CELEBRATE_S
2.5 s

Shorter gets to the next leg sooner; longer makes the win more prominent.

DT_CELEBRATE_GUARD_S
rainbow + 1.0

Leave derived. An explicit value shorter than the rainbow reopens the fake-bounce hole.

04 / GAME START

Before the first dart

A clean empty-board photograph is more valuable than a fast poisoned one. The trainer retries if a hand or shadow is present, but never blocks play indefinitely.

New game = 0 s

attempts, not a mandatory four-second wait
01234 s
clean-board attempts
The first clean photograph wins. Four attempts one second apart therefore mean a worst-case delay of about 3 s between first and final capture, not 4 s. After the final attempt the best available frame is used and play continues.
DT_CLEAN_BOARD_WAIT_S
1.0 s

Spacing between retries. Shorter samples a hand still in motion more often; longer makes a dirty start more noticeable.

DT_CLEAN_BOARD_TRIES
4 tries

More attempts improve the chance of a clean reference but extend the worst case. The trainer remains best-effort.

DT_MODEL_GATE_S
8.0 s

Only when a manually pinned model is not yet serving: wait once for download and swap, then start with an explicit warning rather than block offline play.

DT_SAVE_FIRST_MAX_S
4.0 s

During an open score correction, a pull waits this long for the edit to save before it books the visit.

05 / REFERENCE

Complete timing reference

Defaults are the shipped v0.9.59 values. “Derived” means another setting computes the default; an explicit environment value still overrides it.

DT_LED_FLASH_S
player-visible
1.5 s

White/red score flash emitted by the WLED sidecar.

DT_ANCHOR_FLASH_GUARD_S
derived
flash + 0.3

Rejects empty-reference photographs while the score flash can still be visible.

DT_COOLDOWN_S
1.0 s

Minimum gap after a detected throw before another trigger may fire.

DT_IGNORE_COOLDOWN_S
regression guard
0.0 s

Cooldown retained after an IGNORE. Keep below 0.24 s; zero releases it next tick.

DT_TAKEOUT_CONFIRM_MIN_QUIET_S
0.35 s

Continuous stillness required before a clean takeout re-read may execute.

DT_TAKEOUT_CONFIRM_MAX_S
3.0 s

Fail-open ceiling for takeout confirmation in a noisy scene.

DT_POST_PULL_SUPPRESS_S
1.0 s

Motion suppression after a clean pull.

DT_POST_PULL_SUPPRESS_DIRTY_S
1.8 s

Longer suppression after a dirty or ceiling-booked pull.

DT_TURN_FLIP_DELAY_S
must be < suppress
0.4 s

Defers the new player-colour event into the protected window.

DT_BOUNCE_TAKEOUT_LOCKOUT_S
2.5 s

Forbids bounce records and hints while pull-tail impacts are plausible.

DT_LED_CELEBRATE_S
player-visible
2.5 s

Rainbow duration after a leg or game ends.

DT_CELEBRATE_GUARD_S
derived
rainbow + 1.0

Suppresses lighting-driven false bounces through the rainbow's return transition.

DT_CLEAN_BOARD_WAIT_S
1.0 s

Interval between clean-board reference attempts.

DT_SAVE_FIRST_MAX_S
4.0 s

Maximum pull deferral while a score correction is saving.

DT_MODEL_GATE_S
8.0 s

One-time game-start wait for a manually pinned model that has not swapped in yet.

DT_RECONCILE_EVERY_S
feature off
1.5 s

Cadence of the optional reconcile recheck. It matters only with DT_RECONCILE=1; reconciliation is off by default because it invented phantom darts.

Related non-time controls

DT_CLEAN_BOARD_TRIES=4 limits clean-board attempts. DT_REF_ADOPT_MAX=150 pixels caps lighting-sized reference adoption. DT_RECONCILE=0 keeps the reconcile net off. DT_AUTO_BOUNCE=1 auto-records strong bounce candidates into review.

06 / OPERATION

Change one thing, then play

These are per-rig experiments, not universal physics. Camera position, lighting, strip brightness, and throwing pace all change the safe operating range.

Safe tuning loop

  1. Edit /etc/dart-trainer/config.env on the Pi.
  2. Change one value only and note the old value.
  3. Restart the trainer; a dart-switch off/on cycle does this.
  4. Play complete visits, including quick throws, messy pulls, and a leg end.
  5. Revert immediately if darts disappear or the board invents motion.

No software update is required. Invalid floating-point values in the params.py timing controls fall back to their defaults, but do not rely on that as validation: constraint-breaking numbers can still be syntactically valid.

# /etc/dart-trainer/config.env

# Shorter celebration; guard follows to 3.0 s.
DT_LED_CELEBRATE_S=2.0

# Brisker clean-pull handoff.
DT_POST_PULL_SUPPRESS_S=0.8

# Keep the flip safely inside that window.
DT_TURN_FLIP_DELAY_S=0.4