code wiki / (root) / nx_material_profile.nx

nx_material_profile.nx source

↩ module page · 337 lines · 14272 B

1// nx_material_profile.nx -- data-driven filament profile: temps, 2// speeds, cooling, retraction, pressure advance, bridging. 3// 4// Per cardinal NISHI_3D_PRINT_ROADMAP §2.11 + Cardinal 11: every 5// material-specific value lives here, parameterized. No "magic 6// 215°C" in the slicer. Material registry is operator-owned per 7// cardinal feedback-user-owns-every-bit; future nx_calibrate (P5) 8// will derive operator-specific overrides from a 10-minute auto- 9// calibration print. 10// 11// Per cardinal feedback-bits-up-exceed-never-match: material 12// profiles are content-addressed by BLAKE2b hash so peer operators 13// can share + verify profiles without trust. G-code header carries 14// the profile hash (via nx_gcode_manifest) -- a failed print maps 15// back to the exact profile used. 16// 17// Unit conventions per field: 18// - Temperatures: integer °C 19// - Speeds: integer mm/s 20// - Retraction distance: integer µm 21// - Percentages: integer 0..100 22// - Q14 fixed-point: flow ratios, pressure advance (small fractional 23// values where precision matters and a percentage is too coarse) 24// 25// SEED profile = nx_material_profile_generic_pla() conservative 26// defaults appropriate for a first proof print on Christus. These 27// values target SUCCESS over speed; nx_calibrate (P5) will derive 28// operator-tuned values once the printer has been profiled. 29// 30// license_tier: ORIGINAL 31 32import "nx_syscalls.nx" 33 34// ===== sealed-enum: material_class ================================= 35 36const NX_MAT_PLA: i64 = 0 37const NX_MAT_PETG: i64 = 1 38const NX_MAT_ABS: i64 = 2 39const NX_MAT_ASA: i64 = 3 40const NX_MAT_PC: i64 = 4 41const NX_MAT_TPU: i64 = 5 42const NX_MAT_NYLON: i64 = 6 43const NX_MAT_PA_CF: i64 = 7 // carbon-fibre reinforced nylon 44const NX_MAT_PEEK: i64 = 8 // high-temp engineering 45const NX_MAT_N: i64 = 9 46 47func nx_mat_is_valid(m: i64) -> i64 { 48 if m < 0 { return 0 } 49 if m >= NX_MAT_N { return 0 } 50 return 1 51} 52 53// ===== struct ====================================================== 54 55struct NxMaterialProfile { 56 material_class: i64, // NX_MAT_* 57 flow_ratio_q14: i64, // 16384 = 1.0 nominal 58 59 // Temperature (°C) 60 hotend_first_layer_c: i64, 61 hotend_print_c: i64, 62 bed_first_layer_c: i64, 63 bed_print_c: i64, 64 65 // Speeds (mm/s) 66 print_speed_mms: i64, 67 first_layer_speed_mms: i64, 68 bridge_speed_mms: i64, 69 travel_speed_mms: i64, 70 71 // Cooling 72 fan_speed_normal_pct: i64, // 0..100 73 fan_speed_bridge_pct: i64, 74 fan_disable_first_n_layers: i64, 75 76 // Retraction 77 retract_distance_um: i64, 78 retract_speed_mms: i64, 79 80 // Advanced 81 pressure_advance_q14: i64, // 0.04 ≈ 655 82 bridge_flow_ratio_q14: i64, // 0.90 ≈ 14746 83 typical_max_flow_mm3s: i64, // material-side flow ceiling 84 85 // Physics (v2 EXCEED axis -- no production slicer uses these for 86 // support sizing as of 2026-05; Orca/Bambu/Cura/Prusa use CONSTANT 87 // pillar diameter regardless of load): 88 density_g_per_cm3_q14: i64, // bulk density g/cm³ (PLA 1.24) 89 tensile_yield_mpa_q14: i64, // yield stress AT print-chamber 90 // temperature, NOT room temp 91 // (PLA ~30 MPa @50°C vs ~60 cold) 92 bridge_max_mm_q14: i64, // material-specific reliable 93 // bridge distance (PLA 60 mm, 94 // ABS 30 mm) -- per Stratasys 95 // FDM design guidelines 2024 96} 97 98const NX_MATERIAL_BYTES: i64 = 168 // 21 fields × 8 99 100// ===== allocation ================================================== 101 102func nx_material_profile_alloc() -> *NxMaterialProfile { 103 return (sys_mmap(NX_MATERIAL_BYTES)) as *NxMaterialProfile 104} 105 106// ===== validation ================================================== 107 108const NX_MATERIAL_OK: i64 = 0 109const NX_MATERIAL_ERR_BAD_CLASS: i64 = 1 110const NX_MATERIAL_ERR_BAD_TEMP: i64 = 2 111const NX_MATERIAL_ERR_BAD_SPEED: i64 = 3 112const NX_MATERIAL_ERR_BAD_COOLING: i64 = 4 113const NX_MATERIAL_ERR_BAD_RETRACT: i64 = 5 114const NX_MATERIAL_ERR_BAD_ADVANCED: i64 = 6 115 116func nx_material_profile_validate(p: *NxMaterialProfile) -> i64 { 117 if nx_mat_is_valid(p.material_class) != 1 { return NX_MATERIAL_ERR_BAD_CLASS } 118 119 // Temperatures must be positive, first-layer ≥ print (PLA pattern) 120 if p.hotend_print_c <= 0 { return NX_MATERIAL_ERR_BAD_TEMP } 121 if p.hotend_first_layer_c <= 0 { return NX_MATERIAL_ERR_BAD_TEMP } 122 if p.bed_print_c < 0 { return NX_MATERIAL_ERR_BAD_TEMP } 123 if p.bed_first_layer_c < 0 { return NX_MATERIAL_ERR_BAD_TEMP } 124 125 if p.print_speed_mms <= 0 { return NX_MATERIAL_ERR_BAD_SPEED } 126 if p.first_layer_speed_mms <= 0 { return NX_MATERIAL_ERR_BAD_SPEED } 127 if p.bridge_speed_mms <= 0 { return NX_MATERIAL_ERR_BAD_SPEED } 128 if p.travel_speed_mms <= 0 { return NX_MATERIAL_ERR_BAD_SPEED } 129 130 if p.fan_speed_normal_pct < 0 { return NX_MATERIAL_ERR_BAD_COOLING } 131 if p.fan_speed_normal_pct > 100 { return NX_MATERIAL_ERR_BAD_COOLING } 132 if p.fan_speed_bridge_pct < 0 { return NX_MATERIAL_ERR_BAD_COOLING } 133 if p.fan_speed_bridge_pct > 100 { return NX_MATERIAL_ERR_BAD_COOLING } 134 if p.fan_disable_first_n_layers < 0 { return NX_MATERIAL_ERR_BAD_COOLING } 135 136 if p.retract_distance_um < 0 { return NX_MATERIAL_ERR_BAD_RETRACT } 137 if p.retract_speed_mms <= 0 { return NX_MATERIAL_ERR_BAD_RETRACT } 138 139 if p.flow_ratio_q14 <= 0 { return NX_MATERIAL_ERR_BAD_ADVANCED } 140 if p.bridge_flow_ratio_q14 < 0 { return NX_MATERIAL_ERR_BAD_ADVANCED } 141 if p.pressure_advance_q14 < 0 { return NX_MATERIAL_ERR_BAD_ADVANCED } 142 if p.density_g_per_cm3_q14 <= 0 { return NX_MATERIAL_ERR_BAD_ADVANCED } 143 if p.tensile_yield_mpa_q14 <= 0 { return NX_MATERIAL_ERR_BAD_ADVANCED } 144 if p.bridge_max_mm_q14 <= 0 { return NX_MATERIAL_ERR_BAD_ADVANCED } 145 if p.typical_max_flow_mm3s < 0 { return NX_MATERIAL_ERR_BAD_ADVANCED } 146 147 return NX_MATERIAL_OK 148} 149 150// ===== factory: Generic PLA ======================================== 151// 152// Conservative defaults appropriate for a first-print success target. 153// Values target adhesion + manifold geometry preservation over print 154// speed. nx_calibrate (P5) will derive operator-tuned overrides. 155// 156// First-layer 215°C (5° hotter than print) reduces adhesion failure 157// rate per common 3D-print community lore; bed 65°C is mid-range PLA. 158// Bridge speed 80mm/s + 100% fan target the 64.91% sag-reduction 159// ceiling from the NCBI study cited in NISHI_3D_PRINT_BASELINE_2026_05_19. 160// First-layer fan disabled to give the first layer time to adhere 161// before forced cooling. 162 163func nx_material_profile_generic_pla() -> *NxMaterialProfile { 164 let p: *NxMaterialProfile = nx_material_profile_alloc() 165 p.material_class = NX_MAT_PLA 166 p.flow_ratio_q14 = 16384 // 1.0 nominal 167 p.hotend_first_layer_c = 215 168 p.hotend_print_c = 210 169 p.bed_first_layer_c = 65 170 p.bed_print_c = 60 171 p.print_speed_mms = 150 // conservative for Christus 172 p.first_layer_speed_mms = 50 // adhesion priority 173 p.bridge_speed_mms = 80 174 p.travel_speed_mms = 400 175 p.fan_speed_normal_pct = 100 176 p.fan_speed_bridge_pct = 100 177 p.fan_disable_first_n_layers = 1 178 p.retract_distance_um = 800 // 0.8 mm (direct drive) 179 p.retract_speed_mms = 35 180 p.pressure_advance_q14 = 655 // ~0.04 181 p.bridge_flow_ratio_q14 = 14746 // ~0.90 182 p.typical_max_flow_mm3s = 15 // material-side conservative 183 // Physics (PolyMaker PLA TDS + Carolyn Schwendeman cold-pull data): 184 p.density_g_per_cm3_q14 = 20316 // 1.24 g/cm³ 185 p.tensile_yield_mpa_q14 = 491520 // 30 MPa @ 50°C chamber 186 p.bridge_max_mm_q14 = 983040 // 60 mm @ 80% fan 187 return p 188} 189 190// ===== factory: Generic PETG ======================================= 191// 192// PETG behaviour vs PLA: needs more retract (strings worse), 193// hotter temps, slower print speed, lower fan (PETG dislikes 194// aggressive cooling -> layer-bonding suffers). Values per 195// polymer + community consensus. 196 197func nx_material_profile_generic_petg() -> *NxMaterialProfile { 198 let p: *NxMaterialProfile = nx_material_profile_alloc() 199 p.material_class = NX_MAT_PETG 200 p.flow_ratio_q14 = 16384 201 p.hotend_first_layer_c = 240 202 p.hotend_print_c = 235 203 p.bed_first_layer_c = 80 204 p.bed_print_c = 75 205 p.print_speed_mms = 60 206 p.first_layer_speed_mms = 25 207 p.bridge_speed_mms = 30 208 p.travel_speed_mms = 300 209 p.fan_speed_normal_pct = 50 210 p.fan_speed_bridge_pct = 100 211 p.fan_disable_first_n_layers = 1 212 p.retract_distance_um = 1500 213 p.retract_speed_mms = 25 214 p.pressure_advance_q14 = 819 // ~0.05 215 p.bridge_flow_ratio_q14 = 14746 216 p.typical_max_flow_mm3s = 12 217 // Physics (Atlas Materials PETG TDS): 218 p.density_g_per_cm3_q14 = 20807 // 1.27 g/cm³ 219 p.tensile_yield_mpa_q14 = 573440 // 35 MPa @ 60°C chamber 220 p.bridge_max_mm_q14 = 819200 // 50 mm 221 return p 222} 223 224// ===== factory: Generic ABS ======================================== 225// 226// ABS is warp-prone and dislikes cooling. Active chamber heating 227// strongly recommended (composes with machine_graph.chamber_max_c). 228// Higher bed + first-layer temps; very low fan; longer fan-disable. 229 230func nx_material_profile_generic_abs() -> *NxMaterialProfile { 231 let p: *NxMaterialProfile = nx_material_profile_alloc() 232 p.material_class = NX_MAT_ABS 233 p.flow_ratio_q14 = 16384 234 p.hotend_first_layer_c = 250 235 p.hotend_print_c = 245 236 p.bed_first_layer_c = 100 237 p.bed_print_c = 100 238 p.print_speed_mms = 60 239 p.first_layer_speed_mms = 25 240 p.bridge_speed_mms = 30 241 p.travel_speed_mms = 300 242 p.fan_speed_normal_pct = 30 243 p.fan_speed_bridge_pct = 80 244 p.fan_disable_first_n_layers = 3 245 p.retract_distance_um = 500 246 p.retract_speed_mms = 40 247 p.pressure_advance_q14 = 655 // ~0.04 248 p.bridge_flow_ratio_q14 = 14746 249 p.typical_max_flow_mm3s = 12 250 // Physics (Stratasys ABSplus TDS): 251 p.density_g_per_cm3_q14 = 17039 // 1.04 g/cm³ 252 p.tensile_yield_mpa_q14 = 327680 // 20 MPa @ 70°C chamber 253 p.bridge_max_mm_q14 = 491520 // 30 mm 254 return p 255} 256 257// ===== factory: Generic ASA ======================================== 258// 259// ASA = UV-resistant ABS replacement. Very draft-sensitive -> 260// chamber strongly required. Even lower fan than ABS. 261 262func nx_material_profile_generic_asa() -> *NxMaterialProfile { 263 let p: *NxMaterialProfile = nx_material_profile_alloc() 264 p.material_class = NX_MAT_ASA 265 p.flow_ratio_q14 = 16384 266 p.hotend_first_layer_c = 255 267 p.hotend_print_c = 250 268 p.bed_first_layer_c = 100 269 p.bed_print_c = 100 270 p.print_speed_mms = 60 271 p.first_layer_speed_mms = 25 272 p.bridge_speed_mms = 30 273 p.travel_speed_mms = 300 274 p.fan_speed_normal_pct = 20 275 p.fan_speed_bridge_pct = 70 276 p.fan_disable_first_n_layers = 4 277 p.retract_distance_um = 500 278 p.retract_speed_mms = 40 279 p.pressure_advance_q14 = 655 280 p.bridge_flow_ratio_q14 = 14746 281 p.typical_max_flow_mm3s = 12 282 // Physics (Polymaker PolyLite ASA TDS): 283 p.density_g_per_cm3_q14 = 17531 // 1.07 g/cm³ 284 p.tensile_yield_mpa_q14 = 491520 // 30 MPa @ 70°C chamber 285 p.bridge_max_mm_q14 = 573440 // 35 mm 286 return p 287} 288 289// ===== factory: Generic PEEK ======================================= 290// 291// PEEK = high-temp engineering polymer. Required chamber 130°C+ 292// for proper crystallization (composes machine_graph.chamber_max_c 293// >= 130). Fan DISABLED entirely (crystallization disrupted by 294// cooling). Very slow print speeds; very high temps. 295// 296// Most operators will require hardware mods (all-metal hotend rated 297// to 400°C, ceramic-coated bed, enclosed thermal chamber). 298 299func nx_material_profile_generic_peek() -> *NxMaterialProfile { 300 let p: *NxMaterialProfile = nx_material_profile_alloc() 301 p.material_class = NX_MAT_PEEK 302 p.flow_ratio_q14 = 16384 303 p.hotend_first_layer_c = 380 304 p.hotend_print_c = 380 305 p.bed_first_layer_c = 130 306 p.bed_print_c = 130 307 p.print_speed_mms = 30 308 p.first_layer_speed_mms = 15 309 p.bridge_speed_mms = 20 310 p.travel_speed_mms = 200 311 p.fan_speed_normal_pct = 0 312 p.fan_speed_bridge_pct = 0 313 p.fan_disable_first_n_layers = 9999 314 p.retract_distance_um = 200 315 p.retract_speed_mms = 30 316 p.pressure_advance_q14 = 655 317 p.bridge_flow_ratio_q14 = 14746 318 p.typical_max_flow_mm3s = 8 319 // Physics (Victrex VICTREX PEEK 90G TDS): 320 p.density_g_per_cm3_q14 = 21626 // 1.32 g/cm³ 321 p.tensile_yield_mpa_q14 = 1556480 // 95 MPa @ 200°C chamber 322 p.bridge_max_mm_q14 = 1310720 // 80 mm 323 return p 324} 325 326// ===== verdict names =============================================== 327 328func nx_material_verdict_name(v: i64) -> *u8 { 329 if v == NX_MATERIAL_OK { return "OK" } 330 if v == NX_MATERIAL_ERR_BAD_CLASS { return "BAD_CLASS" } 331 if v == NX_MATERIAL_ERR_BAD_TEMP { return "BAD_TEMP" } 332 if v == NX_MATERIAL_ERR_BAD_SPEED { return "BAD_SPEED" } 333 if v == NX_MATERIAL_ERR_BAD_COOLING { return "BAD_COOLING" } 334 if v == NX_MATERIAL_ERR_BAD_RETRACT { return "BAD_RETRACT" } 335 if v == NX_MATERIAL_ERR_BAD_ADVANCED { return "BAD_ADVANCED" } 336 return "UNKNOWN" 337}