project
12 V to 5 V / 1 A Buck Molecule (TPS54202)
Public Unreviewedby John Lauer
An independently designed 12 V to 5 V, 1 A synchronous buck molecule (TI TPS54202), with calculations, ngspice and PSpice simulation, KiCad 10 schematic and board, and the board laid out and analysed with adom-aiflow.
← Commit history
scaffold/viewer.htmldeleted−141@@ -1,141 +0,0 @@-<!doctype html>-<html lang="en">-<head>-<meta charset="utf-8">-<meta name="viewport" content="width=device-width, initial-scale=1">-<title>Buck Probe Scaffold</title>-<style>- :root { --bg: #f4f5f7; --fg: #1d2330; --muted: #5b6475; --panel: rgba(255,255,255,0.92); --line: #d8dce3; }- @media (prefers-color-scheme: dark) {- :root:not([data-theme="light"]) { --bg: #14171d; --fg: #e6e9ef; --muted: #9aa3b2; --panel: rgba(28,32,40,0.92); --line: #323845; }- }- :root[data-theme="dark"] { --bg: #14171d; --fg: #e6e9ef; --muted: #9aa3b2; --panel: rgba(28,32,40,0.92); --line: #323845; }- html, body { margin: 0; height: 100%; background: var(--bg); color: var(--fg); font: 14px/1.45 system-ui, -apple-system, "Segoe UI", sans-serif; overflow: hidden; }- #c { position: fixed; inset: 0; }- #legend { position: fixed; left: 16px; top: 16px; max-width: min(420px, calc(100vw - 32px)); background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px; }- #legend h1 { font-size: 15px; margin: 0 0 6px; }- #legend p { margin: 0 0 8px; color: var(--muted); font-size: 12.5px; }- #legend table { border-collapse: collapse; width: 100%; font-size: 12.5px; }- #legend td { padding: 2px 6px 2px 0; vertical-align: top; }- .sw { display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin-right: 4px; vertical-align: -1px; }- #status { position: fixed; right: 16px; bottom: 12px; color: var(--muted); font-size: 12px; }- @media (max-width: 600px) { #legend { font-size: 12px; padding: 10px; } }-</style>-</head>-<body>-<canvas id="c"></canvas>-<div id="legend">- <h1>12 V to 5 V buck on a probing scaffold</h1>- <p>Buck molecule (28 x 20 mm, medium pins) on a LrgMed 64 x 64 scaffold, wired to the Control Panel scaffold. Positions come from <code>buck-probe-layout.json</code>; the control panel's place is approximate.</p>- <table id="wires"></table>-</div>-<div id="status">loading models</div>-<script type="importmap">-{ "imports": { "three": "https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js",- "three/addons/": "https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/" } }-</script>-<script type="module">-import * as THREE from 'three';-import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';-import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';-import { OrbitControls } from 'three/addons/controls/OrbitControls.js';--const params = new URLSearchParams(location.search);-if (params.has('clean')) { document.getElementById('legend').style.display = 'none'; document.getElementById('status').style.display = 'none'; }-const status = document.getElementById('status');-const canvas = document.getElementById('c');-const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, preserveDrawingBuffer: true });-renderer.setPixelRatio(Math.min(devicePixelRatio, 2));-const dark = matchMedia('(prefers-color-scheme: dark)').matches && document.documentElement.dataset.theme !== 'light';-const scene = new THREE.Scene();-scene.background = new THREE.Color(dark ? 0x14171d : 0xf4f5f7);-scene.add(new THREE.HemisphereLight(0xffffff, 0x445066, 1.6));-const sun = new THREE.DirectionalLight(0xffffff, 1.6); sun.position.set(200, -300, 500); scene.add(sun);--// World frame = the layout frame: millimetres, X right, Y back, Z up (three.js is Y-up, so rotate once).-const world = new THREE.Group(); world.rotation.x = -Math.PI / 2; scene.add(world);-const camera = new THREE.PerspectiveCamera(35, 1, 1, 5000);-const controls = new OrbitControls(camera, canvas);--const CP = { centre: [272, 603], boardCentre: [119, 70.5] }; // control panel: board 160 x 45 mm (Edge.Cuts x 39..199, y 48..93)-const loader = new GLTFLoader();-const draco = new DRACOLoader(); draco.setDecoderPath('https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/libs/draco/gltf/');-loader.setDRACOLoader(draco);-const load = url => new Promise((ok, bad) => loader.load(url, g => ok(g.scene), undefined, bad));--function box(o) { return new THREE.Box3().setFromObject(o); }--async function main() {- const [layout, cpContacts] = await Promise.all([fetch('buck-probe-layout.json').then(r => r.json()), fetch('cp-contacts.json').then(r => r.json())]);- // base scaffold: 576 x 576 mm plate with the 18 x 18 large-contact grid (16 + 32 n)- const base = new THREE.Mesh(new THREE.BoxGeometry(576, 576, 3), new THREE.MeshStandardMaterial({ color: dark ? 0x2a2f3a : 0xd9dde4 }));- base.position.set(288, 288, -1.5); world.add(base);- const dotG = new THREE.CylinderGeometry(2.6, 2.6, 0.4, 20); dotG.rotateX(Math.PI / 2);- const dotM = new THREE.MeshStandardMaterial({ color: 0xc9a227, metalness: 0.6, roughness: 0.4 });- for (let i = 0; i < 18; i++) for (let j = 0; j < 18; j++) { const d = new THREE.Mesh(dotG, dotM); d.position.set(16 + 32 * i, 16 + 32 * j, 0.2); world.add(d); }-- // LrgMed scaffold: OCCT GLB in metres, Z up, centred on its board; its FL large pin sits 32 mm from centre- const sc = layout.molecules['Scaffold LrgMed 64x64'];- const scaf = await load('scaffold-lrgmed-64x64.glb');- scaf.scale.setScalar(1000);- const scafG = new THREE.Group(); scafG.add(scaf); scafG.position.set(sc.position.x + 32, sc.position.y + 32, 12.5); world.add(scafG);-- // buck molecule: step2glb anchors MP1 (FL pin) at the origin, metres, Z up- const bm = layout.molecules['Buck 12V-5V 1A'];- const buck = await load('buck-12v5v-molecule.glb');- buck.scale.setScalar(1000);- const buckG = new THREE.Group(); buckG.add(buck); buckG.position.set(bm.position.x, bm.position.y, bm.position.z + 12.5); world.add(buckG);-- // control panel: Draco GLB; scale its long side to 160 mm and set it on the base's back edge- const cp = await load('control-panel-scaffold.glb');- const cpG = new THREE.Group(); cpG.add(cp);- let b = box(cpG); const s = b.getSize(new THREE.Vector3());- cp.scale.setScalar(160 / Math.max(s.x, s.y));- b = box(cpG); const c = b.getCenter(new THREE.Vector3());- // the bounding box includes the dock connector behind the board: anchor on the board's FRONT edge (min y), 22.5 mm in front of its centre- cp.position.sub(new THREE.Vector3(c.x, b.min.y + 22.5, b.min.z));- cpG.position.set(CP.centre[0], CP.centre[1], 0); world.add(cpG);- // the panel's board is the flat mesh about 160 x 45 mm: its top face is where the contacts are- world.updateMatrixWorld(true);- const inv = new THREE.Matrix4().copy(world.matrixWorld).invert();- let cpTop = 3, best = 0, cpBoard = null;- cpG.traverse(o => { if (!o.isMesh) return; const bb = new THREE.Box3().setFromObject(o).applyMatrix4(inv); const sz = bb.getSize(new THREE.Vector3());- const area = sz.x * sz.y; if (area > best && sz.z < 3) { best = area; cpTop = bb.max.z; cpBoard = bb; } });-- // wires: molecule-local contact -> control-panel contact, raised arcs- const tbl = document.getElementById('wires');- for (const w of layout.wires) {- const st = w.startReference, m = layout.molecules[st.moleculeName];- const a = new THREE.Vector3(m.position.x + st.contactPosition.x, m.position.y + st.contactPosition.y, m.position.z + 12.5 + st.contactPosition.z);- const [bx, by] = cpContacts[w.endReference.controlPanelContactName];- // KiCad board frame: Edge.Cuts x 39..199, y 48..93 (y down, y = 93 is the front edge facing the workspace)- const e = new THREE.Vector3(cpBoard.min.x + (bx - 39), cpBoard.min.y + (93 - by), 3);- e.z = cpTop + 0.6;- const up = Math.max(a.z, e.z) + 18;- const curve = new THREE.CatmullRomCurve3([a, new THREE.Vector3(a.x, a.y, up), new THREE.Vector3((a.x + e.x) / 2, (a.y + e.y) / 2, up + 6), new THREE.Vector3(e.x, e.y, up), e]);- const col = new THREE.Color(w.color.r, w.color.g, w.color.b);- world.add(new THREE.Mesh(new THREE.TubeGeometry(curve, 80, 0.9, 10), new THREE.MeshStandardMaterial({ color: col, roughness: 0.5 })));- const tip = new THREE.Mesh(new THREE.SphereGeometry(1.6, 16, 12), new THREE.MeshStandardMaterial({ color: col })); tip.position.copy(e); world.add(tip);- const hex = '#' + col.getHexString();- tbl.insertAdjacentHTML('beforeend', `<tr><td><span class="sw" style="background:${hex}"></span>${w.name}</td><td>${st.contactName} to ${w.endReference.controlPanelContactName}</td></tr>`);- }-- const focus = new THREE.Vector3(272, 540, 10).applyMatrix4(world.matrix);- world.updateMatrixWorld(); const f = new THREE.Vector3(272, 545, 10); world.localToWorld(f);- const view = params.get('view') || 'iso';- if (view === 'cp') f.set(272, 586, 0), world.localToWorld(f);- if (view === 'orbit') f.set(272, 540, 0), world.localToWorld(f);- const eye = view === 'orbit' ? new THREE.Vector3(272, 300, 260) : view === 'cp' ? new THREE.Vector3(272, 540, 75) : view === 'top' ? new THREE.Vector3(272, 545, 260) : view === 'close' ? new THREE.Vector3(215, 430, 95) : new THREE.Vector3(150, 360, 190);- world.localToWorld(eye);- camera.position.copy(eye); controls.target.copy(f); controls.update();- status.textContent = 'drag to orbit, scroll to zoom';- if (params.has('spin')) { controls.autoRotate = true; controls.autoRotateSpeed = parseFloat(params.get('spin')) || 0.6; }- document.body.dataset.ready = '1';-}-function size() { const w = innerWidth, h = innerHeight; renderer.setSize(w, h, false); camera.aspect = w / h; camera.updateProjectionMatrix(); }-addEventListener('resize', size); size();-renderer.setAnimationLoop(() => { controls.update(); renderer.render(scene, camera); });-main().catch(e => { status.textContent = 'error: ' + e.message; document.body.dataset.ready = 'err'; console.error(e); });-</script>-</body>-</html>