Exit Full View
Up

/Garden/LEDGroundSpike2.foocad

LEDGroundSpike2

I modified some shop-bought solar powered LED garden lights, so that they also have wired power, and brighter LEDs. So I need new ground spikes to accommodate the 12V wires.

My first attempt printed them upside down, but this made them weak along the (short) layer lines. So this version I'm printing it laying on its side.

Adjust lenth and spikeT for your soil type. Hard soil, bump up spikeT, and lower length.

Print Notes

Given the overhangs, don't go too crazy with the layer heights (but my prototype printed ugly, but functional with a 0.3 layer height with 0.4 nozzle).

Use a brim. The "spike" has very little contact with the bed.

I used 5 perimeters (I wanted it to be solid)

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

class LEDGroundSpike4 : Model {
    
    @Custom( about="Length of the spike" )
    var length = 100

    @Custom( about="Less than the internal diameter of the LED's pole") 
    var diameter = 20.5

    @Custom( about="Height of the tube above ground" )
    var height = 20


    @Custom( about="Thickness of the blades of the spike. Doesn't need to be as thick as topT" )
    var spikeT = 2.0
    
    @Custom
    var headT = 2.0

    @Custom
    var shoulderSize = Vector2(3.0, 2.0)

    override fun build() : Shape3d {
        val foo = diameter
        val blade = PolygonBuilder().apply {
            moveTo( 0,0 )
            lineBy( 0, diameter/2 )
            lineBy( length - foo, 0 )
            lineTo( length, 3 )
            lineTo( length, 0 )
        }.build().roundCorner(6,10)
            .extrude( spikeT )
            .centerZ()
  
        // Note, the vanes are not equally spaced, giving an easier overhang.
        val spike = blade.rotateX(-90) + blade.rotateX(45).mirrorY().also()

        val cylinder = (
            Circle( diameter/2 ) -
            Circle( diameter/2 - headT )
        ).extrude(height).rotateY(-90)

        val r = diameter/2 - headT + spikeT/2

        
        val gap2d = PolygonBuilder().apply {
            moveTo(0,0)
            lineTo( -r,0 )
            circularArcTo( Vector2(r,0).rotate(45/180 * Math.PI), r, false, true )
        }.build().offset(-spikeT/2)
        val gap = gap2d.extrude( 30 ).rotateY(-90).leftTo(-1)
            .color("Red")


        val shoulder = (
            Circle( diameter/2 + shoulderSize.y )
        ).extrude(shoulderSize.x)
            .bottomTo(-shoulderSize.x)
            .rotateY(-90)
        val head = cylinder + shoulder

        val coneLength = diameter*1.5
        val cone = PolygonBuilder().apply {
            moveTo(0,0)
            lineTo( diameter/2, 0)
            lineTo( 0, coneLength )
        }.build()
            .revolve(220)
            .rotateY(90)
            .leftTo(shoulder.right)
        val coneHole = Circle( diameter/2 - headT ).extrudeToPoint( coneLength )
            .rotateY(90)
            .leftTo(-0.1)
            .color("Orange")

        val all = (spike + head + cone - gap - coneHole).bottomTo( -shoulderSize.y-headT/2)
        val result = all / Cube( length*3 ).centerXY() 

        return result.rotateZ(90)
            
    }
}