Skip to content

3 · The trigger

A blaster that cannot be fired is a lamp. Carry on from part 2 — or open Project ▾ ▸ Examples ▸ Tutorial · 02 first light to catch up.

Live Press TRIGGER. White flash, red afterglow, back to idle.

SETUP ▸ Inputs ▸ type trigger into + new input.

An input card in the Studio named trigger: a type dropdown set to digital, a label box reading TRIGGER, a colour swatch showing #ff3b30, a wiring dropdown set to pin, a pin box set to 14, a ticked activeLow checkbox described as 'button to GND', a pull dropdown set to up, a hold-in-milliseconds box, and a filter row with a '+ stage' picker.
An input card. type, wiring and pull are dropdowns; the rest is a label, a colour and a pin.
Control Set it to Meaning
type digital a button, not a knob
label TRIGGER what the on-screen button says
color #ff3b30 what the on-screen button looks like
wiring pin it is soldered to a GPIO
pin 14 which GPIO
activeLow ticked button to GND: pressing pulls the pin down
pull up enable the internal pull-up
hold blank the tap/held split in ms; blank means the default, 400

It does not decide what a press means. Every digital input emits all four of these, always:

Event Fires when
trigger.pressed it went active — the moment of contact
trigger.released it went inactive
trigger.tapped released quickly: a short press, under holdMs (default 400)
trigger.held still down past holdMs: a long press begins

Your states pick which ones they care about, from a dropdown. The same physical button is a tap in one state and a hold in another, and you write no timer.

BEHAVIORS ▸ Scripts ▸ + new script ▸ fire.

Add two set steps to its list (+ action ▸ set, twice) and fill them in:

Step device mode colour sec
1 @barrel color #ffffff 0.05
2 @barrel color #ff2a00 0.12

A device set row has a color / on-off dropdown, because a device set is one or the other and never both. Leave it on color.

3 · Give the state machine somewhere to go

Section titled “3 · Give the state machine somewhere to go”

Open States. You have Ready from part 2; add Firing with + new state.

The Ready state card in the Studio: a ticked 'make initial' checkbox; an ON ENTER list containing a start step targeting idle; a 'when trigger.pressed → Firing' row with a '+ actions' button; a '+ when event' picker; a '+ after a delay' button; and an ON EXIT list containing a stop step targeting idle.
A whole state on one card: what happens on entry, what each event does, what happens on the way out.

On the Ready card:

  1. on enter already has start ▸ idle from part 2.
  2. on exit — + action ▸ stop, target idle.
  3. Click + when event and choose trigger.pressed from the list. A row appears: when trigger.pressed → (stay). Change the second dropdown to Firing.

On the Firing card:

  1. on enter — + action ▸ run, target fire.
  2. + when event ▸ fire.done → Ready.

Both begin a script; the difference is what you get back.

  • start — set it going and forget it. For looks and loops. stop ends it.
  • run — set it going, and the engine promises a <script>.done event when it finishes. For anything the show has to wait for.

fire.done is what brings the state machine home. Nothing had to know how long the fire script takes; change its timings and the transition still lands on the last frame.

The live preview panel with a red TRIGGER button above a GPIO16 ledstrip of eight pixels.
The button exists because a state handles one of its events.

There is no separate list of which buttons are live. A button is enabled exactly when the current state has a handler for one of its events, and the Studio dims it when it is not. If you press something and nothing happens, the answer is almost always that the current state has no handler for that event.

Both patterns come out of the same button and the same two dropdowns:

  • Tap to toggle — handle trigger.tapped in both states, one going each way. The button is momentary; the states remember which side you are on.
  • Hold to run — trigger.pressed starts it, trigger.released stops it.
step-03-the-trigger.json 56 lines
{
  // ===========================================================
  //  BLASTER · STEP 3 — The trigger
  //  A button, and a state machine with somewhere to go.
  // ===========================================================
  "schemaVersion": 1,
  "name": "Blaster 03 - The Trigger",
  "board": "t-display-s3",

  "devices": {
    "barrel": { "kind": "ledstrip", "count": 8, "pin": 16, "order": "GRB", "brightness": 160 }
  },

  // An input is the HARDWARE. What a press MEANS is decided by
  // the states below, which is why one button can be a tap in
  // one state and a hold in another.
  "inputs": {
    "trigger": { "label": "TRIGGER", "color": "#ff3b30", "pin": 14, "activeLow": true, "pull": "up" }
  },

  "scripts": {
    "idle": {
      "children": [
        { "blink": "@barrel", "color": "#ff6a00", "off": "#140400", "sec": 1.4, "loop": true }
      ]
    },

    // A one-shot. Two steps, one after the other: a white flash,
    // then a red afterglow. `sec` on a `set` HOLDS the colour for
    // that long — without it the set lasts a single frame.
    "fire": {
      "children": [
        { "set": "@barrel", "color": "#ffffff", "sec": 0.05 },
        { "set": "@barrel", "color": "#ff2a00", "sec": 0.12 }
      ]
    }
  },

  "states": {
    "initial": "Ready",

    "Ready": {
      "enter": [ { "start": "idle" } ],
      "exit":  [ { "stop": "idle" } ],
      "on": { "trigger.pressed": "Firing" }
    },

    // `run` starts the script AND promises a `fire.done` event
    // when it finishes. That event is what brings us home.
    "Firing": {
      "enter": [ { "run": "fire" } ],
      "on": { "fire.done": "Ready" }
    }
  }
}

Two shapes worth recognising in that file, because the editor draws them differently:

  • A handler that is a bare string — "fire.done": "Ready" — is a pure transition. That is the when … → … row with no actions under it.
  • A handler that is an object — { "do": [...], "to": "...", "when": "..." } — has actions, and optionally a guard. Click + actions on a when row and the editor converts one into the other for you.

Next: 4 · Flow — the one idea the rest of the engine is built on.