/Hardware/Wheel.foocad

A wheel with a recess for a standard skate bearing. (The wheel can turn, when the axel is fixed).
The hub
uses a sacrificial layer so that supports aren't needed.
Punch/drill through this layer.
The recesses are deep enough for the nuts to be hidden within the wheel using
hubCap
and insideHubCap
.
A small dab of glue may be required to prevent these pieces falling off over time.
There is no clearance between the tyre and the hub, and therefore we are relying on the tyre being stretchy (TPU). I don't expect the tyre to loosen over time, but if it does, use a small dab of glue.
import uk.co.nickthecoder.foocad.threaded.v2.* import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.* import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.* import uk.co.nickthecoder.foocad.smartextrusion.v1.* import static uk.co.nickthecoder.foocad.smartextrusion.v1.SmartExtrusion.* class Wheel : Model { @Custom( about="Diameter and width of the hub" ) var hubSize = Vector2( 60, 19 ) @Custom( about="The final wheel's diameter = hubSize.x + typeDiameter*2" ) var tyreThickness = 6 @Custom var tyreRounding = 5 @Custom( about="Default is 8mm for M8 threaded rods" ) var axelDiameter = 10 @Custom( about="Diameter and thickness of the bearing. The hole is given additional `clearance`" ) var bearingSize = Vector2( 22, 7 ) @Custom var threadDiameter = 35 @Custom( about="Additional width and thickness for the hub cap" ) var capSize = Vector2( 6, 2 ) // 0.075 gives a perfect fit using a 0.6mm nozzel on Qidi Max3 @Custom( about="Additional space for the bearing to fit into its hole" ) var clearance = 0.075 @Custom( about="Offsets for the tyre. Negative for a tight fit" ) var tyreClearance = -0.2 @Custom( about="Chamfer on the hub and the type to locate it in place" ) var tyreChamfer = 1.0 meth recessDepth() = (hubSize.y - bearingSize.y) / 2 meth hubThread() = Thread( threadDiameter, 2 ) .rodChamfer( 0.5 ) @Piece meth testFit() : Shape3d { val inside = Circle( bearingSize.x/2 + clearance/2) val outside = inside.offset(3) val text = Text( "${clearance}", 8 ) val text3d = ( text.boundingSquare().offset(2).roundAllCorners(3).extrude(0.8) + text.extrude(1.6) ).leftTo( outside.right - 2 ).centerY() return text3d + (outside-inside).extrude( bearingSize.y + 2) + (outside - outside.offset(-6)).extrude(2) } @Piece meth hub() : Shape3d { val main = Circle( hubSize.x/2 ) .smartExtrude( hubSize.y ) .top( Chamfer( 1 ) ) // To help put on the tyre. .bottom( Chamfer(-tyreChamfer,tyreChamfer) ) val threadedRecess = hubThread().threadedHole( recessDepth() ) .chamferStart(false) .topTo(main.top + 0.01) val forBearing = Circle( bearingSize.x / 2 + clearance ) .smartExtrude( main.size.z ) .bottomTo( main.top - recessDepth() - bearingSize.y ) val throughHole = Cylinder(hubSize.y, axelDiameter * 1.6 / 2) .bottomTo( -0.01 ) return main - forBearing - threadedRecess - throughHole } @Piece meth hubCap() : Shape3d { val diameter = hubThread().diameter + capSize.x*2 println( "cap diameter = $diameter" ) val thread = hubThread() val cap = Circle( diameter/2 ) .smartExtrude( capSize.y ) .bottom( Chamfer( capSize.y/2 ) ) val rod = thread.threadedRod( recessDepth() + capSize.y/2 - 0.5 ) .chamferBottom(false) .bottomTo( capSize.y/2 ) val hole = Cylinder( recessDepth(), thread.coreRadius() -2 ) .bottomTo( cap.top + 0.01 ) return cap + rod - hole } @Piece //@Slice( fillDensity=100 ) meth tyre() : Shape3d { val inside = Circle( hubSize.x/2 + tyreClearance ) val outside = inside.offset( tyreThickness ) val shape = outside - inside return shape .smartExtrude( hubSize.y ) .outside( roundedChamfer( tyreRounding ) ) .insideTop( Chamfer(tyreChamfer) ) } @Piece meth bearingWhacker() : Shape3d { val pin = Cylinder( 16, axelDiameter/2 - 0.2 ) + Cylinder( 16 - bearingSize.y, axelDiameter/2 + 2 ) val standCircle = Circle( bearingSize.x / 2 + 0.5 ) val stand = (standCircle.offset(1) - standCircle) .extrude( bearingSize.y + 2 ) + standCircle.extrude(1) return pin + stand.leftTo(pin.right + 1 ) } meth assembly() : Shape3d { val hub = hub().color("Orange") val cap = hubCap() .rotateX(180) .topTo( hub.top + 2.02 ) .previewOnly() val tyre = tyre() .rotateX(180) .bottomTo(0.1).color( "DarkGrey" ) return (hub + tyre + cap) .rotateY(90) } @Piece( printable=false ) override meth build() = assembly() }