Test Sequences
Build automated test sequences with stages, timing, and abort handling
Test sequences are ordered procedures that step through stages: pressurize, hold, fire, shutdown. Arc sequences handle this naturally with stages, transitions, and concurrent monitoring for abort conditions.
Basic Sequence
A minimal sequence with idle, active, and complete states:
sequence main {
stage idle {
// Wait for operator to start
0 -> press_vlv_cmd
}
stage active {
1 -> press_vlv_cmd
ox_pt_1 > 500 => next
}
stage complete {
0 -> press_vlv_cmd
}
}
start_cmd => main Wire start_cmd to a button in Console. When clicked, the sequence moves from idle to
active, opens the valve, waits for pressure to reach 500, then closes the valve and
stops.
The entry point start_cmd => main triggers the sequence when the channel
receives a truthy value (non-zero). Create start_cmd as a u8 virtual
channel in Synnax, then wire it to a button in your Console schematic.
Timed Stages
Use wait to add delays between stages:
sequence main {
stage pressurize {
1 -> press_vlv_cmd
ox_pt_1 > 500 => next
}
stage hold {
// Keep valve open, wait 30 seconds
1 -> press_vlv_cmd
wait{duration=30s} => next
}
stage depressurize {
0 -> press_vlv_cmd
ox_pt_1 < 50 => next
}
stage complete {
0 -> press_vlv_cmd
}
}
start_cmd => main The sequence pressurizes to 500 psi, holds for 30 seconds, then depressurizes.
Abort Handling
Real test sequences need abort capability. List abort conditions first in each stage (line order determines priority):
sequence main {
stage pressurize {
// ABORT CONDITIONS FIRST
ox_pt_1 > 700 => abort // over-pressure
abort_btn => abort // operator abort
// Normal operations
1 -> press_vlv_cmd
ox_pt_1 > 500 => next
}
stage hold {
ox_pt_1 > 700 => abort
abort_btn => abort
1 -> press_vlv_cmd
wait{duration=30s} => next
}
stage depressurize {
abort_btn => abort
0 -> press_vlv_cmd
ox_pt_1 < 50 => next
}
stage complete {
0 -> press_vlv_cmd
}
}
sequence abort {
stage safing {
0 -> press_vlv_cmd
0 -> fuel_vlv_cmd
0 -> igniter_cmd
}
}
start_cmd => main
emergency_stop => abort The abort sequence closes all valves and disables actuators. Both the automated
conditions and the emergency_stop channel can trigger it.
Always put abort conditions before normal operation flows in each stage.
When multiple conditional transitions (=>) are truthy in the same cycle, the
first one listed wins. Safety conditions should always have priority.
Conditional Progression
Advance based on multiple conditions being satisfied:
sequence main {
stage verify {
// Check all systems ready
ox_pt_1 > 100 and ox_pt_1 < 200 and fuel_pt_1 > 100 => next
// Timeout if conditions not met
wait{duration=10s} => timeout
}
stage pressurize {
ox_pt_1 > 700 => abort
abort_btn => abort
1 -> press_vlv_cmd
ox_pt_1 > 500 => next
}
stage hold {
// ... rest of sequence
}
stage timeout {
// Handle timeout condition
0 -> press_vlv_cmd
}
} The verify stage waits until both pressure readings are in range. If they don’t reach the required values within 10 seconds, the sequence moves to a timeout stage instead.
Inline Gates for Linear Procedures
When a test is mostly ordered writes and waits but has one step that needs to watch multiple conditions, an inline stage keeps the procedure readable without forcing every step into its own named stage:
sequence prime {
// Straight-line setup
0 -> vent_vlv_cmd
1 -> press_vlv_cmd
// Inline gate: success, over-pressure abort, and timeout all watched at once
stage {
tank_pressure > 700 => abort
abort_btn => abort
tank_pressure > 500 => next
wait{30s} => timeout
}
// Procedure resumes
0 -> press_vlv_cmd
}
sequence abort {
stage safed {
0 -> press_vlv_cmd
1 -> vent_vlv_cmd
}
}
sequence timeout {
stage safed {
0 -> press_vlv_cmd
1 -> vent_vlv_cmd
}
}
start_btn => prime
emergency_stop => abort All four transitions inside the inline stage are armed in parallel. Line order breaks
ties, so the over-pressure abort wins if it fires at the same instant as the success
check. => next advances to the next item in prime; => abort and => timeout jump
to those named sequences.
Use this pattern when the rest of the procedure is straight-line and only one step needs a multi-exit gate.
Rate-Limited Pressurization
Control the pressurization rate to avoid thermal shock or mechanical stress:
func rate_monitor{dt_ms f64, max_rate f64} (value f64) u8 {
prev $= 0.0
d := value - prev
prev = value
dt_s := dt_ms / 1000.0
if dt_s <= 0 {
return 0
}
rate := d / dt_s
// Check magnitude
if rate < 0 {
rate = 0.0 - rate
}
if rate > max_rate {
return 1
}
return 0
}
sequence main {
stage pressurize {
// Abort conditions
ox_pt_1 > 700 => abort
ox_pt_1 -> rate_monitor{dt_ms=50.0, max_rate=100.0} -> ox_rate_high
ox_rate_high => abort
abort_btn => abort
// Pressurize slowly by pulsing the valve
interval{period=100ms} -> press_valve_pulse{}
ox_pt_1 > 500 => next
}
// ... rest of sequence
} The rate monitor triggers an abort if pressure rises faster than 100 psi/second.
Complete Test Stand Sequence
A realistic rocket engine test sequence with all the patterns combined:
// Rate monitoring
func pressure_rate{dt_ms f64} (value f64) f64 {
prev $= 0.0
d := value - prev
prev = value
dt_s := dt_ms / 1000.0
if dt_s <= 0 {
return 0.0
}
return d / dt_s
}
sequence main {
// Stage 1: System checkout
stage checkout {
ox_pt_1 > 50 => abort // tank should be empty
fuel_pt_1 > 50 => abort
abort_btn => abort
// All systems nominal, proceed
wait{duration=2s} => next
}
// Stage 2: Pressurize oxidizer
stage press_ox {
ox_pt_1 > 650 => abort
ox_pt_1 -> pressure_rate{dt_ms=50.0} -> ox_rate
ox_rate > 100 => abort
abort_btn => abort
1 -> ox_press_vlv_cmd
ox_pt_1 > 500 => next
}
// Stage 3: Pressurize fuel
stage press_fuel {
ox_pt_1 > 650 => abort
fuel_pt_1 > 450 => abort
abort_btn => abort
1 -> ox_press_vlv_cmd // maintain ox pressure
1 -> fuel_press_vlv_cmd
fuel_pt_1 > 350 => next
}
// Stage 4: Pre-fire hold
stage hold {
ox_pt_1 > 650 => abort
fuel_pt_1 > 450 => abort
ox_pt_1 < 400 => abort // pressure decay = leak
fuel_pt_1 < 250 => abort
abort_btn => abort
1 -> ox_press_vlv_cmd
1 -> fuel_press_vlv_cmd
wait{duration=5s} => next
}
// Stage 5: Ignition
stage ignite {
ox_pt_1 > 650 => abort
fuel_pt_1 > 450 => abort
abort_btn => abort
1 -> ox_press_vlv_cmd
1 -> fuel_press_vlv_cmd
1 -> igniter_cmd
// Wait for combustion confirmation
chamber_tc_1 > 500 => next
// Ignition timeout
wait{duration=3s} => ignition_fail
}
// Stage 6: Main run
stage main_run {
ox_pt_1 > 700 => abort
fuel_pt_1 > 500 => abort
chamber_tc_1 > 2000 => abort
abort_btn => abort
1 -> ox_press_vlv_cmd
1 -> fuel_press_vlv_cmd
1 -> ox_main_vlv_cmd
1 -> fuel_main_vlv_cmd
0 -> igniter_cmd
wait{duration=10s} => next
}
// Stage 7: Shutdown
stage shutdown {
// Controlled shutdown sequence
0 -> ox_main_vlv_cmd
0 -> fuel_main_vlv_cmd
wait{duration=1s} => next
}
// Stage 8: Depressurize
stage depress {
0 -> ox_press_vlv_cmd
0 -> fuel_press_vlv_cmd
1 -> ox_vent_vlv_cmd
1 -> fuel_vent_vlv_cmd
ox_pt_1 < 20 and fuel_pt_1 < 20 => next
}
// Stage 9: Complete
stage complete {
0 -> ox_vent_vlv_cmd
0 -> fuel_vent_vlv_cmd
}
// Stage: Ignition failure
stage ignition_fail {
0 -> igniter_cmd
1 => abort
}
}
sequence abort {
stage safing {
// Close all valves immediately
0 -> ox_press_vlv_cmd
0 -> fuel_press_vlv_cmd
0 -> ox_main_vlv_cmd
0 -> fuel_main_vlv_cmd
0 -> igniter_cmd
// Open vents
1 -> ox_vent_vlv_cmd
1 -> fuel_vent_vlv_cmd
}
}
// Entry points
start_cmd => main
emergency_stop => abort Sequence Design Tips
List abort conditions first. Line order determines priority. Safety conditions should always win over normal operations.
Use multiple abort thresholds. A pressure of 600 psi might be a warning, but 700 psi triggers an immediate abort.
Add timeouts. Sequences that wait indefinitely for conditions can hang. Use wait
to set maximum durations and transition to error stages.
Keep stages focused. Each stage should have one primary purpose. Split complex operations into multiple stages for clarity and easier debugging.
Monitor continuously. While waiting for one condition, continue checking abort conditions. All flows in a stage run concurrently.
Test abort paths. Simulate abort conditions during development to verify the system reaches a safe state. The abort sequence is the most important part of your automation.