ShiboSoftwareDev/nema8-20mm-dual-usbc-stepper-controller

A compact 4-layer USB‑C PD stepper-motor controller PCB using a CH32X035 MCU, TMC2209 driver, dual USB‑C ports, power protection/regulation, ESD/TVS diodes, current-sense resistors, and NEMA‑8 motor connector.

Version
1.0.13
License
unset
Stars
0

scripts/search-via-positions.mjs

import fs from "node:fs"
import { runAllRoutingChecks } from "@tscircuit/checks"

const raw = JSON.parse(fs.readFileSync("dist/index/circuit.json", "utf8"))
const clean = raw.filter((element) => !String(element.type).endsWith("error"))

const samePoint = (point, x, y) => Math.hypot(point.x - x, point.y - y) < 1e-5

const moveVia = (circuit, viaId, x, y) => {
  const via = circuit.find((element) => element.type === "pcb_via" && element.pcb_via_id === viaId)
  if (!via) throw new Error(`Missing ${viaId}`)
  return circuit.map((element) => {
    if (element.type === "pcb_via" && element.pcb_via_id === viaId) return { ...element, x, y }
    if (element.type !== "pcb_trace" || element.pcb_trace_id !== via.pcb_trace_id) return element
    return {
      ...element,
      route: element.route.map((point) => samePoint(point, via.x, via.y) ? { ...point, x, y } : point),
    }
  })
}

let base = clean
if (process.env.SKIP_BASE_MOVES !== "1") {
  for (const [viaId, x, y] of [
    ["pcb_via_53", 0.4072, 4.6301],
    ["pcb_via_75", -2.7599, 1.7044],
    ["pcb_via_89", -2.3924, -2.575],
  ]) base = moveVia(base, viaId, x, y)
}

const vmEdgeTraceId = "source_trace_3__source_trace_4__source_trace_5__source_trace_6__source_trace_7__source_trace_8__source_trace_9__source_trace_10__source_trace_11_mst6_0"
base = base.map((element) => element.type === "pcb_trace" && element.pcb_trace_id === vmEdgeTraceId
  ? { ...element, route: element.route.map((point) => point.x > 9.65 ? { ...point, x: 9.65 } : point) }
  : element)

const hardErrors = async (circuit) => (await runAllRoutingChecks(circuit))
  .filter((error) => error.type !== "pcb_trace_warning")

const targets = process.argv.slice(2)
const searchTargets = targets.length ? targets : ["pcb_via_41", "pcb_via_48", "pcb_via_55", "pcb_via_57"]
const searchRange = Number(process.env.SEARCH_RANGE ?? "0.6")
const searchStep = Number(process.env.SEARCH_STEP ?? "0.1")
const centerOverride = process.env.SEARCH_CENTER?.split(",").map(Number)

for (const viaId of searchTargets) {
  const via = base.find((element) => element.type === "pcb_via" && element.pcb_via_id === viaId)
  if (!via) throw new Error(`Missing ${viaId}`)
  const centerX = centerOverride?.[0] ?? via.x
  const centerY = centerOverride?.[1] ?? via.y
  const candidates = []
  for (let dx = -searchRange; dx <= searchRange + 0.0001; dx += searchStep) {
    for (let dy = -searchRange; dy <= searchRange + 0.0001; dy += searchStep) {
      const x = Math.round((centerX + dx) * 10000) / 10000
      const y = Math.round((centerY + dy) * 10000) / 10000
      if ((viaId === "pcb_via_48" || viaId === "pcb_via_55") && y > 9.575) continue
      if (viaId === "pcb_via_74" && x > 9.575) continue
      const errors = await hardErrors(moveVia(base, viaId, x, y))
      const involving = errors.filter((error) => JSON.stringify(error).includes(viaId)).length
      candidates.push({ x, y, total: errors.length, involving })
    }
  }
  candidates.sort((a, b) => a.total - b.total || a.involving - b.involving ||
    Math.hypot(a.x - via.x, a.y - via.y) - Math.hypot(b.x - via.x, b.y - via.y))
  console.log(viaId, JSON.stringify(candidates.slice(0, 20)))
  const best = candidates[0]
  const bestErrors = await hardErrors(moveVia(base, viaId, best.x, best.y))
  console.log(bestErrors.map((error) => `${error.type}\t${error.message}`).join("\n"))
}