|
// Hinge brackets for rolling garden stool |
|
// Ed Nisley – KE4ZNU – 2019-06 |
|
|
|
Layout = "Build"; // [Block,Build,Show] |
|
|
|
Support = true; |
|
|
|
/* [Hidden] */ |
|
|
|
ThreadThick = 0.20; |
|
ThreadWidth = 0.40; |
|
|
|
HoleWindage = 0.2; |
|
|
|
Protrusion = 0.1; // make holes end cleanly |
|
|
|
ID = 0; |
|
OD = 1; |
|
LENGTH = 2; |
|
|
|
//———————- |
|
// Dimensions |
|
|
|
SeatThick = 6.0; // seat panel above cart body |
|
|
|
HingePin = [11.5,12.0,7.0]; // ID = tip OD = base |
|
|
|
HingeOffset = 8.0; // hinge axis above cart body (larger than radius!) |
|
HingeBolster = [5.0,24.0,SeatThick]; // backing block below hinge |
|
|
|
Block = [25.0,HingeOffset + 30.0,23.0]; // Z = above cart body |
|
|
|
Screw = [3.8,11.0,2.5]; // self-tapping #8 OD=head LENGTH=head thickness |
|
ScrewOC = 15.0; // spacing > greater than head OD |
|
ScrewOffset = Block.y/2 – (ScrewOC/2 + Screw[OD]/2 + HingeOffset); // space for head behind hinge |
|
|
|
BlockRadius = 7.0; // corner rounding |
|
|
|
//———————- |
|
// 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); |
|
} |
|
|
|
// Basic block shape |
|
// X axis collinear with hinge axes, hinge base at X=0 |
|
|
|
module HingeBlock() { |
|
|
|
PinSides = 3*4; |
|
PinSupport = [HingePin[LENGTH] – 2*ThreadWidth,0.6*HingeOffset,HingePin[OD]]; // pre-rotated |
|
|
|
union() { |
|
translate([Protrusion,Block.y/2 – HingeOffset,HingeOffset]) |
|
rotate([0,-90,0]) |
|
rotate(180/PinSides) |
|
cylinder(d=HingePin[OD],h=HingePin[LENGTH] + Protrusion,$fn=PinSides); |
|
difference() { |
|
hull() { |
|
translate([Block.x – BlockRadius,-(Block.y/2 – BlockRadius),Block.z – BlockRadius]) |
|
rotate(180/PinSides) |
|
sphere(r=BlockRadius/cos(180/PinSides),$fn=PinSides); |
|
translate([0,-(Block.y/2 – BlockRadius),Block.z – BlockRadius]) |
|
rotate([0,90,0]) rotate(180/PinSides) |
|
cylinder(r=BlockRadius/cos(180/PinSides),h=Block.x/2,$fn=PinSides); |
|
translate([Block.x – BlockRadius,(Block.y/2 – BlockRadius),Block.z – BlockRadius]) |
|
sphere(r=BlockRadius/cos(180/PinSides),$fn=PinSides); |
|
translate([0,(Block.y/2 – BlockRadius),Block.z – BlockRadius]) |
|
rotate([0,90,0]) rotate(180/PinSides) |
|
cylinder(r=BlockRadius/cos(180/PinSides),h=Block.x/2,$fn=PinSides); |
|
translate([0,-Block.y/2,0]) |
|
cube([Block.x,Block.y – HingeOffset,Block.z/2],center=false); |
|
translate([0,Block.y/2 – HingeOffset,HingeOffset]) |
|
rotate([0,90,0]) rotate(180/PinSides) |
|
cylinder(r=HingeOffset/cos(180/PinSides),h=Block.x,$fn=PinSides); |
|
} |
|
translate([Block.x/2 + HingeBolster.x,0,(SeatThick – Protrusion)/2]) |
|
cube([Block.x,2*Block.y,SeatThick + Protrusion],center=true); |
|
translate([0,-HingeBolster.y,(SeatThick – Protrusion)/2]) |
|
cube([3*Block.x,Block.y,SeatThick + Protrusion],center=true); |
|
for (j=[-1,1]) |
|
translate([Block.x/2,j*ScrewOC/2 + ScrewOffset,-4*ThreadThick]) |
|
rotate(180/8) |
|
PolyCyl(Screw[ID],Block.z,8); |
|
} |
|
} |
|
|
|
if (Support) { // totally ad-hoc |
|
color("Yellow") render(convexity=4) |
|
difference() { |
|
translate([-(PinSupport.x/2 + 2*ThreadWidth),Block.y/2 – PinSupport.y/2,HingeOffset]) |
|
cube(PinSupport,center=true); |
|
translate([Protrusion,Block.y/2 – HingeOffset,HingeOffset]) |
|
rotate([0,-90,0]) |
|
rotate(180/PinSides) |
|
cylinder(d=HingePin[OD] + 2*ThreadThick,h=2*HingePin[LENGTH],$fn=PinSides); |
|
for (i=[-1:1]) |
|
translate([i*4*ThreadWidth – HingePin[LENGTH]/2, |
|
Block.y/2 – (PinSupport.y + 1*ThreadThick), |
|
HingeOffset]) |
|
cube([2*ThreadWidth,2*PinSupport.y,2*PinSupport.z],center=true); |
|
} |
|
} |
|
} |
|
|
|
module Blocks(Hand = "Left") { |
|
if (Hand == "Left") |
|
HingeBlock(); |
|
else |
|
mirror([1,0,0]) |
|
HingeBlock(); |
|
} |
|
|
|
//- Build it |
|
|
|
if (Layout == "Block") |
|
HingeBlock(); |
|
|
|
if (Layout == "Show") { |
|
translate([1.5*HingePin[LENGTH],0,0]) |
|
Blocks("Left"); |
|
translate([-1.5*HingePin[LENGTH],0,0]) |
|
Blocks("Right"); |
|
} |
|
|
|
if (Layout == "Build") { |
|
translate([0,-Block.z/2,Block.y/2]) |
|
rotate([-90,0,0]) { |
|
translate([1.5*HingePin[LENGTH],0,0]) |
|
Blocks("Left"); |
|
translate([-1.5*HingePin[LENGTH],0,0]) |
|
Blocks("Right"); |
|
} |
|
|
|
} |