From 05bc10563dac2a23cd8a5ed7e8c3f563db7cbadd Mon Sep 17 00:00:00 2001 From: Kaan Barmore-Genc Date: Sun, 17 Dec 2023 12:40:52 -0600 Subject: [PATCH] add thread library --- Thread_Library.scad | 286 +++++++++++++++++++++++++ display-camera-pi-mount-experiment.stl | 4 +- display-camera-pi.scad | 25 ++- gift-box.scad | 69 ++++++ gift-box.stl | 3 + 5 files changed, 383 insertions(+), 4 deletions(-) create mode 100644 Thread_Library.scad create mode 100644 gift-box.scad create mode 100644 gift-box.stl diff --git a/Thread_Library.scad b/Thread_Library.scad new file mode 100644 index 0000000..e5a7fe3 --- /dev/null +++ b/Thread_Library.scad @@ -0,0 +1,286 @@ +module threadPiece(Xa, Ya, Za, Xb, Yb, Zb, radiusa, radiusb, tipRatioa, tipRatiob, threadAngleTop, threadAngleBottom) +{ + angleZ=atan2(Ya, Xa); + twistZ=atan2(Yb, Xb)-atan2(Ya, Xa); + + polyPoints=[ + [Xa+ radiusa*cos(+angleZ), Ya+ radiusa*sin(+angleZ), Za ], + [Xa+ radiusa*cos(+angleZ), Ya+ radiusa*sin(+angleZ), Za + radiusa*tipRatioa ], + [Xa , Ya , Za+ radiusa*(tipRatioa+sin(threadAngleTop)) ], + [Xa , Ya , Za ], + [Xa , Ya , Za+ radiusa*sin(threadAngleBottom) ], + + [Xb+ radiusb*cos(angleZ+twistZ), Yb+ radiusb*sin(angleZ+twistZ), Zb ], + [Xb+ radiusb*cos(angleZ+twistZ), Yb+ radiusb*sin(angleZ+twistZ), Zb+ radiusb*tipRatiob ], + [Xb , Yb , Zb+ radiusb*(tipRatiob+sin(threadAngleTop)) ], + [Xb , Yb , Zb ], + [Xb , Yb , Zb+ radiusb*sin(threadAngleBottom)] ]; + + polyTriangles=[ + [ 0, 1, 6 ], [ 0, 6, 5 ], // tip of profile + [ 1, 7, 6 ], [ 1, 2, 7 ], // upper side of profile + [ 0, 5, 4 ], [ 4, 5, 9 ], // lower side of profile + [ 4, 9, 3 ], [ 9, 8, 3 ], [ 3, 8, 2 ], [ 8, 7, 2 ], // back of profile + [ 0, 4, 3 ], [ 0, 3, 2 ], [ 0, 2, 1 ], // a side of profile + [ 5, 8, 9 ], [ 5, 7, 8 ], [ 5, 6, 7 ] // b side of profile + ]; + + polyhedron( polyPoints, polyTriangles ); +} + +module shaftPiece(Xa, Ya, Za, Xb, Yb, Zb, radiusa, radiusb, tipRatioa, tipRatiob, threadAngleTop, threadAngleBottom) +{ + angleZ=atan2(Ya, Xa); + twistZ=atan2(Yb, Xb)-atan2(Ya, Xa); + + threadAngleTop=15; + threadAngleBottom=-15; + + shaftRatio=0.5; + + polyPoints1=[ + [Xa, Ya, Za + radiusa*sin(threadAngleBottom) ], + [Xa, Ya, Za + radiusa*(tipRatioa+sin(threadAngleTop)) ], + [Xa*shaftRatio, Ya*shaftRatio , Za + radiusa*(tipRatioa+sin(threadAngleTop)) ], + [Xa*shaftRatio , Ya*shaftRatio , Za ], + [Xa*shaftRatio , Ya*shaftRatio , Za + radiusa*sin(threadAngleBottom) ], + + [Xb, Yb, Zb + radiusb*sin(threadAngleBottom) ], + [Xb, Yb, Zb + radiusb*(tipRatiob+sin(threadAngleTop)) ], + [Xb*shaftRatio , Yb*shaftRatio , Zb + radiusb*(tipRatiob+sin(threadAngleTop)) ], + [Xb*shaftRatio , Yb*shaftRatio , Zb ], + [Xb*shaftRatio , Yb*shaftRatio , Zb + radiusb*sin(threadAngleBottom) ] ]; + + polyTriangles1=[ + [ 0, 1, 6 ], [ 0, 6, 5 ], // tip of profile + [ 1, 7, 6 ], [ 1, 2, 7 ], // upper side of profile + [ 0, 5, 4 ], [ 4, 5, 9 ], // lower side of profile + [ 3, 4, 9 ], [ 9, 8, 3 ], [ 2, 3, 8 ], [ 8, 7, 2 ], // back of profile + [ 0, 4, 3 ], [ 0, 3, 2 ], [ 0, 2, 1 ], // a side of profile + [ 5, 8, 9 ], [ 5, 7, 8 ], [ 5, 6, 7 ] // b side of profile + ]; + + + // this is the back of the raised part of the profile + polyhedron( polyPoints1, polyTriangles1 ); +} + +module trapezoidThread( + length=45, // axial length of the threaded rod + pitch=10, // axial distance from crest to crest + pitchRadius=10, // radial distance from center to mid-profile + threadHeightToPitch=0.5, // ratio between the height of the profile and the pitch + // std value for Acme or metric lead screw is 0.5 + profileRatio=0.5, // ratio between the lengths of the raised part of the profile and the pitch + // std value for Acme or metric lead screw is 0.5 + threadAngle=30, // angle between the two faces of the thread + // std value for Acme is 29 or for metric lead screw is 30 + RH=true, // true/false the thread winds clockwise looking along shaft, i.e.follows the Right Hand Rule + clearance=0.1, // radial clearance, normalized to thread height + backlash=0.1, // axial clearance, normalized to pitch + stepsPerTurn=24 // number of slices to create per turn + ) +{ + + numberTurns=length/pitch; + + steps=stepsPerTurn*numberTurns; + + trapezoidRatio= 2*profileRatio*(1-backlash); + + function threadAngleTop(i)= threadAngle/2; + function threadAngleBottom(i)= -threadAngle/2; + + function threadHeight(i)= pitch*threadHeightToPitch; + + function pitchRadius(i)= pitchRadius; + function minorRadius(i)= pitchRadius(i)-0.5*threadHeight(i); + + function X(i)= minorRadius(i)*cos(i*360*numberTurns); + function Y(i)= minorRadius(i)*sin(i*360*numberTurns); + function Z(i)= pitch*numberTurns*i; + + function tip(i)= trapezoidRatio*(1-0.5*sin(threadAngleTop(i))+0.5*sin(threadAngleBottom(i))); + + // this is the threaded rod + + if (RH==true) + translate([0,0,-threadHeight(0)*sin(threadAngleBottom(0))]) + for (i=[0:steps-1]) + { + threadPiece( + Xa= X(i/steps), + Ya= Y(i/steps), + Za= Z(i/steps), + Xb= X((i+1)/steps), + Yb= Y((i+1)/steps), + Zb= Z((i+1)/steps), + radiusa= threadHeight(i/steps), + radiusb= threadHeight((i+1)/steps), + tipRatioa= tip(i/steps), + tipRatiob= tip((i+1)/steps), + threadAngleTop= threadAngleTop(i), + threadAngleBottom= threadAngleBottom(i) + ); + + shaftPiece( + Xa= X(i/steps), + Ya= Y(i/steps), + Za= Z(i/steps), + Xb= X((i+1)/steps), + Yb= Y((i+1)/steps), + Zb= Z((i+1)/steps), + radiusa= threadHeight(i/steps), + radiusb= threadHeight((i+1)/steps), + tipRatioa= tip(i/steps), + tipRatiob= tip((i+1)/steps), + threadAngleTop= threadAngleTop(i), + threadAngleBottom= threadAngleBottom(i) + ); + } + + if (RH==false) + translate([0,0,-threadHeight(0)*sin(threadAngleBottom(0))]) + mirror([0,1,0]) + for (i=[0:steps-1]) + { + threadPiece( + Xa= X(i/steps), + Ya= Y(i/steps), + Za= Z(i/steps), + Xb= X((i+1)/steps), + Yb= Y((i+1)/steps), + Zb= Z((i+1)/steps), + radiusa= threadHeight(i/steps), + radiusb= threadHeight((i+1)/steps), + tipRatioa= tip(i/steps), + tipRatiob= tip((i+1)/steps), + threadAngleTop= threadAngleTop(i), + threadAngleBottom= threadAngleBottom(i) + ); + + shaftPiece( + Xa= X(i/steps), + Ya= Y(i/steps), + Za= Z(i/steps), + Xb= X((i+1)/steps), + Yb= Y((i+1)/steps), + Zb= Z((i+1)/steps), + radiusa= threadHeight(i/steps), + radiusb= threadHeight((i+1)/steps), + tipRatioa= tip(i/steps), + tipRatiob= tip((i+1)/steps), + threadAngleTop= threadAngleTop(i), + threadAngleBottom= threadAngleBottom(i) + ); + } + + rotate([0,0,180/stepsPerTurn]) + cylinder( + h=length+threadHeight(1)*(tip(1)+sin( threadAngleTop(1) )-1*sin( threadAngleBottom(1) ) ), + r1=minorRadius(0)-clearance*threadHeight(0), + r2=minorRadius(0)-clearance*threadHeight(0), + $fn=stepsPerTurn + ); +} + +module trapezoidThreadNegativeSpace( + length=45, // axial length of the threaded rod + pitch=10, // axial distance from crest to crest + pitchRadius=10, // radial distance from center to mid-profile + threadHeightToPitch=0.5, // ratio between the height of the profile and the pitch + // std value for Acme or metric lead screw is 0.5 + profileRatio=0.5, // ratio between the lengths of the raised part of the profile and the pitch + // std value for Acme or metric lead screw is 0.5 + threadAngle=30, // angle between the two faces of the thread + // std value for Acme is 29 or for metric lead screw is 30 + RH=true, // true/false the thread winds clockwise looking along shaft, i.e.follows the Right Hand Rule + countersunk=0, // depth of 45 degree chamfered entries, normalized to pitch + clearance=0.1, // radial clearance, normalized to thread height + backlash=0.1, // axial clearance, normalized to pitch + stepsPerTurn=24 // number of slices to create per turn + ) +{ + + translate([0,0,-countersunk*pitch]) + cylinder( + h=2*countersunk*pitch, + r2=pitchRadius+clearance*pitch+0.25*pitch, + r1=pitchRadius+clearance*pitch+0.25*pitch+2*countersunk*pitch, + $fn=24 + ); + + translate([0,0,countersunk*pitch]) + translate([0,0,-pitch]) + trapezoidThread( + length=length+0.5*pitch, // axial length of the threaded rod + pitch=pitch, // axial distance from crest to crest + pitchRadius=pitchRadius+clearance*pitch, // radial distance from center to mid-profile + threadHeightToPitch=threadHeightToPitch, // ratio between the height of the profile and the pitch + // std value for Acme or metric lead screw is 0.5 + profileRatio=profileRatio, // ratio between the lengths of the raised part of the profile and the pitch + // std value for Acme or metric lead screw is 0.5 + threadAngle=threadAngle, // angle between the two faces of the thread + // std value for Acme is 29 or for metric lead screw is 30 + RH=true, // true/false the thread winds clockwise looking along shaft + // i.e.follows Right Hand Rule + clearance=0, // radial clearance, normalized to thread height + backlash=-backlash, // axial clearance, normalized to pitch + stepsPerTurn=stepsPerTurn // number of slices to create per turn + ); + + translate([0,0,length-countersunk*pitch]) + cylinder( + h=2*countersunk*pitch, + r1=pitchRadius+clearance*pitch+0.25*pitch, + r2=pitchRadius+clearance*pitch+0.25*pitch+2*countersunk*pitch,$fn=24, + $fn=24 + ); +} + +module trapezoidNut( + length=45, // axial length of the threaded rod + radius=25, // outer radius of the nut + pitch=10, // axial distance from crest to crest + pitchRadius=10, // radial distance from center to mid-profile + threadHeightToPitch=0.5, // ratio between the height of the profile and the pitch + // std value for Acme or metric lead screw is 0.5 + profileRatio=0.5, // ratio between the lengths of the raised part of the profile and the pitch + // std value for Acme or metric lead screw is 0.5 + threadAngle=30, // angle between the two faces of the thread + // std value for Acme is 29 or for metric lead screw is 30 + RH=true, // true/false the thread winds clockwise looking along shaft, i.e.follows the Right Hand Rule + countersunk=0, // depth of 45 degree chamfered entries, normalized to pitch + clearance=0.1, // radial clearance, normalized to thread height + backlash=0.1, // axial clearance, normalized to pitch + stepsPerTurn=24 // number of slices to create per turn + ) +{ + difference() + { + cylinder( + h=length, + r1=radius, + r2=radius, + $fn=6 + ); + + trapezoidThreadNegativeSpace( + length=length, // axial length of the threaded rod + pitch=pitch, // axial distance from crest to crest + pitchRadius=pitchRadius, // radial distance from center to mid-profile + threadHeightToPitch=threadHeightToPitch, // ratio between the height of the profile and the pitch + // std value for Acme or metric lead screw is 0.5 + profileRatio=profileRatio, // ratio between the lengths of the raised part of the profile and the pitch + // std value for Acme or metric lead screw is 0.5 + threadAngle=threadAngle, // angle between the two faces of the thread + // std value for Acme is 29 or for metric lead screw is 30 + RH=true, // true/false the thread winds clockwise looking along shaft + // i.e.follows Right Hand Rule + countersunk=countersunk, // depth of 45 degree countersunk entries, normalized to pitch + clearance=clearance, // radial clearance, normalized to thread height + backlash=backlash, // axial clearance, normalized to pitch + stepsPerTurn=stepsPerTurn // number of slices to create per turn + ); + } +} \ No newline at end of file diff --git a/display-camera-pi-mount-experiment.stl b/display-camera-pi-mount-experiment.stl index 8c11a52..9e4e7cc 100644 --- a/display-camera-pi-mount-experiment.stl +++ b/display-camera-pi-mount-experiment.stl @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f3b10033c64f3e2fdde52ed5ad04e65548ebf8424fac046dcaa30507fa9541e2 -size 174284 +oid sha256:da89c85079b6766787d9f5d1d664a2113679ef1e5925c5aa11937e90f06be11e +size 126284 diff --git a/display-camera-pi.scad b/display-camera-pi.scad index b875e3e..9629537 100644 --- a/display-camera-pi.scad +++ b/display-camera-pi.scad @@ -8,9 +8,30 @@ $triangle_y_hole_gap = 20; $triangle_x_offset = 19; $triangle_y_offset = 5; -$fn=200; +$fn=10; -screen_mount(); +use + +camera_mount(); + +$camera_mount_thickness = 1; +$camera_screw_gap_y = 25.2; +$camera_screw_diameter = 2.75; +module camera_mount() { + difference() { + cylinder(h=$camera_mount_thickness, d=$camera_screw_gap_y); + translate([0, 0, -0.1]) + cylinder(h=3 * $camera_mount_thickness, d=$camera_screw_gap_y - $camera_screw_diameter * 3); + rotate([0, 0, 90]) + translate([$camera_screw_gap_y / 2 - $camera_screw_diameter / 1.33, 0, -0.1]) + cylinder(h=3 * $camera_mount_thickness, d=$camera_screw_diameter); + rotate([0, 0, -90]) + translate([$camera_screw_gap_y / 2 - $camera_screw_diameter / 1.33, 0, -0.1]) + cylinder(h=3 * $camera_mount_thickness, d=$camera_screw_diameter); + translate([-1 * $camera_screw_gap_y - $camera_screw_diameter / 1.33, -1 * $camera_screw_gap_y / 2, -0.1]) + cube([$camera_screw_gap_y, $camera_screw_gap_y, 3 * $camera_mount_thickness]); + }; +} module attachment_point() { difference() { diff --git a/gift-box.scad b/gift-box.scad new file mode 100644 index 0000000..cb569df --- /dev/null +++ b/gift-box.scad @@ -0,0 +1,69 @@ +/** + +# Parameters + + */ +$box_inner_width = 10; +$box_inner_depth = 20; +$box_inner_height = 15; +$box_wall_thickness = 4; +// [0, 1] Higher the ratio, the bigger the bottom will be. +$box_bottom_top_height_fraction = 0.2; +// [0, 1] The amount the bottom and top will overlap. +$overlap_fraction = 0.8; +// [0, 1] The thickness of the overlap as a fraction of the wall thickness. +$overlap_thickness_fraction = 0.5; + +/** + +# Code + +*/ +include ; + +$box_outer_width = $box_inner_width + $box_wall_thickness * 2; +$box_outer_depth = $box_inner_depth + $box_wall_thickness * 2; +$box_outer_height = $box_inner_height + $box_wall_thickness * 2; + +$bottom_height = $box_inner_height * $box_bottom_top_height_fraction; +$top_height = $box_inner_height * (1 - $box_bottom_top_height_fraction); + +$overlap_height = $box_inner_height * $overlap_fraction; +$overlap_thickness = $box_wall_thickness * $overlap_thickness_fraction; + + +bottom(); +top(); + +module top() { + translate([-1 * $box_inner_width - $box_wall_thickness * 2 - 10, 0, 0]) + difference() { + box_half($box_inner_width, $box_inner_depth, $top_height, $box_wall_thickness); + translate([-0.002, -0.002, 0]) + scale([1.001, 1.001, 1.001]) + translate([0, 0, $top_height + $bottom_height + $box_wall_thickness * 2]) + color("red") + mirror([0, 0, 1]) + bottom(); + }; +} + +module bottom() { + union() { + box_half($box_inner_width, $box_inner_depth, $bottom_height, $box_wall_thickness); + box_half($box_inner_width + $box_wall_thickness, $box_inner_depth + $box_wall_thickness, $overlap_height + $box_wall_thickness, $overlap_thickness); + }; +}; + +module box_half($width, $depth, $height, $wall_thickness) { + difference() { + cube([ + $width + $wall_thickness * 2, + $depth + $wall_thickness * 2, + $height + $wall_thickness + ]); + translate([$wall_thickness, $wall_thickness, $wall_thickness]) + cube([$width, $depth, $height + 0.1]); + }; +}; + diff --git a/gift-box.stl b/gift-box.stl new file mode 100644 index 0000000..15e92b5 --- /dev/null +++ b/gift-box.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:825e4e5e7265d0de33396ce76378dd6b1a691561aa4e9932cc803ec4cfb001fa +size 4484