The bent-steel brake levers on our Drive Blue Streak wheelchair present themselves edge-on to the rider:

There are good mechanical reasons for shaping and orienting the steel like that, but the handle concentrates the considerable force required to push the brake tab into the rubberoid tire on your (well, my) palms. After a couple of weeks, I decided I didn’t need two more sore spots and conjured a palm-filling knob from the vasty digital deep:

Bonus part: the little octagon near the wheel prevents the leg rest (seen in the first picture) from smashing into the end of the brake tab and chipping the lovely blue powder coat. The brown fuzzy felt foot seemed like a good idea at the time, but isn’t strictly necessary.
A cylindrical handle on Thingiverse apparently fits on the bare steel underneath the rubberish “cushion”, but cutting a perfectly good, albeit uncomfortable, cushion off seemed like a step in the wrong direction. My knob thus descends from a doodle of the OEM dimensions:

The knob builds in two halves adjoining the bonus octagon, which stands on edge to eliminate support inside its slot:

You (probably) need two of all those shapes, a job your slicer is ready to perform. At three hours for each knob, I just printed the same G-Code twice.
You can customize the knob width to fit your palm, with the other two dimensions fitting themselves around the cushion. Mary and I settled on a knob size that fits both our hands reasonably well, so it’s probably not critical.
I tried building the knob halves without support for the first prototype, but the sloped upper surface produced awful bridging:

It’s easy enough to design a customized support structure:

I oriented the knob to put the split on the narrow sides of the brake handle in order to not have a seam facing my palm:

The quartet of M3×20 mm socket-head cap screws thread into brass inserts epoxied into the rear half. I recessed their heads deeply into the front half and avoided thinking too hard about plugs matching the surface curvature:

The low-vertex-count polygonal shape is a stylin’ thing and produces a nice feel during a firm shove, at least to my paws. Although I’d rather not need a wheelchair at all, setting the brakes now seems authoritative instead of annoying.
The OpenSCAD source code as a GitHub gist:
// 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); | |
} | |
} |
A doodle with dimensions of other parts:

The angled tab on the middle left is for the leg rest release latch, but I decided not to silk-purse-ize the thing.
One thought on “Drive Wheelchair Brake Knob”
Comments are closed.