"""Right-angle through-hole subminiature pushbutton, NKK Series BB, BB15AH (single pole, SPDT, momentary, right-angle PC terminals with a support bracket), with or without a slip-on cap. The origin is terminal 2 (COM) on the board's top face (the XY plane); terminals 1, 2 and 3 lie along X, 2.54 apart; the plunger points along -Y, its axis 3.4 above the board. Dimensions from NKK's Series BB sheet, in the README.""" from steve import Model kind = "BB15AH" # Type cap = "none" # Slip-on cap: none, F (AT475, 5.1 dia.) or H (AT496, 7.5 dia.) cap_color = "black" # Cap colour: black, white or red # NKK "Series BB, Process Sealed Subminiature Antistatic Pushbuttons", catalogue pages C12 to C17 (PDF of 2016-10-25, # nkkswitches.com/pdf/Bpushbuttons.pdf), in inches (mm); the mm values are used. # Page C17, Typical Switch Dimensions, Single Pole, Right Angle PC (BB15AH-FA): body (8.8) .346 wide and (7.3) .287 high; bushing # (6.0) dia. .236, (2.7) .106 long; plunger (2.8) dia. .110, (5.4) .213 out of the bushing; (13.9) .546 from the bushing's nose to # the terminals' row; plunger axis (3.4) .134 above the board; terminals (2.54) .100 apart, (0.6) dia. .024, (3.1) .122 below the # board; bracket legs (5.08) .200 in front of the terminals, (5.08) .200 apart (under terminals 1 and 3), (0.4) .016 thick; # F cap (5.1) dia. .201, (4.0) .157 long, its face (6.3) .248 from the bushing's nose. # Page C15, PC Terminals, H Right Angle with Bracket: terminals (0.6) dia. .024; bracket legs (0.6) .024 wide, (0.4) .016 thick; # bracket (0.5) .020 thick. Slip-On Caps: F AT475, (5.1) dia. .201; H AT496, (7.5) dia. .295; both (6.3) .248 from the bushing, # (4.0) .157 long; polyamide; black, white or red. TYPES = {"BB15AH": 3} # terminals BODY_W = 8.8 BODY_H = 7.3 BUSHING_D = 6.0 BUSHING_L = 2.7 PLUNGER_D = 2.8 PLUNGER_OUT = 5.4 NOSE = 13.9 AXIS = 3.4 PITCH = 2.54 PIN_D = 0.6 TAIL = 3.1 LEG_Y = 5.08 LEG_X = 5.08 LEG_W = 0.6 LEG_T = 0.4 BRACKET_T = 0.5 CAPS = {"F": 5.1, "H": 7.5} CAP_FACE = 6.3 CAP_L = 4.0 SHADES = {"black": "#222325", "white": "#ecebe6", "red": "#c8202a"} # Proportions, for looks only (the sheet doesn't dimension them; scaled from the C17 side and rear views, README): the housing's width, # the front part's height and length, where the housing's underside and the terminals' exit are, and the rear face's distance from # the terminals' row. HOUSING_W = 8.0 FRONT_TOP = 6.6 STEP = 6.0 # the front part ends this far in front of the terminals' row; the taller rear block runs from there to the back REAR = 0.8 # the rear face, in front of the terminals' row EXIT_Z = 2.5 # the terminals leave the rear face this high, run back to their row and bend down if kind not in TYPES: raise ValueError(f"no type {kind!r}: {', '.join(TYPES)}") if cap != "none" and cap not in CAPS: raise ValueError(f"no cap {cap!r}: none, {', '.join(CAPS)}") if cap_color not in SHADES: raise ValueError(f"no cap colour {cap_color!r}: {', '.join(SHADES)}") nose = -NOSE plate = nose + BUSHING_L # the bracket's front plate starts behind the bushing front = plate + BRACKET_T # the housing's front face bottom = BRACKET_T # the housing's front part stands on the bracket's bottom plate model = Model() # Housing (glass fibre reinforced polyamide): a front part over the bracket and a taller rear block down to the board. model.box("housing_front", HOUSING_W, -STEP - front, FRONT_TOP - bottom, at=(0, (front - STEP) / 2, (FRONT_TOP + bottom) / 2), op="new", body="housing_body", name="Housing") model.box("housing_rear", HOUSING_W, STEP - REAR + 0.01, BODY_H - bottom, at=(0, (-STEP - REAR) / 2 - 0.005, (BODY_H + bottom) / 2), op="join", body="housing_body", name="Rear block") leg_back = -LEG_Y + LEG_T / 2 # the bracket's bottom plate ends behind the legs; the rear block reaches the board behind it model.box("housing_foot", HOUSING_W, -REAR - leg_back, bottom + 0.01, at=(0, (leg_back - REAR) / 2, (bottom + 0.01) / 2), op="join", body="housing_body", name="Rear foot") # Bushing (carbon blended polyamide), from the bracket's plate to the nose. model.cylinder("bushing", BUSHING_D / 2, BUSHING_L + BRACKET_T, at=(0, front, AXIS), direction=(0, -1, 0), op="new", body="bushing_body", name="Bushing") # Plunger (polyacetal, white): out of the bushing's nose. model.cylinder("plunger", PLUNGER_D / 2, PLUNGER_OUT, at=(0, nose, AXIS), direction=(0, -1, 0), op="new", body="plunger_body", name="Plunger") # Support bracket (tin plated phosphor bronze, 0.5): a front plate round the bushing, a bottom plate under the housing's front part, # and two legs 0.6 x 0.4 under terminals 1 and 3, 5.08 in front of the terminals' row. model.box("bracket_plate", BODY_W, BRACKET_T, BODY_H, at=(0, plate + BRACKET_T / 2, BODY_H / 2), op="new", body="bracket_body", name="Bracket front plate") model.cylinder("bracket_hole", BUSHING_D / 2, BRACKET_T + 0.2, at=(0, plate + BRACKET_T + 0.1, AXIS), direction=(0, -1, 0), op="cut", body="bracket_body", name="Bushing hole") model.box("bracket_bottom", HOUSING_W, leg_back - front + 0.01, BRACKET_T, at=(0, (leg_back + front) / 2 - 0.005, BRACKET_T / 2), op="join", body="bracket_body", name="Bracket bottom plate") for i, sx in enumerate((-1, 1)): model.box(f"leg_{i + 1}", LEG_W, LEG_T, TAIL + 0.01, at=(sx * LEG_X / 2, -LEG_Y, -(TAIL - 0.01) / 2), op="join", body="bracket_body", name="Bracket leg") # Terminals 1-3 (copper alloy, gold plated): round wire 0.6 dia. out of the rear face at EXIT_Z, back to the row and down to the tip. pins = [] for i, x in enumerate((-PITCH, 0.0, PITCH)): body = f"terminal_{i + 1}_body" model.cylinder(f"terminal_{i + 1}_run", PIN_D / 2, REAR + PIN_D / 2, at=(x, -REAR, EXIT_Z), direction=(0, 1, 0), op="new", body=body, name=f"Terminal {i + 1}") model.cylinder(f"terminal_{i + 1}_down", PIN_D / 2, EXIT_Z + TAIL, at=(x, 0, -TAIL), op="join", body=body, name=f"Terminal {i + 1} tail") pins.append(body) if cap != "none": # Slip-on cap (polyamide): its face CAP_FACE in front of the bushing's nose, over the plunger's end. model.cylinder("cap", CAPS[cap] / 2, CAP_L, at=(0, nose - CAP_FACE, AXIS), direction=(0, 1, 0), op="new", body="cap_body", name="Cap") tip = nose - PLUNGER_OUT model.cylinder("cap_bore", PLUNGER_D / 2, nose - CAP_FACE + CAP_L - tip, at=(0, tip, AXIS), direction=(0, 1, 0), op="cut", body="cap_body", name="Cap bore") # Materials from page C13: housing glass fibre reinforced polyamide and bushing carbon blended polyamide (pa6, black), plunger # polyacetal (pom-copolymer, white), bracket tin plated phosphor bronze (copper-c51000), terminals copper alloy, gold plated (copper); # caps polyamide (pa6) in their colour. model.material("pa6", bodies=["housing_body"], color="#2a2b2e") model.material("pa6", bodies=["bushing_body"], color="#1d1e20") model.material("pom-copolymer", bodies=["plunger_body"], color="#ecebe6") model.material("copper-c51000", bodies=["bracket_body"], color="#c9ccd0") model.material("copper", bodies=pins, color="#d8b25a") if cap != "none": model.material("pa6", bodies=["cap_body"], color=SHADES[cap_color]) result = model.result()