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-candidates.mjs

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

const baseline = JSON.parse(
  fs.readFileSync("frozen-global-router-baseline.json", "utf8"),
).filter((element) => !String(element.type).endsWith("error"))

const targets = [
  ["source_net_30_0", 0.3165170373, 2.4681926742],
  ["source_net_26_mst1_0", -4.9635288614, 0.8009878988],
  ["source_net_26_mst1_0", -1.0149987646, -4.722238758],
  ["source_net_22_mst0_0", -5.975494, -3.367],
  ["source_net_22_mst1_0", 1.9745212144, 2.375001],
  ["source_net_21_0", -3.2397362534, -2.7668353546],
  ["source_net_21_0", 1.6, -3.9750010113],
  ["source_net_20_0", -4.3972237089, -1.6200715176],
  ["source_net_23_mst0_0", -3.9238737059, -2.7701900181],
  ["source_net_23_mst1_0", -3.0264205132, -3.6563618696],
  ["source_net_16_mst1_0", -3.6537511544, -3.7702748294],
  ["source_net_7_0", -2.2608049598, -3.9417301825],
  ["source_net_15_0", -2.5563157055, 0.4729727559],
]

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

const moveVia = (traceId, oldX, oldY, newX, newY) => baseline.map((element) => {
  if (element.type === "pcb_via" && element.pcb_trace_id === traceId &&
      samePoint(element, oldX, oldY)) {
    return { ...element, x: newX, y: newY }
  }
  if (element.type === "pcb_trace" && element.pcb_trace_id === traceId) {
    return {
      ...element,
      route: element.route.map((point) => samePoint(point, oldX, oldY)
        ? { ...point, x: newX, y: newY }
        : point),
    }
  }
  return element
})

const baselineErrors = await runAllRoutingChecks(baseline)
const baselineCount = baselineErrors.length
console.log(`baseline\t${baselineCount}`)

for (const [traceId, oldX, oldY] of targets.slice(2)) {
  let best = { count: baselineCount, x: oldX, y: oldY, errors: baselineErrors }
  const radius = 1
  const step = 0.1
  for (let dx = -radius; dx <= radius + 1e-6; dx += step) {
    for (let dy = -radius; dy <= radius + 1e-6; dy += step) {
      if (Math.abs(dx) < 1e-6 && Math.abs(dy) < 1e-6) continue
      const x = Number((oldX + dx).toFixed(4))
      const y = Number((oldY + dy).toFixed(4))
      if (Math.abs(x) > 9.4 || Math.abs(y) > 9.4) continue
      let errors
      try {
        errors = await runAllRoutingChecks(moveVia(traceId, oldX, oldY, x, y))
      } catch {
        continue
      }
      if (errors.length < best.count) best = { count: errors.length, x, y, errors }
    }
  }
  const kinds = Object.entries(Object.groupBy(best.errors, (error) => error.type))
    .map(([kind, errors]) => `${kind}:${errors.length}`)
    .join(",")
  console.log(`${traceId}@${oldX},${oldY}\t${best.count}\t${best.x},${best.y}\t${kinds}`)
}