Scotch Yoke Mechanism

Hello again!

Its time for another customizable mechanism!

This time its called a Scotch Yoke. This one turns rotating motion into straight line motion via a boss on the crank and a slot on the piece that rides straight.

I had looked at a few reciprocating saws when I thought to do this. I noticed some yokes had straight while others had curved yokes. Being a curious engineer I decided to do a little math.

The straight yoke yields a sin wave output which you may know from any number of animations like this.

Using the greatest engineering program known to man, Microsoft Excel, I set up two graphs, one graphing velocity of the straight yoke, and the other graphing acceleration (the derivative of the first) and jerk (the derivative of acceleration). I made the sheet in such a way that I could change the radius of the curved yoke and it would automatically graph.

I employed a guess and check method to find what happened with the graph. I noticed that the velocity graph got linear when I changed the radius value to around 1.73 times the crank diameter. This number might look familiar to those who remember trigonometry from school, it happens to be tan(60).

Below are the graphs from a straight yoke and the curved yoke.

The straight yoke graphs
The curved yoke graphs with the ‘golden zone’ highlighted

Because of that linear velocity section I mentioned you can see that there is a section of constant acceleration and thus no jerk. This gives a nice predictable range that a designer can use downstream in their mechanism. now the edges of this nice range have jerk, potentially bad jerk but if you only want to use a section of the rotation for say, the cutting stroke of a reciprocating saw or jigsaw, the curved yoke gives good controllable acceleration.

Now on to the OpenSCAD model. The parameters should be pretty obvious what they do. What I will talk about to make it clear is the Yoke parameter and the View parameter.

The Yoke is an option based parameter. Depending on that number an if statement changes the yoke from straight to curved.

The View works the same way and is identical to my other model, the Geneva Mechanism. This helps for when you want to view the model assembled vs when you want it all on the same plane and arranged for printing.

Here is the Thingiverse link.

Below is the OpenSCAD code

//Scotch Yoke Mechanism
//
//By: Matt from Artofrandomness.net
//
//Thingiverse #: 2707377  
//
//For more information visit the follorwing URL
//https://en.wikipedia.org/wiki/Scotch_yoke

//Input Parameters:

//Wheel Diameter
WD = 1.5;

//Nub Diameter
ND = .375;

//Thickness
t = .25;

//Clearance (.015625 is .4mm)
C = .015625;

//Yoke Arm Edge Thickness
YT = .1875;

//Bolt Diameter (these are for a #8 screw)
B = .178;

//Bolt Head Diameter
BH = .338;

//Nut Outer Diameter
Nutd = .360;

//Nut Thickness
Nutt = .131;

//Curved Yoke Radius Multiplier
F = tan(60);

//1: Straight Yoke, 2: Curved Yoke
Yoke = 1;

//1: Assembed View, 2: Printing View
View = 1;

//Calculated Parameters
R = WD*F;

delta = WD-ND;

TriY = sqrt(pow(R,2)-pow(delta/2,2));

TriX = delta;

Off = R-TriY;

echo("Min Bed Size");
echo("X Direction:");
echo(4.25*WD);
echo("Y Direction:");
echo(4*WD);

if(View==1){

//Assembled View

//Knob
translate([0,0,t/2]){
    union(){
    difference(){
    cylinder(t,WD/2,WD/2,center=true,$fn=100);
    union(){
    cylinder(2*t,B/2,B/2,center=true,$fn=100);
    translate([0,0,t/2]){
    cylinder(t,BH/2,BH/2,center=true,$fn=100);   
    }}}
    translate([((WD/2)-(ND/2)),0,t]){
    union(){
    cylinder(t,ND/2,ND/2,center=true,$fn=100);
    translate([0,0,t]){
    cylinder(t,ND/2,0,center=true,$fn=100);
    }
    translate([0,0,1.5*t]){
    sphere(ND/2,center=true,$fn=100);
    }}}}}
    
//Base            
translate([0,0,-t/2]){
    difference(){
    union(){
    cube([1.25*WD,4*WD,t],center=true);
    translate([0,2*delta,t]){
    cube([2*(B+YT),ND,t+(2*C)],center=true);
    }
    translate([0,-2*delta,t]){
    cube([2*(B+YT),ND,t+(2*C)],center=true);
    }}
    cylinder(4*t,B/2,B/2,center=true,$fn=100);
    translate([0,2*delta,0]){
    cylinder(4*t,B/2,B/2,center=true,$fn=100);
    }
    translate([0,-2*delta,0]){
    cylinder(4*t,B/2,B/2,center=true,$fn=100);
    }
    translate([0,0,-t/2]){
    cylinder(2*Nutt,Nutd/2,Nutd/2,center=true,$fn=6);
    translate([0,2*delta,0]){
    cylinder(2*Nutt,Nutd/2,Nutd/2,center=true,$fn=6);
    }
    translate([0,-2*delta,0]){
    cylinder(2*Nutt,Nutd/2,Nutd/2,center=true,$fn=6);
    }}
    }}

//Yoke
translate([0,0,0]){
if(Yoke==1){
//Straight Yoke
translate([0,0,(1.5*t)+C]){
    difference(){
    union(){
    cube([B+(2*YT),5*delta,t],center=true);
    cube([WD-ND,ND+(2*YT),t],center=true);
    translate([delta/2,0,0]){
    cylinder(t,(ND/2)+YT,(ND/2)+YT,center=true,$fn=100);
    }
    translate([-delta/2,0,0]){
    cylinder(t,(ND/2)+YT,(ND/2)+YT,center=true,$fn=100);
    }
    translate([0,2.5*delta,0]){
    cylinder(t,(B+(2*YT))/2,(B+(2*YT))/2,center=true,$fn=100);
    }
    translate([0,-2.5*delta,0]){
    cylinder(t,(B+(2*YT))/2,(B+(2*YT))/2,center=true,$fn=100);
    }}
    cube([WD-ND,ND+(2*C),2*t],center=true); 
    translate([delta/2,0,0]){
    cylinder(2*t,(ND/2)+C,(ND/2)+C,center=true,$fn=100);
    }
    translate([-delta/2,0,0]){
    cylinder(2*t,(ND/2)+C,(ND/2)+C,center=true,$fn=100);
    }
    translate([0,2.5*delta,0]){
    cylinder(2*t,(B+C)/2,(B+C)/2,center=true,$fn=100);
    }
    translate([0,1.5*delta,0]){
    cylinder(2*t,(B+C)/2,(B+C)/2,center=true,$fn=100);
    }
    translate([0,-2.5*delta,0]){
    cylinder(2*t,(B+C)/2,(B+C)/2,center=true,$fn=100);
    }
    translate([0,-1.5*delta,0]){
    cylinder(2*t,(B+C)/2,(B+C)/2,center=true,$fn=100);
    }
    translate([0,2*delta,0]){
    cube([B+C,delta,2*t],center=true);
    }
    translate([0,-2*delta,0]){
    cube([B+C,delta,2*t],center=true);
    }
    }}
}
else {
//Curved Yoke
translate([0,Off,(1.5*t)+C]){
    difference(){
    union(){
    cube([B+(2*YT),5*delta,t],center=true);
    translate([0,-R,0]){
    intersection(){
    difference(){
    cylinder(t,R+(ND/2)+YT,R+(ND/2)+YT,center=true,$fn=100);
    cylinder(2*t,R-(ND/2)-YT,R-(ND/2)-YT,center=true,$fn=100);
    }
    linear_extrude(2*t,center=true){
    polygon([[0,0],[1.5*TriX,3*TriY],[-1.5*TriX,3*TriY]]);
    }}}
    translate([delta/2,-Off,0]){
    cylinder(t,(ND/2)+YT,(ND/2)+YT,center=true,$fn=100);
    }
    translate([-delta/2,-Off,0]){
    cylinder(t,(ND/2)+YT,(ND/2)+YT,center=true,$fn=100);
    }
    translate([0,2.5*delta,0]){
    cylinder(t,(B+(2*YT))/2,(B+(2*YT))/2,center=true,$fn=100);
    }
    translate([0,-2.5*delta,0]){
    cylinder(t,(B+(2*YT))/2,(B+(2*YT))/2,center=true,$fn=100);
    }}
    translate([0,-R,0]){
    intersection(){
    difference(){
    cylinder(2*t,R+(ND/2)+(C/2),R+(ND/2)+(C/2),center=true,$fn=100);
    cylinder(2*t,R-(ND/2)-(C/2),R-(ND/2)-(C/2),center=true,$fn=100);
    }
    linear_extrude(2*t,center=true){
    polygon([[0,0],[1.5*TriX,3*TriY],[-1.5*TriX,3*TriY]]);
    }}}
    translate([delta/2,-Off,0]){
    cylinder(2*t,(ND/2)+(C/2),(ND/2)+(C/2),center=true,$fn=100);
    }
    translate([-delta/2,-Off,0]){
    cylinder(2*t,(ND/2)+(C/2),(ND/2)+(C/2),center=true,$fn=100);
    }
    translate([0,2.5*delta,0]){
    cylinder(2*t,(B+C)/2,(B+C)/2,center=true,$fn=100);
    }
    translate([0,1.5*delta,0]){
    cylinder(2*t,(B+C)/2,(B+C)/2,center=true,$fn=100);
    }
    translate([0,-2.5*delta,0]){
    cylinder(2*t,(B+C)/2,(B+C)/2,center=true,$fn=100);
    }
    translate([0,-1.5*delta,0]){
    cylinder(2*t,(B+C)/2,(B+C)/2,center=true,$fn=100);
    }
    translate([0,2*delta,0]){
    cube([B+C,delta,2*t],center=true);
    }
    translate([0,-2*delta,0]){
    cube([B+C,delta,2*t],center=true);
    }
    }}
}
}
}

else {
  //Printing View
    
  //Knob
translate([0,0,t/2]){
    union(){
    difference(){
    cylinder(t,WD/2,WD/2,center=true,$fn=100);
    union(){
    cylinder(2*t,B/2,B/2,center=true,$fn=100);
    translate([0,0,t/2]){
    cylinder(t,BH/2,BH/2,center=true,$fn=100);   
    }}}
    translate([((WD/2)-(ND/2)),0,t]){
    union(){
    cylinder(t,ND/2,ND/2,center=true,$fn=100);
    translate([0,0,t]){
    cylinder(t,ND/2,0,center=true,$fn=100);
    }
    translate([0,0,1.5*t]){
    sphere(ND/2,center=true,$fn=100);
    }}}}}
    
//Base            
translate([-1.5*WD,0,t/2]){
    difference(){
    union(){
    cube([1.25*WD,4*WD,t],center=true);
    translate([0,2*delta,t]){
    cube([2*(B+YT),ND,t+(2*C)],center=true);
    }
    translate([0,-2*delta,t]){
    cube([2*(B+YT),ND,t+(2*C)],center=true);
    }}
    cylinder(4*t,B/2,B/2,center=true,$fn=100);
    translate([0,2*delta,0]){
    cylinder(4*t,B/2,B/2,center=true,$fn=100);
    }
    translate([0,-2*delta,0]){
    cylinder(4*t,B/2,B/2,center=true,$fn=100);
    }
    translate([0,0,-t/2]){
    cylinder(2*Nutt,Nutd/2,Nutd/2,center=true,$fn=6);
    translate([0,2*delta,0]){
    cylinder(2*Nutt,Nutd/2,Nutd/2,center=true,$fn=6);
    }
    translate([0,-2*delta,0]){
    cylinder(2*Nutt,Nutd/2,Nutd/2,center=true,$fn=6);
    }}
    }}

//Yoke
translate([1.5*WD,0,0]){
if(Yoke==1){
//Straight Yoke
translate([0,0,t/2]){
    difference(){
    union(){
    cube([B+(2*YT),5*delta,t],center=true);
    cube([WD-ND,ND+(2*YT),t],center=true);
    translate([delta/2,0,0]){
    cylinder(t,(ND/2)+YT,(ND/2)+YT,center=true,$fn=100);
    }
    translate([-delta/2,0,0]){
    cylinder(t,(ND/2)+YT,(ND/2)+YT,center=true,$fn=100);
    }
    translate([0,2.5*delta,0]){
    cylinder(t,(B+(2*YT))/2,(B+(2*YT))/2,center=true,$fn=100);
    }
    translate([0,-2.5*delta,0]){
    cylinder(t,(B+(2*YT))/2,(B+(2*YT))/2,center=true,$fn=100);
    }}
    cube([WD-ND,ND+(2*C),2*t],center=true); 
    translate([delta/2,0,0]){
    cylinder(2*t,(ND/2)+C,(ND/2)+C,center=true,$fn=100);
    }
    translate([-delta/2,0,0]){
    cylinder(2*t,(ND/2)+C,(ND/2)+C,center=true,$fn=100);
    }
    translate([0,2.5*delta,0]){
    cylinder(2*t,(B+C)/2,(B+C)/2,center=true,$fn=100);
    }
    translate([0,1.5*delta,0]){
    cylinder(2*t,(B+C)/2,(B+C)/2,center=true,$fn=100);
    }
    translate([0,-2.5*delta,0]){
    cylinder(2*t,(B+C)/2,(B+C)/2,center=true,$fn=100);
    }
    translate([0,-1.5*delta,0]){
    cylinder(2*t,(B+C)/2,(B+C)/2,center=true,$fn=100);
    }
    translate([0,2*delta,0]){
    cube([B+C,delta,2*t],center=true);
    }
    translate([0,-2*delta,0]){
    cube([B+C,delta,2*t],center=true);
    }
    }}
}
else {
//Curved Yoke
translate([0,Off,t/2]){
    difference(){
    union(){
    cube([B+(2*YT),5*delta,t],center=true);
    translate([0,-R,0]){
    intersection(){
    difference(){
    cylinder(t,R+(ND/2)+YT,R+(ND/2)+YT,center=true,$fn=100);
    cylinder(2*t,R-(ND/2)-YT,R-(ND/2)-YT,center=true,$fn=100);
    }
    linear_extrude(2*t,center=true){
    polygon([[0,0],[1.5*TriX,3*TriY],[-1.5*TriX,3*TriY]]);
    }}}
    translate([delta/2,-Off,0]){
    cylinder(t,(ND/2)+YT,(ND/2)+YT,center=true,$fn=100);
    }
    translate([-delta/2,-Off,0]){
    cylinder(t,(ND/2)+YT,(ND/2)+YT,center=true,$fn=100);
    }
    translate([0,2.5*delta,0]){
    cylinder(t,(B+(2*YT))/2,(B+(2*YT))/2,center=true,$fn=100);
    }
    translate([0,-2.5*delta,0]){
    cylinder(t,(B+(2*YT))/2,(B+(2*YT))/2,center=true,$fn=100);
    }}
    translate([0,-R,0]){
    intersection(){
    difference(){
    cylinder(2*t,R+(ND/2)+(C/2),R+(ND/2)+(C/2),center=true,$fn=100);
    cylinder(2*t,R-(ND/2)-(C/2),R-(ND/2)-(C/2),center=true,$fn=100);
    }
    linear_extrude(2*t,center=true){
    polygon([[0,0],[1.5*TriX,3*TriY],[-1.5*TriX,3*TriY]]);
    }}}
    translate([delta/2,-Off,0]){
    cylinder(2*t,(ND/2)+(C/2),(ND/2)+(C/2),center=true,$fn=100);
    }
    translate([-delta/2,-Off,0]){
    cylinder(2*t,(ND/2)+(C/2),(ND/2)+(C/2),center=true,$fn=100);
    }
    translate([0,2.5*delta,0]){
    cylinder(2*t,(B+C)/2,(B+C)/2,center=true,$fn=100);
    }
    translate([0,1.5*delta,0]){
    cylinder(2*t,(B+C)/2,(B+C)/2,center=true,$fn=100);
    }
    translate([0,-2.5*delta,0]){
    cylinder(2*t,(B+C)/2,(B+C)/2,center=true,$fn=100);
    }
    translate([0,-1.5*delta,0]){
    cylinder(2*t,(B+C)/2,(B+C)/2,center=true,$fn=100);
    }
    translate([0,2*delta,0]){
    cube([B+C,delta,2*t],center=true);
    }
    translate([0,-2*delta,0]){
    cube([B+C,delta,2*t],center=true);
    }
    }}
}
}
}

Leave a Reply

Your email address will not be published. Required fields are marked *