component
TPS16850VMAR - 9 V to 80 V, 20 A eFuse
Public Made by Adomby adom
Texas Instruments TPS16850VMAR: 9 V to 80 V, 20 A stackable integrated hot-swap eFuse with a 3.5 mOhm FET, fast current monitor and auto-retry fault response, LQFN-CLIP-23 (VMA, 6.0 x 5.0 mm). KiCad symbol and footprint, Fusion and Altium libraries, datasheet-built 3D model and datasheet.
main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
#!/usr/bin/env python3
"""Add the heatsink vias to the hero GLB as their own layer: TI's 12 vias of the land pattern (SLVSHA1D p.55,
0.2 mm drill) drawn as copper barrels through a pretend 1.6 mm board, 65 % transparent (alpha 0.35, BLEND,
double-sided, unlit), group node "Adom.HeatsinkVias" declared as layer "vias" ("Heatsink vias (1.6 mm board)").
Positions are read from the footprint's plated thru_hole pads; frame as hero_glb.py: glTF x = KiCad x,
y = -KiCad y, Z up, metres. Runs after hero_glb.py; idempotent (an existing Adom.HeatsinkVias node is replaced).
usage: hero_post_vias.py hero.glb footprint.kicad_mod"""
import re, sys, math
import numpy as np
from pygltflib import GLTF2, Accessor, BufferView, Material, Mesh, Node, Primitive, Attributes, PbrMetallicRoughness
glb, fp = sys.argv[1:3]
txt = open(fp).read()
vias = [(float(x), float(y), float(d)) for x, y, d in
re.findall(r'\(pad "24" thru_hole circle \(at (-?[\d.]+) (-?[\d.]+)\) \(size [\d.]+ [\d.]+\) \(drill ([\d.]+)\)', txt)]
assert vias, "no plated vias found"
g = GLTF2().load(glb)
if any(n.name == "Adom.HeatsinkVias" for n in g.nodes): sys.exit("hero already has Adom.HeatsinkVias")
N, BOARD = 20, 1.6e-3
pos, idx = [], []
for x, y, d in vias:
r = d / 2 * 1e-3; cx, cy = x * 1e-3, -y * 1e-3; b = len(pos)
for i in range(N):
a = 2 * math.pi * i / N
pos += [(cx + r * math.cos(a), cy + r * math.sin(a), -1e-5), (cx + r * math.cos(a), cy + r * math.sin(a), -BOARD)]
for i in range(N):
j = (i + 1) % N
idx += [b + 2 * i, b + 2 * i + 1, b + 2 * j, b + 2 * j, b + 2 * i + 1, b + 2 * j + 1]
P = np.array(pos, np.float32); I = np.array(idx, np.uint32)
blob = g.binary_blob() or b""
def add(data, target):
global blob
pad = (-len(blob)) % 4; blob += b"\0" * pad
off = len(blob); blob += data.tobytes()
g.bufferViews.append(BufferView(buffer=0, byteOffset=off, byteLength=len(data.tobytes()), target=target))
return len(g.bufferViews) - 1
bp = add(P, 34962); bi = add(I, 34963)
g.accessors.append(Accessor(bufferView=bp, componentType=5126, count=len(P), type="VEC3",
min=P.min(0).tolist(), max=P.max(0).tolist()))
ap = len(g.accessors) - 1
g.accessors.append(Accessor(bufferView=bi, componentType=5125, count=len(I), type="SCALAR"))
ai = len(g.accessors) - 1
g.materials.append(Material(name="Heatsink vias - copper barrels - 65 percent transparent",
pbrMetallicRoughness=PbrMetallicRoughness(baseColorFactor=[0.85, 0.5, 0.3, 0.35], metallicFactor=0.0, roughnessFactor=0.6),
alphaMode="BLEND", doubleSided=True, extensions={"KHR_materials_unlit": {}}))
g.meshes.append(Mesh(name="Adom.HeatsinkVias", primitives=[Primitive(attributes=Attributes(POSITION=ap), indices=ai, material=len(g.materials) - 1)]))
g.nodes.append(Node(name="Adom.HeatsinkVias", mesh=len(g.meshes) - 1,
extras={"adomLayer": {"key": "vias", "label": "Heatsink vias (1.6 mm board)", "group": "Board"},
"tooltip": f"{len(vias)} heatsink vias, 0.2 mm drill, under the exposed pad (IN)\nTI SLVSHA1D p.55 land pattern"}))
g.scenes[g.scene or 0].nodes.append(len(g.nodes) - 1)
if "KHR_materials_unlit" not in (g.extensionsUsed or []): g.extensionsUsed = (g.extensionsUsed or []) + ["KHR_materials_unlit"]
g.buffers[0].byteLength = len(blob)
g.set_binary_blob(blob)
ex = g.asset.extras or {}
if "adomHero" in ex:
ex["adomHero"].setdefault("layers", {})["heatsink_vias"] = {"node": "Adom.HeatsinkVias", "layer_key": "vias", "rgba": [0.85, 0.5, 0.3, 0.35],
"vias": len(vias), "drill_mm": vias[0][2], "board_mm": 1.6, "source": "footprint plated thru_hole pads 24 (TI SLVSHA1D p.55)",
"added_by": "provenance/tools/hero_post_vias.py"}
g.save(glb)
# pygltflib 1.16 drops asset.extras on save: write it back into the JSON chunk
import json, struct
b = open(glb, "rb").read(); L = struct.unpack("<I", b[12:16])[0]
j = json.loads(b[20:20 + L]); j["asset"]["extras"] = ex
js = json.dumps(j, separators=(",", ":")).encode(); js += b" " * ((-len(js)) % 4)
rest = b[20 + L:]
out = b[:12] + struct.pack("<I", len(js)) + b"JSON" + js + rest
out = out[:8] + struct.pack("<I", len(out)) + out[12:]
open(glb, "wb").write(out)
print(f"OK {glb}: {len(vias)} via barrels in Adom.HeatsinkVias")