Files
OptoTest/PCB/Libs/generate_3d_models.py

131 lines
4.6 KiB
Python

"""Generate the custom STEP models used by the OptoTest PCB libraries.
The coordinate system follows Altium's usual convention: XY is the PCB plane and
Z points away from the top side of the PCB. All dimensions are in millimetres.
"""
from pathlib import Path
import sys
CADQUERY_PATH = Path.home() / "AppData/Local/Temp/codex-cadquery"
if CADQUERY_PATH.exists():
sys.path.insert(0, str(CADQUERY_PATH))
import cadquery as cq
OUT_DIR = Path(__file__).resolve().parent
def box(x, y, z, cx=0.0, cy=0.0, bottom=0.0):
return cq.Workplane("XY").box(x, y, z).translate((cx, cy, bottom + z / 2))
def cylinder(diameter, height, cx=0.0, cy=0.0, bottom=0.0):
return (
cq.Workplane("XY")
.circle(diameter / 2)
.extrude(height)
.translate((cx, cy, bottom))
)
def add_dip8_precision_socket(assembly):
"""7.62-mm-row precision/turned-pin DIP-8 socket seated on the PCB."""
black = cq.Color(0.055, 0.055, 0.060)
gold = cq.Color(0.78, 0.55, 0.12)
dark = cq.Color(0.015, 0.015, 0.018)
# Two turned-pin carrier rails and end bridges. The centre remains open,
# matching the precision socket used by the SN75451 model.
assembly.add(box(2.35, 10.15, 3.65, -3.81, 0, 0.35), color=black)
assembly.add(box(2.35, 10.15, 3.65, +3.81, 0, 0.35), color=black)
assembly.add(box(5.30, 1.15, 1.10, 0, -4.50, 0.35), color=black)
assembly.add(box(5.30, 1.15, 1.10, 0, +4.50, 0.35), color=black)
for x in (-3.81, 3.81):
for y in (-3.81, -1.27, 1.27, 3.81):
assembly.add(cylinder(0.50, 3.15, x, y, -2.80), color=gold)
assembly.add(cylinder(1.22, 3.20, x, y, 0.55), color=gold)
assembly.add(cylinder(0.70, 3.23, x, y, 0.57), color=dark)
def make_opa380_adapter():
assembly = cq.Assembly(name="OPA380_SOIC8_ADAPTER_DIP8_PRECISION_SOCKET")
add_dip8_precision_socket(assembly)
green = cq.Color(0.035, 0.30, 0.12)
copper = cq.Color(0.72, 0.43, 0.12)
silver = cq.Color(0.72, 0.74, 0.76)
black = cq.Color(0.035, 0.035, 0.040)
marking = cq.Color(0.82, 0.82, 0.78)
# DIP-8/SOIC-8 adapter. Its lower pins plug into the precision socket.
for x in (-3.81, 3.81):
for y in (-3.81, -1.27, 1.27, 3.81):
assembly.add(cylinder(0.46, 3.30, x, y, 2.80), color=copper)
assembly.add(box(10.25, 10.25, 1.20, 0, 0, 6.00), color=green)
# Visible DIP pads on the adapter PCB.
for x in (-3.81, 3.81):
for y in (-3.81, -1.27, 1.27, 3.81):
assembly.add(cylinder(1.30, 0.06, x, y, 7.20), color=copper)
# OPA380 in TI D (SOIC-8): nominal 3.9 x 4.9 mm body, 1.27-mm pitch.
body = box(3.90, 4.90, 1.55, 0, 0, 7.33)
try:
body = body.edges("|Z").fillet(0.18)
except Exception:
pass
assembly.add(body, color=black)
# Gull-wing leads. Pin 1 is at the lower-left corner in top view.
for x in (-2.55, 2.55):
for y in (-1.905, -0.635, 0.635, 1.905):
assembly.add(box(1.25, 0.42, 0.16, x, y, 7.25), color=silver)
assembly.add(cylinder(0.42, 0.035, -1.28, -1.55, 8.88), color=marking)
output = OUT_DIR / "OPA380_SOIC8_ADAPTER_DIP8_PRECISION_SOCKET.step"
assembly.save(str(output), mode="default")
return output
def make_bpw34_vertical():
assembly = cq.Assembly(name="BPW34_VERTICAL_P5.08mm")
silver = cq.Color(0.72, 0.74, 0.76)
clear = cq.Color(0.72, 0.78, 0.80, 0.58)
die = cq.Color(0.10, 0.16, 0.19)
cathode_mark = cq.Color(0.25, 0.28, 0.30)
# Leads occupy footprint positions 1 and 3. Position 2 (x=0) is omitted.
# Centre-to-centre distance is therefore exactly 2 x 2.54 = 5.08 mm.
for x in (-2.54, 2.54):
assembly.add(box(0.50, 0.38, 5.30, x, 0, -2.60), color=silver)
# Upright BPW34 body, based on Vishay drawing 6.544-5315.01-4:
# 4.65-mm face width, 4.3-mm face height and 2.0-mm package depth.
# The leads are deliberately formed out to the requested 5.08-mm spacing.
body = box(4.65, 2.00, 4.30, 0, 0, 2.15)
try:
body = body.edges("|Z").fillet(0.25)
except Exception:
pass
assembly.add(body, color=clear)
# Visible detector die and bond area inside the transparent package.
assembly.add(box(3.00, 0.12, 3.00, 0, -0.89, 2.80), color=die)
# Cathode-side stripe, located by footprint pad 1 (left in top/front view).
assembly.add(box(0.22, 0.08, 3.55, -2.16, -1.06, 2.50), color=cathode_mark)
output = OUT_DIR / "BPW34_VERTICAL_P5.08mm.step"
assembly.save(str(output), mode="default")
return output
if __name__ == "__main__":
for model in (make_opa380_adapter(), make_bpw34_vertical()):
print(model)