diff --git a/involute_gears.scad b/involute_gears.scad new file mode 100644 index 0000000..2756628 --- /dev/null +++ b/involute_gears.scad @@ -0,0 +1,670 @@ +// Parametric Involute Bevel and Spur Gears by GregFrost +// It is licensed under the Creative Commons - GNU GPL license. +// © 2010 by GregFrost +// http://www.thingiverse.com/thing:3575 + +// Simple Test: +//gear (circular_pitch=700, +// gear_thickness = 12, +// rim_thickness = 15, +// hub_thickness = 17, +// circles=8); + +//Complex Spur Gear Test: +//test_gears (); + +// Meshing Double Helix: +//meshing_double_helix (); + +// Demonstrate the backlash option for Spur gears. +//test_backlash (); + +// Demonstrate how to make meshing bevel gears. +bevel_gear_pair (); + +pi=3.1415926535897932384626433832795; + +//================================================== +// Bevel Gears: +// Two gears with the same cone distance, circular pitch (measured at the cone distance) +// and pressure angle will mesh. + +module bevel_gear_pair ( + gear1_teeth = 41, + gear2_teeth = 7, + axis_angle = 90, + outside_circular_pitch=1000) +{ + outside_pitch_radius1 = gear1_teeth * outside_circular_pitch / 360; + outside_pitch_radius2 = gear2_teeth * outside_circular_pitch / 360; + pitch_apex1=outside_pitch_radius2 * sin (axis_angle) + + (outside_pitch_radius2 * cos (axis_angle) + outside_pitch_radius1) / tan (axis_angle); + cone_distance = sqrt (pow (pitch_apex1, 2) + pow (outside_pitch_radius1, 2)); + pitch_apex2 = sqrt (pow (cone_distance, 2) - pow (outside_pitch_radius2, 2)); + echo ("cone_distance", cone_distance); + pitch_angle1 = asin (outside_pitch_radius1 / cone_distance); + pitch_angle2 = asin (outside_pitch_radius2 / cone_distance); + echo ("pitch_angle1, pitch_angle2", pitch_angle1, pitch_angle2); + echo ("pitch_angle1 + pitch_angle2", pitch_angle1 + pitch_angle2); + + rotate([0,0,90]) + translate ([0,0,pitch_apex1+20]) + { + translate([0,0,-pitch_apex1]) + bevel_gear ( + number_of_teeth=gear1_teeth, + cone_distance=cone_distance, + pressure_angle=30, + outside_circular_pitch=outside_circular_pitch); + + rotate([0,-(pitch_angle1+pitch_angle2),0]) + translate([0,0,-pitch_apex2]) + bevel_gear ( + number_of_teeth=gear2_teeth, + cone_distance=cone_distance, + pressure_angle=30, + outside_circular_pitch=outside_circular_pitch); + } +} + +//Bevel Gear Finishing Options: +bevel_gear_flat = 0; +bevel_gear_back_cone = 1; + +module bevel_gear ( + number_of_teeth=11, + cone_distance=100, + face_width=20, + outside_circular_pitch=1000, + pressure_angle=30, + clearance = 0.2, + bore_diameter=5, + gear_thickness = 15, + backlash = 0, + involute_facets=0, + finish = -1) +{ + echo ("bevel_gear", + "teeth", number_of_teeth, + "cone distance", cone_distance, + face_width, + outside_circular_pitch, + pressure_angle, + clearance, + bore_diameter, + involute_facets, + finish); + + // Pitch diameter: Diameter of pitch circle at the fat end of the gear. + outside_pitch_diameter = number_of_teeth * outside_circular_pitch / 180; + outside_pitch_radius = outside_pitch_diameter / 2; + + // The height of the pitch apex. + pitch_apex = sqrt (pow (cone_distance, 2) - pow (outside_pitch_radius, 2)); + pitch_angle = asin (outside_pitch_radius/cone_distance); + + echo ("Num Teeth:", number_of_teeth, " Pitch Angle:", pitch_angle); + + finish = (finish != -1) ? finish : (pitch_angle < 45) ? bevel_gear_flat : bevel_gear_back_cone; + + apex_to_apex=cone_distance / cos (pitch_angle); + back_cone_radius = apex_to_apex * sin (pitch_angle); + + // Calculate and display the pitch angle. This is needed to determine the angle to mount two meshing cone gears. + + // Base Circle for forming the involute teeth shape. + base_radius = back_cone_radius * cos (pressure_angle); + + // Diametrial pitch: Number of teeth per unit length. + pitch_diametrial = number_of_teeth / outside_pitch_diameter; + + // Addendum: Radial distance from pitch circle to outside circle. + addendum = 1 / pitch_diametrial; + // Outer Circle + outer_radius = back_cone_radius + addendum; + + // Dedendum: Radial distance from pitch circle to root diameter + dedendum = addendum + clearance; + dedendum_angle = atan (dedendum / cone_distance); + root_angle = pitch_angle - dedendum_angle; + + root_cone_full_radius = tan (root_angle)*apex_to_apex; + back_cone_full_radius=apex_to_apex / tan (pitch_angle); + + back_cone_end_radius = + outside_pitch_radius - + dedendum * cos (pitch_angle) - + gear_thickness / tan (pitch_angle); + back_cone_descent = dedendum * sin (pitch_angle) + gear_thickness; + + // Root diameter: Diameter of bottom of tooth spaces. + root_radius = back_cone_radius - dedendum; + + half_tooth_thickness = outside_pitch_radius * sin (360 / (4 * number_of_teeth)) - backlash / 4; + half_thick_angle = asin (half_tooth_thickness / back_cone_radius); + + face_cone_height = apex_to_apex-face_width / cos (pitch_angle); + face_cone_full_radius = face_cone_height / tan (pitch_angle); + face_cone_descent = dedendum * sin (pitch_angle); + face_cone_end_radius = + outside_pitch_radius - + face_width / sin (pitch_angle) - + face_cone_descent / tan (pitch_angle); + + // For the bevel_gear_flat finish option, calculate the height of a cube to select the portion of the gear that includes the full pitch face. + bevel_gear_flat_height = pitch_apex - (cone_distance - face_width) * cos (pitch_angle); + +// translate([0,0,-pitch_apex]) + difference () + { + intersection () + { + union() + { + rotate (half_thick_angle) + translate ([0,0,pitch_apex-apex_to_apex]) + cylinder ($fn=number_of_teeth*2, r1=root_cone_full_radius,r2=0,h=apex_to_apex); + for (i = [1:number_of_teeth]) +// for (i = [1:1]) + { + rotate ([0,0,i*360/number_of_teeth]) + { + involute_bevel_gear_tooth ( + back_cone_radius = back_cone_radius, + root_radius = root_radius, + base_radius = base_radius, + outer_radius = outer_radius, + pitch_apex = pitch_apex, + cone_distance = cone_distance, + half_thick_angle = half_thick_angle, + involute_facets = involute_facets); + } + } + } + + if (finish == bevel_gear_back_cone) + { + translate ([0,0,-back_cone_descent]) + cylinder ( + $fn=number_of_teeth*2, + r1=back_cone_end_radius, + r2=back_cone_full_radius*2, + h=apex_to_apex + back_cone_descent); + } + else + { + translate ([-1.5*outside_pitch_radius,-1.5*outside_pitch_radius,0]) + cube ([3*outside_pitch_radius, + 3*outside_pitch_radius, + bevel_gear_flat_height]); + } + } + + if (finish == bevel_gear_back_cone) + { + translate ([0,0,-face_cone_descent]) + cylinder ( + r1=face_cone_end_radius, + r2=face_cone_full_radius * 2, + h=face_cone_height + face_cone_descent+pitch_apex); + } + + translate ([0,0,pitch_apex - apex_to_apex]) + cylinder (r=bore_diameter/2,h=apex_to_apex); + } +} + +module involute_bevel_gear_tooth ( + back_cone_radius, + root_radius, + base_radius, + outer_radius, + pitch_apex, + cone_distance, + half_thick_angle, + involute_facets) +{ +// echo ("involute_bevel_gear_tooth", +// back_cone_radius, +// root_radius, +// base_radius, +// outer_radius, +// pitch_apex, +// cone_distance, +// half_thick_angle); + + min_radius = max (base_radius*2,root_radius*2); + + pitch_point = + involute ( + base_radius*2, + involute_intersect_angle (base_radius*2, back_cone_radius*2)); + pitch_angle = atan2 (pitch_point[1], pitch_point[0]); + centre_angle = pitch_angle + half_thick_angle; + + start_angle = involute_intersect_angle (base_radius*2, min_radius); + stop_angle = involute_intersect_angle (base_radius*2, outer_radius*2); + + res=(involute_facets!=0)?involute_facets:($fn==0)?5:$fn/4; + + translate ([0,0,pitch_apex]) + rotate ([0,-atan(back_cone_radius/cone_distance),0]) + translate ([-back_cone_radius*2,0,-cone_distance*2]) + union () + { + for (i=[1:res]) + { + assign ( + point1= + involute (base_radius*2,start_angle+(stop_angle - start_angle)*(i-1)/res), + point2= + involute (base_radius*2,start_angle+(stop_angle - start_angle)*(i)/res)) + { + assign ( + side1_point1 = rotate_point (centre_angle, point1), + side1_point2 = rotate_point (centre_angle, point2), + side2_point1 = mirror_point (rotate_point (centre_angle, point1)), + side2_point2 = mirror_point (rotate_point (centre_angle, point2))) + { + polyhedron ( + points=[ + [back_cone_radius*2+0.1,0,cone_distance*2], + [side1_point1[0],side1_point1[1],0], + [side1_point2[0],side1_point2[1],0], + [side2_point2[0],side2_point2[1],0], + [side2_point1[0],side2_point1[1],0], + [0.1,0,0]], + triangles=[[0,1,2],[0,2,3],[0,3,4],[0,5,1],[1,5,2],[2,5,3],[3,5,4],[0,4,5]]); + } + } + } + } +} + +module gear ( + number_of_teeth=15, + circular_pitch=false, diametral_pitch=false, + pressure_angle=28, + clearance = 0.2, + gear_thickness=5, + rim_thickness=8, + rim_width=5, + hub_thickness=10, + hub_diameter=15, + bore_diameter=5, + circles=0, + backlash=0, + twist=0, + involute_facets=0) +{ + if (circular_pitch==false && diametral_pitch==false) + echo("MCAD ERROR: gear module needs either a diametral_pitch or circular_pitch"); + + //Convert diametrial pitch to our native circular pitch + circular_pitch = (circular_pitch!=false?circular_pitch:180/diametral_pitch); + + // Pitch diameter: Diameter of pitch circle. + pitch_diameter = number_of_teeth * circular_pitch / 180; + pitch_radius = pitch_diameter/2; + echo ("Teeth:", number_of_teeth, " Pitch radius:", pitch_radius); + + // Base Circle + base_radius = pitch_radius*cos(pressure_angle); + + // Diametrial pitch: Number of teeth per unit length. + pitch_diametrial = number_of_teeth / pitch_diameter; + + // Addendum: Radial distance from pitch circle to outside circle. + addendum = 1/pitch_diametrial; + + //Outer Circle + outer_radius = pitch_radius+addendum; + + // Dedendum: Radial distance from pitch circle to root diameter + dedendum = addendum + clearance; + + // Root diameter: Diameter of bottom of tooth spaces. + root_radius = pitch_radius-dedendum; + backlash_angle = backlash / pitch_radius * 180 / pi; + half_thick_angle = (360 / number_of_teeth - backlash_angle) / 4; + + // Variables controlling the rim. + rim_radius = root_radius - rim_width; + + // Variables controlling the circular holes in the gear. + circle_orbit_diameter=hub_diameter/2+rim_radius; + circle_orbit_curcumference=pi*circle_orbit_diameter; + + // Limit the circle size to 90% of the gear face. + circle_diameter= + min ( + 0.70*circle_orbit_curcumference/circles, + (rim_radius-hub_diameter/2)*0.9); + + difference () + { + union () + { + difference () + { + linear_extrude (height=rim_thickness, convexity=10, twist=twist) + gear_shape ( + number_of_teeth, + pitch_radius = pitch_radius, + root_radius = root_radius, + base_radius = base_radius, + outer_radius = outer_radius, + half_thick_angle = half_thick_angle, + involute_facets=involute_facets); + + if (gear_thickness < rim_thickness) + translate ([0,0,gear_thickness]) + cylinder (r=rim_radius,h=rim_thickness-gear_thickness+1); + } + if (gear_thickness > rim_thickness) + cylinder (r=rim_radius,h=gear_thickness); + if (hub_thickness > gear_thickness) + translate ([0,0,gear_thickness]) + cylinder (r=hub_diameter/2,h=hub_thickness-gear_thickness); + } + translate ([0,0,-1]) + cylinder ( + r=bore_diameter/2, + h=2+max(rim_thickness,hub_thickness,gear_thickness)); + if (circles>0) + { + for(i=[0:circles-1]) + rotate([0,0,i*360/circles]) + translate([circle_orbit_diameter/2,0,-1]) + cylinder(r=circle_diameter/2,h=max(gear_thickness,rim_thickness)+3); + } + } +} + +module gear_shape ( + number_of_teeth, + pitch_radius, + root_radius, + base_radius, + outer_radius, + half_thick_angle, + involute_facets) +{ + union() + { + rotate (half_thick_angle) circle ($fn=number_of_teeth*2, r=root_radius); + + for (i = [1:number_of_teeth]) + { + rotate ([0,0,i*360/number_of_teeth]) + { + involute_gear_tooth ( + pitch_radius = pitch_radius, + root_radius = root_radius, + base_radius = base_radius, + outer_radius = outer_radius, + half_thick_angle = half_thick_angle, + involute_facets=involute_facets); + } + } + } +} + +module involute_gear_tooth ( + pitch_radius, + root_radius, + base_radius, + outer_radius, + half_thick_angle, + involute_facets) +{ + min_radius = max (base_radius,root_radius); + + pitch_point = involute (base_radius, involute_intersect_angle (base_radius, pitch_radius)); + pitch_angle = atan2 (pitch_point[1], pitch_point[0]); + centre_angle = pitch_angle + half_thick_angle; + + start_angle = involute_intersect_angle (base_radius, min_radius); + stop_angle = involute_intersect_angle (base_radius, outer_radius); + + res=(involute_facets!=0)?involute_facets:($fn==0)?5:$fn/4; + + union () + { + for (i=[1:res]) + assign ( + point1=involute (base_radius,start_angle+(stop_angle - start_angle)*(i-1)/res), + point2=involute (base_radius,start_angle+(stop_angle - start_angle)*i/res)) + { + assign ( + side1_point1=rotate_point (centre_angle, point1), + side1_point2=rotate_point (centre_angle, point2), + side2_point1=mirror_point (rotate_point (centre_angle, point1)), + side2_point2=mirror_point (rotate_point (centre_angle, point2))) + { + polygon ( + points=[[0,0],side1_point1,side1_point2,side2_point2,side2_point1], + paths=[[0,1,2,3,4,0]]); + } + } + } +} + +// Mathematical Functions +//=============== + +// Finds the angle of the involute about the base radius at the given distance (radius) from it's center. +//source: http://www.mathhelpforum.com/math-help/geometry/136011-circle-involute-solving-y-any-given-x.html + +function involute_intersect_angle (base_radius, radius) = sqrt (pow (radius/base_radius, 2) - 1) * 180 / pi; + +// Calculate the involute position for a given base radius and involute angle. + +function rotated_involute (rotate, base_radius, involute_angle) = +[ + cos (rotate) * involute (base_radius, involute_angle)[0] + sin (rotate) * involute (base_radius, involute_angle)[1], + cos (rotate) * involute (base_radius, involute_angle)[1] - sin (rotate) * involute (base_radius, involute_angle)[0] +]; + +function mirror_point (coord) = +[ + coord[0], + -coord[1] +]; + +function rotate_point (rotate, coord) = +[ + cos (rotate) * coord[0] + sin (rotate) * coord[1], + cos (rotate) * coord[1] - sin (rotate) * coord[0] +]; + +function involute (base_radius, involute_angle) = +[ + base_radius*(cos (involute_angle) + involute_angle*pi/180*sin (involute_angle)), + base_radius*(sin (involute_angle) - involute_angle*pi/180*cos (involute_angle)), +]; + + +// Test Cases +//=============== + +module test_gears() +{ + translate([17,-15]) + { + gear (number_of_teeth=17, + circular_pitch=500, + circles=8); + + rotate ([0,0,360*4/17]) + translate ([39.088888,0,0]) + { + gear (number_of_teeth=11, + circular_pitch=500, + hub_diameter=0, + rim_width=65); + translate ([0,0,8]) + { + gear (number_of_teeth=6, + circular_pitch=300, + hub_diameter=0, + rim_width=5, + rim_thickness=6, + pressure_angle=31); + rotate ([0,0,360*5/6]) + translate ([22.5,0,1]) + gear (number_of_teeth=21, + circular_pitch=300, + bore_diameter=2, + hub_diameter=4, + rim_width=1, + hub_thickness=4, + rim_thickness=4, + gear_thickness=3, + pressure_angle=31); + } + } + + translate ([-61.1111111,0,0]) + { + gear (number_of_teeth=27, + circular_pitch=500, + circles=5, + hub_diameter=2*8.88888889); + + translate ([0,0,10]) + { + gear ( + number_of_teeth=14, + circular_pitch=200, + pressure_angle=5, + clearance = 0.2, + gear_thickness = 10, + rim_thickness = 10, + rim_width = 15, + bore_diameter=5, + circles=0); + translate ([13.8888888,0,1]) + gear ( + number_of_teeth=11, + circular_pitch=200, + pressure_angle=5, + clearance = 0.2, + gear_thickness = 10, + rim_thickness = 10, + rim_width = 15, + hub_thickness = 20, + hub_diameter=2*7.222222, + bore_diameter=5, + circles=0); + } + } + + rotate ([0,0,360*-5/17]) + translate ([44.444444444,0,0]) + gear (number_of_teeth=15, + circular_pitch=500, + hub_diameter=10, + rim_width=5, + rim_thickness=5, + gear_thickness=4, + hub_thickness=6, + circles=9); + + rotate ([0,0,360*-1/17]) + translate ([30.5555555,0,-1]) + gear (number_of_teeth=5, + circular_pitch=500, + hub_diameter=0, + rim_width=5, + rim_thickness=10); + } +} + +module meshing_double_helix () +{ + test_double_helix_gear (); + + mirror ([0,1,0]) + translate ([58.33333333,0,0]) + test_double_helix_gear (teeth=13,circles=6); +} + +module test_double_helix_gear ( + teeth=17, + circles=8) +{ + //double helical gear + { + twist=200; + height=20; + pressure_angle=30; + + gear (number_of_teeth=teeth, + circular_pitch=700, + pressure_angle=pressure_angle, + clearance = 0.2, + gear_thickness = height/2*0.5, + rim_thickness = height/2, + rim_width = 5, + hub_thickness = height/2*1.2, + hub_diameter=15, + bore_diameter=5, + circles=circles, + twist=twist/teeth); + mirror([0,0,1]) + gear (number_of_teeth=teeth, + circular_pitch=700, + pressure_angle=pressure_angle, + clearance = 0.2, + gear_thickness = height/2, + rim_thickness = height/2, + rim_width = 5, + hub_thickness = height/2, + hub_diameter=15, + bore_diameter=5, + circles=circles, + twist=twist/teeth); + } +} + +module test_backlash () +{ + backlash = 2; + teeth = 15; + + translate ([-29.166666,0,0]) + { + translate ([58.3333333,0,0]) + rotate ([0,0,-360/teeth/4]) + gear ( + number_of_teeth = teeth, + circular_pitch=700, + gear_thickness = 12, + rim_thickness = 15, + rim_width = 5, + hub_thickness = 17, + hub_diameter=15, + bore_diameter=5, + backlash = 2, + circles=8); + + rotate ([0,0,360/teeth/4]) + gear ( + number_of_teeth = teeth, + circular_pitch=700, + gear_thickness = 12, + rim_thickness = 15, + rim_width = 5, + hub_thickness = 17, + hub_diameter=15, + bore_diameter=5, + backlash = 2, + circles=8); + } + + color([0,0,128,0.5]) + translate([0,0,-5]) + cylinder ($fn=20,r=backlash / 4,h=25); +} +