// Pride wheelchair brake lever mods | |
// Ed Nisley KE4ZNU 2020-11 | |
/* [Layout options] */ | |
Layout = "Build"; // [Build, Show, Fit, TabCap, Handle, Knob, Support] | |
// Hold up the knob's inside | |
Support = true; | |
/* [Extrusion parameters] */ | |
/* [Hidden] */ | |
ThreadThick = 0.25; | |
ThreadWidth = 0.40; | |
HoleWindage = 0.2; | |
function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit); | |
function IntegerLessMultiple(Size,Unit) = Unit * floor(Size / Unit); | |
Protrusion = 0.1; // make holes end cleanly | |
inch = 25.4; | |
ID = 0; | |
OD = 1; | |
LENGTH = 2; | |
//---------------------- | |
// 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 dimensions] */ | |
WallThick = 4.0; // min wall thickness | |
Screw = [3.0,5.5,20.0]; // thread, head, length under head | |
Insert = [3.0,4.1,8.0]; // thread, knurl, length | |
//---------------------- | |
// Brake tab cap | |
BrakeTab = [15,21,3.1]; // length to wheel, width, thickness | |
BrakeTabSagitta = 8.0; // height of curved endcap | |
CapOAL = [BrakeTab.y + 2*WallThick,BrakeTab.y + 2*WallThick,BrakeTab.z + 2*WallThick]; | |
module TabCap() { | |
difference() { | |
rotate(180/8) | |
cylinder(d=CapOAL.y,h=CapOAL.z,center=true,$fn=8); | |
translate([BrakeTab.x/2,0,0]) | |
cube(BrakeTab,center=true); | |
rotate(180/8) | |
cylinder(d=BrakeTab.y/cos(180/8),h=BrakeTab.z,center=true,$fn=8); | |
} | |
} | |
//---------------------- | |
// Brake lever handle | |
// Soft covering with rounded sides that we square off for simplicity | |
HandleRibs = [15,34,14]; // ignoring slight taper from end | |
HandleCore = [50.0,24.0,12.0]; // straight section of lever to top of ribs | |
HandleTipWidth = 30.0; // ignoring actual sector height | |
module Handle() { | |
union() { | |
hull() { | |
rotate(180/8) | |
cylinder(d=HandleTipWidth/cos(180/8),h=HandleCore.z,center=true,$fn=8); | |
translate([-HandleCore.x/2,0,0]) | |
cube(HandleCore,center=true); | |
} | |
translate([-(3*HandleCore.x/2 - Protrusion),0,0]) // extend base for ball trimming | |
cube(HandleCore,center=true); | |
translate([-HandleRibs.x/2,0,0]) | |
cube(HandleRibs,center=true); | |
} | |
} | |
//---------------------- | |
// Support structure for handle cavity inside knob | |
// Totally ad-hoc tweakage | |
// Remember it's lying on its side to match the handle | |
NumRibs = 2 + 1; // must be odd | |
RibSpace = floor(HandleCore.z/(NumRibs + 1)); | |
module KnobSupport() { | |
color("Yellow") { // support overlaps in the middle | |
render(convexity=3) | |
intersection() { | |
for (k=[-1,1]) | |
translate([0,k*ThreadThick,0]) // shrink inward to break adhesion | |
Handle(); | |
translate([(HandleCore.x - HandleRibs.x)/2 - HandleCore.x - Protrusion,0,0]) | |
cube([HandleCore.x - HandleRibs.x,HandleRibs.y,HandleCore.z],center=true); | |
union() | |
for (k=[-floor(NumRibs/2):floor(NumRibs/2)]) | |
translate([0,0,k* RibSpace]) | |
cube([2*HandleCore.x,HandleRibs.y,2*ThreadWidth],center=true); | |
} | |
translate([(HandleCore.x - HandleRibs.x)/2 - HandleCore.x,0,0]) | |
cube([HandleCore.x - HandleRibs.x,4*ThreadWidth,NumRibs*RibSpace],center=true); | |
} | |
} | |
//---------------------- | |
// Brake handle knob | |
// Largely built with magic numbers | |
// Includes support because it's not really optional | |
KnobOD = 55.0; | |
KnobOffset = HandleRibs.x/1; | |
KnobSides = 2*4*3; | |
module Knob() { | |
difference() { | |
hull() { | |
resize([0,HandleRibs.y + 4*WallThick,HandleCore.x + HandleTipWidth/2 + WallThick]) | |
sphere(d=KnobOD,$fn=KnobSides); | |
} | |
translate([0,0,KnobOffset]) | |
rotate([0,-90,0]) | |
Handle(); | |
for (i=[-1,1],k=[-1,1]) | |
translate([i*KnobOD/4,0,k*KnobOD/4]) { | |
rotate([90,0,0]) | |
PolyCyl(Insert[OD],1.5*Insert[LENGTH],6); | |
translate([0,-Screw[LENGTH]/2,0]) | |
rotate([-90,0,0]) | |
PolyCyl(Screw[ID],KnobOD,6); | |
translate([0,Screw[LENGTH] - Insert[LENGTH],0]) | |
rotate([-90,0,0]) | |
PolyCyl(Screw[OD],KnobOD,6); | |
} | |
} | |
if (Support) | |
translate([0,0,KnobOffset]) | |
rotate([0,-90,0]) | |
KnobSupport(); | |
} | |
//---------------------- | |
// Lash it together | |
if (Layout == "TabCap") { | |
TabCap(); | |
} | |
if (Layout == "Handle") { | |
Handle(); | |
} | |
if (Layout == "Support") { | |
KnobSupport(); | |
} | |
if (Layout == "Knob") { | |
Knob(); | |
} | |
if (Layout == "Show") { | |
translate([60,0,0]) | |
TabCap(); | |
Knob(); | |
} | |
if (Layout == "Fit") { | |
translate([60,0,0]) | |
difference() { | |
TabCap(); | |
translate([0,0,CapOAL.z/2]) | |
cube(CapOAL,center=true); | |
} | |
difference() { | |
Knob(); | |
translate([KnobOD + KnobOD/4,0*KnobOD,0]) | |
cube(2*KnobOD,center=true); | |
translate([-KnobOD,-KnobOD,0]) | |
cube(2*KnobOD,center=true); | |
} | |
} | |
if (Layout == "Build") { | |
translate([KnobOD/2,0,(CapOAL.y*cos(180/8))/2]) | |
rotate([0,-90,90]) | |
TabCap(); | |
for (j=[-1,1]) | |
translate([0,-j*0.75*HandleCore.x,0]) | |
difference() { | |
rotate([j*90,0,0]) | |
Knob(); | |
translate([0,0,-KnobOD]) | |
cube(2*KnobOD,center=true); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
More details on my blog at https://wp.me/poZKh-9Et