benikigai/plus-onePublic

Plus One

mating_half.py · 2.5 KB · commit #5 · Nov 2, 2026

SHA-256 7b8f26359cf254e678dafcff14add82e97d905af4f3d7ebf0d7a34a6317cd2ee

"""Parametric mating half for the Plus One base (interface plus-one-base@1).

Change the parameters, run it, and get a STEP file for your own back:

    pip install build123d
    python mating_half.py --plate 3.0 --out my-back.step

Then model your mount, clip or stand onto the plate's underside (z below
-plate). The top face, the collar, the hooks, the key tab and the steel ring
pocket are the interface: keep them as they are. Numbers come from
accessories/interface.yaml; every one is a target for a prototype in design.
Print accessories/cad/fit-gauge.step first to check your printer's tolerance.
"""
import argparse
import math

from build123d import Align, Box, Cylinder, Pos, Rot, export_step

BASE = (Align.CENTER, Align.CENTER, Align.MIN)

# Interface (keep)
LUG_ANGLES = (30, 150, 270)
LOCKED_OFFSET_DEG = 9.0
R_BASE = 27.2
POGO = [(21.0 * math.cos(math.radians(a)), 21.0 * math.sin(math.radians(a))) for a in (246, 258, 270, 282, 294)]
BOOT = (-12.0, -1.0)

# Fit (tune for your printer)
COLLAR_IN = 28.75     # 0.25 mm radial clearance to the puck
COLLAR_OUT = 30.35
HOOK_IN_R = 27.7
HOOK_Z = (1.25, 1.65)
HOOK_W = 6.4
RING = (23.0, 26.8, 0.6)  # steel ring: inner radius, outer radius, thickness


def cyl(r, z0, z1, x=0.0, y=0.0):
    return Pos(x, y, z0) * Cylinder(r, z1 - z0, align=BASE)


def box(cx, cy, z0, sx, sy, sz):
    return Pos(cx, cy, z0) * Box(sx, sy, sz, align=BASE)


def mating_half(plate=2.0):
    m = cyl(COLLAR_OUT, -plate, 0.0)
    m += cyl(COLLAR_OUT, 0.0, HOOK_Z[1]) - cyl(COLLAR_IN, -0.1, HOOK_Z[1] + 0.1)
    for a in LUG_ANGLES:
        m += Rot(0, 0, a + LOCKED_OFFSET_DEG) * box((HOOK_IN_R + COLLAR_IN) / 2 + 0.05, 0.0, HOOK_Z[0], COLLAR_IN - HOOK_IN_R + 0.1, HOOK_W, HOOK_Z[1] - HOOK_Z[0])
    m += Rot(0, 0, 90.0) * box(R_BASE - 0.7, 0.0, 0.0, 1.0, 0.9, 0.8)               # key tab
    m -= cyl(RING[1] + 0.15, -RING[2] - 0.05, 0.01) - cyl(RING[0] - 0.15, -RING[2] - 0.1, 0.1)  # steel ring pocket
    for x, y in POGO:
        m -= cyl(1.8, -0.4, 0.1, x, y)                                                # leave the pads untouched
    m -= cyl(1.5, -plate - 0.1, 0.1, *BOOT)                                           # BOOT stays reachable
    return m


if __name__ == "__main__":
    ap = argparse.ArgumentParser()
    ap.add_argument("--plate", type=float, default=2.0, help="plate thickness below the interface, mm")
    ap.add_argument("--out", default="mating-half.step")
    a = ap.parse_args()
    export_step(mating_half(a.plate), a.out)
    print(f"wrote {a.out}")