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 one-shot transitions (=>) are true simultaneously, 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.
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.