// ====================================================================== // Crowned Pulley for 2" Flat Belt (FRC) // UNITS & EXPORT BEHAVIOR: // - All *input parameters* marked *_IN are in INCHES. *_MM variables are in millimeters. // - Internally, the model is built in MILLIMETERS (OpenSCAD geometry is unitless). // - Most slicers/CAD import STL as MM. If yours assumes INCHES, enable export_in_inches. // - The "crown" is a DEGREE-based cosine profile: edges fixed at input OD, center raised. // // Defaults: // - Edge OD: 4.000" (at belt edges) // - Belt width: 2.000" // - Crown: 0.035" (thousandths override = 35) // - Flanges: ON // - Hex: 1/2" with 0.006" radial clearance // ====================================================================== inch = 25.4; // 1 inch = 25.4 mm // ------------------------------ // GENERAL SIZE (INCHES) // ------------------------------ pulley_edge_d_od_IN = 4.000; // Edge OD (inches) — running diameter at belt edges [0.75:0.0625:6.00] belt_width_IN = 2.000; // Belt nominal width (inches) [0.50:0.010:3.00] face_overhang_IN = 0.400; // Extra crowned span beyond belt width (inches) [0.10:0.010:0.75] // ------------------------------ // FLANGE OPTIONS // ------------------------------ make_flanges = true; // Include flanges? (checkbox) [true:false] flange_height_IN = 0.080; // Flange radial height (inches) [0.04:0.005:0.15] flange_thickness_IN = 0.080; // Flange axial thickness (inches) [0.05:0.005:0.15] flange_z_overlap_IN = 0.020; // Flange axial overlap into crowned span (inches) [0.000:0.001:0.050] flange_r_overlap_IN = 0.015; // Flange inner radius undercuts edge (inches) [0.000:0.001:0.040] // ------------------------------ // BORE (INCHES) // ------------------------------ hex_across_flats_IN = 0.500; // 1/2" hex across flats (inches) [0.375:0.001:0.500] hex_clearance_IN = 0.006; // Radial clearance for print fit (inches) [0.000:0.001:0.012] // ------------------------------ // CROWN CONTROLS (INCHES) // ------------------------------ // Option A: Floating override (if your Customizer supports 0.001" steps) crown_override_IN = 0.000; // Manual crown height at center (inches) [0.000:0.001:0.100] // Option B: Thousandths override (robust). 35 => 0.035" crown_override_thou = 35; // Crown thousandths of an inch at center (integer) [0:1:100] crown_scale_debug = 1.0; // Visual multiplier (2.0 doubles crown) (unitless) [0.1:0.1:5.0] // ------------------------------ // DEBUG & EXPORT // ------------------------------ debug_slice = false; // Show a thin cross-section slice? [false:true] slice_thickness_IN = 0.080; // Slice thickness (inches) [0.010:0.010:0.200] circum_res_min = 240; // circumferential smoothness ($fn) crown_steps = 240; // axial samples for crown profile // Export control: set true to export STL "in inches" (scaled down by 25.4 so mm tools show inch sizes) export_in_inches = false; // Export STL scaled for inch-sized numbers? [false:true] // ------------------------------ // DERIVED (MM) // ------------------------------ pulley_edge_d_od_MM = pulley_edge_d_od_IN * inch; belt_width_MM = belt_width_IN * inch; face_overhang_MM = face_overhang_IN * inch; flange_height_MM = flange_height_IN * inch; flange_thickness_MM = flange_thickness_IN * inch; flange_z_overlap_MM = flange_z_overlap_IN * inch; flange_r_overlap_MM = flange_r_overlap_IN * inch; hex_af_MM = hex_across_flats_IN * inch; hex_clearance_MM = hex_clearance_IN * inch; face_width_MM = belt_width_MM + face_overhang_MM; // crowned span (between inner flange faces) r_edge_MM = pulley_edge_d_od_MM / 2; // running radius at the edges // Auto crown (inches) -> clamp 0.015"–0.035", then override/scale. // For 4.000" OD, auto = min(0.035", 0.016 + 0.006*4 = 0.040") = 0.035" crown_auto_IN = max(0.015, min(0.035, 0.016 + 0.006 * pulley_edge_d_od_IN)); crown_from_float_IN = (crown_override_IN > 0) ? crown_override_IN : crown_auto_IN; crown_from_thou_IN = (crown_override_thou > 0) ? (crown_override_thou / 1000.0) : 0.0; crown_height_IN = (crown_override_thou > 0) ? crown_from_thou_IN : crown_from_float_IN; crown_height_MM = crown_height_IN * inch * crown_scale_debug; // Flange radii (inner slightly SMALLER than edge radius to overlap) flange_inner_r_MM = max(0.1, r_edge_MM - flange_r_overlap_MM); flange_outer_r_MM = flange_inner_r_MM + flange_height_MM; // Axial Z range for crowned face z0_MM = -face_width_MM/2; z1_MM = face_width_MM/2; // Flange center positions (pulled inward for axial overlap) z_flange_pos_MM = face_width_MM/2 + flange_thickness_MM/2 - flange_z_overlap_MM; // Circumferential facets (target ~0.5 mm chord length) circum_fn = max(circum_res_min, ceil(PI * pulley_edge_d_od_MM / 0.5)); // Debug slice thickness (mm) slice_thickness_MM = slice_thickness_IN * inch; // ------------------------------ // HELPERS (DEGREE-BASED TRIG) // ------------------------------ // Cosine crown: edges fixed at r_edge; center at r_edge + crown_height. // OpenSCAD uses DEGREE trig: cos(180 * (2*z/W)) function crown_r_MM(zMM) = r_edge_MM + crown_height_MM * 0.5 * (1 + cos(180 * (2*zMM/face_width_MM))); // Across-flats → circumradius for $fn=6 hex: AF = 2*R*cos(30°) => R = AF / sqrt(3) function hex_circum_r_MM(afMM, clrMM) = (afMM / sqrt(3)) + clrMM; // Revolve profile [ [x=r, y=z], ... ] closed to axis (x=0) function crown_profile_pts(n) = concat( [ for (i = [0:n]) let(z = z0_MM + (face_width_MM * i / n)) [ crown_r_MM(z), z ] ], [ [0, z1_MM], [0, z0_MM] ] // close along axis ); // ------------------------------ // GEOMETRY // ------------------------------ module crowned_body() { rotate_extrude(angle=360, $fn=circum_fn) polygon(points = crown_profile_pts(crown_steps)); } module flange_at(z_center_MM) { translate([0,0,z_center_MM]) difference() { cylinder(h=flange_thickness_MM, r=flange_outer_r_MM, center=true, $fn=circum_fn); cylinder(h=flange_thickness_MM+0.4, r=flange_inner_r_MM, center=true, $fn=circum_fn); } } module hex_bore() { cylinder(h = face_width_MM + (make_flanges ? 2*flange_thickness_MM : 0) + 10, r = hex_circum_r_MM(hex_af_MM, hex_clearance_MM), center = true, $fn = 6); } module crowned_pulley_solid() { if (make_flanges) { union() { crowned_body(); flange_at(+z_flange_pos_MM); flange_at(-z_flange_pos_MM); } } else { crowned_body(); } } module crowned_pulley() { difference() { crowned_pulley_solid(); hex_bore(); } } module slice_view(th_MM = 2.0) { // Slab normal to X to expose radius-vs-Z profile intersection() { crowned_pulley(); rotate([0,90,0]) cube([th_MM, pulley_edge_d_od_MM + 2*inch, face_width_MM + (make_flanges ? 2*flange_thickness_MM : 0) + 12], center=true); } } // ------------------------------ // RENDER / EXPORT // ------------------------------ module render_root() { if (debug_slice) { slice_view(th_MM = slice_thickness_MM); } else { crowned_pulley(); } } // ======== DEBUG: Echo the *actual* sizes in the console ======== echo("Pulley edge OD (IN): ", pulley_edge_d_od_IN); echo("Pulley edge OD (MM): ", pulley_edge_d_od_IN * 25.4); echo("Face width (IN): ", belt_width_IN + face_overhang_IN); echo("Face width (MM): ", (belt_width_IN + face_overhang_IN) * 25.4); echo("Crown height (IN): ", crown_height_IN); // Final export scaling: true -> scale by 1/25.4 so mm tools show inch-sized numbers scale(export_in_inches ? [1/25.4, 1/25.4, 1/25.4] : [1,1,1]) render_root();