diff --git a/OrcaSlicer/filament/PolyLite PLA YOOPAI_Exhaust_Flange.info b/OrcaSlicer/filament/PolyLite PLA YOOPAI_Exhaust_Flange.info new file mode 100644 index 0000000..f838654 --- /dev/null +++ b/OrcaSlicer/filament/PolyLite PLA YOOPAI_Exhaust_Flange.info @@ -0,0 +1,5 @@ +sync_info = create +user_id = +setting_id = +base_id = OGFSL19 +updated_time = 1774475531 diff --git a/OrcaSlicer/filament/PolyLite PLA YOOPAI_Exhaust_Flange.json b/OrcaSlicer/filament/PolyLite PLA YOOPAI_Exhaust_Flange.json new file mode 100644 index 0000000..4a4e637 --- /dev/null +++ b/OrcaSlicer/filament/PolyLite PLA YOOPAI_Exhaust_Flange.json @@ -0,0 +1,34 @@ +{ + "close_fan_the_first_x_layers": [ + "3" + ], + "compatible_printers": [ + "Sovol SV06 ACE 0.4 nozzle" + ], + "fan_cooling_layer_time": [ + "20" + ], + "fan_max_speed": [ + "70" + ], + "fan_min_speed": [ + "50" + ], + "filament_settings_id": [ + "PolyLite PLA YOOPAI_Exhaust_Flange" + ], + "from": "User", + "hot_plate_temp_initial_layer": [ + "60" + ], + "inherits": "PolyLite PLA @System", + "is_custom_defined": "0", + "name": "PolyLite PLA YOOPAI_Exhaust_Flange", + "nozzle_temperature": [ + "215" + ], + "nozzle_temperature_initial_layer": [ + "215" + ], + "version": "2.3.0.3" +} diff --git a/OrcaSlicer/process/YOOPAI-Exhaust_PLA.info b/OrcaSlicer/process/YOOPAI-Exhaust_PLA.info new file mode 100644 index 0000000..2912f98 --- /dev/null +++ b/OrcaSlicer/process/YOOPAI-Exhaust_PLA.info @@ -0,0 +1,5 @@ +sync_info = update +user_id = +setting_id = +base_id = GP004 +updated_time = 1774475531 diff --git a/OrcaSlicer/process/YOOPAI-Exhaust_PLA.json b/OrcaSlicer/process/YOOPAI-Exhaust_PLA.json new file mode 100644 index 0000000..4eddea6 --- /dev/null +++ b/OrcaSlicer/process/YOOPAI-Exhaust_PLA.json @@ -0,0 +1,29 @@ +{ + "bottom_shell_layers": "8", + "brim_type": "outer_only", + "from": "User", + "infill_wall_overlap": "15%", + "inherits": "0.20mm Standard @Sovol SV06 ACE", + "initial_layer_line_width": "0.45", + "initial_layer_print_height": "0.2", + "inner_wall_line_width": "0.45", + "inner_wall_speed": "80", + "is_custom_defined": "0", + "line_width": "0.45", + "name": "YOOPAI-Exhaust_PLA", + "notes": "Per ChatGPT as 1st prototype test run with PLA:\n\nStructural Prototype Profile\n\nLayer height: 0.20\nWalls: 6\nTop/Bottom: 6\nInfill: 50% Gyroid\nNozzle temp: 210–215 PLA\nFan: 60%\nOuter wall width: 0.45", + "only_one_wall_top": "0", + "outer_wall_acceleration": "1500", + "outer_wall_line_width": "0.45", + "outer_wall_speed": "35", + "print_settings_id": "YOOPAI-Exhaust_PLA", + "seam_gap": "0", + "seam_position": "back", + "skirt_loops": "2", + "sparse_infill_density": "50%", + "sparse_infill_pattern": "gyroid", + "top_shell_layers": "6", + "top_solid_infill_flow_ratio": "1", + "version": "2.3.0.3", + "wall_loops": "6" +} diff --git a/freecad/YOOPAI_medium_vent_flange.FCStd b/freecad/YOOPAI_medium_vent_flange.FCStd new file mode 100644 index 0000000..475452f Binary files /dev/null and b/freecad/YOOPAI_medium_vent_flange.FCStd differ diff --git a/freecad/YOOPAI_medium_vent_flange.csv b/freecad/YOOPAI_medium_vent_flange.csv new file mode 100644 index 0000000..b109cd5 --- /dev/null +++ b/freecad/YOOPAI_medium_vent_flange.csv @@ -0,0 +1,14 @@ +86 base_plate length of a side, it is a square +3 base_thickness low 2s, I raised to 3mm for strength +75 duct_flange_base_top_OD_diameter outside diameter of duct flange at base plate at top of base plate +70 duct_flange_base_bottom_ID_diameter inside diameter at the bottom of base plate, the taper goes to the bottom of the plate, there is no perpendicular segment within the base plate +70 duct_flex_diameter +43 duct_flange_total_height includes base and adds 1mm since I measued 42, but I'm increasing base by 1mm to 3mm +73 duct_flange_top_outside_diameter +69 duct_flange_top_inside_diameter +40 round_transition +6 screw_hole_diameter +4 screw_hole_from_edge from both adjacent edges +40 taper_height dervied, 'from top of plate +36 hole_center_offset base_plate/2 - screw_hole_from_edge - screw_hole_diameter/2 +5 base_corner_radius diff --git a/python/assign_alias.py b/python/assign_alias.py new file mode 100644 index 0000000..cf1b2e0 --- /dev/null +++ b/python/assign_alias.py @@ -0,0 +1,21 @@ +import FreeCAD as App + +# Change 'Spreadsheet' to the actual name of your sheet if different +sheet = App.ActiveDocument.getObject('Spreadsheet') + +# Set the range of rows you want to process (e.g., row 1 to 20) +start_row = 1 +end_row = 20 + +for i in range(start_row, end_row + 1): + val_cell = f"A{i}" + name_cell = f"B{i}" + + alias_name = sheet.get(name_cell) + + if alias_name: + # FreeCAD aliases cannot have spaces or special characters + clean_alias = "".join(filter(str.isalnum, alias_name)) + sheet.setAlias(val_cell, clean_alias) + +App.ActiveDocument.recompute() diff --git a/python/show_constraints.py b/python/show_constraints.py new file mode 100644 index 0000000..00f30ba --- /dev/null +++ b/python/show_constraints.py @@ -0,0 +1,20 @@ +# +# 3/23/26 ChatGPT +# shows details of constraints +# + +sk = App.ActiveDocument.ActiveObject + +App.Console.PrintMessage("Constraint Listing:\n") +print(f'Constraint Listing: ') +for i, c in enumerate(sk.Constraints): + App.Console.PrintMessage(f"\nConstraint {i}: {c.Type}") + + if hasattr(c, "Value") and c.Value != 0: + App.Console.PrintMessage(f" = {c.Value}") + + App.Console.PrintMessage( + f"\n First : Geo {c.First}, Pos {c.FirstPos}" + f"\n Second: Geo {c.Second}, Pos {c.SecondPos}" + f"\n Third : Geo {c.Third}, Pos {c.ThirdPos}\n" + ) diff --git a/scad/YOOPAI_round_to_rectangular_duct_transition_adapter.scad b/scad/YOOPAI_round_to_rectangular_duct_transition_adapter.scad new file mode 100644 index 0000000..26cc9e8 --- /dev/null +++ b/scad/YOOPAI_round_to_rectangular_duct_transition_adapter.scad @@ -0,0 +1,197 @@ +// +// duct_round_to_window_slot.scad +// 20260321 ChatGPT +// $Id$ +// $HeadURL$ +// +// Example command lines: +// +// openscad -o duct_round_to_window_slot_20260321_1830.stl duct_round_to_window_slot.scad +// +// openscad \ +// -D 'round_stub_od=72.0' \ +// -D 'round_fit_clearance=0.6' \ +// -D 'slot_h=25.4' \ +// -D 'slot_w=162.0' \ +// -D 'wall=2.4' \ +// -D 'round_stub_len=30' \ +// -D 'transition_len=140' \ +// -D 'slot_stub_len=30' \ +// -o duct_round_to_window_slot_20260321_1831.stl \ +// duct_round_to_window_slot.scad +// + +$fn = 128; + +// ------------------------------------------------------------ +// PARAMETERS +// ------------------------------------------------------------ + +// Measured OD of the existing plastic tent outlet that your flex duct +// currently wraps around. +round_stub_od = 72.0; + +// Extra diameter added so the flex duct can slip over this printed stub. +// Start with 0.4 to 0.8 mm and adjust after a test print. +round_fit_clearance = 0.6; + +// Wall thickness +wall = 2.4; + +// Length of straight circular collar for flex duct attachment +round_stub_len = 30; + +// Length of tapered transition body +transition_len = 140; + +// Length of straight rectangular outlet section for insertion under window +slot_stub_len = 30; + +// Window slot internal size +slot_h = 25.4; // 1.0 inch +slot_w = 162.0; // approximately area-preserving for 72 mm round + +// Corner radius for rounded rectangle, internal passage +slot_r = 6.0; + +// Optional lip / stop ring on circular end so the duct has something +// to register against before clamp/strap tightening. +add_round_stop_ring = true; +round_stop_ring_len = 5.0; +round_stop_ring_extra_od = 6.0; + + +// ------------------------------------------------------------ +// DERIVED VALUES +// ------------------------------------------------------------ + +// This is the OD of the printed round collar that the flexible duct +// will fit around. +round_outer_d = round_stub_od + round_fit_clearance; + +// Inner flow diameter at the round side +round_inner_d = round_outer_d - 2*wall; + +// Outer dimensions of the rectangular outlet +slot_outer_h = slot_h + 2*wall; +slot_outer_w = slot_w + 2*wall; +slot_outer_r = slot_r + wall; + +// Z locations +z0 = 0; +z1 = round_stub_len; +z2 = round_stub_len + transition_len; +z3 = round_stub_len + transition_len + slot_stub_len; + + +// ------------------------------------------------------------ +// HELPERS +// ------------------------------------------------------------ + +module rounded_rect_2d(w, h, r) { + rr = min(r, min(w,h)/2 - 0.01); + hull() { + translate([-(w/2 - rr), -(h/2 - rr)]) circle(r=rr); + translate([ +(w/2 - rr), -(h/2 - rr)]) circle(r=rr); + translate([-(w/2 - rr), +(h/2 - rr)]) circle(r=rr); + translate([ +(w/2 - rr), +(h/2 - rr)]) circle(r=rr); + } +} + +module round_profile_3d(d, z, h=1) { + translate([0,0,z]) + linear_extrude(height=h) + circle(d=d); +} + +module rect_profile_3d(w, h_rect, r, z, h=1) { + translate([0,0,z]) + linear_extrude(height=h) + rounded_rect_2d(w, h_rect, r); +} + + +// ------------------------------------------------------------ +// OUTER SHELL +// ------------------------------------------------------------ + +module outer_shell() { + union() { + // Straight round collar + hull() { + round_profile_3d(round_outer_d, z0, 1); + round_profile_3d(round_outer_d, z1, 1); + } + + // Transition + hull() { + round_profile_3d(round_outer_d, z1, 1); + rect_profile_3d(slot_outer_w, slot_outer_h, slot_outer_r, z2, 1); + } + + // Straight rectangular collar + hull() { + rect_profile_3d(slot_outer_w, slot_outer_h, slot_outer_r, z2, 1); + rect_profile_3d(slot_outer_w, slot_outer_h, slot_outer_r, z3, 1); + } + } +} + + +// ------------------------------------------------------------ +// INNER VOID +// ------------------------------------------------------------ + +module inner_void() { + union() { + // Straight round passage + hull() { + round_profile_3d(round_inner_d, z0 - 0.2, 1.4); + round_profile_3d(round_inner_d, z1 + 0.2, 1.4); + } + + // Transition passage + hull() { + round_profile_3d(round_inner_d, z1 - 0.2, 1.4); + rect_profile_3d(slot_w, slot_h, slot_r, z2 + 0.2, 1.4); + } + + // Straight rectangular passage + hull() { + rect_profile_3d(slot_w, slot_h, slot_r, z2 - 0.2, 1.4); + rect_profile_3d(slot_w, slot_h, slot_r, z3 + 0.2, 1.4); + } + } +} + + +// ------------------------------------------------------------ +// OPTIONAL ROUND STOP RING +// ------------------------------------------------------------ + +module round_stop_ring() { + if (add_round_stop_ring) { + translate([0,0,z0]) { + difference() { + cylinder(d = round_outer_d + round_stop_ring_extra_od, + h = round_stop_ring_len); + translate([0,0,-0.2]) + cylinder(d = round_outer_d, + h = round_stop_ring_len + 0.4); + } + } + } +} + + +// ------------------------------------------------------------ +// FINAL PART +// ------------------------------------------------------------ + +union() { + difference() { + outer_shell(); + inner_void(); + } + round_stop_ring(); +}