Close
0%
0%

PLANTINATOR 2026

Every weeding machine needs a PLANTINATOR

Similar projects worth following
0 followers

The plan is to create a simulated FreeCAD model so that all the geometry can be checked before going ahead into the fabrication stage. Parts will be made and arranged by means of Python macros created with the help of an LLM. So far so good.

  • Testing Macro Drawings

    GOAT INDUSTRIES3 hours ago 0 comments

    First Macro drawing for FreeCad is just to check it can be done easily. It works. Here is the first Macro:

    import FreeCAD as App
    import Part
    import math
    try:
        from PySide import QtCore
    except ImportError:
        from PySide6 import QtCore
    
    doc_name = "Chain_Sprocket_13T_15T_Simulation"
    doc = App.newDocument(doc_name)
    
    # --- 1. System Parameters ---
    t1 = 13 # Left Sprocket Teeth
    t2 = 15 # Right Sprocket Teeth
    pitch = 9.525
    roller_diameter = 6.35
    bore_diameter = 10.0
    plate_thickness = 5.3
    num_links = 32 # Increased chain length to accommodate larger sprocket
    
    # Chain Link Specs
    inner_width = 5.72
    pin_diameter = 3.28
    link_plate_thickness = 1.3
    
    # Calculated Radii
    R1 = pitch / (2 * math.sin(math.pi / t1))
    R2 = pitch / (2 * math.sin(math.pi / t2))
    root1 = R1 - (roller_diameter / 2.0)
    root2 = R2 - (roller_diameter / 2.0)
    
    # --- 2. Iterative Solver for Exact Center Distance (C) ---
    # A closed chain requires a geometrically perfect loop length.
    L_target = num_links * pitch
    C = 85.0 # Initial guess
    for _ in range(50): # Newton-Raphson method for exact distance
        theta = math.asin((R2 - R1) / C)
        L_calc = 2 * C * math.cos(theta) + R1 * (math.pi - 2*theta) + R2 * (math.pi + 2*theta)
        C -= (L_calc - L_target) / (2 * math.cos(theta))
    
    # Final Path Geometry Variables
    theta = math.asin((R2 - R1) / C)
    L_str = C * math.cos(theta)
    L_arc1 = R1 * (math.pi - 2 * theta)
    L_arc2 = R2 * (math.pi + 2 * theta)
    L_total = L_arc1 + L_arc2 + 2 * L_str
    
    # Tangent Points defining the path layout
    T1top = App.Vector(-R1 * math.sin(theta), R1 * math.cos(theta), 0)
    T1bot = App.Vector(-R1 * math.sin(theta), -R1 * math.cos(theta), 0)
    T2top = App.Vector(C - R2 * math.sin(theta), R2 * math.cos(theta), 0)
    T2bot = App.Vector(C - R2 * math.sin(theta), -R2 * math.cos(theta), 0)
    
    # --- 3. Dynamic Sprocket Generator ---
    def create_sprocket(name, teeth, R_pitch, R_root):
        R_outer = R_pitch + 2.3 # Scaled OD
        base_cylinder = Part.makeCylinder(R_outer, plate_thickness)
        scale_y = 0.85 
        
        # Parameterized Wedge Cutter to adapt to different radii
        p_root = App.Vector(R_root, 0, 0)
        p_A = App.Vector(R_pitch - 1.6, 2.77 * scale_y, 0)
        p_B = App.Vector(R_pitch - 1.6, -2.77 * scale_y, 0)
        p_M_up = App.Vector(R_pitch + 1.75, 4.5 * scale_y, 0)
        p_M_low = App.Vector(R_pitch + 1.75, -4.5 * scale_y, 0)
        p_3 = App.Vector(R_pitch + 5.1, 5.5 * scale_y, 0)
        p_4 = App.Vector(R_pitch + 5.1, -5.5 * scale_y, 0)
    
        arc_root = Part.Arc(p_B, p_root, p_A).toShape()
        arc_up = Part.Arc(p_A, p_M_up, p_3).toShape()
        arc_low = Part.Arc(p_4, p_M_low, p_B).toShape()
        line_out = Part.LineSegment(p_3, p_4).toShape()
    
        wedge_wire = Part.Wire([arc_root, arc_up, line_out, arc_low])
        wedge_solid = Part.Face(wedge_wire).extrude(App.Vector(0, 0, plate_thickness + 2.0))
        wedge_solid.translate(App.Vector(0, 0, -1.0))
    
        sprocket = base_cylinder
        for i in range(teeth):
            cutter = wedge_solid.copy()
            cutter.rotate(App.Vector(0, 0, 0), App.Vector(0, 0, 1), i * (360.0 / teeth))
            sprocket = sprocket.cut(cutter)
            
        bore = Part.makeCylinder(bore_diameter / 2.0, plate_thickness + 2.0)
        bore.translate(App.Vector(0, 0, -1.0))
        
        obj = doc.addObject("Part::Feature", name)
        obj.Shape = sprocket.cut(bore)
        obj.ViewObject.ShapeColor = (0.2, 0.2, 0.2)
        return obj
    
    sprocket_1 = create_sprocket("Sprocket_13T", t1, R1, root1)
    sprocket_2 = create_sprocket("Sprocket_15T", t2, R2, root2)
    sprocket_2.Placement.Base = App.Vector(C, 0, 0)
    
    # --- 4. Chain Link Geometry ---
    def create_link_plate(thickness, z_offset):
        r = 4.0
        cyl1 = Part.makeCylinder(r, thickness, App.Vector(0,0,z_offset))
        cyl2 = Part.makeCylinder(r, thickness, App.Vector(pitch,0,z_offset))
        box = Part.makeBox(pitch, r*2, thickness, App.Vector(0, -r, z_offset))
        return cyl1.fuse(cyl2).fuse(box)
    
    inner_plate_z1 = plate_thickness/2 + inner_width/2
    inner_plate_z2 = plate_thickness/2 - inner_width/2 - link_plate_thickness
    p1 = create_link_plate(link_plate_thickness, inner_plate_z1)
    p2 = create_link_plate(link_plate_thickness, inner_plate_z2)
    r1 = Part.makeCylinder(roller_diameter/2, inner_width,...
    Read more »

View project log

Enjoy this project?

Share

Discussions

Does this project spark your interest?

Become a member to follow this project and never miss any updates