| Main > Project Announcements |
| 3d printed or CNC milled mounting plate for Ultimarc ServoStik |
| (1/3) > >> |
| PL1:
Like the title says, this is the thread for developing and testing a 3d printed or CNC milled ServoStik mounting plate and spacers for use with the "Under mount (support blocks)" method described here in the wiki. Anyone who wants to join in, grab a copy of OpenSCAD and bookmark the OpenSCAD cheatsheet to help you with the commands and syntax. ;D --------------------- Gilrock came up with the original plate design and measurements. He fabricated some here in his build thread. DXF file: http://www.threebuttes.com/Extras/mame/JoystickPlate.dxf The original design used this hardware. I made parametric 3d models for the plate and spacers based on Gilrock's measurements. - Your choice whether to use threaded spacers like the original or 3d printed spacers with four #8 screws and locknuts. - In addition to generating the models, OpenSCAD uses echo commands to show key measurements that you may find useful. OpenSCAD code for the plate: --- Code: ---// ServoStik Mount Plate v1 // Original plate design and measurements by Gilrock // 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 //////////////////////////////////////////// // // Variables: // //////////////////////////////////////////// PlateThick = 2.4; // Mount plate thickness PlateX = 102; // Plate body width PlateY = 85.5; // Plate body length TabCornerDia = 3; // Tab corner rounding diameter InsideCornerDia = 6; // Inside corner rounding diameter or bit diameter for CNC milling TTabX = 15.92; // T-Tab width TTabY = 13.61; // T-Tab length HTabX = 15.92; // H-Tab width HTabY = 13.61; // H-Tab length ServoStikBodyX = 68.5; // ServoStik body width ServoStikBodyY = 68.5; // ServoStik body length PlateScrewHoleDia = 5; // Plate screw hole diameter PlateScrewHoleX = 77.5; // X-axis distance between plate screw holes PlateScrewHoleY = 68.5; // Y-axis distance between plate screw holes MountScrewHoleDia = 5; // Mount tab screw hole diameter TTabScrewXOffset = 0.965; // Screw hole X-axis offset from center of T-Tab, increase to move away from center, decrease to move toward center HTabScrewYOffset = 0.445; // Screw hole Y-axis offset from center of H-Tab, increase to move away from center, decrease to move toward center // 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. //////////////////////////////////////////// // // Automatically calculated variables: // //////////////////////////////////////////// TTabScrewX = PlateX/2 + TTabX/2 + TTabScrewXOffset; // X-axis position of T-Tab screw hole TTabScrewY = PlateY/2 - TTabY/2; // Y-axis position of T-Tab screw hole HTabScrewX = PlateX/2 - HTabX/2; // X-axis position of H-Tab screw hole HTabScrewY = - PlateY/2 - HTabY/2 - HTabScrewYOffset; // Y-axis position of H-Tab screw hole //////////////////////////////////////////// // // Make the part: // //////////////////////////////////////////// difference(){ // Mount plate body union minus holes union(){ // Plate body union cube ([PlateX, PlateY, PlateThick], center=true); // Center plate body hull() { // T-tab body hull translate ([PlateX/2 + TTabX - TabCornerDia/2, PlateY/2 - TabCornerDia/2, 0]) cylinder (PlateThick, d = TabCornerDia, center=true); // Upper right corner translate ([PlateX/2 + TTabX - TabCornerDia/2, PlateY/2 - TTabY + TabCornerDia/2, 0]) cylinder (PlateThick, d = TabCornerDia, center=true); // Lower right corner translate ([-PlateX/2 - TTabX + TabCornerDia/2, PlateY/2 - TTabY + TabCornerDia/2, 0]) cylinder (PlateThick, d = TabCornerDia, center=true); // Lower left corner translate ([-PlateX/2 - TTabX + TabCornerDia/2, PlateY/2 - TabCornerDia/2, 0]) cylinder (PlateThick, d = TabCornerDia, center=true); // Upper left corner } // End T-tab body hull // hull() { // Right H-tab body hull translate ([PlateX/2 - TabCornerDia/2, - PlateY/2 + TabCornerDia/2, 0]) cylinder (PlateThick, d = TabCornerDia, center=true); // Upper right corner translate ([PlateX/2 - TabCornerDia/2, - PlateY/2 - HTabY + TabCornerDia/2, 0]) cylinder (PlateThick, d = TabCornerDia, center=true); // Lower right corner translate ([PlateX/2 - HTabX + TabCornerDia/2, - PlateY/2 - HTabY + TabCornerDia/2, 0]) cylinder (PlateThick, d = TabCornerDia, center=true); // Lower left corner translate ([PlateX/2 - HTabX + TabCornerDia/2, - PlateY/2 + TabCornerDia/2, 0]) cylinder (PlateThick, d = TabCornerDia, center=true); // Upper left corner } // End right H-tab body hull // hull() { // Left H-tab body hull translate ([-PlateX/2 + TabCornerDia/2, - PlateY/2 + TabCornerDia/2, 0]) cylinder (PlateThick, d = TabCornerDia, center=true); // Upper left corner translate ([-PlateX/2 + TabCornerDia/2, - PlateY/2 - HTabY + TabCornerDia/2, 0]) cylinder (PlateThick, d = TabCornerDia, center=true); // Lower left corner translate ([-PlateX/2 + HTabX - TabCornerDia/2, - PlateY/2 - HTabY + TabCornerDia/2, 0]) cylinder (PlateThick, d = TabCornerDia, center=true); // Lower right corner translate ([-PlateX/2 + HTabX - TabCornerDia/2, - PlateY/2 + TabCornerDia/2, 0]) cylinder (PlateThick, d = TabCornerDia, center=true); // Upper right corner } // End left H-tab body hull // } // End plate body union // // Holes to remove from plate body union cube ([ServoStikBodyX, ServoStikBodyY, PlateThick + 1], center=true); // ServoStik body hole translate ([ServoStikBodyX/2, ServoStikBodyY/2, 0]) rotate ([0, 0, 45]) translate ([-InsideCornerDia/2, 0, 0]) cylinder (PlateThick + 1, d = InsideCornerDia, center=true); // Upper right corner rounding for Servostik body hole translate ([ServoStikBodyX/2, -ServoStikBodyY/2, 0]) rotate ([0, 0, 315]) translate ([-InsideCornerDia/2, 0, 0]) cylinder (PlateThick + 1, d = InsideCornerDia, center=true); // Lower right corner rounding for Servostik body hole translate ([-ServoStikBodyX/2, -ServoStikBodyY/2, 0]) rotate ([0, 0, 225]) translate ([-InsideCornerDia/2, 0, 0]) cylinder (PlateThick + 1, d = InsideCornerDia, center=true); // Lower left corner rounding for Servostik body hole translate ([-ServoStikBodyX/2, ServoStikBodyY/2, 0]) rotate ([0, 0, 135]) translate ([-InsideCornerDia/2, 0, 0]) cylinder (PlateThick + 1, d = InsideCornerDia, center=true); // Upper left corner rounding for Servostik body hole translate ([PlateScrewHoleX/2, PlateScrewHoleY/2, 0]) cylinder (PlateThick + 1, d = PlateScrewHoleDia, center=true); // Upper right plate screw hole translate ([PlateScrewHoleX/2, -PlateScrewHoleY/2, 0]) cylinder (PlateThick + 1, d = PlateScrewHoleDia, center=true); // Lower right plate screw hole translate ([-PlateScrewHoleX/2, -PlateScrewHoleY/2, 0]) cylinder (PlateThick + 1, d = PlateScrewHoleDia, center=true); // Lower left plate screw hole translate ([-PlateScrewHoleX/2, PlateScrewHoleY/2, 0]) cylinder (PlateThick + 1, d = PlateScrewHoleDia, center=true); // Upper left plate screw hole translate ([TTabScrewX, TTabScrewY, 0]) cylinder (PlateThick + 1, d = MountScrewHoleDia, center=true); // Upper right T-Tab screw hole translate ([-TTabScrewX, TTabScrewY, 0]) cylinder (PlateThick + 1, d = MountScrewHoleDia, center=true); // Upper left T-Tab screw hole translate ([HTabScrewX, HTabScrewY, 0]) cylinder (PlateThick + 1, d = MountScrewHoleDia, center=true); // Lower right H-Tab screw hole translate ([-HTabScrewX, HTabScrewY, 0]) cylinder (PlateThick + 1, d = MountScrewHoleDia, center=true); // Lower left H-Tab screw hole } // End mount plate body union minus holes // // Add the inside corners next to the tabs difference(){ // Inside corner by upper right tab translate ([PlateX/2 + InsideCornerDia/4, PlateY/2 - TTabY - InsideCornerDia/4, 0]) cube ([InsideCornerDia/2, InsideCornerDia/2, PlateThick], center=true); // Cube translate ([PlateX/2 + InsideCornerDia/2, PlateY/2 - TTabY - InsideCornerDia/2, 0]) cylinder (PlateThick + 1, d = InsideCornerDia, center=true); // Minus cylnder } // End inside corner by upper right tab // difference(){ // Inside corner by lower right tab translate ([PlateX/2 - HTabX - InsideCornerDia/4, - PlateY/2 - InsideCornerDia/4, 0]) cube ([InsideCornerDia/2, InsideCornerDia/2, PlateThick], center=true); // Cube translate ([PlateX/2 - HTabX - InsideCornerDia/2, - PlateY/2 - InsideCornerDia/2, 0]) cylinder (PlateThick + 1, d = InsideCornerDia, center=true); // Minus cylnder } // End inside corner by lower right tab // difference(){ // Inside corner by lower left tab translate ([-PlateX/2 + HTabX + InsideCornerDia/4, - PlateY/2 - InsideCornerDia/4, 0]) cube ([InsideCornerDia/2, InsideCornerDia/2, PlateThick], center=true); // Cube translate ([-PlateX/2 + HTabX + InsideCornerDia/2, - PlateY/2 - InsideCornerDia/2, 0]) cylinder (PlateThick + 1, d = InsideCornerDia, center=true); // Minus cylnder } // End inside corner by lower left tab // difference(){ // Inside corner by upper left tab translate ([-PlateX/2 - InsideCornerDia/4, PlateY/2 - TTabY - InsideCornerDia/4, 0]) cube ([InsideCornerDia/2, InsideCornerDia/2, PlateThick], center=true); // Cube translate ([-PlateX/2 - InsideCornerDia/2, PlateY/2 - TTabY - InsideCornerDia/2, 0]) cylinder (PlateThick + 1, d = InsideCornerDia, center=true); // Minus cylnder } // End inside corner by upper left tab // // Echo statements with X/Y position of T-Tab and H-Tab screw hole positions and center-to-center distances echo("--------------------------------------------------------------------------------------------------"); echo("T-Tab screw hole position measurements"); echo(str("X-axis distance = ", TTabScrewX, " and Y-axis distance = ", TTabScrewY, " from center")); echo(str("X-axis center-to-center distance = ", TTabScrewX*2)); echo(); echo("H-Tab screw hole position measurements"); echo(str("X-axis distance = ", HTabScrewX, " and Y-axis distance = ", HTabScrewY, " from center")); echo(str("X-axis center-to-center distance = ", HTabScrewX*2)); echo("--------------------------------------------------------------------------------------------------"); // --- End code --- OpenSCAD code for the spacers: --- Code: ---// ServoStik Mount Spacers v1 // Original plate design and measurements by Gilrock // Inner diameter of 4.5 should work with #8 screws // 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 //////////////////////////////////////////// // // Variables: // //////////////////////////////////////////// OuterDiameter = 6.35; // Spacer outer diameter InnerDiameter = 4.5; // Spacer inner diameter TallHeight = 8.25; // Tall spacer height // 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. //////////////////////////////////////////// // // Automatically calculated variables: // //////////////////////////////////////////// ShortHeight = TallHeight - 1.9; // Short spacer height //////////////////////////////////////////// // // Make the part: // //////////////////////////////////////////// // Tall spacer 1 difference(){ // Outer cylinder minus inner cylinder translate ([- OuterDiameter * 0.75, OuterDiameter * 0.75, TallHeight/2]) cylinder (TallHeight, d = OuterDiameter, center=true); // Outer cylinder translate ([- OuterDiameter * 0.75, OuterDiameter * 0.75, TallHeight/2]) cylinder (TallHeight + 1, d = InnerDiameter, center=true); // Inner cylinder } // End outer cylinder minus inner cylinder // // Tall spacer 2 difference(){ // Outer cylinder minus inner cylinder translate ([OuterDiameter * 0.75, OuterDiameter * 0.75, TallHeight/2]) cylinder (TallHeight, d = OuterDiameter, center=true); // Outer cylinder translate ([OuterDiameter * 0.75, OuterDiameter * 0.75, TallHeight/2]) cylinder (TallHeight + 1, d = InnerDiameter, center=true); // Inner cylinder } // End outer cylinder minus inner cylinder // // Short spacer 1 difference(){ // Outer cylinder minus inner cylinder translate ([- OuterDiameter * 0.75, - OuterDiameter * 0.75, ShortHeight/2]) cylinder (ShortHeight, d = OuterDiameter, center=true); // Outer cylinder translate ([- OuterDiameter * 0.75, - OuterDiameter * 0.75, ShortHeight/2]) cylinder (ShortHeight + 1, d = InnerDiameter, center=true); // Inner cylinder } // End outer cylinder minus inner cylinder // // Short spacer 2 difference(){ // Outer cylinder minus inner cylinder translate ([OuterDiameter * 0.75, - OuterDiameter * 0.75, ShortHeight/2]) cylinder (ShortHeight, d = OuterDiameter, center=true); // Outer cylinder translate ([OuterDiameter * 0.75, - OuterDiameter * 0.75, ShortHeight/2]) cylinder (ShortHeight + 1, d = InnerDiameter, center=true); // Inner cylinder } // End outer cylinder minus inner cylinder // // Echo statements with tall and short spacer heights and mount plate screw length echo("--------------------------------------------------------------------------------------------------"); echo(str("Tall spacer height = ", TallHeight, " and short spacer height = ", ShortHeight)); echo(str("The length of the plate mount screws must be at least ", TallHeight + 1.65, "mm plus the thickness of the mount plate, washers, and nut.")); echo("--------------------------------------------------------------------------------------------------"); // --- End code --- *** Click here to download a .zip file containing the v1 .STL files and OpenSCAD files. *** *** Click here to download a .zip file containing the v1 .DXF file. *** *** Click here to download the v1 .SVG file. *** -------------------- Next steps: Get someone with a 3d printer (or CNC machine) and a ServoStik to test print (or mill) the plate and see if everything fits properly. Are there any measurements that are off? Get feedback from CNC users on whether .STL files are a useful format or if there is a better/preferred format that OpenSCAD can export to. Are there any features you'd like to see added or changed? Scott |
| PL1:
Found this interesting thread about converting OpenSCAD files to a CNC-friendly format. https://forum.openscad.org/Is-OpenSCAD-to-CNC-possible-td22175.html One way is to use PyCAM to generate toolpaths (GCode) from .STL files. Another way is to import the OpenSCAD file into FreeCAD. - There have been issues importing some files as mentioned here. Have any of you with CNC experience tried one of these methods? Scott |
| Gilrock:
I've never ventured past the one way I learned to create GCode for my CNC. I bought Aspire when I bought the CNC kit and so I've always figured out a way to get my designs into that program and then use it to create GCode. I figured out how to set things up several years ago and I'd be started from scratch if I had to do it again. |
| Mike A:
Damn. Aspire? I can only afford VCarve Pro. Vectric makes good software. If I did more 3 dimensional work I would try to find a way to buy Aspire. |
| PL1:
So far, sounds like PyCAM, eSTLcam, FreeCAD, Aspire, and VCarve Pro are good software packages to consider/test. PyCAM - STL files - Not familiar with the software so not sure what the work flow steps are. eSTLcam - STL files - Commonly used and inexpensive software. https://www.estlcam.de/ FreeCAD - Opens most OpenSCAD files, mount plate files haven't been tested yet - Requires a plugin. - Not familiar with the software so not sure what the work flow steps are. Aspire - STL and DXF(?) files https://www.vectric.com/products/aspire --- Quote ---Import 3D Models & Clip Art (STL, OBJ, 3DM etc.) Any model you create in Aspire can be saved as a piece of clipart for use in other projects. Import 3D mesh files created in other CAD software such as, Rhino 5, SolidWorks, AutoCAD, Silo, MOI, Blender, SketchUp etc. STL, 3D DXF, OBJ, 3DS, VRML, 3DM, SKP file formats --- End quote --- - Not familiar with the software so not sure what the work flow steps are. - OpenSCAD can only export 2D DXF files, not 3D DXF files. https://en.m.wikibooks.org/wiki/OpenSCAD_User_Manual/DXF_Export - That might be good enough for a mount plate if you can convert a 2D DXF into a 3D shape in Aspire. VCarve Pro - STL and DXF(?) files https://www.vectric.com/products/vcarve-pro --- Quote ---Import 3D Models (STL, OBJ, 3DM etc.) & Clipart (V3M) Import a single 3D mesh file created in other CAD software such as, Rhino 5, SolidWorks, AutoCAD, Silo, MOI, Blender, SketchUp etc. STL, 3D DXF, OBJ, 3DS, VRML, 3DM, SKP file formats --- End quote --- - Not familiar with the software so not sure what the work flow steps are. - OpenSCAD can only export 2D DXF files, not 3D DXF files. https://en.m.wikibooks.org/wiki/OpenSCAD_User_Manual/DXF_Export - That might be good enough for a mount plate if you can convert a 2D DXF into a 3D shape in VCarve Pro. The OpenSCAD code for converting the mount plate STL to a DXF file is very simple -- directions are in the comments. --- Code: ---// ServoStik Mount Plate DXF projection // Place this file in the same directory as the "ServoStik Mount Plate.stl" file. // Preview shows the imported STL, render shows the 2D shape. // Click on File -- Export -- Export as DXF. projection(cut = true) import("ServoStik Mount Plate.stl"); --- End code --- If you have one or more of these software packages installed and working, please test importing the file and let everyone know if it worked or not. :cheers: - If anyone wants to test importing the DXF file from OpenSCAD, you can download it here. Scott EDIT: Added eSTLcam -- recommended below by 601 Arcades. |
| Navigation |
| Message Index |
| Next page |