Created
April 24, 2026 20:51
-
-
Save relistan/f004b4b852eccdd98c984c8a83c6ceff to your computer and use it in GitHub Desktop.
3D Printed Reduction Drive for Variable Capacitors
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Reduction Drive © 2026 by Karl Matthias is licensed under CC BY-SA 4.0. To | |
| // view a copy of this license, visit | |
| // https://creativecommons.org/licenses/by-sa/4.0/ | |
| // 5:1 Reduction for Variable Capacitor | |
| // Herringbone gears with adjustable center distance for anti-backlash | |
| /* [Gear Parameters] */ | |
| gear_module = 0.9; // Gear module (mm) | |
| pinion_teeth = 12; // Pinion tooth count | |
| gear_teeth = 60; // Driven gear tooth count (5:1 ratio) | |
| pressure_angle = 20; // Degrees | |
| helix_angle = 30; // Herringbone helix angle (degrees) | |
| gear_width = 10; // Total herringbone width (mm) | |
| apex_gap = 0; // No gap — solid herringbone | |
| /* [Shaft Parameters] */ | |
| cap_shaft_dia = 9.53; // Capacitor shaft diameter (mm) | |
| axle_dia = 5.0; // Fixed axle for pinion (5mm stainless rod) | |
| bearing_oversize = 0.4; // Diametral clearance where pinion rotates on axle (FDM needs ~0.2mm/side) | |
| pillar_clearance = 0.2; // Diametral clearance where axle sits in pillar (snug but insertable) | |
| snug_tolerance = 0.05; // Per-side tolerance for press/snug fits | |
| knob_stub_dia = 6.35; // D-shaft stub on pinion for standard pot knob | |
| knob_stub_length = 15; // Length of knob stub | |
| d_flat_depth = 1.0; // D-flat cut depth on knob stub | |
| /* [Platform Parameters] */ | |
| shaft_height = 30.63; // Capacitor shaft center height from mounting surface | |
| base_thickness = 5; // Platform base plate thickness | |
| pillar_wall = 4; // Bearing pillar wall thickness | |
| mount_hole_dia = 4.2; // M4 mounting screw clearance | |
| base_margin = 10; // Extra base material around pillars | |
| /* [Print Tuning] */ | |
| print_clearance = 0.1; // Extra root clearance for FDM (mm) | |
| $fn = 96; | |
| // ============================================= | |
| // Derived values | |
| // ============================================= | |
| pinion_pitch_r = pinion_teeth * gear_module / 2; | |
| gear_pitch_r = gear_teeth * gear_module / 2; | |
| center_distance = pinion_pitch_r + gear_pitch_r; | |
| cap_gear_bore = cap_shaft_dia + snug_tolerance * 2; // Driven gear bore (snug on shaft) | |
| cap_pillar_bore = cap_shaft_dia + 0.4; // Loose pass-through (cap bearings locate the shaft) | |
| axle_bore = axle_dia + bearing_oversize; // Pinion bore (rotates freely on axle) | |
| axle_press = axle_dia + pillar_clearance; // Pillar bore (snug on axle, doesn't rotate) | |
| cap_pillar_od = cap_pillar_bore + pillar_wall * 2; | |
| knob_pillar_od = axle_press + pillar_wall * 2; | |
| slot_travel = 6.0; // End travel (mm) for tensioner clamp plate | |
| clamp_l = knob_pillar_od + 9; // Clamp plate length (X) — accommodates pillar + screws | |
| clamp_w = knob_pillar_od + 4; // Clamp plate width (Y) | |
| gear_outer_r = gear_pitch_r + gear_module; | |
| pinion_outer_r = pinion_pitch_r + gear_module; | |
| // Pillar height: short bearing surface so the capacitor shaft | |
| // reaches well into the gear (19.5mm shaft protrusion). | |
| pillar_height = 5; | |
| // ============================================= | |
| // Involute math | |
| // ============================================= | |
| // Point on involute of base circle rb at roll angle t (degrees) | |
| function inv_pt(rb, t) = | |
| let(tr = t * PI / 180) | |
| [ rb * (cos(t) + tr * sin(t)), | |
| rb * (sin(t) - tr * cos(t)) ]; | |
| // Roll angle (degrees) when the involute reaches radius r | |
| function inv_roll(rb, r) = | |
| sqrt(pow(r / rb, 2) - 1) * 180 / PI; | |
| // Rotate 2D point by angle a (degrees) | |
| function r2(p, a) = | |
| [ p[0] * cos(a) - p[1] * sin(a), | |
| p[0] * sin(a) + p[1] * cos(a) ]; | |
| // ============================================= | |
| // 2D involute gear profile | |
| // | |
| // Each tooth polygon traces the involute flanks directly. | |
| // Right flank uses the mirrored involute (curves CW → converges | |
| // toward tooth center going outward). Left flank uses the normal | |
| // involute (curves CCW → also converges). Result: teeth are wide | |
| // at the root and taper toward the tip. | |
| // ============================================= | |
| module gear_2d(teeth, mod, pa) { | |
| pr = teeth * mod / 2; | |
| br = pr * cos(pa); | |
| ar = pr + mod; | |
| rr = max(pr - 1.25 * mod - print_clearance, 0.5); | |
| n = 24; // points per involute flank | |
| // Roll angle range | |
| t_start = (br > rr) ? 0 : inv_roll(br, rr); | |
| t_outer = inv_roll(br, ar); | |
| // Centering rotation: places the tooth symmetrically about | |
| // the x-axis with correct thickness at the pitch circle | |
| t_pitch = inv_roll(br, pr); | |
| pp = inv_pt(br, t_pitch); | |
| theta_p = atan2(pp.y, pp.x); | |
| half_tooth = 90 / teeth; | |
| rot = half_tooth + theta_p; | |
| union() { | |
| // Root body | |
| circle(r = rr); | |
| // Teeth | |
| for (i = [0 : teeth - 1]) | |
| rotate([0, 0, i * 360 / teeth]) | |
| polygon(concat( | |
| // Radial line from root to base circle (right side) | |
| (br > rr) ? [ | |
| [rr * cos(rot), rr * sin(rot)] | |
| ] : [], | |
| // Right flank: mirrored involute rotated by +rot | |
| // (curves CW going outward → tooth tapers) | |
| [for (s = [0 : n]) | |
| let(t = t_start + (t_outer - t_start) * s / n) | |
| let(p = inv_pt(br, t)) | |
| r2([p[0], -p[1]], rot) | |
| ], | |
| // Tip arc at addendum | |
| [for (s = [1 : 3]) | |
| let(rp = inv_pt(br, t_outer)) | |
| let(rt = r2([rp[0], -rp[1]], rot)) | |
| let(a_right = atan2(rt.y, rt.x)) | |
| let(lt = r2(rp, -rot)) | |
| let(a_left = atan2(lt.y, lt.x)) | |
| let(a = a_right + (a_left - a_right) * s / 4) | |
| [ar * cos(a), ar * sin(a)] | |
| ], | |
| // Left flank: normal involute rotated by -rot | |
| // (curves CCW going outward → tooth tapers) | |
| [for (s = [n : -1 : 0]) | |
| let(t = t_start + (t_outer - t_start) * s / n) | |
| r2(inv_pt(br, t), -rot) | |
| ], | |
| // Radial line from base circle to root (left side) | |
| (br > rr) ? [ | |
| [rr * cos(-rot), rr * sin(-rot)] | |
| ] : [] | |
| )); | |
| } | |
| } | |
| // ============================================= | |
| // Herringbone gear — two mirrored helical halves | |
| // | |
| // hand = 1 or -1 controls helix direction. | |
| // Meshing gears MUST have opposite hands. | |
| // ============================================= | |
| module herringbone_gear(teeth, mod, pa, ha, width, bore_dia, hand = 1) { | |
| half_w = (width - apex_gap) / 2; | |
| pr = teeth * mod / 2; | |
| twist_deg = hand * 360 * half_w * tan(ha) / (2 * PI * pr); | |
| difference() { | |
| union() { | |
| // Top half: extrudes upward from center | |
| translate([0, 0, width / 2 + apex_gap / 2]) | |
| linear_extrude(height = half_w, twist = twist_deg, | |
| convexity = 10, slices = 24) | |
| gear_2d(teeth, mod, pa); | |
| // Bottom half: mirror with SAME twist — the mirror | |
| // reverses the helix direction, creating the V | |
| translate([0, 0, width / 2 - apex_gap / 2]) | |
| mirror([0, 0, 1]) | |
| linear_extrude(height = half_w, twist = twist_deg, | |
| convexity = 10, slices = 24) | |
| gear_2d(teeth, mod, pa); | |
| } | |
| // Center bore | |
| translate([0, 0, -1]) | |
| cylinder(d = bore_dia, h = width + 2); | |
| } | |
| } | |
| // ============================================= | |
| // Gear parts | |
| // ============================================= | |
| module driven_gear() { | |
| color("SteelBlue") | |
| herringbone_gear(gear_teeth, gear_module, pressure_angle, | |
| helix_angle, gear_width, cap_gear_bore, hand = 1); | |
| } | |
| stub_flare_h = 2; // Flared boss height bridging gear top to stub | |
| module pinion() { | |
| color("Orange") { | |
| // Gear body — rotates on the fixed 5mm axle | |
| herringbone_gear(pinion_teeth, gear_module, pressure_angle, | |
| helix_angle, gear_width, axle_bore, hand = -1); | |
| // Flared boss — cone from full gear OD down to stub OD, so the | |
| // stub grips the whole gear top face instead of just the thin | |
| // ring between the axle bore and the stub radius. | |
| translate([0, 0, gear_width]) | |
| cylinder(d1 = 2 * pinion_outer_r, | |
| d2 = knob_stub_dia, | |
| h = stub_flare_h); | |
| // D-shaft stub on top face for knob mounting | |
| translate([0, 0, gear_width + stub_flare_h]) | |
| difference() { | |
| cylinder(d = knob_stub_dia, h = knob_stub_length); | |
| // D-flat so standard pot knobs grip | |
| translate([knob_stub_dia / 2 - d_flat_depth, | |
| -knob_stub_dia / 2 - 1, -1]) | |
| cube([d_flat_depth + 1, knob_stub_dia + 2, | |
| knob_stub_length + 2]); | |
| } | |
| } | |
| } | |
| // ============================================= | |
| // Platform parts | |
| // ============================================= | |
| // Bearing pillar with reinforcement flange | |
| module bearing_pillar(bore_dia, outer_dia, height) { | |
| color("SlateGray") | |
| difference() { | |
| union() { | |
| cylinder(d = outer_dia, h = height); | |
| cylinder(d = outer_dia + 4, h = min(3, height)); | |
| } | |
| translate([0, 0, -1]) | |
| cylinder(d = bore_dia, h = height + 2); | |
| } | |
| } | |
| // Mounting face parameters — vertical wall along the -Y long side of | |
| // the base, with holes going through in Y so the whole assembly bolts | |
| // flat to a wooden board (shared with the capacitor). | |
| bracket_face_thick = 5; // Thin — buttresses at the outer X edges reinforce | |
| bracket_face_height = shaft_height + 15; | |
| mount_hole_margin = 8; // Margin from bracket edge to mounting hole center | |
| gear_clearance = 3; // Swing clearance around driven gear | |
| gusset_thick = 4; // X thickness of each buttress | |
| gusset_y_depth = 12; // How far the buttress reaches into the drive | |
| gusset_z_tall = 22; // Buttress height on the bracket inner face | |
| module pinion_pillar_assembly() { | |
| // Push tab — must stay below the gear bottom to avoid interference. | |
| // Gear bottom is at base_thickness + pillar_height. | |
| tab_width = 10; | |
| tab_height = base_thickness + pillar_height - 1; // 1mm below gear | |
| tab_thick = 4; | |
| // Clamp plate slides in the base slot | |
| color("DarkGray") | |
| difference() { | |
| union() { | |
| // Main clamp plate | |
| translate([-clamp_l / 2, -clamp_w / 2, 0]) | |
| cube([clamp_l, clamp_w, base_thickness]); | |
| // Push tab on the back face for the adjustment screw | |
| translate([clamp_l / 2 - tab_thick, -tab_width / 2, 0]) | |
| cube([tab_thick, tab_width, tab_height]); | |
| } | |
| // M3 clamping screw holes | |
| for (dx = [-clamp_l / 2 + 4, clamp_l / 2 - 4]) | |
| translate([dx, 0, -1]) | |
| cylinder(d = 3.4, h = base_thickness + 2); | |
| } | |
| // Pillar on top of clamp plate — press-fit bore holds the 5mm axle | |
| translate([0, 0, base_thickness]) | |
| bearing_pillar(axle_press, knob_pillar_od, pillar_height); | |
| } | |
| /* [Adjustment Screw] */ | |
| adjust_screw_pilot = 3.5; // M4 pilot hole for self-tapping into PLA | |
| thrust_wall_thick = 12; // Thrust wall thickness | |
| // Screw and push tab must be BELOW the gear bottom to clear it. | |
| // Gear bottom is at base_thickness + pillar_height = 10mm. | |
| adjust_screw_z = base_thickness + pillar_height / 2; // Centered in pillar zone | |
| thrust_wall_height = adjust_screw_z + adjust_screw_pilot + 6; // Enough material around the screw | |
| module platform_base() { | |
| knob_x = center_distance; | |
| // Base plate — extends from past the driven gear to the thrust wall. | |
| // y_half = shaft_height puts the cap-shaft axis exactly shaft_height | |
| // above the bracket's outer face (the surface that lies on the board). | |
| x_min = -(gear_outer_r + 10); | |
| y_half = shaft_height; | |
| plate_wid = y_half * 2; | |
| // Slot geometry — snug fit on the sides, slot_travel of end play | |
| slot_w = clamp_w + 0.4; | |
| slot_x = knob_x - clamp_l / 2; | |
| slot_len = clamp_l + slot_travel; | |
| thrust_x = slot_x + slot_len; | |
| x_max = thrust_x + thrust_wall_thick; | |
| color("SlateGray") | |
| difference() { | |
| union() { | |
| // Base plate — full extent | |
| translate([x_min, -y_half, 0]) | |
| cube([x_max - x_min, plate_wid, base_thickness]); | |
| // Cap shaft bearing pillar at x=0 | |
| translate([0, 0, base_thickness]) { | |
| cylinder(d = cap_pillar_od, h = pillar_height); | |
| cylinder(d = cap_pillar_od + 4, h = 3); | |
| } | |
| // Mounting face — vertical wall along the -Y long side, | |
| // spanning the full X length of the base plate. When the | |
| // assembly is laid on the wooden board, this face is the | |
| // one that sits against the board. | |
| translate([x_min, -y_half, 0]) | |
| cube([x_max - x_min, bracket_face_thick, | |
| bracket_face_height]); | |
| // Buttresses at the outer X edges — triangular gussets from | |
| // base plate top up the bracket inner face. | |
| for (bx = [x_min, x_max - gusset_thick]) | |
| translate([bx, 0, 0]) | |
| rotate([90, 0, 90]) | |
| linear_extrude(height = gusset_thick) | |
| translate([-y_half + bracket_face_thick, | |
| base_thickness]) | |
| polygon([[0, 0], | |
| [gusset_y_depth, 0], | |
| [0, gusset_z_tall]]); | |
| // Thrust wall at far right for adjustment screw | |
| translate([thrust_x, -slot_w / 2 - 3, 0]) | |
| cube([thrust_wall_thick, slot_w + 6, thrust_wall_height]); | |
| } | |
| // Cap shaft bore through pillar and base plate | |
| translate([0, 0, -1]) | |
| cylinder(d = cap_pillar_bore, h = base_thickness + pillar_height + 2); | |
| // Swing clearance for the driven gear — rectangular slot through | |
| // the bracket face, from the bottom up past the gear top, wide | |
| // enough for the gear to rotate freely. | |
| cutout_x_half = sqrt(pow(gear_outer_r, 2) | |
| - pow(y_half - bracket_face_thick, 2)) | |
| + gear_clearance; | |
| translate([-cutout_x_half, -y_half - 0.5, -0.5]) | |
| cube([2 * cutout_x_half, | |
| bracket_face_thick + 1, | |
| base_thickness + pillar_height + gear_width | |
| + gear_clearance + 0.5]); | |
| // 4x mounting holes through the bracket face (along Y). Three | |
| // are at the standard corner positions; the bottom-right is | |
| // shifted inward so the +X buttress doesn't block screwdriver | |
| // access. | |
| mount_positions = [ | |
| [x_min + mount_hole_margin, | |
| base_thickness + mount_hole_margin], // bottom-left | |
| [x_min + mount_hole_margin, | |
| bracket_face_height - mount_hole_margin], // top-left | |
| [x_max - mount_hole_margin, | |
| bracket_face_height - mount_hole_margin], // top-right | |
| [x_max - gusset_thick - 12, | |
| base_thickness + mount_hole_margin] // bottom-right (shifted) | |
| ]; | |
| for (p = mount_positions) | |
| translate([p[0], -y_half - 1, p[1]]) | |
| rotate([-90, 0, 0]) | |
| cylinder(d = mount_hole_dia, | |
| h = bracket_face_thick + 2); | |
| // Slot for pinion pillar adjustment | |
| translate([slot_x, -slot_w / 2, -1]) | |
| cube([slot_len, slot_w, base_thickness + 2]); | |
| // Adjustment screw pilot hole centered in thrust wall | |
| translate([thrust_x - 1, 0, adjust_screw_z]) | |
| rotate([0, 90, 0]) | |
| cylinder(d = adjust_screw_pilot, h = thrust_wall_thick + 2); | |
| } | |
| } | |
| // ============================================= | |
| // Assembly (preview) | |
| // ============================================= | |
| module assembly() { | |
| gear_bottom_z = base_thickness + pillar_height; | |
| // Platform: base plate, cap pillar, mounting face, thrust wall | |
| platform_base(); | |
| // Driven gear on capacitor shaft | |
| translate([0, 0, gear_bottom_z]) | |
| driven_gear(); | |
| // Pinion pillar on adjustable clamp plate | |
| translate([center_distance, 0, 0]) | |
| pinion_pillar_assembly(); | |
| // Pinion with D-shaft knob stub | |
| translate([center_distance, 0, gear_bottom_z]) | |
| rotate([0, 0, 180 / pinion_teeth]) | |
| pinion(); | |
| // Visual shafts (translucent) | |
| %cylinder(d = cap_shaft_dia, h = shaft_height + gear_width); | |
| %translate([center_distance, 0, 0]) | |
| cylinder(d = axle_dia, h = shaft_height + gear_width); | |
| } | |
| // ============================================= | |
| // Print layout — all parts laid flat on the bed | |
| // ============================================= | |
| module print_layout() { | |
| spacing = 10; | |
| platform_y_half = shaft_height; | |
| // Driven gear | |
| driven_gear(); | |
| // Pinion (with knob stub pointing up) | |
| translate([gear_outer_r + pinion_outer_r + spacing, 0, 0]) | |
| pinion(); | |
| // Base plate with thrust wall | |
| translate([0, -(gear_outer_r + platform_y_half + spacing), 0]) | |
| platform_base(); | |
| // Pinion pillar assembly | |
| translate([-(gear_outer_r + spacing + 20), | |
| 0, 0]) | |
| pinion_pillar_assembly(); | |
| } | |
| // ============================================= | |
| // Render — uncomment one | |
| // ============================================= | |
| //assembly(); | |
| print_layout(); | |
| // driven_gear(); | |
| // pinion(); | |
| // platform_base(); | |
| // pinion_pillar_assembly(); | |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Reduction Drive for Variable Capacitors
See the blog post at https://ei9itb.com/