The NEW Build Your Own Arcade Controls
Main => Project Announcements => Topic started by: PL1 on September 12, 2018, 06:20:06 am
-
Like the title says, this is the thread for developing and testing a printable LS-30 handle for the J-Stik/ServoStik Ikari 12-way Rotary Upgrade announced here (http://forum.arcadecontrols.com/index.php/topic,158159.0.html).
Ultimarc product page:
http://www.ultimarc.com/controls.html (http://www.ultimarc.com/controls.html)
Installation directions:
http://www.ultimarc.com/12wayrotary.pdf (http://www.ultimarc.com/12wayrotary.pdf)
Anyone who wants to join in, grab a copy of OpenSCAD (http://www.openscad.org/index.html) and bookmark the OpenSCAD cheatsheet (http://www.openscad.org/cheatsheet/index.html?version=2015.03) to help you with the commands and syntax. ;D
---------------------
The plan is to start with the code from the 3d printed LS-30 replacement handle for the Happ Rotary Joystick (http://forum.arcadecontrols.com/index.php/topic,158253.0.html) and remix it to include these features:
- Removable top like the original handle.
- Two free-floating eject pins instead of the long legs on the original top.
(less likely to break and easier to print)
(http://www.emphatic.se/wp-content/uploads/2012/01/new_top_comparison.jpg)
- M6 locknut and maybe a star washer or two to secure the handle to the shaft.
(http://www.jstookey.com/images/ls30_top.jpg)
- No shaft mods, just print and assemble.
Any more features you'd like to see added or changed?
--------------------
Needed measurements to design the part:
Shaft diagram.
(http://forum.arcadecontrols.com/index.php?action=dlattach;topic=149895.0;attach=389031;image)
Mounting plate to shaft shoulder distance = 46mm.
(http://forum.arcadecontrols.com/index.php?action=dlattach;topic=158159.0;attach=370975;image)
Next step: A diagram to work out the vertical positioning of the handle on the shaft.
Scott
EDIT: Uploaded a copy of the shaft diagram since it is no longer at the old URL.
-
Just ordered the rotary kit.
-
Looking forward to your advice and observations, Deven. ;D
Here's the promised vertical positioning diagram. (Not drawn to scale.)
(http://forum.arcadecontrols.com/index.php?action=dlattach;topic=149895.0;attach=371001;image)
First thing to do is solve for Shaft Height with a typical 3/4" wood panel (19.05mm) and a typical metal panel (1.6 mm) since most panels will fall within that range.
3/4" wood panel:
PanelThickness + 15.6mm (handle to panel distance) +ShaftHeight = Shoulder Height
19.05mm + 15.6mm + ShaftHeight = 46mm
ShaftHeight = 11.35mm
Metal panel:
1.6mm + 15.6mm + ShaftHeight = 46mm
ShaftHeight = 28.8mm
The original handle BodyHeight is 35.6mm, so ShaftHeight + ThreadedHeight + TopThickness (the removable cover) have to fit into that vertical space.
Wood panel:
ShaftHeight + ThreadedHeight + TopThickness <= BodyHeight
11.35mm + 9.4mm + TopThickness <= 35.6mm
TopThickness <= 14.85mm -- Lots of wiggle room there. ;D
Metal panel:
28.8mm + 9.4mm + TopThickness <= 35.6mm
TopThickness <= -2.6mm -- Threads are higher than the handle body, needs some 5mm spacers (or larger) between the stick and panel.
Metal panel + 5mm spacers:
23.8mm + 9.4mm + TopThickness <= 35.6mm
TopThickness <= 2.4mm -- Just enough wiggle room for a 2mm top.
------------------
Looks like the handle will work with 6.6mm (metal panel + 5mm spacers) - 19.05mm (3/4" wood) panels and leaves room for a 2mm recess for the top cover.
Next step: Define variable names and trim/organize the code.
Scott
EDIT: Fixed several errors in the metal panel calculations. :embarassed:
-
Great work, id be in for 2 x tops if anyone makes them in nice quality :-)
-
Test print updated with new variables and comments. ;D
LS30_Test_Print_Ultimarc.scad
// LS-30 handle for Ultimarc Ikari 12-way Rotary Upgrade
// - Test print
// This test print allows you to verify the correct variable values for your specific hardware and your slicer software before you render/export/print the whole handle.
// Hardware tested:
// - Joystick M6 threaded diameter (clears without engaging threads)
// - Joysick shaft diameter (snug fit)
// This part is oriented upside-down compared to the handle so print supports are not needed.
/////////////////////////////
// Define variables
/////////////////////////////
ShaftDiameter = 9.35; // Default = 9.35
ShaftHeight = 9; // Default = 9
ThreadedDiameter = 6.2; // Default = 6.2
// The diameter values may need to be *very slightly* larger to account for the 180-sided polygon used to render circles -- see "undersized holes" at https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Primitive_Solids#cylinder
$fn=180; // Number of fragments (polygon sides) used to render a circle
/////////////////////////////
// Make the part
/////////////////////////////
// Make the shaft test layer
difference() {
cylinder(ShaftHeight, d=ShaftDiameter+6, center=true); // Shaft outer cylinder
cylinder(ShaftHeight+2, d=ShaftDiameter, center=true);
// Remove Shaft Collar hole
}
//
// Make the thread test layer (red)
difference() {
color("red") translate([0,0,-1 - ShaftHeight/2]) cylinder(2, d=ShaftDiameter + 6, center=true);
// Outer cylinder
translate([0,0,-1 - ShaftHeight/2]) cylinder(ShaftHeight, d=ThreadedDiameter, center=true);
// Remove threaded hole
}
Scott
-
First pass on the handle updated with new variables and comments. ;D
LS30_Handle_Ultimarc.scad
// LS-30 handle for Ultimarc Ikari 12-way Rotary Upgrade
// -- Handle
// Required hardware:
// - 6mm locknut
// - 6mm star washer
/////////////////////////////
// Adjustable variables
/////////////////////////////
// Body
BodyHeight = 35.6; // Default = 35.6
// Height of the body, not including the dome
TopDiameter = 22; // Default = 22
// Hole for remvable top. 2mm deep.
// Sides
SideRoundSphere = 0.7; // Default = 0.7
// Radius of the side roundover sphere
LowerBodyDiameter = 31.51; // Default = 31.51
// Farthest distance from lower point-to-point edge
UpperBodyDiameter = 29.41; // Default = 29.41
// Farthest distance from upper point-to-point edge
// Bottom octagon
LowerRoundSphere = 1.59; // Default = 1.59
// Radius of the lower roundover sphere
// Top octagon
UpperRoundSphere = 3.18; // Default = 3.18
// Radius of the upper roundover sphere
// Spaces to remove from body
ShaftHeight = 11.35; // Default = 11.35 (3/4" wood panel) or 23.5 (1.6mm metal panel with 2mm spacers)
// Height of the unthreaded shaft cavity
ShaftDiameter = 9.35; // Default = 9.35
// Diameter of the joystick unthreaded shaft cavity
ThreadedHeight = 6; // Default = 6
// Height of the thread hole
ThreadedDiameter = 6.2; // Default = 6.2
// Outer diameter of the thread hole
LocknutHeight = (BodyHeight - ShaftHeight - ThreadedHeight);
LocknutDiameter = 12; // Default = 12
// Diameter of the locknut cavity
// Number of fragments (polygon sides) used to render a full circle.
$fn = 180; // Default = 180 Typical range = 6 - 360
// 6 will render a circular hole as a hexagon, 8 will render a circular hole as an octagon.
// Lower the number for faster rendering, raise the number for smoother rendering.
/////////////////////////////
// Non-adjustable variables
/////////////////////////////
// Bottom octagon
LowerSmallArccosine = SideRoundSphere * 1.0823922002923939687994464107328;
// Calculates distance from center of lower small sphere to point of lower octagon [radius*acos(22.5)]
LowerLargeArccosine = LowerRoundSphere * 1.0823922002923939687994464107328;
// Calculates distance from point of lower octagon to center of lower large sphere [radius*acos(22.5)]
LowerLargeSphereCenter = LowerBodyDiameter/2 - SideRoundSphere + LowerSmallArccosine - LowerLargeArccosine;
// Rounded octagon point - side (small) sphere radius + distance from center of small sphere to point of octagon - distance from point of octagon to center of large sphere
// Top octagon
UpperSmallArccosine = SideRoundSphere * 1.0823922002923939687994464107328;
// Calculates distance from center of upper small sphere to point of upper octagon [radius*acos(22.5)]
UpperLargeArccosine = UpperRoundSphere * 1.0823922002923939687994464107328;
// Calculates distance from point of upper octagon to center of upper large sphere [radius*acos(22.5)]
UpperLargeSphereCenter = UpperBodyDiameter/2 - SideRoundSphere + UpperSmallArccosine - UpperLargeArccosine;
// Rounded octagon point - side (small) sphere radius + distance from center of small sphere to point of octagon - distance from point of octagon to center of large sphere
/////////////////////////////
// Make the part
/////////////////////////////
// Make the main body
difference(){ // Main body minus holes
hull() { // Main body hull
// Lower roundover large spheres
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 22.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 67.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 112.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 157.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 202.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 247.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 292.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 337.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
// Lower side small spheres
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 22.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 67.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 112.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 157.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 202.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 247.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 292.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 337.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
// Upper side small spheres
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 22.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere, center = true);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 67.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 112.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 157.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 202.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 247.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 292.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 337.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
// Upper roundover large spheres
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 22.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 67.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 112.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 157.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 202.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 247.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 292.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 337.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
} // End main body hull
// Holes
color("gray") translate ([0, 0, ShaftHeight/2]) rotate ([0, 0, 0]) cylinder (ShaftHeight+2, d = ShaftDiameter, center=true); // Make hole for Shaft
color("blue") translate ([0, 0, ShaftHeight+ThreadedHeight/2]) cylinder (2 + ThreadedHeight, d = ThreadedDiameter, center=true); // Make hole for threaded
color("white") translate ([0, 0, ShaftHeight + ThreadedHeight + LocknutHeight/2]) cylinder (LocknutHeight + 1, d = LocknutDiameter, center=true);
// Make hole for locknut
color("red") translate ([0, 0, BodyHeight]) cylinder (4, d = TopDiameter, center=true);
// Make hole for removable top
color("green") translate ([-9, 0, 0]) cylinder (6, d = 2, center=true);
// Eject pin access hole 1
color("green") translate ([9, 0, 0]) cylinder (6, d = 2, center=true);
// Eject pin access hole 2
color("purple") translate ([-9, 0, BodyHeight/2 + 2]) cylinder (BodyHeight, d = 4, center=true);
// Eject pin hole 1
color("purple") translate ([9, 0, BodyHeight/2 + 2]) cylinder (BodyHeight, d = 4, center=true);
// Eject pin hole 2
} //End difference main body hull minus holes
//
Eject pin (print 2)
LS30_Eject_Pin_Ultimarc.scad
// LS-30 handle for Ultimarc Ikari 12-way Rotary Upgrade
// -- Eject pin (handle requires 2)
// Number of fragments (polygon sides) used to render a full circle.
$fn = 180; // Default = 180 Typical range = 6 - 360
/////////////////////////////
// Make the part
/////////////////////////////
// Make the main body
translate ([0, 0, 15]) cylinder (22, d = 3.8, center=true); // Eject pin body
translate ([0, 0, 2]) cylinder (4, d1 = 3.2, d2 = 3.8, center=true); // Eject pin bottom
translate ([0, 0, 28]) cylinder (4, d1 = 3.8, d2 =3.2, center=true); // Eject pin body
Scott
-
Almost done. ;D
(http://forum.arcadecontrols.com/index.php?action=dlattach;topic=149895.0;attach=371315;image)
Items remaining:
- Print a handle and two pins to confirm two tiny changes.
- Get a 6mm locknut and star washer to confirm, but it looks like there is enough clearance even on a 1.6mm metal panel + 5mm spacers. (panel + spacers = 6.6mm total thickness)
- Review documentation for errors and typos.
I'd greatly appreciate if someone (Deven? :angel:) with a 3d printer and the Ultimarc Upgrade Kit or other Ultimarc 9mm shaft stick can do a test print to check if ShaftDiameter = 9.35 is good default value for a 9mm shaft stick.
-- ShaftDiameter is set on line 21 of LS30_Test_Print_Ultimarc.scad and line 45 of LS30_Handle_Ultimarc.scad.
-- ShaftDiameter = 10.35 works for the 10mm shaft on a Zippyy.
LS30_Test_Print_Ultimarc.scad
// LS-30 handle for Ultimarc Ikari 12-way Rotary Upgrade
// - Test print
// Other prints needed:
// -- Handle
// -- Handle top
// -- Eject pin (2 pins per handle)
// This test print allows you to verify the correct variable values for your specific hardware and your slicer software before you render/export/print the whole handle.
// Hardware tested:
// - Joystick M6 threaded diameter (clears without engaging threads)
// - Joysick shaft diameter (snug fit)
// This part is oriented upside-down compared to the handle so print supports are not needed.
/////////////////////////////
// Define variables
/////////////////////////////
ShaftDiameter = 9.35; // Default = 9.35
ShaftHeight = 9; // Default = 9
ThreadedDiameter = 6.2; // Default = 6.2
// The diameter values may need to be *very slightly* larger to account for the 180-sided polygon used to render circles -- see "undersized holes" at [url]https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Primitive_Solids#cylinder[/url]
$fn=180; // Number of fragments (polygon sides) used to render a circle
/////////////////////////////
// Make the part
/////////////////////////////
// Make the shaft test layer
difference() {
cylinder(ShaftHeight, d=ShaftDiameter+6, center=true); // Shaft outer cylinder
cylinder(ShaftHeight+2, d=ShaftDiameter, center=true);
// Remove Shaft Collar hole
}
//
// Make the thread test layer (red)
difference() {
color("red") translate([0,0,-1 - ShaftHeight/2]) cylinder(2, d=ShaftDiameter + 6, center=true);
// Outer cylinder
translate([0,0,-1 - ShaftHeight/2]) cylinder(ShaftHeight, d=ThreadedDiameter, center=true);
// Remove threaded hole
}
LS30_Handle_Ultimarc.scad
// LS-30 handle for Ultimarc Ikari 12-way Rotary Upgrade
// -- Handle
// Other prints needed:
// -- Test print
// -- Handle top
// -- Eject pin (2 pins per handle)
// Required hardware:
// - 6mm locknut
// - 6mm star washer
/////////////////////////////
// Adjustable variables
/////////////////////////////
// Body
BodyHeight = 35.6; // Default = 35.6
// Height of the body, not including the dome
// Sides
SideRoundSphere = 0.7; // Default = 0.7
// Radius of the side roundover sphere
LowerBodyDiameter = 31.51; // Default = 31.51
// Farthest distance from lower point-to-point edge
UpperBodyDiameter = 29.41; // Default = 29.41
// Farthest distance from upper point-to-point edge
// Bottom octagon
LowerRoundSphere = 1.59; // Default = 1.59
// Radius of the lower roundover sphere
// Top octagon
UpperRoundSphere = 3.18; // Default = 3.18
// Radius of the upper roundover sphere
// Spaces to remove from body
ShaftHeight = 23.8; // Default = 30.4mm - panel thickness. (This formula positions the bottom of the handle 15.6mm above the top of the panel, same as Ikari Warriors.)
// 11.35 for a 3/4" wood panel (19.05mm)
// 23.8 for a 1.6mm metal panel with 5mm spacers (6.6mm)
// Height of the unthreaded shaft cavity
ShaftDiameter = 9.35; // Default = 9.35 for a 9mm shaft
// Diameter of the joystick unthreaded shaft cavity. This value needs to be *very slightly* larger than the actual joystick shaft diameter to allow for the 180-sided polygon used to render circles -- see "undersized holes" at [url]https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Primitive_Solids#cylinder[/url]
ThreadedHeight = 6; // Default = 6
// Height of the thread hole
ThreadedDiameter = 6.2; // Default = 6.2
// Outer diameter of the thread hole
LocknutDiameter = 12; // Default = 12
// Diameter of the locknut cavity. (Height is automatically calculated below.)
PinDistance = 9; // Default =9
// Horizontal distance from handle center to eject pin center
PinDiameter = 4; // Default = 4
// Diameter of the eject pin body
TopDiameter = 22.6; // Default = 22.6
// Hole for removable top.
TopHeight = 2; // Default = 2
// Hole for removable top.
// Number of fragments (polygon sides) used to render a full circle.
$fn = 180; // Default = 180 Typical range = 6 - 360
// 6 will render a circular hole as a hexagon, 8 will render a circular hole as an octagon.
// Lower the number for faster rendering, raise the number for smoother rendering.
/////////////////////////////
// Non-adjustable variables
/////////////////////////////
// Bottom octagon
LowerSmallArccosine = SideRoundSphere * 1.0823922002923939687994464107328;
// Calculates distance from center of lower small sphere to point of lower octagon [radius*acos(22.5)]
LowerLargeArccosine = LowerRoundSphere * 1.0823922002923939687994464107328;
// Calculates distance from point of lower octagon to center of lower large sphere [radius*acos(22.5)]
LowerLargeSphereCenter = LowerBodyDiameter/2 - SideRoundSphere + LowerSmallArccosine - LowerLargeArccosine;
// Rounded octagon point - side (small) sphere radius + distance from center of small sphere to point of octagon - distance from point of octagon to center of large sphere
// Top octagon
UpperSmallArccosine = SideRoundSphere * 1.0823922002923939687994464107328;
// Calculates distance from center of upper small sphere to point of upper octagon [radius*acos(22.5)]
UpperLargeArccosine = UpperRoundSphere * 1.0823922002923939687994464107328;
// Calculates distance from point of upper octagon to center of upper large sphere [radius*acos(22.5)]
UpperLargeSphereCenter = UpperBodyDiameter/2 - SideRoundSphere + UpperSmallArccosine - UpperLargeArccosine;
// Rounded octagon point - side (small) sphere radius + distance from center of small sphere to point of octagon - distance from point of octagon to center of large sphere
// Locknut cavity
LocknutHeight = (BodyHeight - ShaftHeight - ThreadedHeight);
// Height of the locknut cavity
/////////////////////////////
// Make the part
/////////////////////////////
// Make the main body
difference(){ // Main body minus holes
hull() { // Main body hull
// Lower roundover large spheres
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 22.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 67.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 112.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 157.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 202.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 247.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 292.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 337.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
// Lower side small spheres
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 22.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 67.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 112.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 157.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 202.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 247.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 292.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 337.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
// Upper side small spheres
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 22.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere, center = true);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 67.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 112.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 157.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 202.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 247.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 292.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 337.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
// Upper roundover large spheres
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 22.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 67.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 112.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 157.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 202.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 247.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 292.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 337.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
} // End main body hull
// Holes
color("limegreen") translate ([0, 0, ShaftHeight/2]) cylinder (ShaftHeight, d = ShaftDiameter, center=true); // Make hole for Shaft
color("blue") translate ([0, 0, ShaftHeight+ThreadedHeight/2]) cylinder (ThreadedHeight + .001, d = ThreadedDiameter, center=true); // Make hole for threaded
color("white") translate ([0, 0, ShaftHeight + ThreadedHeight + LocknutHeight/2]) cylinder (LocknutHeight + .001, d = LocknutDiameter, center=true);
// Make hole for locknut
color("red") translate ([0, 0, BodyHeight - TopHeight/2]) cylinder (TopHeight, d = TopDiameter, center=true);
// Make hole for removable top
color("aqua") translate ([-PinDistance, 0, 1]) cylinder (2.01, d1 = 3.5, d2 = 2, center=true);
// Eject pin access hole 1
color("aqua") translate ([PinDistance, 0, 1]) cylinder (2.01, d1 = 3.5, d2 = 2, center=true);
// Eject pin access hole 2
color("purple") translate ([-PinDistance, 0, BodyHeight/2 + 2]) cylinder (BodyHeight, d = PinDiameter, center=true);
// Eject pin hole 1
color("purple") translate ([PinDistance, 0, BodyHeight/2 + 2]) cylinder (BodyHeight, d = PinDiameter, center=true);
// Eject pin hole 2
} //End difference main body hull minus holes
//
LS30_Handle_Top_Ultimarc.scad
// LS-30 handle for Ultimarc Ikari 12-way Rotary Upgrade
// -- Handle top
// Other prints needed:
// -- Test print
// -- Handle
// -- Eject pin (2 pins per handle)
// Logo exported from Inkscape to .dxf file using [url]https://github.com/brad/Inkscape-OpenSCAD-DXF-Export[/url]
/////////////////////////////
// Adjustable variables
/////////////////////////////
// Logo
LogoDepth = 1.0; // Default = 1.0
// Logo height above the main body
// Dome
DomeHeight = 0.8; // Default = 0.8
// Dome height above the main body
DomeDiameter = 22; // Default = 22
// This variable is not used to generate the part, but is used to calculate DomeSphereRadius.
DomeSphereRadius = 76.02; // Default = 76.02
// Sphere radius that will generate the desired dome.
// Enter the "Width of Arc" (DomeDiameter) and "Height of Arc" (DomeHeight) into the calculator at http://handymath.com/cgi-bin/arc18mm2.cgi?submit=Entry The resulting "Radius of Arc" = DomeSphereRadius.
// Body
TopHeight = 2; // Default = 2
// Height of the body, not including the dome
TopDiameter = 22.6; // Default = 22.6
// Diameter of the body that fits inside the handle
TopWiggleRoom = 0.65; // Default = 0.65
// Amount to decrease the body diameter for easier insertion/removal of top. It also allows for the 180-sided polygon used to render circles -- see "undersized holes" at [url]https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Primitive_Solids#cylinder[/url]
TopTaper = 0.2; // Default = 0.2
// Amount to reduce the bottom diameter of the body
// Number of fragments (polygon sides) used to render a full circle.
$fn = 180; // Default = 180 Typical range = 6 - 360
// 6 will render a circular hole as a hexagon, 8 will render a circular hole as an octagon.
// Lower the number for faster rendering, raise the number for smoother rendering.
/////////////////////////////
// Make the part
/////////////////////////////
// Make the SNK Logo (Optional)
// Comment out the next three lines to skip the logo
translate([-6, -3, 0])
linear_extrude(height = LogoDepth, convexity = 10)
import(file = "SNK_Logo.dxf", layer="Logo");
// The "SNK_Logo.dxf" file needs to be in the same directory as this SCAD file.
//
// Make the dome
difference(){ // Sphere minus cube
translate([0,0,DomeHeight-DomeSphereRadius]) sphere(r=DomeSphereRadius, center=true); // Sphere
translate([0,0,- DomeSphereRadius]) cube([DomeSphereRadius*2,DomeSphereRadius*2,DomeSphereRadius*2], center=true);
// Cube to cut off bottom of sphere
}
//
// Make the body
translate ([0, 0, -TopHeight/2]) cylinder (TopHeight, d1 = TopDiameter - TopTaper - TopWiggleRoom, d2 = TopDiameter - TopWiggleRoom, center=true);
//
LS30_Eject_Pin_Ultimarc.scad
// LS-30 handle for Ultimarc Ikari 12-way Rotary Upgrade
// -- Eject pin (2 pins per handle)
// Other prints needed:
// -- Test print
// -- Handle
// -- Handle top
/////////////////////////////
// Adjustable variables
/////////////////////////////
PinHeight = 30; // Default = 30
// Height of the whole pin
TaperHeight = 2; // Default = 2
// Height of the taper on each end
PinDiameter = 4; // Default = 4
// Diameter of the eject pin body
TaperDiameter = 3.2; // Default = 3.2
// Diameter of the pin tips
PinWiggleRoom = 0.5; // Default = 0.5
// Amount to decrease pin diameter and tips for easier insertion/removal. It also allows for the 180-sided polygon used to render circles -- see "undersized holes" at [url]https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Primitive_Solids#cylinder[/url]
// Number of fragments (polygon sides) used to render a full circle.
$fn = 180; // Default = 180 Typical range = 6 - 360
/////////////////////////////
// Make the part
/////////////////////////////
// Make the first pin
translate ([0, 0, PinHeight/2]) cylinder (PinHeight - TaperHeight*2, d = PinDiameter - PinWiggleRoom, center=true);
// Eject pin body 1
translate ([0, 0, TaperHeight/2]) cylinder (TaperHeight, d1 = TaperDiameter - PinWiggleRoom, d2 = PinDiameter - PinWiggleRoom, center=true);
// Eject pin bottom 1
translate ([0, 0, PinHeight - TaperHeight/2]) cylinder (TaperHeight, d1 = PinDiameter - PinWiggleRoom, d2 = TaperDiameter - PinWiggleRoom, center=true);
// Eject pin top 1
// Make the second pin
translate ([0, PinDiameter * 2, PinHeight/2]) cylinder (PinHeight - TaperHeight*2, d = PinDiameter - PinWiggleRoom, center=true);
// Eject pin body 2
translate ([0, PinDiameter * 2, TaperHeight/2]) cylinder (TaperHeight, d1 = TaperDiameter - PinWiggleRoom, d2 = PinDiameter - PinWiggleRoom, center=true);
// Eject pin bottom 2
translate ([0, PinDiameter * 2, PinHeight - TaperHeight/2]) cylinder (TaperHeight, d1 = PinDiameter - PinWiggleRoom, d2 = TaperDiameter - PinWiggleRoom, center=true);
// Eject pin top 2
Scott
EDIT: Updated LS30_Eject_Pin_Ultimarc.scad to generate two pins instead of just one.
-
Lots of good work here! I have the upgrade and servo stick in hand. Need to find some sample mounting panels and will try your test print.
-
Lots of good work here! I have the upgrade and servo stick in hand. Need to find some sample mounting panels and will try your test print.
Thanks. :cheers:
You don't need mounting panels for the test print. (LS30_Test_Print_Ultimarc.scad)
It's just a small cylinder (15.35mm diameter x 11 mm high) that lets you test different values for ShaftDiameter (yellow part) and ThreadedDiameter (red part) without printing a whole handle.
- Test print = 0.44 meters / 1 gram of filament
- Handle = 3.96 meters / 12 grams of filament
(http://forum.arcadecontrols.com/index.php?action=dlattach;topic=149895.0;attach=371322)
Scott
-
Did a super rough print. The inner diameter has enough play that you can wiggle it back and forth. Im thinking bringing it down to maybe 9.15-9.20 would be enough so it doesn't have much play but still slides on and off.
****JUST NOTICED THE TEST IS DIFFERENT FROM THE ACTUAL ONE****
(https://i.imgur.com/gWlo3Bx.jpg?1)
(https://i.imgur.com/ITCD91x.jpg)
(https://i.imgur.com/iICuvPQ.jpg)
I printed it at .2 mm layer height, the top part gets a little rough. Im not sure if adding the cap would help smooth it out. Might try doing .1mm layer height to smooth it out but adds another hour to the print.
Also the bottom curve had to much overhang, printing at .1mm might fix that.
(http://forum.arcadecontrols.com/index.php?action=dlattach;topic=149895.0;attach=371323;image)
I need to get some hardware from the store, printing another one out with other settings. Need more top layers, 2 was not enough.
-
Did a super rough print. The inner diameter has enough play that you can wiggle it back and forth. Im thinking bringing it down to maybe 9.15-9.20 would be enough so it doesn't have much play but still slides on and off.
Yeah, there are lots of little tweaks to the variables that will dial-in these prints for your slicer/firmware-settings/printer.
A firmware setting that I changed on my printer possibly causes it to over-extrude by about 4-6%.
Once you get a good clean print for the handle, it's easy to adjust variables and reprint the smaller pin and handle top prints to fit the handle.
You can probably reduce the "WiggleRoom" variables in the eject pin and handle top OpenSCAD files.
I printed it at .2 mm layer height, the top part gets a little rough. Im not sure if adding the cap would help smooth it out. Might try doing .1mm layer height to smooth it out but adds another hour to the print.
Also the bottom curve had to much overhang, printing at .1mm might fix that.
The overhang on the bottom prints OK here. :dunno
The cap should help to smooth the top, but you might also want to slightly reduce TopDiameter so you get a circle connecting the inside of the top layer's 8 triangles. (red circle)
(http://forum.arcadecontrols.com/index.php?action=dlattach;topic=149895.0;attach=371323;image)
If you do that, you might also need to reduce PinDistance. (handle file, line 57)
Scott
-
Wowwww! :o
-
Wowwww! :o
Thanks. :cheers:
I've been working on the design and here's a change that will keep the handle from turning separately from the shaft when the friction between the shaft, handle, and nut isn't high enough.
Instead of using a cylindrical cavity for a socket or nut-driver, use a hexagonal cavity so the handle is the nut-driver for tightening the locknut.
- Use cardboard padded vise-grips to keep the shaft from turning while installing the handle and locknut
A locknut won't easily spin off the threads and with this design change the handle can't turn without also turning the locknut and shaft.
Here's a test print to verify that the hexagonal cavity is a snug fit for the locknut . . .
LS30_Test_Print2_Ultimarc.scad
// LS-30 handle for Ultimarc Ikari 12-way Rotary Upgrade
// - Test print 2
// Other prints needed:
// -- Handle
// -- Handle top
// -- Eject pin (2 pins per handle)
// This test print allows you to verify the correct variable values for your specific hardware and your slicer software before you render/export/print the whole handle.
// Hardware tested:
// - Joystick M6 threaded diameter (clears without engaging threads)
// - Locknut (snug fit)
/////////////////////////////
// Define variables
/////////////////////////////
LocknutDiameter = 11.65; // Default = 11.55 + wiggle room
// 10mm flat-to-flat = 11.55mm point-to-point
LocknutHeight = 9; // Default = 9
ThreadedDiameter = 6.2; // Default = 6.2
// The diameter values may need to be *very slightly* larger to account for the 180-sided polygon used to render circles -- see "undersized holes" at [url]https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Primitive_Solids#cylinder[/url]
$fn=180; // Number of fragments (polygon sides) used to render a circle
/////////////////////////////
// Make the part
/////////////////////////////
// Make the locknut test layer
difference() {
hull() { // Make outer hexagon
rotate ([0, 0, 0]) translate ([3 + LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight, d = 0.01, center=true);
rotate ([0, 0, 60]) translate ([3 + LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight, d = 0.01, center=true);
rotate ([0, 0, 120]) translate ([3 + LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight, d = 0.01, center=true);
rotate ([0, 0, 180]) translate ([3 + LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight, d = 0.01, center=true);
rotate ([0, 0, 240]) translate ([3 + LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight, d = 0.01, center=true);
rotate ([0, 0, 300]) translate ([3 + LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight, d = 0.01, center=true);
}
hull() { // Remove inner hexagon
translate ([0, 0, 0])
rotate ([0, 0, 0]) translate ([LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight + 0.01, d = 0.01, center=true);
translate ([0, 0, 0])
rotate ([0, 0, 60]) translate ([LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight + 0.01, d = 0.01, center=true);
translate ([0, 0, 0])
rotate ([0, 0, 120]) translate ([LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight + 0.01, d = 0.01, center=true);
translate ([0, 0, 0])
rotate ([0, 0, 180]) translate ([LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight + 0.01, d = 0.01, center=true);
translate ([0, 0, 0])
rotate ([0, 0, 240]) translate ([LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight + 0.01, d = 0.01, center=true);
translate ([0, 0, 0])
rotate ([0, 0, 300]) translate ([LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight + 0.01, d = 0.01, center=true);
}
}
//
// Make the thread test layer (red)
difference() {
color("red") translate([0,0,-1 - LocknutHeight/2]) cylinder(2, d=LocknutDiameter + 6, center=true);
// Outer cylinder
translate([0,0,-1 - LocknutHeight/2]) cylinder(LocknutHeight, d=ThreadedDiameter, center=true);
// Remove threaded hole
}
(http://forum.arcadecontrols.com/index.php?action=dlattach;topic=149895.0;attach=372349)
. . . and here's the updated handle code.
LS30_Handle_Ultimarc.scad
// LS-30 handle for Ultimarc Ikari 12-way Rotary Upgrade
// -- Handle
// Other prints needed:
// -- Test print
// -- Test print 2
// -- Handle top
// -- Eject pin (2 pins per handle)
// Required hardware:
// - 6mm locknut
/////////////////////////////
// Adjustable variables
/////////////////////////////
// Body
BodyHeight = 35.6; // Default = 35.6
// Height of the body, not including the dome
// Sides
SideRoundSphere = 0.7; // Default = 0.7
// Radius of the side roundover sphere
LowerBodyDiameter = 31.51; // Default = 31.51
// Farthest distance from lower point-to-point edge
UpperBodyDiameter = 29.41; // Default = 29.41
// Farthest distance from upper point-to-point edge
// Bottom octagon
LowerRoundSphere = 1.59; // Default = 1.59
// Radius of the lower roundover sphere
// Top octagon
UpperRoundSphere = 3.18; // Default = 3.18
// Radius of the upper roundover sphere
// Spaces to remove from body
ShaftHeight = 23.8; // Default = 30.4mm - panel thickness. (This formula positions the bottom of the handle 15.6mm above the top of the panel, same as Ikari Warriors.)
// 11.35 for a 3/4" wood panel (19.05mm)
// 23.8 for a 1.6mm metal panel with 5mm spacers (6.6mm)
// Height of the unthreaded shaft cavity
ShaftDiameter = 9.35; // Default = 9.35 for a 9mm shaft
// Diameter of the joystick unthreaded shaft cavity. This value needs to be *very slightly* larger than the actual joystick shaft diameter to allow for the 180-sided polygon used to render circles -- see "undersized holes" at [url]https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Primitive_Solids#cylinder[/url]
ThreadedHeight = 6; // Default = 6
// Height of the thread hole
ThreadedDiameter = 6.2; // Default = 6.2
// Outer diameter of the thread hole
LocknutDiameter = 11.65; // Default = 11.55 + wiggle room
// 10mm flat-to-flat = 11.55mm point-to-point
// (Height is automatically calculated below.)
PinDistance = 9.3; // Default = 9.3
// Horizontal distance from handle center to eject pin center
PinDiameter = 4; // Default = 4
// Diameter of the eject pin body
TopDiameter = 22.6; // Default = 22.6
// Hole for removable top.
TopHeight = 2; // Default = 2
// Hole for removable top.
// Number of fragments (polygon sides) used to render a full circle.
$fn = 180; // Default = 180 Typical range = 6 - 360
// 6 will render a circular hole as a hexagon, 8 will render a circular hole as an octagon.
// Lower the number for faster rendering, raise the number for smoother rendering.
/////////////////////////////
// Non-adjustable variables
/////////////////////////////
// Bottom octagon
LowerSmallArccosine = SideRoundSphere * 1.0823922002923939687994464107328;
// Calculates distance from center of lower small sphere to point of lower octagon [radius*acos(22.5)]
LowerLargeArccosine = LowerRoundSphere * 1.0823922002923939687994464107328;
// Calculates distance from point of lower octagon to center of lower large sphere [radius*acos(22.5)]
LowerLargeSphereCenter = LowerBodyDiameter/2 - SideRoundSphere + LowerSmallArccosine - LowerLargeArccosine;
// Rounded octagon point - side (small) sphere radius + distance from center of small sphere to point of octagon - distance from point of octagon to center of large sphere
// Top octagon
UpperSmallArccosine = SideRoundSphere * 1.0823922002923939687994464107328;
// Calculates distance from center of upper small sphere to point of upper octagon [radius*acos(22.5)]
UpperLargeArccosine = UpperRoundSphere * 1.0823922002923939687994464107328;
// Calculates distance from point of upper octagon to center of upper large sphere [radius*acos(22.5)]
UpperLargeSphereCenter = UpperBodyDiameter/2 - SideRoundSphere + UpperSmallArccosine - UpperLargeArccosine;
// Rounded octagon point - side (small) sphere radius + distance from center of small sphere to point of octagon - distance from point of octagon to center of large sphere
// Locknut cavity
LocknutHeight = (BodyHeight - ShaftHeight - ThreadedHeight);
// Height of the locknut cavity
/////////////////////////////
// Make the part
/////////////////////////////
// Make the main body
difference(){ // Main body minus holes
hull() { // Main body hull
// Lower roundover large spheres
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 22.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 67.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 112.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 157.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 202.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 247.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 292.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 337.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
// Lower side small spheres
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 22.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 67.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 112.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 157.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 202.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 247.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 292.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 337.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
// Upper side small spheres
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 22.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere, center = true);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 67.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 112.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 157.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 202.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 247.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 292.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 337.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
// Upper roundover large spheres
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 22.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 67.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 112.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 157.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 202.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 247.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 292.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 337.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
} // End main body hull
// Holes
color("limegreen") translate ([0, 0, ShaftHeight/2]) cylinder (ShaftHeight, d = ShaftDiameter, center=true); // Make hole for Shaft
color("blue") translate ([0, 0, ShaftHeight+ThreadedHeight/2]) cylinder (ThreadedHeight + .001, d = ThreadedDiameter, center=true); // Make hole for threaded
color("white") hull() { // Locknut hexagon hull
translate ([0, 0, ShaftHeight + ThreadedHeight + LocknutHeight/2])
rotate ([0, 0, 0]) translate ([LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight + 0.01, d = 0.01, center=true);
translate ([0, 0, ShaftHeight + ThreadedHeight + LocknutHeight/2])
rotate ([0, 0, 60]) translate ([LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight + 0.01, d = 0.01, center=true);
translate ([0, 0, ShaftHeight + ThreadedHeight + LocknutHeight/2])
rotate ([0, 0, 120]) translate ([LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight + 0.01, d = 0.01, center=true);
translate ([0, 0, ShaftHeight + ThreadedHeight + LocknutHeight/2])
rotate ([0, 0, 180]) translate ([LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight + 0.01, d = 0.01, center=true);
translate ([0, 0, ShaftHeight + ThreadedHeight + LocknutHeight/2])
rotate ([0, 0, 240]) translate ([LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight + 0.01, d = 0.01, center=true);
translate ([0, 0, ShaftHeight + ThreadedHeight + LocknutHeight/2])
rotate ([0, 0, 300]) translate ([LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight + 0.01, d = 0.01, center=true);
}
// Make hole for locknut
color("red") translate ([0, 0, BodyHeight - TopHeight/2]) cylinder (TopHeight, d = TopDiameter, center=true);
// Make hole for removable top
color("aqua") translate ([-PinDistance, 0, 1]) cylinder (2.01, d1 = 3.5, d2 = 2, center=true);
// Eject pin access hole 1
color("aqua") translate ([PinDistance, 0, 1]) cylinder (2.01, d1 = 3.5, d2 = 2, center=true);
// Eject pin access hole 2
color("purple") translate ([-PinDistance, 0, BodyHeight/2 + 2]) cylinder (BodyHeight, d = PinDiameter, center=true);
// Eject pin hole 1
color("purple") translate ([PinDistance, 0, BodyHeight/2 + 2]) cylinder (BodyHeight, d = PinDiameter, center=true);
// Eject pin hole 2
} //End difference main body hull minus holes
//
(http://forum.arcadecontrols.com/index.php?action=dlattach;topic=149895.0;attach=372350)
There are still some details to confirm, but things appear to be on the right track. ;D
Scott
-
Looks great. Is there a possibility that one of you guys will run off a batch and offer them for sale once this is dialed in?
-
Looks great. Is there a possibility that one of you guys will run off a batch and offer them for sale once this is dialed in?
Thanks. :cheers:
I do not plan to sell them.
Haven't discussed it with him yet, but if Andy is interested he can either print them himself or sub-contract to a 3rd party.
If Andy is not interested, another possible option is enabling one or more apps on Thingiverse so a 3rd party can print them.
Has anyone used the apps on Thingiverse to print something?
If you have, which app(s) would you recommend?
Scott
-
I have a 3D Hubs (https://www.3dhubs.com) account but have yet to get any jobs to print. I am getting a SLA or DLP printer soon and will be curious to see how well these turn out.
-
The hexagon cavity design works great with an M6-1.0 (coarse thread) nylon-insert locknut like this one (https://www.menards.com/main/tools-hardware/fasteners-fastener-accessories/nuts/lock-nuts/midwest-fastener-reg-6mm-1-00-grade-18-8-stainless-steel-nylon-insert-lock-nut-1-count/87534/p-1444440177418-c-8919.htm?searchTermToProduct=87534). ;D
As expected, the handle works perfectly as a nutdriver when you use cardboard padded vise-grips to keep the shaft from turning during installation/removal of the handle and locknut.
(http://forum.arcadecontrols.com/index.php?action=dlattach;topic=149895.0;attach=375542;image)
(http://forum.arcadecontrols.com/index.php?action=dlattach;topic=149895.0;attach=375544;image)
-------------
Other than the few remaining adjusments listed at the end of this post, the code below should be solid.
If anyone has a 3d printer and the Ultimarc 12-way rotary kit, please test-print a copy to verify.
- Set the ShaftHeight variable (line 40) to 30.4mm minus your panel thickness.
CRITICAL MEASUREMENT: ShaftHeight + ThreadedHeight must be <= 27.8 to allow enough room for the locknut under the top
LS30_Handle_Ultimarc.scad
// LS-30 handle for Ultimarc Ikari 12-way Rotary Upgrade
// -- Handle
// Other prints needed:
// -- Test print
// -- Test print 2
// -- Handle top
// -- Eject pin (2 pins per handle)
// Required hardware:
// - M6 locknut (M6-1.0mm thread)
/////////////////////////////
// Adjustable variables
/////////////////////////////
// Body
BodyHeight = 35.6; // Default = 35.6
// Height of the body, not including the dome
// Sides
SideRoundSphere = 0.7; // Default = 0.7
// Radius of the side roundover sphere
LowerBodyDiameter = 31.51; // Default = 31.51
// Farthest distance from lower point-to-point edge
UpperBodyDiameter = 29.41; // Default = 29.41
// Farthest distance from upper point-to-point edge
// Bottom octagon
LowerRoundSphere = 1.59; // Default = 1.59
// Radius of the lower roundover sphere
// Top octagon
UpperRoundSphere = 3.18; // Default = 3.18
// Radius of the upper roundover sphere
// Spaces to remove from body
ShaftHeight = 21.8; // Default = 30.4mm - panel thickness. (This formula positions the bottom of the handle 15.6mm above the top of the panel, same as Ikari Warriors.)
// 11.35 for a 3/4" wood panel (19.05mm)
// 21.8 for a 1.6mm metal panel with 7mm spacers (8.6mm)
// CRITICAL MEASUREMENT: ShaftHeight + ThreadedHeight must be <= 27.8 to allow enough room for the locknut under the top
// Height of the unthreaded shaft cavity
ShaftDiameter = 9.35; // Default = 9.35 for a 9mm shaft
// Diameter of the joystick unthreaded shaft cavity. This value needs to be *very slightly* larger than the actual joystick shaft diameter to allow for the 180-sided polygon used to render circles -- see "undersized holes" at [url]https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Primitive_Solids#cylinder[/url]
ThreadedHeight = 6; // Default = 6
// CRITICAL MEASUREMENT: ShaftHeight + ThreadedHeight must be <= 27.8 to allow enough room for the locknut under the top
// Height of the thread hole
ThreadedDiameter = 6.2; // Default = 6.2
// Outer diameter of the thread hole
LocknutDiameter = 11.65; // Default = 11.55 + wiggle room
// 10mm flat-to-flat = 11.55mm point-to-point
// (Height is automatically calculated below.)
PinDistance = 9; // Default = 9
// Horizontal distance from handle center to eject pin center
PinDiameter = 4; // Default = 4
// Diameter of the eject pin body
TopDiameter = 22.6; // Default = 22.6
// Hole for removable top.
TopHeight = 2; // Default = 2
// Hole for removable top.
// Number of fragments (polygon sides) used to render a full circle.
$fn = 180; // Default = 180 Typical range = 6 - 360
// 6 will render a circular hole as a hexagon, 8 will render a circular hole as an octagon.
// Lower the number for faster rendering, raise the number for smoother rendering.
/////////////////////////////
// Non-adjustable variables
/////////////////////////////
// Bottom octagon
LowerSmallArccosine = SideRoundSphere * 1.0823922002923939687994464107328;
// Calculates distance from center of lower small sphere to point of lower octagon [radius*acos(22.5)]
LowerLargeArccosine = LowerRoundSphere * 1.0823922002923939687994464107328;
// Calculates distance from point of lower octagon to center of lower large sphere [radius*acos(22.5)]
LowerLargeSphereCenter = LowerBodyDiameter/2 - SideRoundSphere + LowerSmallArccosine - LowerLargeArccosine;
// Rounded octagon point - side (small) sphere radius + distance from center of small sphere to point of octagon - distance from point of octagon to center of large sphere
// Top octagon
UpperSmallArccosine = SideRoundSphere * 1.0823922002923939687994464107328;
// Calculates distance from center of upper small sphere to point of upper octagon [radius*acos(22.5)]
UpperLargeArccosine = UpperRoundSphere * 1.0823922002923939687994464107328;
// Calculates distance from point of upper octagon to center of upper large sphere [radius*acos(22.5)]
UpperLargeSphereCenter = UpperBodyDiameter/2 - SideRoundSphere + UpperSmallArccosine - UpperLargeArccosine;
// Rounded octagon point - side (small) sphere radius + distance from center of small sphere to point of octagon - distance from point of octagon to center of large sphere
// Locknut cavity
LocknutHeight = (BodyHeight - ShaftHeight - ThreadedHeight);
// Height of the locknut cavity
/////////////////////////////
// Make the part
/////////////////////////////
// Make the main body
difference(){ // Main body minus holes
hull() { // Main body hull
// Lower roundover large spheres
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 22.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 67.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 112.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 157.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 202.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 247.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 292.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 337.5]) translate ([LowerLargeSphereCenter, 0, LowerRoundSphere/2]) sphere (r = LowerRoundSphere);
// Lower side small spheres
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 22.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 67.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 112.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 157.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 202.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 247.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 292.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, LowerRoundSphere/2])
rotate ([0, 0, 337.5]) translate ([-SideRoundSphere + LowerBodyDiameter/2, 0, LowerRoundSphere/2]) sphere (r = SideRoundSphere);
// Upper side small spheres
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 22.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere, center = true);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 67.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 112.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 157.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 202.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 247.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 292.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 337.5]) translate ([-SideRoundSphere + UpperBodyDiameter/2, 0, - UpperRoundSphere/2]) sphere (r = SideRoundSphere);
// Upper roundover large spheres
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 22.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 67.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 112.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 157.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 202.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 247.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 292.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
translate ([0, 0, BodyHeight - UpperRoundSphere/2])
rotate ([0, 0, 337.5]) translate ([UpperLargeSphereCenter, 0, - UpperRoundSphere/2]) sphere (r = UpperRoundSphere);
} // End main body hull
// Holes
color("limegreen") translate ([0, 0, ShaftHeight/2]) cylinder (ShaftHeight, d = ShaftDiameter, center=true); // Make hole for Shaft
color("blue") translate ([0, 0, ShaftHeight+ThreadedHeight/2]) cylinder (ThreadedHeight + .001, d = ThreadedDiameter, center=true); // Make hole for threaded
color("white") hull() { // Locknut hexagon hull
translate ([0, 0, ShaftHeight + ThreadedHeight + LocknutHeight/2])
rotate ([0, 0, 0]) translate ([LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight + 0.01, d = 0.01, center=true);
translate ([0, 0, ShaftHeight + ThreadedHeight + LocknutHeight/2])
rotate ([0, 0, 60]) translate ([LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight + 0.01, d = 0.01, center=true);
translate ([0, 0, ShaftHeight + ThreadedHeight + LocknutHeight/2])
rotate ([0, 0, 120]) translate ([LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight + 0.01, d = 0.01, center=true);
translate ([0, 0, ShaftHeight + ThreadedHeight + LocknutHeight/2])
rotate ([0, 0, 180]) translate ([LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight + 0.01, d = 0.01, center=true);
translate ([0, 0, ShaftHeight + ThreadedHeight + LocknutHeight/2])
rotate ([0, 0, 240]) translate ([LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight + 0.01, d = 0.01, center=true);
translate ([0, 0, ShaftHeight + ThreadedHeight + LocknutHeight/2])
rotate ([0, 0, 300]) translate ([LocknutDiameter/2, 0, 0]) cylinder (LocknutHeight + 0.01, d = 0.01, center=true);
}
// Make hole for locknut
color("red") translate ([0, 0, BodyHeight - TopHeight/2]) cylinder (TopHeight, d = TopDiameter, center=true);
// Make hole for removable top
color("aqua") translate ([0, -PinDistance, 1]) cylinder (2.01, d1 = 3.5, d2 = 2, center=true);
// Eject pin access hole 1
color("aqua") translate ([0, PinDistance, 1]) cylinder (2.01, d1 = 3.5, d2 = 2, center=true);
// Eject pin access hole 2
color("purple") translate ([0, -PinDistance, BodyHeight/2 + 2]) cylinder (BodyHeight, d = PinDiameter, center=true);
// Eject pin hole 1
color("purple") translate ([0, PinDistance, BodyHeight/2 + 2]) cylinder (BodyHeight, d = PinDiameter, center=true);
// Eject pin hole 2
} //End difference main body hull minus holes
//
Things left to do:
- Reposition the eject pins Done
- Re-size the removable top diameter so the handle's top layer doesn't have those 8 points
- Review/clarify the code documentation
- Write a step-by-step tutorial
- Compile handle .STLs for common panel thicknesses (3/4", 5/8", 1/2", 18mm, 15mm, and 12mm)
-- Are these the most commonly available metric lumber sizes? Any other sizes?
- Post everything on Thingiverse (the handle .STLs are too large to upload here :( )
Scott
-
I'm about to place an Ultimarc order for a pair of J-Stiks and the 12-way Rotary kits for J-Stik, so I am also very interested in either purchasing a set of finished handles from a 3rd party, or providing specs to a company that can print the parts out.
I've been lurking back and forth in this thread for a little while, and am looking forward to the finished product. Is there an update to this project?
-
I'm about to place an Ultimarc order for a pair of J-Stiks and the 12-way Rotary kits for J-Stik, so I am also very interested in either purchasing a set of finished handles from a 3rd party, or providing specs to a company that can print the parts out.
I've been lurking back and forth in this thread for a little while, and am looking forward to the finished product. Is there an update to this project?
Thanks for your interest and encouragement. :cheers:
There isn't much left to do, but I've been a bit sidetracked between projects around the house, helping Saint with the new server to-do list :) and dealing with a relatively high-volume three-week-long spam-account-creation attack. :angry:
I hope to find better default values for the TopDiameter, TopWiggleRoom, and TopTaper variables in the next week or two.
Once those are dialed-in, the rest should fall into place pretty quickly. ;D
Scott
-
Thank you for the prompt reply Scott, and I really appreciate that you're still finding time to devote to this project. We all look forward to the final solution. :applaud:
My Ultimarc order should be in next week, so let me know if there's anything I can do to help. :)
-
Just installed a J-stick with rotary mod last night. Super excited to see this project! Would love a handle or two!
-
Just installed a J-stick with rotary mod last night. Super excited to see this project!
Thanks for your interest and encouragement. :cheers:
Would love a handle or two!
Print as many as you'd like. ;)
Scott