Created
October 13, 2021 14:30
-
-
Save ednisley/5244a30ea2373ca765dd59bc1d8710d0 to your computer and use it in GitHub Desktop.
OpenSCAD source code: solid models to install BBS02 on Terry Symmetry
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Terry Symmetry - Bafang e-bike conversion | |
// Ed Nisley KE4ZNU 2021-10 | |
Layout = "AllBlocks"; // [Frame,Block,AllBlocks,BuildBlock,DispMount,BrakeMagnet,ShiftCap,BuildShiftCap,MotorSpacer,BuildSpacer,Case,HalfCase,HeadClip, BuildClip,NutMold,ShowAll] | |
Station = 4; // [0:4] | |
Support = false; | |
//- Extrusion parameters must match reality! | |
/* [Hidden] */ | |
ThreadThick = 0.25; | |
ThreadWidth = 0.40; | |
HoleWindage = 0.2; | |
Protrusion = 0.1; // make holes end cleanly | |
inch = 25.4; | |
function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit); | |
ID = 0; | |
OD = 1; | |
LENGTH = 2; | |
//---------- | |
// Dimensions | |
// Bike frame lies along X axis, rear to +X | |
DownTube = [1.125*inch + HoleWindage,1.25*inch + HoleWindage,450]; // ID=tube OD=lug LENGTH=longer | |
FrameSides = 24; | |
SpeedOD = 3.5; // speed sensor cable | |
PowerOD = 6.7; // power cable | |
Harness = [6.0,13.0,30.0]; // main motor-to-handlebar cable | |
GearOD = 3.0; // gear sensor cable | |
HandlebarMax = 1*inch; // middle handlebar diameter | |
HandlebarMin = 24.0; // .. tape section | |
HeadTube = [32.0,35.0,8.0]; // ID=tube OD=lug LENGTH=clear between lugs | |
BottleStud = [5.0,10.0,IntegerMultiple(1.2,ThreadThick)]; // frame fitting for bottle screws | |
BafangClampID = 22.3; // their handlebar clamp diameter | |
ShiftOD = 2.0; // rear shifter cable | |
ShiftFerrule = [ShiftOD,6.0,10.0]; | |
ShiftOffset = 7.5; // .. from downtube | |
ShiftAngle = -20; // .. from midline | |
BatteryBoss = [5.5,16.0,2.5]; // battery mount boss, center boss is round | |
BossSlotOAL = 32.0; // .. end bosses are elongated | |
BossOC = 65.0; // .. along length of mount | |
LatchWidth = 10.0; // battery latches to mount plate | |
LatchThick = 1.5; | |
LatchOC = 56.0; | |
// Per-block features | |
// first element is unadorned block | |
Latches = [false,true,true,false,false]; // clearance for battery latch clips | |
Notch = [false,true,true,false,false]; // notch for battery screw pockets | |
Recess = ["None","TeeNut","Bottle","Bottle","TeeNut"]; // stud or nut clearance against frame | |
HarnessCable = [false,true,true,true,true]; // passage for main harness cable | |
ShiftWire = [false,true,true,true,true]; // .. shifter wire through sensor | |
Ferrules = ["None","Both","Front","None","Back"]; // ferrule and bushing sockets | |
GearCable = [false,false,true,true,true]; // .. gear sensor cable | |
// M3 SHCS nyloc nut | |
Screw3 = [3.0,5.5,35.0]; // OD, LENGTH = head | |
Washer3 = [3.7,7.0,0.7]; | |
Nut3 = [3.0,6.0,4.0]; | |
// M4 SHCS nyloc nut | |
Screw4 = [4.0,7.0,4.0]; // OD, LENGTH = head | |
Washer4 = [4.2,8.9,1.0]; | |
Nut4 = [4.0,7.8,5.0]; | |
// M5 SHCS nyloc nut | |
Screw5 = [5.0,8.5,5.0]; // OD, LENGTH = head | |
Washer5 = [5.5,10.1,1.0]; | |
Nut5 = [5.0,9.0,5.0]; | |
Teenut5 = [6.5,17.0,8.0,2.0]; // OD, LENGTH+1 = flange | |
// 10-32 Philips nyloc nut | |
Screw10 = [5.2,9.8,3.6]; // OD, LENGTH = head | |
Washer10 = [5.5,11.0,1.0]; | |
Nut10 = [5.2,10.7,6.2]; | |
CableTie = [150,5.0,2.0]; | |
WallThick = 4.0; // thinnest wall | |
BlockMinZ = -(DownTube[ID]/2 + WallThick); | |
BlockMaxZ = DownTube[ID]/2 + max(WallThick,Teenut5[LENGTH]) + BatteryBoss[LENGTH]; | |
Block = [25.0,78.0,BlockMaxZ - BlockMinZ]; // Y = battery width | |
echo(str("Block: ",Block)); | |
Kerf = 0.5; // cut through middle to apply compression | |
CornerRadius = 5.0; | |
EmbossDepth = 2*ThreadThick; // lettering depth | |
//---------------------- | |
// 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(d=(FixDia + HoleWindage),h=Height,$fn=Sides); | |
} | |
// frame downtube | |
module Frame() { | |
rotate([0,90,0]) rotate(180/FrameSides) | |
cylinder(d=DownTube[ID],h=DownTube[LENGTH],center=true,$fn=FrameSides); | |
} | |
// clamp overall shape | |
module ClampBlock(BlkNum = 1) { | |
Screw = Screw4; | |
Washer = Washer4; | |
Nut = Nut4; | |
ScrewOC = LatchOC; | |
ScrewSides = 8; | |
ScrewOrient = 180/ScrewSides; | |
ScrewRecess = LatchThick + Screw[LENGTH] + Washer[LENGTH] + 1.0; | |
echo(str("Screw length: ",Block.z - ScrewRecess)); | |
difference() { | |
hull() | |
for (i=[-1,1], j=[-1,1]) | |
translate([i*(Block.x/2 - CornerRadius),j*(Block.y/2 - CornerRadius),BlockMinZ]) | |
cylinder(r=CornerRadius,h=Block.z,$fn=4*3); | |
cube([2*Block.x,2*Block.y,Kerf],center=true); | |
Frame(); | |
for (j=[-1,1]) { | |
translate([0,j*ScrewOC/2,BlockMinZ - Protrusion]) | |
rotate(ScrewOrient) | |
PolyCyl(Screw[ID],2*Block.z,ScrewSides); | |
translate([0,j*ScrewOC/2,BlockMaxZ - ScrewRecess]) | |
rotate(ScrewOrient) | |
PolyCyl(Washer[OD],BlockMaxZ,ScrewSides); | |
} | |
if (Latches[BlkNum]) | |
for (i=[-1,1]) | |
translate([0,i*LatchOC/2,BlockMaxZ - LatchThick/2 + Protrusion]) | |
cube([BossSlotOAL,LatchWidth,LatchThick + Protrusion],center=true); | |
if (Notch[BlkNum]) | |
translate([0,0,BlockMaxZ - BatteryBoss[LENGTH]/2 + Protrusion]) | |
cube([BossSlotOAL,BatteryBoss[OD],BatteryBoss[LENGTH] + Protrusion],center=true); | |
if (HarnessCable[BlkNum]) | |
rotate([-155,0,0]) { | |
translate([0,DownTube[ID]/2 - Harness[ID]/2,0]) | |
cube([2*Block.x,2*Harness[ID],Harness[ID]],center=true); | |
translate([0,DownTube[ID]/2 + Harness[ID]/2,0]) | |
rotate([0,90,0]) | |
translate([0,0,-Block.x]) | |
rotate(180/6) | |
PolyCyl(Harness[ID],2*Block.x,6); | |
} | |
if (GearCable[BlkNum]) | |
rotate([-45,0,0]) { | |
translate([0,DownTube[ID]/2 - GearOD/2,0]) | |
cube([2*Block.x,2*GearOD,GearOD],center=true); | |
translate([0,DownTube[ID]/2 + GearOD/2,0]) | |
rotate([0,90,0]) | |
translate([0,0,-Block.x]) | |
rotate(180/6) | |
PolyCyl(GearOD,2*Block.x,6); | |
} | |
rotate([ShiftAngle,0,0]) { | |
if (ShiftWire[BlkNum]) | |
translate([-Block.x,DownTube[ID]/2 + ShiftOffset,0]) | |
rotate([0,90,0]) rotate(-(90 + ShiftAngle)) | |
PolyCyl(ShiftOD,2*Block.x,6); | |
if (Ferrules[BlkNum] == "Back" || Ferrules[BlkNum] == "Both") { | |
i = 1; | |
translate([i*(Block.x/2 - ShiftFerrule[LENGTH]),DownTube[ID]/2 + ShiftOffset,0]) | |
rotate([0,i*90,0]) rotate(-i*(90 + ShiftAngle)) | |
PolyCyl(ShiftFerrule[OD],Block.x,6); | |
} | |
if (Ferrules[BlkNum] == "Front" || Ferrules[BlkNum] == "Both") { | |
i = -1; | |
translate([i*(Block.x/2 - ShiftFerrule[LENGTH]),DownTube[ID]/2 + ShiftOffset,0]) | |
rotate([0,i*90,0]) rotate(-i*(90 + ShiftAngle)) | |
PolyCyl(ShiftFerrule[OD],Block.x,6); | |
} | |
} | |
if (Recess[BlkNum] == "Bottle") { | |
rotate(ScrewOrient) { | |
PolyCyl(BottleStud[ID],2*Block.z,ScrewSides); | |
PolyCyl(BottleStud[OD],DownTube[ID]/2 + BottleStud[LENGTH],ScrewSides); | |
} | |
} | |
else if (Recess[BlkNum] == "TeeNut") { | |
rotate(ScrewOrient) { | |
PolyCyl(Teenut5[ID],2*Block.z,ScrewSides); | |
PolyCyl(Teenut5[OD],DownTube[ID]/2 + Teenut5[LENGTH+1],ScrewSides); | |
} | |
} | |
translate([0,15,BlockMaxZ - EmbossDepth/2 + Protrusion]) | |
cube([9.0,8,EmbossDepth],center=true); | |
translate([0,17,BlockMinZ + EmbossDepth/2 - Protrusion]) | |
cube([9.0,8,EmbossDepth],center=true); | |
translate([0,-5,BlockMinZ + EmbossDepth/2 - Protrusion]) | |
cube([9.0,30,EmbossDepth],center=true); | |
} | |
translate([0,15,BlockMaxZ - EmbossDepth]) | |
linear_extrude(height=EmbossDepth) | |
rotate(90) | |
text(text=str(BlkNum),size=5,spacing=1.00,font="Bitstream Vera Sans:style=Bold", | |
halign="center",valign="center"); | |
translate([0,17,BlockMinZ]) | |
linear_extrude(height=EmbossDepth) | |
rotate(-90) mirror([0,1,0]) | |
text(text=str(BlkNum),size=4.5,spacing=1.00,font="Bitstream Vera Sans:style=Bold", | |
halign="center",valign="center"); | |
translate([0,-5,BlockMinZ]) | |
linear_extrude(height=EmbossDepth) | |
rotate(-90) mirror([0,1,0]) | |
text(text="KE4ZNU",size=4.5,spacing=1.00,font="Bitstream Vera Sans:style=Bold", | |
halign="center",valign="center"); | |
} | |
// complete clamp block | |
module Clamp(BlkNum = 1) { | |
ClampBlock(BlkNum); | |
if (Support) | |
color("Yellow") { | |
NumRibs = 7; | |
RibOC = Block.x/(NumRibs - 1); | |
intersection() { | |
translate([0,0,BlockMaxZ + Kerf/2]) | |
cube([2*Block.x,2*Block.y,Block.z],center=true); | |
union() { | |
translate([0,0,Kerf/2]) | |
cube([1.1*Block.x,DownTube[ID] - 2*ThreadThick,4*ThreadThick],center=true); | |
for (i=[-floor(NumRibs/2):floor(NumRibs/2)]) | |
translate([i*RibOC,0,0]) | |
rotate([0,90,0]) rotate(180/FrameSides) | |
cylinder(d=DownTube[ID] - 2*ThreadThick,h=2*ThreadWidth,$fn=FrameSides,center=true); | |
/* | |
translate([0,DownTube[ID]/2 + PowerOD/2,Kerf/2]) | |
cube([1.1*Block.x,PowerOD - 2*ThreadWidth,4*ThreadThick],center=true); | |
for (i=[-floor(NumRibs/2):floor(NumRibs/2)]) | |
translate([i*RibOC,DownTube[ID]/2 + PowerOD/2,PowerOD/4]) | |
cube([2*ThreadWidth,PowerOD - 2*ThreadWidth,PowerOD/2 - 2*ThreadThick],center=true); | |
translate([0,-(DownTube[ID]/2 + SpeedOD/2),Kerf/2]) | |
cube([1.1*Block.x,SpeedOD - 2*ThreadWidth,4*ThreadThick],center=true); | |
for (i=[-floor(NumRibs/2):floor(NumRibs/2)]) | |
translate([i*RibOC,-(DownTube[ID]/2 + SpeedOD/2),SpeedOD/4]) | |
cube([2*ThreadWidth,SpeedOD - 2*ThreadWidth,SpeedOD/2 - 2*ThreadThick],center=true); | |
*/ | |
} | |
} | |
} | |
} | |
// Half clamp sections for printing | |
module HalfClamp(BlkNum = 1, Section = "Upper") { | |
render() | |
if (Section == "Upper") | |
intersection() { | |
translate([0,0,BlockMaxZ/2]) | |
cube([1.1*Block.x,Block.y,BlockMaxZ],center=true); | |
translate([0,0,-Kerf/2]) | |
Clamp(BlkNum); | |
} | |
else | |
intersection() { | |
translate([0,0,-BlockMinZ/2]) | |
cube([1.1*Block.x,Block.y,-BlockMinZ],center=true); | |
translate([0,0,-BlockMinZ]) | |
Clamp(BlkNum); | |
} | |
} | |
// Handlebar mount for controller | |
module DispMount() { | |
ClampRing = [HandlebarMax,HandlebarMax + 2*WallThick,10.0]; | |
ClampOffset = (HandlebarMax + BafangClampID)/2 + 6.0; | |
DispStudLenth = 16.5; | |
NumSides = 24; | |
Tilt = 0*atan2((ClampRing[OD] - BafangClampID)/2,ClampOffset); | |
echo(str("Tilt: ",Tilt)); | |
difference() { | |
union() { | |
hull() { | |
cylinder(d=ClampRing[OD],h=ClampRing[LENGTH],$fn=NumSides); | |
translate([0,ClampOffset,0]) | |
cylinder(d=BafangClampID,h=ClampRing[LENGTH],$fn=NumSides); | |
} | |
translate([0,ClampOffset,0]) | |
cylinder(d=BafangClampID,h=ClampRing[LENGTH] + DispStudLenth,$fn=NumSides); | |
translate([-ClampRing[ID]/4,-(ClampRing[OD]/2),ClampRing[LENGTH]/2]) | |
rotate([0,90,0]) rotate(180/8) | |
cylinder(d=ClampRing[LENGTH]/cos(180/8),h=ClampRing[ID]/2,$fn=8); | |
} | |
cube([Kerf,4*ClampOffset,4*DispStudLenth],center=true); | |
translate([0,0,-Protrusion]) | |
cylinder(d=ClampRing[ID],h=ClampRing[LENGTH] + 2*Protrusion,$fn=NumSides); | |
translate([-ClampRing[ID]/2,-(ClampRing[OD]/2),ClampRing[LENGTH]/2]) | |
rotate([0,90,0]) rotate(180/8) | |
PolyCyl(Screw3[ID],ClampRing[ID],8); | |
for (i=[-1,1]) | |
translate([i*ClampRing[ID]/4,-(ClampRing[OD]/2),ClampRing[LENGTH]/2]) | |
rotate([0,i*90,0]) rotate(180/8) | |
PolyCyl(Washer3[OD],ClampRing[ID],$fn=8); | |
translate([-5,25,EmbossDepth/2 - Protrusion/2]) | |
rotate(Tilt) | |
cube([4.5,21.5,EmbossDepth + Protrusion],center=true); | |
if (false) | |
translate([-6,25,EmbossDepth/2 - Protrusion/2]) | |
rotate(-Tilt) | |
cube([4.0,27,EmbossDepth + Protrusion],center=true); | |
} | |
translate([-5,25,0]) | |
linear_extrude(height=EmbossDepth) | |
rotate(90 + Tilt) mirror([0,1,0]) | |
text(text="KE4ZNU",size=3.3,spacing=1.05,font="Bitstream Vera Sans:style=Bold", | |
halign="center",valign="center"); | |
if (false) | |
translate([-6,25,0]) | |
linear_extrude(height=EmbossDepth) | |
rotate(90 - Tilt) mirror([0,1,0]) | |
text(text="softsolder.com",size=2.2,spacing=1.05,font="Bitstream Vera Sans:style=Bold", | |
halign="center",valign="center"); | |
} | |
// Mold to reshape speed sensor nut | |
SensorNut = [0,14.4,13.0]; | |
SensorMold = [SensorNut[OD] + 2*WallThick,SensorNut[OD] + 2*WallThick,SensorNut[LENGTH] + WallThick]; | |
MoldSides = 20; | |
RodOD = 1.6; | |
module NutMoldBlock() { | |
difference() { | |
translate([0,0,SensorMold.z/2]) | |
cube(SensorMold,center=true); | |
translate([0,0,WallThick]) | |
rotate(180/MoldSides) | |
PolyCyl(SensorNut[OD],2*SensorNut[LENGTH],MoldSides); | |
translate([0,0,-Protrusion]) | |
rotate(180/8) | |
PolyCyl(SpeedOD,2*SensorMold.z,8); | |
for (i=[-1,1]) | |
translate([i*(SensorMold.x/2 - WallThick/2),SensorMold.y,SensorMold.z/2]) | |
rotate([90,0,0]) | |
PolyCyl(RodOD,2*SensorMold.y,6); | |
} | |
} | |
module NutMold() { | |
gap = 1.0; | |
for (j=[-1,1]) | |
translate([0,j*gap,0]) | |
intersection() { | |
translate([0,j*SensorMold.y,0]) | |
cube(2*SensorMold,center=true); | |
NutMoldBlock(); | |
} | |
} | |
// Brake sensor magnet mount | |
// Magnetized through thinnest section | |
module BrakeMagnet() { | |
Magnet = [10.5,3.0,5.5]; | |
Plate = 2*ThreadThick; | |
BrakeRad = 10.0; // brake handle curve Radius | |
Holder = [2*BrakeRad,7.0,Magnet.z + Plate]; | |
difference() { | |
intersection() { | |
translate([0,-BrakeRad,0]) | |
rotate(180/24) | |
cylinder(r=BrakeRad,h=Holder.z,$fn=24); | |
translate([0,BrakeRad - Holder.y,Holder.z/2]) | |
cube([2*BrakeRad,2*BrakeRad,Holder.z],center=true); | |
translate([0,0,-2*BrakeRad/sqrt(2) + Holder.z - 3.0 + BrakeRad]) | |
rotate([0,45,0]) | |
cube(2*[BrakeRad,2*BrakeRad,BrakeRad],center=true); | |
} | |
translate([0,Magnet.y/2 - Holder.y - Protrusion/2,Magnet.z/2 + Plate + Protrusion/2]) | |
cube(Magnet + [0,Protrusion,Protrusion],center=true); | |
} | |
} | |
// Shift stud cap | |
// With passage for harness cable | |
CapBlock = [18,18,16.5]; | |
module ShiftCap() { | |
Rounding = 3.5; | |
CapM = 3.0; | |
StudBase = [12.5,12.5,4.5]; | |
Stud = [5.0,9.3,15.5]; | |
difference() { | |
hull() { | |
translate([0,0,CapBlock.z - 0.5]) | |
PolyCyl(Washer5[OD],0.5,12); | |
for (i=[-1,1], j=[-1,1]) | |
translate([i*(CapBlock.x/2 - Rounding),j*(CapBlock.y/2 - Rounding),0]) | |
sphere(r=Rounding,$fn=12); | |
translate([-CapBlock.x/2,-Harness[ID]/2 - StudBase.y/2,StudBase.z/2]) | |
rotate([0,90,0]) | |
cylinder(d=Harness[ID] + 2*WallThick,h=CapBlock.x,$fn=12); | |
} | |
translate([0,0,-(DownTube[ID]/2 - CapM)]) | |
Frame(); | |
PolyCyl(Screw5[ID],2*CapBlock.z,6); | |
PolyCyl(Stud[OD],Stud[LENGTH],12); | |
translate([0,0,StudBase.z/2]) | |
cube(StudBase,center=true); | |
translate([0,-StudBase.y/2,StudBase.z/2]) | |
cube(StudBase + [0,-StudBase.y/2,0],center=true); | |
translate([-CapBlock.x,-Harness[ID]/2 - StudBase.y/2,StudBase.z/2]) | |
rotate([0,90,0]) | |
cylinder(d=1.5*Harness[ID],h=2*CapBlock.x,$fn=12); | |
} | |
} | |
// Head tube clip for harness cable joint | |
module HeadClip() { | |
CableOD = Harness[OD]; | |
difference() { | |
linear_extrude(height=HeadTube[LENGTH],convexity=10) | |
difference() { | |
hull() { | |
circle(d=HeadTube[ID] + 2*WallThick,$fn=FrameSides); | |
translate([0,-(HeadTube[ID] + CableOD)/2]) | |
rotate(180/(FrameSides/2)) | |
circle(d=CableOD + 2*WallThick,$fn=FrameSides/2); | |
} | |
circle(d=HeadTube[ID] + HoleWindage,$fn=FrameSides); | |
translate([0,-(HeadTube[ID] + CableOD)/2]) | |
rotate(180/(FrameSides/2)) | |
circle(d=CableOD + HoleWindage,$fn=FrameSides/2); | |
translate([0,-HeadTube[ID]/2]) | |
square(0.75*CableOD,center=true); | |
translate([0,HeadTube[ID]]) | |
square(2*HeadTube[ID],center=true); | |
} | |
translate([0,-(HeadTube[ID]/2 + CableOD + WallThick - CableTie.z/2),HeadTube[LENGTH]/2]) | |
cube([HeadTube[ID],CableTie.z,CableTie.y],center=true); | |
for (i=[-1,1]) | |
translate([i*(HeadTube[ID]/2 + WallThick - CableTie.z/2),0,HeadTube[LENGTH]/2]) | |
cube([CableTie.z,HeadTube[ID],CableTie.y],center=true); | |
} | |
} | |
// Motor Reaction Block | |
// Holds motor away from downtube enough to miss rear shift wire | |
MotorOD = 111; // motor frame dia | |
MotorOffset = 10.0; // motor OD tangent wrt lug edge | |
ShiftSpace = 6.0; // motor to frame space | |
LugLength = 25.0; // length of section over BB lug | |
Spacer = [5.0 + LugLength,DownTube[ID]/2,4*ShiftSpace]; | |
SpaceAngle = 0*atan(1.8/Spacer.x); // tilt due to non-right-angle meeting | |
echo(str("Spacer angle: ",SpaceAngle)); | |
module MotorSpacer() { | |
difference() { | |
translate([LugLength - Spacer.x/2,0,0]) | |
cube(Spacer,center=true); | |
translate([0,0,DownTube[ID]/2]) | |
rotate([0,90 + SpaceAngle,0]) rotate(180/FrameSides) | |
cylinder(d=DownTube[ID],h=DownTube[LENGTH],$fn=FrameSides,center=true); | |
translate([DownTube[LENGTH]/2,0,DownTube[ID]/2 - DownTube[LENGTH]*sin(SpaceAngle)/2]) // concentric with ID | |
rotate([0,90 + SpaceAngle,0]) rotate(180/FrameSides) | |
cylinder(d=DownTube[OD],h=DownTube[LENGTH],$fn=FrameSides,center=true); | |
translate([MotorOffset,0,-(MotorOD/2 + ShiftSpace)]) | |
rotate([90,0,0]) rotate(180/48) | |
cylinder(d=MotorOD,h=2*Spacer.y,$fn=48,center=true); | |
} | |
} | |
// Programming cable case | |
ProgCavity = [60.0,18.0,7.0]; | |
ProgBlock = [70.0,24.0,13.0]; | |
ProgCableOD = 4.0; | |
module ProgrammerCase() { | |
difference() { | |
hull() { | |
for (i=[-1,1], j=[-1,1]) | |
translate([i*(ProgBlock.x/2 - CornerRadius),j*i*(ProgBlock.y/2 - CornerRadius),-ProgBlock.z/2]) | |
cylinder(r=CornerRadius,h=ProgBlock.z,$fn=12); | |
} | |
translate([-ProgBlock.x,0,0]) | |
rotate([0,90,0]) | |
PolyCyl(ProgCableOD,3*ProgBlock.x,6); | |
cube(ProgCavity,center=true); | |
translate([0,0,ProgBlock.z/2 + ProgCavity.z/2 - EmbossDepth]) | |
cube(ProgCavity,center=true); | |
translate([0,0,-(ProgBlock.z/2 + ProgCavity.z/2 - EmbossDepth)]) | |
cube(ProgCavity,center=true); | |
} | |
translate([0,4,ProgBlock.z/2 - EmbossDepth]) | |
linear_extrude(height=EmbossDepth) | |
text(text="Bafang BBS02", | |
size=5,spacing=1.00,font="Bitstream Vera Sans:style=Bold", | |
halign="center",valign="center"); | |
translate([0,-4,ProgBlock.z/2 - EmbossDepth]) | |
linear_extrude(height=EmbossDepth) | |
text(text="Programmer", | |
size=5,spacing=1.00,font="Bitstream Vera Sans:style=Bold", | |
halign="center",valign="center"); | |
translate([0,4,-ProgBlock.z/2]) | |
linear_extrude(height=EmbossDepth) | |
mirror([1,0]) | |
text(text="Ed Nisley", | |
size=5,spacing=1.00,font="Bitstream Vera Sans:style=Bold", | |
halign="center",valign="center"); | |
translate([0,-4,-ProgBlock.z/2]) | |
linear_extrude(height=EmbossDepth) | |
mirror([1,0]) | |
text(text="softsolder.com", | |
size=5,spacing=1.00,font="Bitstream Vera Sans:style=Bold", | |
halign="center",valign="center"); | |
} | |
// Half case sections for printing | |
module HalfCase(Section = "Upper") { | |
intersection() { | |
translate([0,0,ProgBlock.z/4]) | |
cube([2*ProgBlock.x,2*ProgBlock.y,ProgBlock.z/2],center=true); | |
if (Section == "Upper") | |
ProgrammerCase(); | |
else | |
translate([0,0,ProgBlock.z/2]) | |
ProgrammerCase(); | |
} | |
} | |
//---------- | |
// Build them | |
if (Layout == "Frame") | |
Frame(); | |
if (Layout == "DispMount") | |
DispMount(); | |
if (Layout == "BrakeMagnet") | |
BrakeMagnet(); | |
if (Layout == "ShiftCap") | |
ShiftCap(); | |
if (Layout == "MotorSpacer") | |
MotorSpacer(); | |
if (Layout == "BuildSpacer") | |
translate([0,0,Spacer.y/2]) | |
rotate([90,0,0]) | |
MotorSpacer(); | |
if (Layout == "HeadClip") | |
HeadClip(); | |
if (Layout == "BuildClip") | |
rotate([-90,0,0]) | |
HeadClip(); | |
if (Layout == "BuildShiftCap") | |
translate([0,0,CapBlock.z]) | |
rotate([180,0,0]) | |
ShiftCap(); | |
if (Layout == "Case") | |
ProgrammerCase(); | |
if (Layout == "NutMold") | |
NutMold(); | |
if (Layout == "Upper" || Layout == "Lower") | |
HalfClamp(Station,Layout); | |
if (Layout == "Block") { | |
ClampBlock(Station); | |
if (false) | |
color("Red", 0.3) | |
Frame(); | |
} | |
if (Layout == "AllBlocks") { | |
gap = 3*Block.x; | |
for (i=[1:4]) | |
translate([i*gap - 2*gap,0,0]) | |
Clamp(i); | |
if (true) | |
color("Red", 0.3) | |
Frame(); | |
} | |
if (Layout == "BuildBlock") { | |
gap = 5.0; | |
translate([gap,0,Block.x/2]) | |
rotate([0,90,0]) | |
HalfClamp(Station,"Upper"); | |
translate([-gap - Block.z/2,0,Block.x/2]) | |
rotate([0,90,0]) | |
HalfClamp(Station,"Lower"); | |
} | |
if (Layout == "ShowAll") { | |
gap = 5.0; | |
for (Station=[1:4]) { | |
ctr = 5*Block.z; | |
translate([Station*2*Block.z + gap - ctr,0,Block.x/2]) | |
rotate([0,90,0]) | |
HalfClamp(Station,"Upper"); | |
translate([Station*2*Block.z - gap - Block.z/2 - ctr,0,Block.x/2]) | |
rotate([0,90,0]) | |
HalfClamp(Station,"Lower"); | |
} | |
translate([0,-Block.y,CapBlock.z]) | |
rotate([180,0,0]) | |
ShiftCap(); | |
translate([0,Block.y,0]) | |
DispMount(); | |
translate([-2*HandlebarMax,Block.y,0]) | |
BrakeMagnet(); | |
translate([-2*HandlebarMax,Block.y + 20,0]) | |
BrakeMagnet(); | |
translate([2*HandlebarMax,Block.y,Spacer.y/2]) | |
rotate([90,0,0]) | |
MotorSpacer(); | |
translate([-4*HandlebarMax,Block.y,Spacer.y/2]) | |
rotate([-90,0,0]) | |
HeadClip(); | |
translate([0,-Block.y,0]) { | |
translate([CapBlock.x + ProgBlock.x/2,0,ProgBlock.z/2]) | |
rotate([180,0,0]) | |
HalfCase("Upper"); | |
translate([-CapBlock.x - ProgBlock.x/2,0,0]) | |
HalfCase("Lower"); | |
} | |
translate([4*HandlebarMax,Block.y,0]) | |
rotate([0,0,0]) | |
NutMold(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment