"""Through-hole slide switches: a steel shell over an insulating base, an actuator through a slot in the shell, terminals in a row and legs from the shell. C&K OS102011MS2Q stands upright (actuator up); C&K OS102011MA1Q and E-Switch EG1224 (SPDT) and EG2219 (DPDT) are right-angle (actuator along -Y, parallel to the board). The origin is at the centre of the shell's footprint, on the board's top face (the XY plane); the terminals lie along X. Dimensions from the makers' drawings, in the README.""" from steve import Model kind = "MS2Q" # MS2Q: C&K vertical; MA1Q: C&K right angle; EG1224, EG2219: E-Switch right angle position = 2 # Actuator position (1 or 2) # Each entry: (shell length, shell width or depth, shell height, actuator out of the shell, actuator axis height (right angle only), # base's lower edge above the board (4.7 less its distance below the top), right angle). # C&K "OS Series, Miniature Slide Switches", 8 aug 17 (datasheet.lcsc.com copy), inches (mm): # OS102011MS2QN1 (page I-37): shell .339 (8,60) x .169 (4,30), .185 (4,70) high; actuator .079 (2,00) square, .157 (4,00) above the # shell; the base .157 (4,00) below the shell's top; the shell's top to the tips .295 (7,50). # OS102011MA1QN1 (page I-42): shell .339 (8,60) long, .173 (4,40) deep, .185 (4,70) high; actuator .079 (2,00) square, .157 (4,00) # out of the shell, its axis .102 (2,60) above the board; the base .154 (3,90) below the shell's top. KINDS = { "MS2Q": (8.6, 4.3, 4.7, 4.0, 0.0, 0.7, False), "MA1Q": (8.6, 4.4, 4.7, 4.0, 2.6, 0.8, True), } # Both pages: actuator travel .079 (2,00); terminals 1-2-3 .079 (2,00) apart, .020 (0,50) wide and .012 (0,30) thick; the legs .016 # (0,40) thick and .047 (1,20) wide, their barbs .059 (1,50); the tips .110 (2,80) below the board. PC mounting: legs .323 (8,20) apart # in 2X Ø.059 (1,50) holes, .083 (2,10) from terminals 1 and 3 in 3X Ø.031 (0,80) holes. ACTUATOR = 2.0 TRAVEL = 2.0 PITCH = 2.0 PIN_W = 0.5 PIN_T = 0.3 LEG_T = 0.4 LEG_W = 1.2 BARB_W = 1.5 LEG_PITCH = 8.2 TIP = 2.8 # Proportions, for looks only (the drawings don't dimension them): the shell's sheet thickness (the legs' .016), where the barb sits on # the leg, and the V notch in the actuator's end. SHELL_T = 0.4 BARB = (-0.4, -1.4) NOTCH = 0.6 # E-Switch, each entry: (terminal rows, the rows' Y). # E-Switch drawing P040042 rev. A, "EG 1224 Non-Shorting", 4/27/98, and drawing P040170 rev. B, "EG 2219", 12/20/02 (datasheet.lcsc.com # copies), mm: body 13.8 x 6.5, 8.5 high; actuator 5.0 wide and 4.0 high, its axis 5.5 above the board, 9.0 out of the body (8.5 beyond a # 0.5 step); travel 4.0; terminals 4.0 apart, 0.5 wide and 0.4 thick, 3.5 below the board; four legs 0.8 wide and 0.5 thick, 12.0 apart # along the terminals and 6.0 across. EG1224: one row of three terminals 1.75 from the back legs' row, the body's lower edge 1.5 above # the board. EG2219: two rows 2.5 apart, between the legs' rows. EG = {"EG1224": ((1.25,),), "EG2219": ((-1.25, 1.25),)} EG_BODY = (13.8, 6.5, 8.5) EG_LOW = 1.5 EG_ACTUATOR = (5.0, 4.0) EG_AXIS = 5.5 EG_OUT = 9.0 EG_STEP = 0.5 EG_TRAVEL = 4.0 EG_PITCH = 4.0 EG_PIN = (0.5, 0.4) EG_TIP = 3.5 EG_LEG = (0.8, 0.5) EG_LEGS = (12.0, 6.0) # Proportions, for looks only: the shell's sheet thickness (the legs' 0.5), the actuator's step 4.0 x 3.0 (narrower than the knob, as # drawn), and EG2219's body lower edge, 1.5 above the board as on EG1224's drawing (EG2219's doesn't dimension it). EG_SHELL_T = 0.5 EG_STEP_SIZE = (4.0, 3.0) if kind not in KINDS and kind not in EG: raise ValueError(f"no type {kind!r}: {', '.join([*KINDS, *EG])}") if position not in (1, 2): raise ValueError("position is 1 or 2") if kind in EG: # E-Switch: right angle, the actuator a knob on a narrower step; four legs from the front and back walls. (rows,) = EG[kind] length, depth, height = EG_BODY L, D, t = length / 2, depth / 2, EG_SHELL_T slide = (position - 1.5) * EG_TRAVEL aw, ah = EG_ACTUATOR model = Model() model.box("shell_top", length, depth, t, at=(0, 0, height - t / 2), op="new", body="shell_body", name="Shell top") wall_h = height - EG_LOW for side, sy in (("back", 1), ("front", -1)): model.box(f"wall_{side}", length, t, wall_h, at=(0, sy * (D - t / 2), EG_LOW + wall_h / 2), op="join", body="shell_body", name=f"Shell wall, {side}") for side, sx in (("right", 1), ("left", -1)): model.box(f"end_{side}", t, depth, wall_h, at=(sx * (L - t / 2), 0, EG_LOW + wall_h / 2), op="join", body="shell_body", name=f"End wall, {side}") lx, ly = EG_LEGS for i, (sx, sy) in enumerate(((1, 1), (-1, 1), (-1, -1), (1, -1))): model.box(f"leg_{i + 1}", EG_LEG[0], EG_LEG[1], EG_LOW + EG_TIP + 0.01, at=(sx * lx / 2, sy * ly / 2, (EG_LOW - EG_TIP + 0.01) / 2), op="join", body="shell_body", name=f"Leg {i + 1}") model.box("slot", aw + EG_TRAVEL, t + 0.2, ah, at=(0, -D + t / 2, EG_AXIS), op="cut", body="shell_body", name="Slot") model.box("base", length - 2 * t, depth - 2 * t, height - t - EG_LOW, at=(0, 0, (EG_LOW + height - t) / 2), op="new", body="base_body", name="Base") sw, sh = EG_STEP_SIZE model.box("actuator_step", sw, t + EG_STEP, sh, at=(slide, -D + t - (t + EG_STEP) / 2, EG_AXIS), op="new", body="actuator_body", name="Actuator step") knob = EG_OUT - EG_STEP model.box("actuator", aw, knob + 0.01, ah, at=(slide, -D - EG_STEP - (knob - 0.01) / 2, EG_AXIS), op="join", body="actuator_body", name="Actuator") pins = [] for r, y in enumerate(rows): for i in range(3): n = r * 3 + i + 1 model.box(f"terminal_{n}", EG_PIN[0], EG_PIN[1], EG_LOW + EG_TIP, at=((i - 1) * EG_PITCH, y, (EG_LOW - EG_TIP) / 2), op="new", body=f"terminal_{n}_body", name=f"Terminal {n}") pins.append(f"terminal_{n}_body") # Materials, for looks and a rough mass (the drawings name none): the shell sheet steel (steel-c10), the base black phenolic # (bakelite), the actuator black POM (pom-copolymer), the terminals brass (brass), silver coloured. model.material("steel-c10", bodies=["shell_body"], color="#c9ccd0") model.material("bakelite", bodies=["base_body"], color="#2a2a2c") model.material("pom-copolymer", bodies=["actuator_body"], color="#222325") model.material("brass", bodies=pins, color="#d6d8db") else: # C&K OS102011. length, width, height, out, axis, base_low, angled = KINDS[kind] slide = (position - 1.5) * TRAVEL # pos. 1 and 2 are a travel apart, centred on terminal 2 L, W = length / 2, width / 2 inner = L - SHELL_T model = Model() # Shell: the end walls (whose legs reach through the board), the top, and the long sides (upright) or the front face (right angle); the # actuator's slot, the actuator plus its travel long, in the top (upright) or in the front face (right angle). model.box("shell_top", length, width, SHELL_T, at=(0, 0, height - SHELL_T / 2), op="new", body="shell_body", name="Shell top") for side, sx in (("right", 1), ("left", -1)): model.box(f"end_{side}", SHELL_T, width, height, at=(sx * (L - SHELL_T / 2), 0, height / 2), op="join", body="shell_body", name=f"End wall, {side}") model.box(f"leg_{side}", LEG_T, LEG_W, TIP + 0.01, at=(sx * LEG_PITCH / 2, 0, -(TIP - 0.01) / 2), op="join", body="shell_body", name=f"Leg, {side}") model.box(f"barb_{side}", LEG_T, BARB_W, BARB[0] - BARB[1], at=(sx * LEG_PITCH / 2, 0, (BARB[0] + BARB[1]) / 2), op="join", body="shell_body", name=f"Leg barb, {side}") if angled: model.box("shell_front", length, SHELL_T, height, at=(0, -W + SHELL_T / 2, height / 2), op="join", body="shell_body", name="Shell front") model.box("slot", ACTUATOR + TRAVEL, SHELL_T + 0.2, ACTUATOR, at=(0, -W + SHELL_T / 2, axis), op="cut", body="shell_body", name="Slot") else: for side, sy in (("back", 1), ("front", -1)): model.box(f"side_{side}", length, SHELL_T, height - base_low, at=(0, sy * (W - SHELL_T / 2), (height + base_low) / 2), op="join", body="shell_body", name=f"Shell side, {side}") model.box("slot", ACTUATOR + TRAVEL, ACTUATOR, SHELL_T + 0.2, at=(0, 0, height - SHELL_T / 2), op="cut", body="shell_body", name="Slot") # Base: the phenolic block inside the shell, from its lower edge up to the top. front = -W + SHELL_T back = W if angled else W - SHELL_T # the right-angle shell has no back model.box("base", 2 * inner, back - front, height - SHELL_T - base_low, at=(0, (front + back) / 2, (base_low + height - SHELL_T) / 2), op="new", body="base_body", name="Base") # Actuator: square, out of the slot by `out`, a V notch in its end. if angled: a_in = -W + SHELL_T a_end = -W - out model.box("actuator", ACTUATOR, a_in - a_end, ACTUATOR, at=(slide, (a_in + a_end) / 2, axis), op="new", body="actuator_body", name="Actuator") with model.sketch("notch_sketch", on="XY", name="Actuator notch") as sk: sk.polyline("notch_outline", [(slide - NOTCH / 2, a_end - 0.01), (slide + NOTCH / 2, a_end - 0.01), (slide, a_end + NOTCH)], closed=True) model.extrude("notch", "notch_sketch", distance=height, op="cut", body="actuator_body", name="Actuator notch") else: a_low = height - SHELL_T a_end = height + out model.box("actuator", ACTUATOR, ACTUATOR, a_end - a_low, at=(slide, 0, (a_low + a_end) / 2), op="new", body="actuator_body", name="Actuator") model.plane("notch_plane", on="XZ", offset=-(ACTUATOR / 2 + 0.1), name="Actuator notch") with model.sketch("notch_sketch", on="notch_plane", name="Actuator notch") as sk: sk.polyline("notch_outline", [(slide - NOTCH / 2, a_end + 0.01), (slide + NOTCH / 2, a_end + 0.01), (slide, a_end - NOTCH)], closed=True) model.extrude("notch", "notch_sketch", distance=ACTUATOR + 0.2, op="cut", body="actuator_body", name="Actuator notch") # Terminals 1-3: straight down from the base's lower edge to the tips. for i in range(3): model.box(f"terminal_{i + 1}", PIN_W, PIN_T, base_low + TIP, at=((i - 1) * PITCH, 0, (base_low - TIP) / 2), op="new", body=f"terminal_{i + 1}_body", name=f"Terminal {i + 1}") # Materials (page I-37, Materials): base phenolic resin (bakelite), actuator POM, black (pom-copolymer), housing plate SPCC, tin plated # (steel-c10), terminals brass, silver plated (brass, silver coloured). model.material("steel-c10", bodies=["shell_body"], color="#c9ccd0") model.material("bakelite", bodies=["base_body"], color="#a5562a") model.material("pom-copolymer", bodies=["actuator_body"], color="#222325") model.material("brass", bodies=[f"terminal_{i + 1}_body" for i in range(3)], color="#d6d8db") result = model.result()