Main Restorations Software Audio/Jukebox/MP3 Everything Else Buy/Sell/Trade
Project Announcements Monitor/Video GroovyMAME Merit/JVL Touchscreen Meet Up Retail Vendors
Driving & Racing Woodworking Software Support Forums Consoles Project Arcade Reviews
Automated Projects Artwork Frontend Support Forums Pinball Forum Discussion Old Boards
Raspberry Pi & Dev Board controls.dat Linux Miscellaneous Arcade Wiki Discussion Old Archives
Lightguns Arcade1Up Try the site in https mode Site News

Unread posts | New Replies | Recent posts | Rules | Chatroom | Wiki | File Repository | RSS | Submit news

  

Author Topic: 3d printed or CNC milled mounting plate for Ultimarc ServoStik  (Read 4755 times)

0 Members and 1 Guest are viewing this topic.

PL1

  • Global Moderator
  • Trade Count: (+1)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 9403
  • Last login:Today at 10:06:39 am
  • Designated spam hunter
3d printed or CNC milled mounting plate for Ultimarc ServoStik
« on: September 06, 2021, 09:50:34 am »
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: [Select]
// 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("--------------------------------------------------------------------------------------------------");
//

OpenSCAD code for the spacers:
Code: [Select]
// 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("--------------------------------------------------------------------------------------------------");
//

***  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
« Last Edit: September 14, 2021, 10:29:20 am by PL1 »

PL1

  • Global Moderator
  • Trade Count: (+1)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 9403
  • Last login:Today at 10:06:39 am
  • Designated spam hunter
Re: 3d printed or CNC milled mounting plate for Ultimarc ServoStik
« Reply #1 on: September 12, 2021, 07:24:23 pm »
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

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 1049
  • Last login:March 30, 2024, 05:15:46 pm
Re: 3d printed or CNC milled mounting plate for Ultimarc ServoStik
« Reply #2 on: September 13, 2021, 09:28:22 am »
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

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 5885
  • Last login:Today at 12:02:50 pm
  • This plan is foolproof
Re: 3d printed or CNC milled mounting plate for Ultimarc ServoStik
« Reply #3 on: September 13, 2021, 09:49:55 am »
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

  • Global Moderator
  • Trade Count: (+1)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 9403
  • Last login:Today at 10:06:39 am
  • Designated spam hunter
Re: 3d printed or CNC milled mounting plate for Ultimarc ServoStik
« Reply #4 on: September 14, 2021, 06:24:54 am »
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
- 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
- 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: [Select]
// 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");

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.
« Last Edit: October 01, 2021, 10:31:20 am by PL1 »

Gilrock

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 1049
  • Last login:March 30, 2024, 05:15:46 pm
Re: 3d printed or CNC milled mounting plate for Ultimarc ServoStik
« Reply #5 on: September 14, 2021, 08:50:44 am »
In Aspire and I assume VCarve is similar you wouldn't need the 2D DXF to convert to 3D.  You just need to place the 2D shape in the program and then the material thickness you can set will give it the 3rd dimension.

With Aspire importing a DXF isn't a quick process.  I find the paths are not contiguous and I've had to do a lot of cleanup work.  Sometimes I just use the imported DXF almost the same as an imported image where I use it as a template to draw over top of it using the built-in tools.

Only time I've used 3D in Aspire was when creating plaques like I did a couple Eagle Scout plagues that had a pretty cool detailed eagle carved into the middle but to get that detail I had to use a 1/16" bit for the final passes and it took like 5 hours per plaque but I don't like to run very fast speeds.

Gilrock

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 1049
  • Last login:March 30, 2024, 05:15:46 pm
Re: 3d printed or CNC milled mounting plate for Ultimarc ServoStik
« Reply #6 on: September 14, 2021, 09:02:18 am »
For 2D CAD drawing I've always used a $40 program called DeltaCAD.  I haven't tried any other CAD programs.  That drawing of mine you posted that has the dimensions was created with it.  Its a little quirky to learn to use but its super fast.  It was recommended to me years ago by Clayton Boyer when I was getting the DXF files from him for one of his wooden clock designs so I could import it into Aspire to use the CNC to cut the gears.   Reminds me another project I need to finish someday...lol.

PL1

  • Global Moderator
  • Trade Count: (+1)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 9403
  • Last login:Today at 10:06:39 am
  • Designated spam hunter
Re: 3d printed or CNC milled mounting plate for Ultimarc ServoStik
« Reply #7 on: September 14, 2021, 10:26:09 am »
In Aspire and I assume VCarve is similar you wouldn't need the 2D DXF to convert to 3D.
I figured that if the STL wouldn't import, you could try the 2D DXF.

You just need to place the 2D shape in the program and then the material thickness you can set will give it the 3rd dimension.
That's what I thought.  Import a 2D shape for the X/Y outline then adjust the thickness for Z.

With Aspire importing a DXF isn't a quick process.  I find the paths are not contiguous and I've had to do a lot of cleanup work. 
Is that a general observation about DXF files, or a problem with the specific file I posted?

Do you think SVG or PNG files would require less cleanup work than a DXF file?
- The SVG from OpenSCAD (download here) looks really clean in Inkscape.
- I need to update to be able to export PNGs.


Scott
« Last Edit: September 14, 2021, 10:35:59 am by PL1 »

Gilrock

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 1049
  • Last login:March 30, 2024, 05:15:46 pm
Re: 3d printed or CNC milled mounting plate for Ultimarc ServoStik
« Reply #8 on: September 15, 2021, 08:53:37 am »
I haven't had time to try the file you posted.  So I don't know if its just DXF files I've created in DeltaCad or all DXF's.  What happens is you import it and then when you click on a line it only highlights a tiny segment as pink instead of the entire outline you would expect to be one contiguous path.  It needs to be a continuous path to be able to select it when creating the toolpaths.  There is one feature where you can select a group of those tiny segments and merge them into a path using various "smoothing" options but that just triggers my OCD thinking I won't get perfect straight lines so I end up re-creating the object.

PL1

  • Global Moderator
  • Trade Count: (+1)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 9403
  • Last login:Today at 10:06:39 am
  • Designated spam hunter
Re: 3d printed or CNC milled mounting plate for Ultimarc ServoStik
« Reply #9 on: September 15, 2021, 11:37:07 am »
What happens is you import it and then when you click on a line it only highlights a tiny segment as pink instead of the entire outline you would expect to be one contiguous path.  It needs to be a continuous path to be able to select it when creating the toolpaths.  There is one feature where you can select a group of those tiny segments and merge them into a path using various "smoothing" options but that just triggers my OCD thinking I won't get perfect straight lines so I end up re-creating the object.
If you have to highlight each individual segment of the curves, it will be a nightmare.   :banghead:
- OpenSCAD renders a circle as a 180-sided polygon -- determined by the "$fn = 180;" variable in the code.



If you can select a group of segments and merge them into a single path, it should be much easier.
- Like many Windows programs, Inkscape allows you to left-click + drag to create a selection box.
- You can add more segments to the previously-selected ones using shift + left-click + drag to create another selection box.
- This way, it's pretty easy to select all of the segments for a particular path.
-  I'm guessing that Aspire can do the same thing, right?

There should be a total of 10 paths for this part, right?
- Eight screw holes, the inner perimeter of the plate, and the outer perimeter of the plate.


Scott

601 Arcades

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 21
  • Last login:October 15, 2022, 07:01:08 pm
  • I build my own arcade controls all the time!
Re: 3d printed or CNC milled mounting plate for Ultimarc ServoStik
« Reply #10 on: October 01, 2021, 03:44:30 am »
I have Aspire as well for my CNC shop. I like it best out of all I've tried. IF you wanna do a native stl on your cnc machine, without tons of converting and adding numerous programs to your pc, check out eSTLcam. It's super cheap if you like it, but also fully functional during the trial. It can take your stl and make a file that your CNC machine can work with to cut it out. It's been a life saver for those customers that want custom car parts and they have an 8 sided stl when they come in with.

Currently at my shop, I accept files in CRV, SVG, PDF, DXF, DWG and STL. But usually people have DXF's when they come in so I guess that's definitely the most common.

I'd offer to take on this milling, and or 3D printing, but I don't have a ServoStik. I could print/mill something and send it to you for you to test tho.
Ms Pacman (All Original)
Galaga (All Original)
Dragon's Lair (Original Hardware/Reproduction Cabinet By Me)
WIP Centipede Cabaret (Original Hardware/Reproduction Cabinet By Me)
WIP Robotron Mini (Original Hardware/Reproduction Cabinet By Me)
WIP Multi-Williams

PL1

  • Global Moderator
  • Trade Count: (+1)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 9403
  • Last login:Today at 10:06:39 am
  • Designated spam hunter
Re: 3d printed or CNC milled mounting plate for Ultimarc ServoStik
« Reply #11 on: October 01, 2021, 11:28:59 am »
Has anybody printed or milled one of these plates yet?
- Any feedback on what you like about it or would like to see improved on it?
- The screw hole sizes and plate thickness are still just placeholders.

Here's a v2 update to the OpenSCAD code.
- The echo commands provide more useful info such as screw length info for the spacers.

Mount plate:
Code: [Select]
// ServoStik Mount Plate v2

// Original plate design and measurements by Gilrock
//  http://forum.arcadecontrols.com/index.php/topic,141437.msg1675685.html#msg1675685
// http://forum.arcadecontrols.com/index.php/topic,165589.0.html

// 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 outside 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, "mm and Y-axis distance = ", TTabScrewY, "mm from center"));
echo(str("X-axis center-to-center distance = ", TTabScrewX*2, "mm (", round((TTabScrewX*2)/0.254)/100, " inches)"));
echo();
echo("H-Tab screw hole position measurements");
echo(str("X-axis distance = ", HTabScrewX, "mm and Y-axis distance = ", - HTabScrewY, "mm from center"));
echo(str("X-axis center-to-center distance = ", HTabScrewX*2, "mm (", round((HTabScrewX*2)/0.254)/100, " inches)"));
echo();
echo(str("The Y-axis center-to-center distance between the T-Tab and H-Tab screw holes = ", TTabScrewY - HTabScrewY, "mm (", round((TTabScrewY - HTabScrewY)/0.254)/100, " inches)"));
echo("--------------------------------------------------------------------------------------------------");
//



Spacers:
Code: [Select]
// ServoStik Mount Spacers v2

// Original plate design and measurements by Gilrock
//  http://forum.arcadecontrols.com/index.php/topic,141437.msg1675685.html#msg1675685
// http://forum.arcadecontrols.com/index.php/topic,165589.0.html

// 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, "mm and short spacer height = ", ShortHeight), "mm");
echo(str("The length of the plate mount screws must be at least ", TallHeight + 1.65, "mm (", round((TallHeight + 1.65)/0.254)/100, " inches) plus the thickness of the mount plate, washers, and nut."));
echo("--------------------------------------------------------------------------------------------------");
//



I have Aspire as well for my CNC shop. I like it best out of all I've tried.
Another satisfied Vectric customer.   ;D

This video shows importing an STL into Aspire v9.5.
- Someone mentions in the comments that the process is a bit different for v11.



IF you wanna do a native stl on your cnc machine, without tons of converting and adding numerous programs to your pc, check out eSTLcam. It's super cheap if you like it, but also fully functional during the trial. It can take your stl and make a file that your CNC machine can work with to cut it out. It's been a life saver for those customers that want custom car parts and they have an 8 sided stl when they come in with.
Good catch on this commonly-used software.   :cheers:

Added eSTLcam to the software list above.

Currently at my shop, I accept files in CRV, SVG, PDF, DXF, DWG and STL. But usually people have DXF's when they come in so I guess that's definitely the most common.
Sounds like another vote for using STL and DXF formats.

I'd offer to take on this milling, and or 3D printing, but I don't have a ServoStik. I could print/mill something and send it to you for you to test tho.
Thanks for the offer, but I don't have a ServoStik.

I'm just trying to make it so hobbyists and pros alike can print or mill something that works for them.   ;D


Scott

PL1

  • Global Moderator
  • Trade Count: (+1)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 9403
  • Last login:Today at 10:06:39 am
  • Designated spam hunter
Re: 3d printed or CNC milled mounting plate for Ultimarc ServoStik
« Reply #12 on: October 01, 2021, 05:03:56 pm »
Looks like the ServoStik and the Ultimarc J-Stik are based on the Sanwa JLW-TM-8, in case anyone has one of these and would be willing to run some tests.   ;D


Scott