code wiki / (root) / nx_polymer_thermal.nx

nx_polymer_thermal.nx source

↩ module page · 171 lines · 6916 B

1// nx_polymer_thermal.nx -- per-polymer thermal envelope for FDM 2// printing. Combines polymer chemistry (Tg, Tm, Td) with engineering 3// constraints (recommended print + bed temp ranges) into a single 4// substrate primitive the slicer composes for thermal-safety 5// validation BEFORE emitting G-code with operator-supplied temps. 6// 7// Per META-CARDINAL feedback-engineering-sciences-bits-up-3d-print-first: 8// this is the substrate's FIRST primitive that bridges Layer 2 9// (pure chemistry: nx_chem_periodic / nx_chem_molecule -- already 10// shipped) with Layer 3 (engineering applications: nx_material_profile 11// + nx_gcode_emit). Composes: 12// - nx_material_profile (NX_MAT_* sealed-enum keys) 13// - chemistry knowledge (Tg / Tm / Td values from polymer literature) 14// 15// Future v2 could compose nx_chem_molecule to compute mol weight 16// from PLA repeating unit (C3H4O2)n etc., but v1 ships the slicer- 17// relevant constants directly per material class. 18// 19// Thermal values verified against polymer-literature consensus: 20// PLA: Tg 60°C / Tm 160°C / Td 250°C / print 190-230 / bed 50-65 21// PETG: Tg 80°C / Tm 240°C / Td 290°C / print 220-250 / bed 70-85 22// ABS: Tg 105°C / amorphous / Td 270°C / print 220-260 / bed 90-110 23// ASA: Tg 105°C / amorphous / Td 270°C / print 240-260 / bed 100-110 24// PC: Tg 145°C / amorphous / Td 320°C / print 270-310 / bed 110-130 25// TPU: Tg variable / Tm 180°C / Td 240°C / print 200-230 / bed 50-60 26// NYLON: Tg 50°C / Tm 220°C / Td 320°C / print 240-280 / bed 80-100 27// PA-CF: same as NYLON with reinforcement (no thermal delta) 28// PEEK: Tg 143°C / Tm 343°C / Td 575°C / print 360-400 / bed 120-145 29// 30// Amorphous polymers (ABS, ASA, PC) use Tm = 0 as sentinel meaning 31// "no crystalline melt; soften gradually above Tg". Validator 32// treats this case correctly. 33// 34// license_tier: ORIGINAL 35 36import "nx_syscalls.nx" 37import "nx_material_profile.nx" 38 39// ===== verdicts ==================================================== 40 41const NX_POLYTHERM_SAFE: i64 = 0 42const NX_POLYTHERM_PRINT_TOO_LOW: i64 = 1 43const NX_POLYTHERM_PRINT_TOO_HIGH: i64 = 2 44const NX_POLYTHERM_DECOMP_RISK: i64 = 3 45const NX_POLYTHERM_BED_TOO_LOW: i64 = 4 46const NX_POLYTHERM_BED_TOO_HIGH: i64 = 5 47const NX_POLYTHERM_UNKNOWN_CLASS: i64 = 6 48const NX_POLYTHERM_N: i64 = 7 49 50func nx_polytherm_verdict_name(v: i64) -> *u8 { 51 if v == NX_POLYTHERM_SAFE { return "SAFE" } 52 if v == NX_POLYTHERM_PRINT_TOO_LOW { return "PRINT_TOO_LOW" } 53 if v == NX_POLYTHERM_PRINT_TOO_HIGH { return "PRINT_TOO_HIGH" } 54 if v == NX_POLYTHERM_DECOMP_RISK { return "DECOMP_RISK" } 55 if v == NX_POLYTHERM_BED_TOO_LOW { return "BED_TOO_LOW" } 56 if v == NX_POLYTHERM_BED_TOO_HIGH { return "BED_TOO_HIGH" } 57 if v == NX_POLYTHERM_UNKNOWN_CLASS { return "UNKNOWN_CLASS" } 58 return "UNKNOWN" 59} 60 61// ===== struct ====================================================== 62 63struct NxPolymerThermal { 64 material_class: i64, 65 tg_c: i64, // glass transition 66 tm_c: i64, // crystalline melt (0 = amorphous) 67 td_c: i64, // decomposition onset 68 print_min_c: i64, 69 print_max_c: i64, 70 bed_min_c: i64, 71 bed_max_c: i64, 72} 73 74const NX_POLYTHERM_BYTES: i64 = 64 // 8 i64 75 76// ===== population helper =========================================== 77 78func nx_polytherm_set(p: *NxPolymerThermal, cls: i64, 79 tg: i64, tm: i64, td: i64, 80 pmin: i64, pmax: i64, 81 bmin: i64, bmax: i64) -> i64 { 82 p.material_class = cls 83 p.tg_c = tg 84 p.tm_c = tm 85 p.td_c = td 86 p.print_min_c = pmin 87 p.print_max_c = pmax 88 p.bed_min_c = bmin 89 p.bed_max_c = bmax 90 return 0 91} 92 93// ===== factory ===================================================== 94// 95// Returns a fresh NxPolymerThermal populated with literature-verified 96// values for the given material class. Returns NULL for unknown class. 97// Pure data lookup -- no I/O. 98 99func nx_polymer_thermal_for(material_class: i64) -> *NxPolymerThermal { 100 if material_class < 0 { return 0 as *NxPolymerThermal } 101 if material_class >= NX_MAT_N { return 0 as *NxPolymerThermal } 102 let p: *NxPolymerThermal = (sys_mmap(NX_POLYTHERM_BYTES)) as *NxPolymerThermal 103 104 if material_class == NX_MAT_PLA { 105 nx_polytherm_set(p, NX_MAT_PLA, 60, 160, 250, 190, 230, 50, 65) 106 return p 107 } 108 if material_class == NX_MAT_PETG { 109 nx_polytherm_set(p, NX_MAT_PETG, 80, 240, 290, 220, 250, 70, 85) 110 return p 111 } 112 if material_class == NX_MAT_ABS { 113 nx_polytherm_set(p, NX_MAT_ABS, 105, 0, 270, 220, 260, 90, 110) 114 return p 115 } 116 if material_class == NX_MAT_ASA { 117 nx_polytherm_set(p, NX_MAT_ASA, 105, 0, 270, 240, 260, 100, 110) 118 return p 119 } 120 if material_class == NX_MAT_PC { 121 nx_polytherm_set(p, NX_MAT_PC, 145, 0, 320, 270, 310, 110, 130) 122 return p 123 } 124 if material_class == NX_MAT_TPU { 125 nx_polytherm_set(p, NX_MAT_TPU, 0, 180, 240, 200, 230, 50, 60) 126 return p 127 } 128 if material_class == NX_MAT_NYLON { 129 nx_polytherm_set(p, NX_MAT_NYLON, 50, 220, 320, 240, 280, 80, 100) 130 return p 131 } 132 if material_class == NX_MAT_PA_CF { 133 nx_polytherm_set(p, NX_MAT_PA_CF, 50, 220, 320, 240, 280, 80, 100) 134 return p 135 } 136 if material_class == NX_MAT_PEEK { 137 nx_polytherm_set(p, NX_MAT_PEEK, 143, 343, 575, 360, 400, 120, 145) 138 return p 139 } 140 return 0 as *NxPolymerThermal 141} 142 143// ===== validators ================================================== 144// 145// Check operator-supplied hotend + bed temps against the polymer's 146// thermal envelope. Returns first error encountered. Decomposition 147// risk is the most serious -- printing above Td releases toxic 148// breakdown products (ABS styrene, PLA lactide-like compounds) plus 149// permanently damages mechanical properties. 150 151func nx_polymer_thermal_validate(p: *NxPolymerThermal, 152 hotend_c: i64, bed_c: i64) -> i64 { 153 if (p as i64) == 0 { return NX_POLYTHERM_UNKNOWN_CLASS } 154 155 // Decomposition is the safety-critical check -- runs first. 156 if hotend_c >= p.td_c { return NX_POLYTHERM_DECOMP_RISK } 157 158 if hotend_c < p.print_min_c { return NX_POLYTHERM_PRINT_TOO_LOW } 159 if hotend_c > p.print_max_c { return NX_POLYTHERM_PRINT_TOO_HIGH } 160 161 if bed_c < p.bed_min_c { return NX_POLYTHERM_BED_TOO_LOW } 162 if bed_c > p.bed_max_c { return NX_POLYTHERM_BED_TOO_HIGH } 163 164 return NX_POLYTHERM_SAFE 165} 166 167// Convenience: validate using NxMaterialProfile directly. 168func nx_polymer_validate_profile(mat: *NxMaterialProfile) -> i64 { 169 let p: *NxPolymerThermal = nx_polymer_thermal_for(mat.material_class) 170 return nx_polymer_thermal_validate(p, mat.hotend_print_c, mat.bed_print_c) 171}