code wiki / (root) / nx_print_runtime_zback_test.nx

nx_print_runtime_zback_test.nx source

↩ module page · 97 lines · 4734 B

1// nx_print_runtime_zback_test.nx -- Z-backward jump detection. 2// 3// Spaghetti progenitor: head crashes a tower mid-print, Klipper 4// recovers by rehoming, Z snaps from current layer back to ~0. 5// When the print resumes it does so off-position = spaghetti. 6// 7// Closed-form invariants: 8// (a) Normal layer progression: no fire 9// (b) Tiny Z-hop during travel (< tolerance): no fire 10// (c) Z reverse > tolerance: NX_RT_ISSUE_Z_BACKWARD fires 11// (d) Z_BACKWARD takes precedence over STUCK_LAYER 12// (e) After backward event, monitor recovers (next normal event no fire) 13// (f) Setter rejects negative tolerance 14// (g) Tighter tolerance catches smaller backward jumps 15// 16// expect_exit: 0 17// license_tier: ORIGINAL 18 19import "nx_syscalls.nx" 20import "nx_print_runtime_monitor.nx" 21 22const Q14: i64 = 16384 23 24func main() -> i64 { 25 // ===== (a) Normal layer progression: no fire ===== 26 let m: *NxRuntimeMonitor = nx_runtime_monitor_new(5000, 3, 5 * Q14, 2 * Q14) 27 if (m as i64) == 0 { return 5 } 28 nx_runtime_monitor_step(m, 200 * Q14 / 1000, 0, 0, 0) 29 let v1: i64 = nx_runtime_monitor_step(m, 30 400 * Q14 / 1000, 10 * Q14, 50 * Q14, 5000) 31 if v1 != NX_RT_ISSUE_NONE { return 10 } 32 33 // ===== (b) Tiny Z-hop during travel (0.4mm reverse, default 5mm tol): no fire 34 // Default tolerance is 5mm; 0.4mm back-hop should be silent. 35 let v2: i64 = nx_runtime_monitor_step(m, 36 (400 - 400) * Q14 / 1000, // z = 0.0mm (down 0.4mm from 0.4mm) 37 20 * Q14, 50 * Q14, 6000) 38 if v2 != NX_RT_ISSUE_NONE { return 20 } 39 40 // ===== (c) Z reverse > tolerance fires Z_BACKWARD ===== 41 // Build up to z = 12mm via normal layers, then crash-rehome to z=0. 42 let m2: *NxRuntimeMonitor = nx_runtime_monitor_new(5000, 3, 5 * Q14, 2 * Q14) 43 nx_runtime_monitor_step(m2, 0, 0, 0, 0) 44 nx_runtime_monitor_step(m2, 4 * Q14, 10 * Q14, 50 * Q14, 5000) 45 nx_runtime_monitor_step(m2, 8 * Q14, 20 * Q14, 50 * Q14, 10000) 46 nx_runtime_monitor_step(m2, 12 * Q14, 30 * Q14, 50 * Q14, 15000) 47 if m2.n_issues_total != 0 { return 30 } 48 // Now crash-rehome: z snaps from 12mm to 0mm (12mm back > 5mm tol) 49 let v_back: i64 = nx_runtime_monitor_step(m2, 50 0, // z = 0 51 30 * Q14, 0, 16000) // no extrusion, no XY (homing) 52 if v_back != NX_RT_ISSUE_Z_BACKWARD { return 31 } 53 if m2.n_issues_total != 1 { return 32 } 54 55 // ===== (d) Z_BACKWARD takes precedence over STUCK_LAYER ===== 56 // Build a state where both would fire; precedence rule says Z_BACKWARD wins. 57 let m3: *NxRuntimeMonitor = nx_runtime_monitor_new(5000, 3, 5 * Q14, 2 * Q14) 58 nx_runtime_monitor_step(m3, 0, 0, 0, 0) 59 nx_runtime_monitor_step(m3, 5 * Q14, 10 * Q14, 50 * Q14, 1000) 60 // Long time gap (30s past last layer change) + Z reverse: 61 // STUCK_LAYER threshold = 5000 × 3 = 15000ms; we're at 31000ms. 62 // Z reverse from 5mm to 0 = 5mm exactly (NOT > 5mm tol). Use 10mm reverse. 63 nx_runtime_monitor_step(m3, 10 * Q14, 20 * Q14, 50 * Q14, 5000) 64 // Now at z=10mm. Long gap + reverse to 0: 65 let v_pre: i64 = nx_runtime_monitor_step(m3, 66 0, // z = 0 (10mm reverse, > 5mm tol) 67 20 * Q14, 0, 40000) // 35s past last layer change (STUCK threshold) 68 if v_pre != NX_RT_ISSUE_Z_BACKWARD { return 40 } 69 70 // ===== (e) After backward event, monitor continues ===== 71 // Resumed print: Z advances normally from 0. No fire on next event. 72 let v_resume: i64 = nx_runtime_monitor_step(m2, 73 200 * Q14 / 1000, 31 * Q14, 5 * Q14, 17000) 74 if v_resume != NX_RT_ISSUE_NONE { return 50 } 75 76 // ===== (f) Setter rejects negative tolerance ===== 77 let bad: i64 = nx_runtime_monitor_set_z_backward_tolerance(m, -1) 78 if bad != NX_RT_BAD_INPUT { return 60 } 79 let null_bad: i64 = nx_runtime_monitor_set_z_backward_tolerance( 80 0 as *NxRuntimeMonitor, 1000) 81 if null_bad != NX_RT_BAD_INPUT { return 61 } 82 83 // ===== (g) Tighter tolerance catches smaller backward jumps ===== 84 let m4: *NxRuntimeMonitor = nx_runtime_monitor_new(5000, 3, 5 * Q14, 2 * Q14) 85 // Tighten tolerance to 0.5mm 86 let setok: i64 = nx_runtime_monitor_set_z_backward_tolerance(m4, Q14 / 2) 87 if setok != NX_RT_OK { return 70 } 88 nx_runtime_monitor_step(m4, 0, 0, 0, 0) 89 nx_runtime_monitor_step(m4, 2 * Q14, 10 * Q14, 50 * Q14, 5000) 90 // Reverse 1mm > 0.5mm tol -> fires 91 let v_tight: i64 = nx_runtime_monitor_step(m4, 92 Q14, // z = 1mm (1mm back from 2mm) 93 15 * Q14, 5 * Q14, 6000) 94 if v_tight != NX_RT_ISSUE_Z_BACKWARD { return 71 } 95 96 return 0 97}