"""Single-phase bridge rectifier in a through-hole case, from Vishay's package drawings: the in-line cases GBL, GBU, KBL and KBU, and the square cases KBPC1 and KBPC6 (Vishay outline D-72). In-line: the body stands on the board with its four leads in a row along X, centred on the origin, the leads' centre line at y = 0 and the face with the polarity marks towards -Y; the + lead is at the body's chamfered end (GBL and KBL: -X, GBU and KBU: +X, as each sheet's front view draws it). Square: the body sits on the board centred on the origin, the leads at the corners of a square, + at -X +Y beside the chamfered corner. The board is the XY plane and the leads go down through it. Dimensions from Vishay's data sheets, listed in the README.""" from steve import Model case = "GBU" # GBL, GBU, KBL, KBU, KBPC1 or KBPC6 detail = "full" # full: body and leads; simple: the body only IN = 25.4 # In-line cases, (min, max) in inches as the sheets give them (millimetres in brackets on the sheets); the model uses the middle. # L body length, T body thickness, H body height (top to the body's underside), F feet or shoulders below the body, w lead width (flat # leads) or d lead diameter (round leads), t flat lead thickness, s shoulder width (GBU: outer leads, then inner leads), e pitch, # P lead length below the body's underside (KBU: below the feet), Plus the + lead's extra length, y lead centre line from the front # face, C top-corner chamfer at the + end, slot: (width, centre spacing, centre from the top (GBU) or lower centre above the bottom (KBU)). # Vishay General Semiconductor, "GBL005, GBL01, ... GBL10", document 89300, revision 22-Aug-2023, page 3, "PACKAGE OUTLINE # DIMENSIONS ... Case Type GBL". # Vishay General Semiconductor, "GBU4A, GBU4B, ... GBU4M", document 88614, revision 13-Jul-2020, page 3, "Case Type GBU". # Vishay General Semiconductor, "KBL005 thru KBL10", document 88655, revision 07-Jun-06, page 3, "Case Style KBL" (copy hosted by # static.datasheets.com; vishay.com no longer serves 88655). # Vishay General Semiconductor, "KBU4A, KBU4B, ... KBU4M", document 98731, revision 24-Jan-2025, page 3, "Case Style KBU". INLINE = { "GBL": dict(L=(0.815, 0.825), T=(0.128, 0.140), H=(0.411, 0.421), F=(0.060, 0.080), w=(0.040, 0.050), t=(0.018, 0.022), s=(0.080, 0.095), e=(0.190, 0.210), P=(0.682, 0.718), y=(0.030, 0.040), C=(0.125, 0.125), plus=-1), "GBU": dict(L=(0.860, 0.880), T=(0.130, 0.140), H=(0.720, 0.740), F=(0.060, 0.080), w=(0.040, 0.050), t=(0.020, 0.026), s=(0.085, 0.100), s2=(0.065, 0.080), e=(0.190, 0.210), P=(0.690, 0.710), y=(0.075, 0.085), C=(0.125, 0.125), slot=((0.140, 0.160), (0.065, 0.085), (0.290, 0.310)), plus=1), # KBL: 0.640/0.600 overall at the feet, 0.591/0.567 to the body's underside; + lead 1.1 min below the feet, the others 1.0 min below # the body's underside (the only values given, so the model uses them). "KBL": dict(L=(0.726, 0.768), T=(0.236, 0.256), H=(0.567, 0.591), total=(0.600, 0.640), d=(0.048, 0.052), e=(0.190, 0.210), P=(1.0, 1.0), Pplus=(1.1, 1.1), y=(0.077, 0.091), plus=-1), # KBU: 0.700/0.660 to the body's underside, 0.760 max overall (the only value); leads 1.0 min below the feet, the + lead 0.240/0.200 # longer; lead row 0.205/0.185 from the back face. "KBU": dict(L=(0.895, 0.935), T=(0.260, 0.280), H=(0.660, 0.700), total=(0.760, 0.760), d=(0.048, 0.052), e=(0.180, 0.220), P=(1.0, 1.0), extra=(0.200, 0.240), back=(0.185, 0.205), C=(0.165, 0.185), slot=((0.140, 0.160), (0.065, 0.085), (0.405, 0.455)), plus=1), } # Square cases, (min, max) in millimetres: Vishay Semiconductors, "D-72" Outline Dimensions, document 95250, revision 06-Feb-2024, # "DIMENSIONS in millimeters (inches): KBPC6, KBPC8" and "...: KBPC1" (also page 4 of VS-KBPC1/KBPC6 series, document 93585). # S side, H height, d lead diameter, c lead spacing (both ways), P lead length (min), hole the mounting hole diameter. SQUARE = { "KBPC1": dict(S=(15.7, 16.7), H=(5.5, 6.5), d=(0.7, 0.9), c=(10.0, 11.0), P=(22.0, 22.0), hole=(3.8, 4.2)), "KBPC6": dict(S=(14.75, 15.75), H=(4.33, 5.33), d=(0.90, 1.10), c=(10.0, 10.8), P=(25.4, 25.4), hole=(3.60, 4.00)), } # Proportions, for looks (the drawings show these but don't dimension them): an undimensioned chamfer (KBL's top corner, the KBPC's # + corner) is 0.12 x the body's length or side; KBL's and KBU's feet are 0.06 x the length wide at each end; the GBU's corner radii and # draft angles and the KBPC's top rim aren't modelled; the leads end square. CHAMFER = 0.12 FOOT = 0.06 if case not in INLINE and case not in SQUARE: raise ValueError(f"no case {case!r}: {', '.join([*INLINE, *SQUARE])}") def mid(v, scale=1.0): if isinstance(v, tuple) and isinstance(v[0], tuple): return tuple(mid(x, scale) for x in v) if isinstance(v, tuple): return (v[0] + v[1]) / 2 * scale return v model = Model() def xz_prism(fid, points, y0, depth, body, op, name): """A prism of the (x, z) outline from the plane y = y0 back along -Y by depth (an XZ plane extrudes along -Y).""" model.plane(f"{fid}_plane", on="XZ", offset=-y0, name=name) with model.sketch(f"{fid}_sketch", on=f"{fid}_plane", name=name) as sk: if len(points) == 3 and not isinstance(points[0], tuple): sk.circle(f"{fid}_circle", (points[0], points[1]), points[2]) else: sk.polyline(f"{fid}_outline", points, closed=True) model.extrude(fid, f"{fid}_sketch", distance=depth, op=op, body=body, name=name) def xy_prism(fid, shape, z0, height, body, op, name): model.plane(f"{fid}_plane", on="XY", offset=z0, name=name) with model.sketch(f"{fid}_sketch", on=f"{fid}_plane", name=name) as sk: if len(shape) == 3 and not isinstance(shape[0], tuple): sk.circle(f"{fid}_circle", (shape[0], shape[1]), shape[2]) else: sk.polyline(f"{fid}_outline", shape, closed=True) model.extrude(fid, f"{fid}_sketch", distance=height, op=op, body=body, name=name) leads = [] if case in INLINE: t = {k: mid(v, IN) for k, v in INLINE[case].items() if k != "plus"} plus = INLINE[case]["plus"] L, T, H = t["L"], t["T"], t["H"] if case in ("GBL", "GBU"): F = t["F"] # the leads' shoulders hold the body this far above the board yf = t["y"] else: F = t["total"] - H # feet at both ends yf = t["y"] if case == "KBL" else T - t["back"] C = t["C"] if "C" in t else CHAMFER * L top = F + H # Body outline seen from the front (x, z), the chamfer on the top corner at the + end; KBL and KBU stand on feet at both ends. xp, xm = plus * L / 2, -plus * L / 2 if F and case in ("KBL", "KBU"): f = FOOT * L outline = [(xm, 0.0), (xm + plus * f, 0.0), (xm + plus * f, F), (xp - plus * f, F), (xp - plus * f, 0.0), (xp, 0.0), (xp, top - C), (xp - plus * C, top), (xm, top)] else: outline = [(xm, F), (xp, F), (xp, top - C), (xp - plus * C, top), (xm, top)] xz_prism("body", outline, T - yf, T, "body_body", "new", "Body") if "slot" in t: sw, sp, sz = t["slot"] # GBU: the upper centre sz below the top; KBU: the lower centre sz above the bottom of the feet. z_hi = top - sz if case == "GBU" else sz + sp z_lo = z_hi - sp for i, z in enumerate((z_hi, z_lo)): xz_prism(f"slot_{i}", (0.0, z, sw / 2), T - yf + 1, T + 2, "body_body", "cut", "Mounting slot") xz_prism("slot_mid", [(-sw / 2, z_lo), (sw / 2, z_lo), (sw / 2, z_hi), (-sw / 2, z_hi)], T - yf + 1, T + 2, "body_body", "cut", "Mounting slot") if detail == "full": e = t["e"] xs = [(i - 1.5) * e for i in range(4)] # Lead order from -X: + ~ ~ - (GBL, KBL) or - ~ ~ + (GBU, KBU). for i, x in enumerate(xs): is_plus = i == (0 if plus < 0 else 3) outer = i in (0, 3) if case in ("GBL", "GBU"): w, th = t["w"], t["t"] tip = F - t["P"] xz_prism(f"lead_{i + 1}", [(x - w / 2, tip), (x + w / 2, tip), (x + w / 2, F), (x - w / 2, F)], th / 2, th, f"lead_{i + 1}_body", "new", f"Lead {i + 1}") s = t["s"] if (outer or case == "GBL") else t["s2"] xz_prism(f"shoulder_{i + 1}", [(x - s / 2, 0.0), (x + s / 2, 0.0), (x + s / 2, F), (x - s / 2, F)], th / 2, th, f"lead_{i + 1}_body", "join", f"Lead {i + 1} shoulder") else: if case == "KBL": tip = -t["Pplus"] if is_plus else F - t["P"] else: tip = -t["P"] - (t["extra"] if is_plus else 0.0) xy_prism(f"lead_{i + 1}", (x, 0.0, t["d"] / 2), tip, F - tip, f"lead_{i + 1}_body", "new", f"Lead {i + 1}") leads.append(f"lead_{i + 1}_body") else: t = {k: mid(v) for k, v in SQUARE[case].items()} S, H, c = t["S"], t["H"], t["c"] k = CHAMFER * S xy_prism("body", [(-S / 2, -S / 2), (S / 2, -S / 2), (S / 2, S / 2), (-S / 2 + k, S / 2), (-S / 2, S / 2 - k)], 0.0, H, "body_body", "new", "Body") xy_prism("hole", (0.0, 0.0, t["hole"] / 2), -1.0, H + 2, "body_body", "cut", "Mounting hole") if detail == "full": # + at -X +Y, ~ at +X +Y and -X -Y, - at +X -Y (the top view on D-72). for i, (sx, sy) in enumerate(((-1, 1), (1, 1), (-1, -1), (1, -1))): xy_prism(f"lead_{i + 1}", (sx * c / 2, sy * c / 2, t["d"] / 2), -t["P"], t["P"], f"lead_{i + 1}_body", "new", f"Lead {i + 1}") leads.append(f"lead_{i + 1}_body") # Materials, for looks and a rough mass: the body is epoxy moulding compound, mostly silica filler (density about 1.9 to 2.0), and ptfe (2.2) # is the nearest in the material list; the leads are tin-plated copper. model.material("ptfe", bodies=["body_body"], color="#2b2c2e") if leads: model.material("copper", bodies=leads, color="#c9ccd1") result = model.result()