The Smell of Molten Projects in the Morning

Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.

The New Hotness

  • NEMA17 Motor and Bearing Mounts

    As part of coaching a student (and his father!) on their incredibly ambitious build-a-plotter-from-scratch project, I suggested stealing using HP’s grit-wheel paper drive, rather than fiddling with guide rods to move either the pen carrier or the entire paper platform. Dremel sanding drums seem about the right size and they had an 8 mm shaft harvested from a defunct printer, so a pair of mounts moves the project along:

    NEMA17 and Bearing Mounts - Slic3r preview
    NEMA17 and Bearing Mounts – Slic3r preview

    The motor mount code is a hack job from my old NEMA17 mount and the code has a lot not to like. The bearing mount puts the bearing on the proper centerline using brute force copypasta and depends on friction to hold it in place. The two models should be integrated into the same file, the shaft centerline shouldn’t involve the printed thread width, and blah blah blah:

    NEMA17 motor and bearing mounts
    NEMA17 motor and bearing mounts

    I had him turn the shaft adapter from an aluminum rod in the mini-lathe: he’s hooked.

    The OpenSCAD source code as a GitHub Gist:

    // Ball bearing mount
    // Ed Nisley KE4ZNU 2017-10-09
    //– Extrusion parameters
    ThreadThick = 0.20;
    ThreadWidth = 0.40;
    HoleWindage = 0.2; // enlarge hole dia by this amount
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    Protrusion = 0.1; // make holes look good and joints intersect properly
    //– Useful sizes
    inch = 25.4;
    Tap10_32 = 0.159 * inch;
    Clear10_32 = 0.190 * inch;
    Head10_32 = 0.373 * inch;
    Head10_32Thick = 0.110 * inch;
    Nut10_32Dia = 0.433 * inch;
    Nut10_32Thick = 0.130 * inch;
    // Bearing sizes
    ID = 0;
    OD = 1;
    LENGTH = 2;
    Bearing = [8.0,22.0,7.0];
    ShaftHeight = IntegerMultiple(25.2,ThreadWidth); // arbitrary or copied from motor mount
    WallThick = 3.0;
    //– Mount Sizes
    MountSize = Bearing[OD] + 2*WallThick;
    BaseThick = max(WallThick,ShaftHeight – MountSize/2); // baseplate
    StandBoltHead = IntegerMultiple(Head10_32,2); // bolt head rounded up
    StandBoltClear = 1.25 * StandBoltHead;
    StandBoltOC = IntegerMultiple(MountSize + StandBoltClear,2);
    StandLength = StandBoltOC + StandBoltClear;
    StandThick = StandBoltClear + WallThick;
    StandHeight = MountSize + BaseThick;
    Cutout = (StandLength – MountSize)/2;
    echo(str("Stand Base: ",StandLength," x ",StandThick," x ",BaseThick));
    echo(str("Stand Bolt OC: ",StandBoltOC));
    echo(str("Shaft Height:",ShaftHeight));
    //———————-
    // Useful routines
    module PolyCyl(Dia,Height,ForceSides=0) { // based on nophead's polyholes
    Sides = (ForceSides != 0) ? ForceSides : (ceil(Dia) + 2);
    FixDia = Dia / cos(180/Sides);
    cylinder(r=(FixDia + HoleWindage)/2,
    h=Height,
    $fn=Sides);
    }
    //———————-
    // Put it together
    module BearingMount() {
    difference() {
    translate([BaseThick/2,0,StandThick/2])
    cube([StandHeight,StandLength,StandThick],center=true);
    translate([0,0,-Protrusion])
    PolyCyl(Bearing[OD],(StandThick + 2*Protrusion));
    for (j=[-1,1]) // cutouts over bolts
    translate([-(StandHeight/2 – ShaftHeight + WallThick),
    j*(StandLength/2 – Cutout/2 + Protrusion/2),
    (WallThick + StandThick/2)])
    cube([StandHeight,
    Cutout + Protrusion,
    StandThick],center=true);
    for (j=[-1,1]) // stand bolt holes – base
    translate([(MountSize/2 – Protrusion),
    j*StandBoltOC/2,
    WallThick + StandBoltClear/2])
    rotate([0,90,0])
    rotate(180/6)
    PolyCyl(Clear10_32,BaseThick + 2*Protrusion,6);
    for (j=[-1,1]) // stand bolt holes – back
    translate([0,j*StandBoltOC/2,-Protrusion])
    rotate(180/6)
    PolyCyl(Clear10_32,StandThick + 2*Protrusion,6);
    translate([0,-(MountSize/2 – ThreadWidth/2),(StandThick – WallThick)/2 + WallThick])
    rotate([90,180,0])
    linear_extrude(ThreadWidth,convexity=10)
    text(text=str(ShaftHeight),size=6,spacing=1.20,font="Arial",halign="center",valign="center");
    }
    }
    //———————-
    // Build it
    BearingMount();
    // NEMA 17 stepper mount
    // Ed Nisley KE4ZNU August 2011
    // Tweaked & thinned 2017-10-09
    //– Extrusion parameters
    ThreadThick = 0.25;
    ThreadWidth = 0.4;
    HoleWindage = 0.3; // enlarge hole dia by this amount
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    Protrusion = 0.1; // make holes look good and joints intersect properly
    //– Useful sizes
    inch = 25.4;
    Tap10_32 = 0.159 * inch;
    Clear10_32 = 0.190 * inch;
    Head10_32 = 0.373 * inch;
    Head10_32Thick = 0.110 * inch;
    Nut10_32Dia = 0.433 * inch;
    Nut10_32Thick = 0.130 * inch;
    NEMA17_ShaftDia = 5.0;
    NEMA17_ShaftLength = 24.0;
    NEMA17_PilotDia = 0.866 * inch;
    NEMA17_PilotLength = 0.080 * inch;
    NEMA17_BCD = 1.725 * inch;
    NEMA17_BoltDia = 3.5;
    NEMA17_BoltOC = 1.220 * inch;
    //– Mount Sizes
    MountWidth = IntegerMultiple(NEMA17_BCD,ThreadWidth); // use BCD for motor clearance
    MountThick = IntegerMultiple(4.0,ThreadThick); // for stiffness
    MountBoltDia = 3.0;
    StandThick = 3.0; // baseplate
    StrutThick = IntegerMultiple(3.0,ThreadWidth); // sides holding motor mount
    UprightLength = MountWidth + 2*StrutThick;
    StandBoltHead = IntegerMultiple(Head10_32,5); // bolt head rounded up
    StandBoltOC = IntegerMultiple(UprightLength + 2*StandBoltHead,5);
    StandLength = StandBoltOC + 2*StandBoltHead;
    StandWidth = 2*StandBoltHead;
    StandBoltClear = (StandLength – UprightLength)/2; // flat around bolt head
    MotorRecess = StandWidth – MountThick;
    ShaftHeight = IntegerMultiple(StandThick + MountWidth/2,ThreadWidth);
    echo(str("Stand Base: ",StandLength," x ",StandWidth," x ",StandThick));
    echo(str("Stand Bolt OC: ",StandBoltOC));
    echo(str("Shaft Height:",ShaftHeight));
    echo(str("Strut Thick: ",StrutThick));
    //———————-
    // Useful routines
    module PolyCyl(Dia,Height,ForceSides=0) { // based on nophead's polyholes
    Sides = (ForceSides != 0) ? ForceSides : (ceil(Dia) + 2);
    FixDia = Dia / cos(180/Sides);
    cylinder(r=(FixDia + HoleWindage)/2,
    h=Height,
    $fn=Sides);
    }
    //———————-
    // Model
    module MotorMount() {
    difference() {
    translate([StandThick/2,0,StandWidth/2])
    cube([(MountWidth + StandThick),StandLength,StandWidth],center=true);
    translate([-Protrusion/2,0,StandWidth – (MotorRecess – Protrusion)/2])
    cube([(MountWidth + Protrusion),MountWidth,(MotorRecess + Protrusion)],center=true);
    translate([0,0,-Protrusion]) // pilot hole
    PolyCyl(NEMA17_PilotDia,(MountThick + 2*Protrusion));
    for (i=[-1,1]) // motor bolt holes
    for (j=[-1,1])
    translate([i*NEMA17_BoltOC/2,j*NEMA17_BoltOC/2,-Protrusion])
    PolyCyl(MountBoltDia,(MountThick + 2*Protrusion),6);
    for (j=[-1,1]) // cutouts over bolts
    translate([-Protrusion/2,
    j*((StandLength – StandBoltClear)/2 + Protrusion/2),
    StandWidth/2])
    cube([(MountWidth + Protrusion),
    (StandBoltClear + Protrusion),
    (StandWidth + 2*Protrusion)],center=true);
    for (j=[-1,1]) // stand bolt holes
    translate([(MountWidth/2 – Protrusion),j*StandBoltOC/2,StandWidth/2])
    rotate([0,90,0])
    rotate(180/6)
    PolyCyl(Clear10_32,StandThick + 2*Protrusion,6);
    translate([0,-(UprightLength/2 – ThreadWidth/2),StandWidth/2])
    rotate([90,180,0])
    linear_extrude(ThreadWidth,convexity=10)
    text(text=str(ShaftHeight),size=6,spacing=1.20,font="Arial",halign="center",valign="center");
    }
    }
    //———————-
    // Build it
    MotorMount();