Exit Full View
Up

/Games/LEDJugglingBall.foocad

LEDJugglingBall

A two piece hollow sphere that is joined by a separate screw thread in the middle. Space inside for adding LEDs and battery etc. Or alternatively, fill with plaster/concrete for a weighty juggling ball.

The overhang is solved by creating a flat spot in the interior, so that the interior poles use bridging before the angle gets too steep.

You can change the position of this flat spot using the @Custom overhang.

You can override outerSphere() to make a custom sphere, e.g. with writing or other patterns.

The default size is a "comfortable" size for an adult hand, but larger balls will give a better performance.

Print Notes

I added a 3mm brim for the hemisphere, because one of the prints detatched.

Use transparent PLA for a milky white translucent finish... Coloured LEDs will show up nicely.

If you use PLA, and leave the ball TIGHTLY screwed together for long periods, will the threads deform over time???

You can get a milky white finish from transparent PETG if you lower the extrusion temperature, but this will also reduce the layer strength.

FooCAD Source Code
import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.*
import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.*
import uk.co.nickthecoder.foocad.threaded.v1.Threaded

class LEDJugglingBall : Model {
    
    @Custom
    var diameter = 80

    // The inner diameter
    @Custom
    var innerD = 75

    @Custom
    var thickness = 2


    // Height of the threaded section which joins a hemisphere to the ring part.
    // Note the ring is twice this height.
    var joinH= 10

    // The overhang angle where an internal flat spot is placed.
    @Custom
    var overhang = 65

    @Piece
    fun outerSphere() = Sphere( diameter/2 )

    @Piece
    fun thread() = Threaded.create( 2, innerD, 6 ).apply {
        rodChamfer=0.5
    }

    @Piece
    fun hemiSphere() : Shape3d {
        val flat = Cube( diameter ).centerXY()
            .translateZ(Degrees.sin(overhang)* diameter/2)

        val sphere = outerSphere() -
            (Sphere( diameter/2 - thickness ) - flat)
        val result = sphere / Cube( diameter+2 ).centerXY()

        val thread : Shape3d = Cylinder( joinH, innerD/2 + thickness ) / Sphere( diameter/2 ) -
            thread().hole( joinH + 4 ).translateZ(-2)
        
        val floor = ( Circle( diameter/2 ) - Circle( innerD/2 ) )
            .extrude( thickness )
        return result + thread + floor
    }

    @Piece
    fun ring() : Shape3d {
        val thread : Shape3d = thread().rod( joinH * 2)
        val hole = Cylinder( joinH*3, innerD/2 - thickness*2 ).translateZ(-0.01)
    
        val battery = Cube( 50, 34, 5 ).centerXY().translateZ(thickness).previewOnly()

        return (thread - hole + bridge(innerD-thickness*3)).color("Orange") + battery
    }

    fun bridge(diameter : double) : Shape3d {
        return (Circle( diameter/2 ) / Square( innerD, 35 ).center() )
            .extrude( thickness )
    }

    /**
        Each "layer" of electronics has a spacer between it.
        Then the lasagne is taped together with the "join" piece.
        I also use double sided foam tape.
    */
    @Piece
    fun spacer() = bridge( innerD-thickness*4-1 ).color("Green")

    /**
        A ring on which to place a ball, to prevent the ball rolling around.
    */
    @Piece
    fun ringStand() : Shape3d {
        return( Circle( diameter*0.05 ) / Square( diameter ).centerX() )
            .translateX( diameter*0.2 )
            .revolve() +
        Sphere( diameter/2 ).bottomToOrigin().previewOnly()
    }

    @Piece
    fun domeStand() : Shape3d {
        val hemi = Sphere( diameter/2 ) - Sphere( diameter/2 - thickness ) remove
            Cube( diameter ).centerXY().topTo(0)
        val minus = Sphere( diameter/2 ).bottomTo( 5 )

        val ball = outerSphere().bottomTo( 5 ).previewOnly()
        return hemi remove minus + ball
    }

    @Piece
    fun trippleDomeStand() : Shape3d {
        val one = domeStand()
        val edge =  one.translateX( diameter * 0.59 )
        val main = edge and edge.rotateZ(120) and edge.rotateZ(-120) and one
        val foo = 0.12
        val inner = (Circle( diameter * foo ) - Circle( diameter * foo - thickness ))
            .extrude( 5 )
        return main + inner
    }

    @Piece
    fun spacers() = spacer().tileX(2,1).tileY(3,1)

    override fun build() : Shape3d {
        return hemiSphere() + ring().translateZ(-7.5) + spacer()            
    }
}