"""Through-hole PCB relay: Omron G2RL-2, G5V-1, G5V-2, G6A and G6AK; Finder 30.22, 32.21, 34.51, 36.11 and 40.31/51/52/61; Schrack (TE) RT1, RT2 and RYII. A closed case on the XY plane with the pins down through the board. Pin 1 is at the origin; the pins are placed as the maker's bottom-view PCB layout draws them, seen from above (the layout turned over about its horizontal axis): along it to +X, its next row towards +Y. Dimensions from the makers' data sheets in the README.""" from steve import Model kind = "G6A" # Relay type # kind: (case length along X, width along Y, height above the board; solder pin length below the board, pin across X, pin across Y; # pin 1 from the case's -X end, from its -Y side; pins (x, y) from pin 1, or (x, y, across X, across Y) for a pin of another section). # Omron: the case sizes are the data sheets' average values. # Omron G2RL, Cat. No. J117-E1-17, Dimensions p. 6, G2RL-2: 29 max. (28.8 average) x 12.7 max. (12.5) x 15.7 max. (15.5), terminals 3.5 long, # 0.5 x 0.8; PCB mounting holes (bottom view): columns at 0, 15, 20, 25 (20 from pin 1 to the third, 5 apart), rows 7.5 apart, (2.3) from # the case end and (2.5) from its side. Weight approx. 12 g (p. 2). # Omron G5V-1, Cat. No. K048-E1-07, Dimensions p. 4: 12.5 max. (12.3) x 7.5 max. (7.3) x 10 max. (9.9), terminals 3.5 long, 0.5 x 0.3; # holes at 0, 2.54 and 10.16, rows 5.08 apart, (1.07) and (1.11) from the case. Weight approx. 2 g. # Omron G5V-2, Cat. No. K046-E1-06, Dimensions p. 4: 20.5 max. (20.3) x 10.1 max. (9.9) x 11.5 max. (11.4), terminals 3.5 long, # 0.5 x 0.3; holes at 0, 7.62, 12.7, 17.78, rows 7.62 apart, (1.3) and (1.2) from the case. Weight approx. 5 g. # Omron G6A, Cat. No. K020-E1-15, Dimensions p. 8: 20.2 max. (20) x 10.1 max. (9.9) x 8.4 max. (8.2), terminals 3.16 long, 0.6 x 0.3; # G6A-274P: holes at 0, 7.62, 12.7, 17.78, rows 7.62 apart, (1.2) from the case; G6AK-274P (double-winding latching): also at 2.54, # ten holes. Weight approx. 3.5 g (p. 2). # Finder: pin 1 is coil terminal A1. The rows are centred across the case (the sheets dimension the rows and the case width, not the gap). # Finder 30 series, edition II-2026 (S30EN): 30.22, copper side view p. 3: A1, 11, 12, 14 at 0, 7.62, 12.7, 17.78, rows 7.62 apart, 14 is 1.3 # from the case end; outline drawing p. 5: 20.2 x 10 x 10.9, pins 3.2, coil pins 0.4, contact pins 0.6 along the case, 0.4 across. # Finder 32 series, edition XII-2025 (S32EN): 32.21-4000 and -4300, copper side view p. 3: A1, 11, 14 at 0, 10.16, 17.78, A2 and 12 7.62 # across, 14 is 1.1 from the case end; outline drawing p. 5: 20.2 x 10.1 x 10.7, pins 3.5, coil pins 0.4 x 0.4, contact pins 0.8 x 0.3. # Finder 34 series, edition II-2026 (S34EN): 34.51, copper side view p. 3: one row, A2, A1, 12, 11, 14 at 0, 3.75, 15, 20, 25, 1.3 from the # case side, 14 is 1.9 from the case end; outline drawing p. 9: 28 x 5 x 15, pins 3.5, coil pins 0.5 x 0.5, contact pins 1 x 0.4. # Flat pack version 34.51.7xxx.x019, p. 6: the case lies on the board (28 x 15, 5 high), the pins bent down at its long side, the pin row # 15.4 from the far side, the pin ends 7.5 from the case's top face (2.5 below the board). # Finder 36 series, edition II-2026 (S36EN): 36.11-4011, copper side view p. 3: A1 and A2 6 + 6 apart, 11 between them 2 to the side and # 1.2 from the case end, 14 and 12 12.2 from A1 and A2 and 3.4 from the other end; outline drawing p. 5: 18.8 x 15.2 x 15.5, pins 3.5, # 11 0.3 x 1.2, coil pins 0.5 and contact pins 1 along the case (their thickness across isn't given: 0.5, as drawn). # Finder 40 series, edition VIII-2026 (S40EN): copper side views p. 3: A1, A2 7.5 apart, 2.5 from the case end; 40.31: 12, 14 at 16.5, # 23.5 in A1's row, 11 at 20 in A2's; 40.51: 15, 25 and 20; 40.52 and 40.61: 15, 20, 25 in both rows. Outline drawing p. 10: # 29 x 12.4 x 25.1, pins 0.4 along the case, 1 across, 3.5 (PCB relay, "-3.5" here) or 5.2 (PCB or socket) long. # Schrack (TE Connectivity): pin 1 is coil terminal A1. "PCB layout / terminal assignment, bottom view on solder pins". The sheets don't dimension # the pins' section: 0.55 along the case and 1.0 (RT1, RT2) or 0.8 (RYII) across it, scaled from the outline drawings (line centres). # Schrack RT1, datasheet 01-2020 Rev. 0120, p. 2 (layouts) and p. 3 (THT outline): 29.0 x 12.7 x 15.7, pins 3.6; rows 7.5 apart, 11 20.3 from A1 # in A2's row, the case end 22.65 from 11; 12A 3.5 mm pinning (RT1 1x): 12 and 14 3.5 either side of 11, in A1's row; 12A 5 mm (RT2x): 5.04 # either side; 16A 5 mm (RT3x): 12, 11, 14 in both rows. Form A (RTx3) leaves out 12. Weight 14 g (p. 2). # Schrack RT2 (Asia/Pacific markets), datasheet 11-2020 Rev. 1120, p. 2: the RT1's case and pins; 8A 5 mm pinning, 12, 11, 14 and 22, 21, 24 at # 15.26, 20.3, 25.34 (5.04 apart); 2 form A (RT44) leaves out 12 and 22. Weight 13 g. # Schrack RY II, Datenblatt Rev. HC1, Ausgabe 2008/03, p. 2: 28.5 x 10.1 x 12.3, pins 3.2; 3.2 mm pinning (RY 21), A1 1.9 from the case end, # 18.9 from A1 in A2's row, then 3.2 and 3.2 on, alternately in A1's and A2's rows; 5 mm pinning (RY 53, 1 Schliesser, and the 1 Oeffner on the # same layout), A1 3.25 from the end, 18.9 in A1's row and 18.9 + 5.04 in A2's. Rows three grid steps of 2.5 to 2.54 apart (7.62 here). # Weight 8 g (p. 2). RELAYS = { "G2RL-2": (28.8, 12.5, 15.5, 3.5, 0.5, 0.8, 2.3, 2.5, ((0, 0), (15, 0), (20, 0), (25, 0), (0, 7.5), (15, 7.5), (20, 7.5), (25, 7.5))), "G5V-1": (12.3, 7.3, 9.9, 3.5, 0.5, 0.3, 1.07, 1.11, ((0, 0), (2.54, 0), (10.16, 0), (0, 5.08), (2.54, 5.08), (10.16, 5.08))), "G5V-2": (20.3, 9.9, 11.4, 3.5, 0.5, 0.3, 1.3, 1.2, ((0, 0), (7.62, 0), (12.7, 0), (17.78, 0), (0, 7.62), (7.62, 7.62), (12.7, 7.62), (17.78, 7.62))), "G6A": (20.0, 9.9, 8.2, 3.16, 0.6, 0.3, 1.2, 1.2, ((0, 0), (7.62, 0), (12.7, 0), (17.78, 0), (0, 7.62), (7.62, 7.62), (12.7, 7.62), (17.78, 7.62))), "G6AK": (20.0, 9.9, 8.2, 3.16, 0.6, 0.3, 1.2, 1.2, ((0, 0), (2.54, 0), (7.62, 0), (12.7, 0), (17.78, 0), (0, 7.62), (2.54, 7.62), (7.62, 7.62), (12.7, 7.62), (17.78, 7.62))), "30.22": (20.2, 10.0, 10.9, 3.2, 0.6, 0.4, 1.12, 1.19, ((0, 0, 0.4, 0.4), (7.62, 0), (12.7, 0), (17.78, 0), (0, 7.62, 0.4, 0.4), (7.62, 7.62), (12.7, 7.62), (17.78, 7.62))), "32.21-4000": (20.2, 10.1, 10.7, 3.5, 0.8, 0.3, 1.32, 1.24, ((0, 0, 0.4, 0.4), (10.16, 0), (17.78, 0), (0, 7.62, 0.4, 0.4), (17.78, 7.62))), "32.21-4300": (20.2, 10.1, 10.7, 3.5, 0.8, 0.3, 1.32, 1.24, ((0, 0, 0.4, 0.4), (10.16, 0), (17.78, 0), (0, 7.62, 0.4, 0.4))), "34.51": (28.0, 5.0, 15.0, 3.5, 1.0, 0.4, 4.85, 3.7, ((0, 0, 0.5, 0.5), (-3.75, 0, 0.5, 0.5), (11.25, 0), (16.25, 0), (21.25, 0))), "34.51-flat": (28.0, 15.0, 5.0, 2.5, 1.0, 0.4, 4.85, -0.4, ((0, 0, 0.5, 0.5), (-3.75, 0, 0.5, 0.5), (11.25, 0), (16.25, 0), (21.25, 0))), "36.11": (18.8, 15.2, 15.5, 3.5, 1.0, 0.5, 3.2, 1.6, ((0, 0, 0.5, 0.5), (12.2, 0), (-2, 6, 0.3, 1.2), (0, 12, 0.5, 0.5), (12.2, 12))), "40.31": (29.0, 12.4, 25.1, 5.2, 0.4, 1.0, 2.5, 2.45, ((0, 0), (16.5, 0), (23.5, 0), (0, 7.5), (20, 7.5))), "40.31-3.5": (29.0, 12.4, 25.1, 3.5, 0.4, 1.0, 2.5, 2.45, ((0, 0), (16.5, 0), (23.5, 0), (0, 7.5), (20, 7.5))), "40.51": (29.0, 12.4, 25.1, 5.2, 0.4, 1.0, 2.5, 2.45, ((0, 0), (15, 0), (25, 0), (0, 7.5), (20, 7.5))), "40.51-3.5": (29.0, 12.4, 25.1, 3.5, 0.4, 1.0, 2.5, 2.45, ((0, 0), (15, 0), (25, 0), (0, 7.5), (20, 7.5))), "40.52": (29.0, 12.4, 25.1, 5.2, 0.4, 1.0, 2.5, 2.45, ((0, 0), (15, 0), (20, 0), (25, 0), (0, 7.5), (15, 7.5), (20, 7.5), (25, 7.5))), "40.61": (29.0, 12.4, 25.1, 5.2, 0.4, 1.0, 2.5, 2.45, ((0, 0), (15, 0), (20, 0), (25, 0), (0, 7.5), (15, 7.5), (20, 7.5), (25, 7.5))), "40.61-3.5": (29.0, 12.4, 25.1, 3.5, 0.4, 1.0, 2.5, 2.45, ((0, 0), (15, 0), (20, 0), (25, 0), (0, 7.5), (15, 7.5), (20, 7.5), (25, 7.5))), "RT11": (29.0, 12.7, 15.7, 3.6, 0.55, 1.0, 2.35, 2.6, ((0, 0), (16.8, 0), (23.8, 0), (0, 7.5), (20.3, 7.5))), "RT13": (29.0, 12.7, 15.7, 3.6, 0.55, 1.0, 2.35, 2.6, ((0, 0), (23.8, 0), (0, 7.5), (20.3, 7.5))), "RT21": (29.0, 12.7, 15.7, 3.6, 0.55, 1.0, 2.35, 2.6, ((0, 0), (15.26, 0), (25.34, 0), (0, 7.5), (20.3, 7.5))), "RT23": (29.0, 12.7, 15.7, 3.6, 0.55, 1.0, 2.35, 2.6, ((0, 0), (25.34, 0), (0, 7.5), (20.3, 7.5))), "RT31": (29.0, 12.7, 15.7, 3.6, 0.55, 1.0, 2.35, 2.6, ((0, 0), (15.26, 0), (20.3, 0), (25.34, 0), (0, 7.5), (15.26, 7.5), (20.3, 7.5), (25.34, 7.5))), "RT33": (29.0, 12.7, 15.7, 3.6, 0.55, 1.0, 2.35, 2.6, ((0, 0), (20.3, 0), (25.34, 0), (0, 7.5), (20.3, 7.5), (25.34, 7.5))), "RT42": (29.0, 12.7, 15.7, 3.6, 0.55, 1.0, 2.35, 2.6, ((0, 0), (15.26, 0), (20.3, 0), (25.34, 0), (0, 7.5), (15.26, 7.5), (20.3, 7.5), (25.34, 7.5))), "RT44": (29.0, 12.7, 15.7, 3.6, 0.55, 1.0, 2.35, 2.6, ((0, 0), (20.3, 0), (25.34, 0), (0, 7.5), (20.3, 7.5), (25.34, 7.5))), "RY21": (28.5, 10.1, 12.3, 3.2, 0.55, 0.8, 1.9, 1.24, ((0, 0), (22.1, 0), (0, 7.62), (18.9, 7.62), (25.3, 7.62))), "RY53": (28.5, 10.1, 12.3, 3.2, 0.55, 0.8, 3.25, 1.24, ((0, 0), (18.9, 0), (0, 7.62), (23.94, 7.62))), "RY5-NC": (28.5, 10.1, 12.3, 3.2, 0.55, 0.8, 3.25, 1.24, ((0, 0), (18.9, 0), (0, 7.62), (23.94, 7.62))), } # Relays lying on the board with their pins bent down at the case's -Y side: kind: height of the pins' bend above the board (Finder 34.51 flat # pack: the pins leave the case 1.3 from its face, the standing version's 1.3 from the case side, p. 3). FLAT = {"34.51-flat": 1.3} # Case colours, as the makers' pictures show them (black when not listed). COLOURS = {"30.22": "#e9e7e1", "32.21-4000": "#e9e7e1", "32.21-4300": "#e9e7e1", "36.11": "#e9e7e1", "40.31": "#3f7fc4", "40.31-3.5": "#3f7fc4", "40.51": "#3f7fc4", "40.51-3.5": "#3f7fc4", "40.52": "#3f7fc4", "40.61": "#3f7fc4", "40.61-3.5": "#3f7fc4", "RT11": "#c4482f", "RT13": "#c4482f", "RT21": "#c4482f", "RT23": "#c4482f", "RT31": "#c4482f", "RT33": "#c4482f", "RT42": "#d9d9d6", "RT44": "#d9d9d6", "RY21": "#e9e7e1", "RY53": "#e9e7e1", "RY5-NC": "#e9e7e1"} # Proportions (the data sheets don't dimension the inside): the case is a cover WALL thick over a base plate as thick; the coil, core and contacts inside are one # copper block filling FILL of the space inside the case, standing on its floor, so that the mass comes out near the data sheets' weights. WALL = 0.5 FILL = 0.27 if kind not in RELAYS: raise ValueError(f"no relay {kind!r}: {', '.join(RELAYS)}") length, width, height, pin_length, pin_x, pin_y, from_end, from_side, pins = RELAYS[kind] # Pin 1's place in the case: the PCB layouts' distances from pin 1 to the case's end and side (Omron: the bracketed reference values, the # far end taking what's left of the average case size). x0 = -from_end y0 = -from_side model = Model() # The case: a cover, open underneath, over a base plate WALL thick that closes it. model.box("case", length, width, height, at=(x0 + length / 2, y0 + width / 2, height / 2), op="new", body="case_body", name="Cover") inner = (length - 2 * WALL, width - 2 * WALL, height - 2 * WALL) model.box("inside", inner[0], inner[1], height - WALL, at=(x0 + length / 2, y0 + width / 2, (height - WALL) / 2), op="cut", body="case_body", name="Inside") model.box("base", inner[0], inner[1], WALL, at=(x0 + length / 2, y0 + width / 2, WALL / 2), op="new", body="base_body", name="Base") scale = FILL ** (1 / 3) core = (inner[0] * scale, inner[1] * scale, inner[2] * scale) model.box("coil", core[0], core[1], core[2], at=(x0 + length / 2, y0 + width / 2, WALL + core[2] / 2), op="new", body="coil_body", name="Coil and contacts") bend = FLAT.get(kind) pin_bodies = [] for i, pin in enumerate(pins): x, y = pin[0], pin[1] sx, sy = (pin[2], pin[3]) if len(pin) == 4 else (pin_x, pin_y) body = f"pin_{i + 1}_body" if bend is None: model.box(f"pin_{i + 1}", sx, sy, pin_length, at=(x, y, -pin_length / 2), op="new", body=body, name=f"Pin {i + 1}") else: # Bent pin: down through the board from the bend, and across to the case's side at the bend's height. top = bend + sy / 2 model.box(f"pin_{i + 1}", sx, sy, pin_length + top, at=(x, y, (top - pin_length) / 2), op="new", body=body, name=f"Pin {i + 1}") model.box(f"pin_{i + 1}_leg", sx, y0 - y, sy, at=(x, (y0 + y) / 2, bend), op="join", body=body, name=f"Pin {i + 1} leg") pin_bodies.append(body) # Materials, for looks and a rough mass (the data sheets name none): a plastic case (pa6) in the maker's colour, the inside copper, tin-plated pins. model.material("pa6", bodies=["case_body", "base_body"], color=COLOURS.get(kind, "#1d1e20")) model.material("copper", bodies=["coil_body"], color="#b87333") model.material("copper", bodies=pin_bodies, color="#c9cbc8") result = model.result()